6 /* Simple wrappers for ANSI C I/O functions, used for bootstrapping.
8 Note the ugly loop logic in almost every function; we have to handle EINTR
9 and restart the operation if the system call was interrupted. Naive
10 applications don't do this, but then they quickly fail if one enables
11 itimer()s or other signals.
13 The Factor library provides platform-specific code for Unix and Windows
14 with many more capabilities so these words are not usually used in
17 void factor_vm::init_c_io()
19 userenv[STDIN_ENV] = allot_alien(F,(cell)stdin);
20 userenv[STDOUT_ENV] = allot_alien(F,(cell)stdout);
21 userenv[STDERR_ENV] = allot_alien(F,(cell)stderr);
24 void factor_vm::io_error()
31 general_error(ERROR_IO,tag_fixnum(errno),F,NULL);
34 inline void factor_vm::primitive_fopen()
36 gc_root<byte_array> mode(dpop(),this);
37 gc_root<byte_array> path(dpop(),this);
38 mode.untag_check(this);
39 path.untag_check(this);
43 FILE *file = fopen((char *)(path.untagged() + 1),
44 (char *)(mode.untagged() + 1));
55 PRIMITIVE_FORWARD(fopen)
57 inline void factor_vm::primitive_fgetc()
59 FILE *file = (FILE *)unbox_alien();
82 PRIMITIVE_FORWARD(fgetc)
84 inline void factor_vm::primitive_fread()
86 FILE *file = (FILE *)unbox_alien();
87 fixnum size = unbox_array_size();
91 dpush(tag<string>(allot_string(0,0)));
95 gc_root<byte_array> buf(allot_array_internal<byte_array>(size),this);
99 int c = fread(buf.untagged() + 1,1,size,file);
114 byte_array *new_buf = allot_byte_array(c);
115 memcpy(new_buf + 1, buf.untagged() + 1,c);
124 PRIMITIVE_FORWARD(fread)
126 inline void factor_vm::primitive_fputc()
128 FILE *file = (FILE *)unbox_alien();
129 fixnum ch = to_fixnum(dpop());
133 if(fputc(ch,file) == EOF)
137 /* Still here? EINTR */
144 PRIMITIVE_FORWARD(fputc)
146 inline void factor_vm::primitive_fwrite()
148 FILE *file = (FILE *)unbox_alien();
149 byte_array *text = untag_check<byte_array>(dpop());
150 cell length = array_capacity(text);
151 char *string = (char *)(text + 1);
158 size_t written = fwrite(string,1,length,file);
159 if(written == length)
168 /* Still here? EINTR */
175 PRIMITIVE_FORWARD(fwrite)
177 inline void factor_vm::primitive_fseek()
179 int whence = to_fixnum(dpop());
180 FILE *file = (FILE *)unbox_alien();
181 off_t offset = to_signed_8(dpop());
185 case 0: whence = SEEK_SET; break;
186 case 1: whence = SEEK_CUR; break;
187 case 2: whence = SEEK_END; break;
189 critical_error("Bad value for whence",whence);
193 if(FSEEK(file,offset,whence) == -1)
197 /* Still here? EINTR */
198 critical_error("Don't know what to do; EINTR from fseek()?",0);
202 PRIMITIVE_FORWARD(fseek)
204 inline void factor_vm::primitive_fflush()
206 FILE *file = (FILE *)unbox_alien();
209 if(fflush(file) == EOF)
216 PRIMITIVE_FORWARD(fflush)
218 inline void factor_vm::primitive_fclose()
220 FILE *file = (FILE *)unbox_alien();
223 if(fclose(file) == EOF)
230 PRIMITIVE_FORWARD(fclose)
232 /* This function is used by FFI I/O. Accessing the errno global directly is
233 not portable, since on some libc's errno is not a global but a funky macro that
234 reads thread-local storage. */
235 VM_C_API int err_no()
240 VM_C_API void clear_err_no()