summaryrefslogtreecommitdiff
path: root/std/io.toc
blob: acba6732ed5ee55952f0e14a3b5e119c0eed3aa9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "std/base.toc", base;
#include "std/mem.toc", mem;

str_to_cstr ::= fn(s: []char) []char {
	ret := mem.news(char, s.len+1);
	mem.mem_copy(&ret[0], &s[0], s.len);
	ret
}

#if base.PLATFORM_IS_UNIX {
	// @TODO: use syscall instead
	write ::= #foreign("write", base.libc) fn(#C int, #C &"const void", #C size_t) #C long;
	open ::= #foreign("open", base.libc) fn (#C &"const char", #C int) #C int;

	O_RDONLY ::= 0x00;
	O_WRONLY ::= 0x01;
	O_CREAT  ::= 0x40;

	RawFile ::= int;
	raw_file_write ::= fn(file: RawFile, buf: &void, size: int) bool {
		while size > 0 {
			bytes_written := write(file as #C int, buf, size as #C size_t);
			if bytes_written < 0 {
				return false;
			}
			size -= bytes_written;
			buf += bytes_written;
		}
		true
	}
	raw_stdout ::= fn() RawFile {
		1
	}
	raw_stderr ::= fn() RawFile {
		2
	}
	file_open_write ::= fn(name: []char) f: RawFile, success: bool {
		cstr := str_to_cstr(name);
		defer mem.dels(cstr);
		// @TODO: switch to bitwise or when that exists
		f = open(&cstr[0], (O_WRONLY + O_CREAT) as #C int) as RawFile;
		success = f != -1;
	}
} 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) bool {
		bytes_written := fwrite(buf, 1, size, file) as int;
		bytes_written == size
	}
	raw_stdout ::= fn() RawFile {
		#builtin("stdout")
	}
	raw_stderr ::= fn() RawFile {
		#builtin("stdout")
	}
	file_open_write ::= fn(name: []char) f: RawFile, success: bool {
		cstr := base.str_to_cstr(name);
		defer mem.dels(cstr);
		mode := "w\0";
		f = fopen(&cstr[0], &mode[0]);
		success = f != null;
	}
}


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 {
			mem.mem_copy(&buffer[0], &s[0], s.len);
			written = s.len;
		}
	} else {
		mem.mem_copy(&buffer[written], &s[0], s.len);
		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;
}