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 special_objects[OBJ_STDIN] = allot_alien(false_object,(cell)stdin);
20 special_objects[OBJ_STDOUT] = allot_alien(false_object,(cell)stdout);
21 special_objects[OBJ_STDERR] = allot_alien(false_object,(cell)stderr);
24 void factor_vm::io_error()
31 general_error(ERROR_IO,tag_fixnum(errno),false_object);
34 FILE *factor_vm::safe_fopen(char *filename, char *mode)
39 file = fopen(filename,mode);
48 int factor_vm::safe_fgetc(FILE *stream)
67 size_t factor_vm::safe_fread(void *ptr, size_t size, size_t nitems, FILE *stream)
69 size_t items_read = 0;
74 ret = fread((void*)((int*)ptr+items_read*size),size,nitems-items_read,stream);
83 } while(items_read != nitems);
88 void factor_vm::safe_fputc(int c, FILE *stream)
92 if(fputc(c,stream) == EOF)
99 size_t factor_vm::safe_fwrite(void *ptr, size_t size, size_t nitems, FILE *stream)
101 size_t items_written = 0;
105 ret = fwrite((void*)((int*)ptr+items_written*size),size,nitems-items_written,stream);
108 items_written += ret;
109 } while(items_written != nitems);
111 return items_written;
114 int factor_vm::safe_ftell(FILE *stream)
119 if((offset = FTELL(stream)) == -1)
127 void factor_vm::safe_fseek(FILE *stream, off_t offset, int whence)
131 case 0: whence = SEEK_SET; break;
132 case 1: whence = SEEK_CUR; break;
133 case 2: whence = SEEK_END; break;
135 critical_error("Bad value for whence",whence);
140 if(FSEEK(stream,offset,whence) == -1)
147 void factor_vm::safe_fflush(FILE *stream)
151 if(fflush(stream) == EOF)
158 void factor_vm::safe_fclose(FILE *stream)
162 if(fclose(stream) == EOF)
169 void factor_vm::primitive_fopen()
171 data_root<byte_array> mode(ctx->pop(),this);
172 data_root<byte_array> path(ctx->pop(),this);
173 mode.untag_check(this);
174 path.untag_check(this);
177 file = safe_fopen((char *)(path.untagged() + 1),
178 (char *)(mode.untagged() + 1));
179 ctx->push(allot_alien(file));
182 FILE *factor_vm::pop_file_handle()
184 return (FILE *)alien_offset(ctx->pop());
187 void factor_vm::primitive_fgetc()
189 FILE *file = pop_file_handle();
191 int c = safe_fgetc(file);
192 if(c == EOF && feof(file))
193 ctx->push(false_object);
195 ctx->push(tag_fixnum(c));
198 void factor_vm::primitive_fread()
200 FILE *file = pop_file_handle();
201 fixnum size = unbox_array_size();
205 ctx->push(tag<string>(allot_string(0,0)));
209 data_root<byte_array> buf(allot_uninitialized_array<byte_array>(size),this);
211 int c = safe_fread(buf.untagged() + 1,1,size,file);
213 ctx->push(false_object);
218 byte_array *new_buf = allot_byte_array(c);
219 memcpy(new_buf + 1, buf.untagged() + 1,c);
223 ctx->push(buf.value());
227 void factor_vm::primitive_fputc()
229 FILE *file = pop_file_handle();
230 fixnum ch = to_fixnum(ctx->pop());
231 safe_fputc(ch, file);
234 void factor_vm::primitive_fwrite()
236 FILE *file = pop_file_handle();
237 cell length = to_cell(ctx->pop());
238 char *text = alien_offset(ctx->pop());
243 size_t written = safe_fwrite(text,1,length,file);
244 if(written != length)
248 void factor_vm::primitive_ftell()
250 FILE *file = pop_file_handle();
251 ctx->push(from_signed_8(safe_ftell(file)));
254 void factor_vm::primitive_fseek()
256 FILE *file = pop_file_handle();
257 int whence = to_fixnum(ctx->pop());
258 off_t offset = to_signed_8(ctx->pop());
259 safe_fseek(file,offset,whence);
262 void factor_vm::primitive_fflush()
264 FILE *file = pop_file_handle();
268 void factor_vm::primitive_fclose()
270 FILE *file = pop_file_handle();
274 /* This function is used by FFI I/O. Accessing the errno global directly is
275 not portable, since on some libc's errno is not a global but a funky macro that
276 reads thread-local storage. */
277 VM_C_API int err_no()
282 VM_C_API void set_err_no(int err)