#include "std/base.toc", base; #if base.PLATFORM_IS_UNIX { // @TODO: use syscall instead write ::= #foreign("write", "libc.so.6") fn(#C int, #C &"const void", #C size_t) #C long; RawFile ::= int; raw_file_write ::= fn(file: RawFile, buf: &void, size: int) int { write(file as #C int, buf, size as #C size_t) as int } raw_stdout ::= fn() RawFile { 1 } raw_stderr ::= fn() RawFile { 2 } } else { // @TODO: on windows, use WriteFile fwrite ::= #foreign("fwrite", base.libc) fn(#C &"const void", #C size_t, #C size_t, &void) #C size_t; RawFile ::= &void; raw_file_write ::= fn(file: RawFile, buf: &void, size: int) int { fwrite(buf, 1, size, file); } raw_stdout ::= fn() RawFile { #builtin("stdout") } raw_stderr ::= fn() RawFile { #builtin("stdout") } } File ::= struct { BUFSZ ::= 4096; raw : RawFile; written : int; // ranges from 0 to FILE_BUFSZ-1 nobuffer : bool; // if true, flush after every write buffer : [BUFSZ]char; } raw_file_to_file ::= fn(raw : RawFile) f: File { f.raw = raw; } std_out, std_err : File; file_flush ::= fn(use f: &File) { raw_file_write(raw, &buffer[0], written); written = 0; } file_writes ::= fn(use f: &File, s : []char) { if f.nobuffer { raw_file_write(raw, &s[0], s.len); return; } if written + s.len > BUFSZ { file_flush(f); if s.len > BUFSZ { raw_file_write(raw, &s[0], s.len); } else { base.memcpy(&buffer[0], &s[0], s.len as #C size_t); written = s.len; } } else { base.memcpy(&buffer[written], &s[0], s.len as #C size_t); written += s.len; } } io_init ::= fn() { std_out = raw_file_to_file(raw_stdout()); std_out.nobuffer = true; std_err = raw_file_to_file(raw_stderr()); std_err.nobuffer = true; }