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,NULL);
34 FILE *factor_vm::safe_fopen(char *filename, char *mode)
38 file = fopen(filename,mode);
43 } while(errno == EINTR);
47 int factor_vm::safe_fgetc(FILE *stream)
61 } while(errno == EINTR);
65 size_t factor_vm::safe_fread(void *ptr, size_t size, size_t nitems, FILE *stream)
67 size_t items_read = 0;
70 items_read += fread((void*)((int*)ptr+items_read*size),size,nitems-items_read,stream);
71 } while(items_read != nitems && errno == EINTR);
76 void factor_vm::safe_fputc(int c, FILE *stream)
79 if(fputc(c,stream) == EOF)
83 } while(errno == EINTR);
86 size_t factor_vm::safe_fwrite(void *ptr, size_t size, size_t nitems, FILE *stream)
88 size_t items_written = 0;
91 items_written += fwrite((void*)((int*)ptr+items_written*size),size,nitems-items_written,stream);
92 } while(items_written != nitems && errno == EINTR);
97 int factor_vm::safe_ftell(FILE *stream)
101 if((offset = FTELL(stream)) == -1)
105 } while(errno == EINTR);
109 void factor_vm::safe_fseek(FILE *stream, off_t offset, int whence)
113 case 0: whence = SEEK_SET; break;
114 case 1: whence = SEEK_CUR; break;
115 case 2: whence = SEEK_END; break;
117 critical_error("Bad value for whence",whence);
121 if(FSEEK(stream,offset,whence) == -1)
125 } while(errno == EINTR);
128 void factor_vm::safe_fflush(FILE *stream)
131 if(fflush(stream) == EOF)
135 } while(errno == EINTR);
138 void factor_vm::safe_fclose(FILE *stream)
141 if(fclose(stream) == EOF)
145 } while(errno == EINTR);
148 void factor_vm::primitive_fopen()
150 data_root<byte_array> mode(ctx->pop(),this);
151 data_root<byte_array> path(ctx->pop(),this);
152 mode.untag_check(this);
153 path.untag_check(this);
156 file = safe_fopen((char *)(path.untagged() + 1),
157 (char *)(mode.untagged() + 1));
158 ctx->push(allot_alien(file));
161 FILE *factor_vm::pop_file_handle()
163 return (FILE *)alien_offset(ctx->pop());
166 void factor_vm::primitive_fgetc()
168 FILE *file = pop_file_handle();
170 int c = safe_fgetc(file);
171 if(c == EOF && feof(file))
172 ctx->push(false_object);
174 ctx->push(tag_fixnum(c));
177 void factor_vm::primitive_fread()
179 FILE *file = pop_file_handle();
180 fixnum size = unbox_array_size();
184 ctx->push(tag<string>(allot_string(0,0)));
188 data_root<byte_array> buf(allot_uninitialized_array<byte_array>(size),this);
190 int c = safe_fread(buf.untagged() + 1,1,size,file);
194 ctx->push(false_object);
202 byte_array *new_buf = allot_byte_array(c);
203 memcpy(new_buf + 1, buf.untagged() + 1,c);
207 ctx->push(buf.value());
211 void factor_vm::primitive_fputc()
213 FILE *file = pop_file_handle();
214 fixnum ch = to_fixnum(ctx->pop());
215 safe_fputc(ch, file);
218 void factor_vm::primitive_fwrite()
220 FILE *file = pop_file_handle();
221 byte_array *text = untag_check<byte_array>(ctx->pop());
222 cell length = array_capacity(text);
223 char *string = (char *)(text + 1);
228 size_t written = safe_fwrite(string,1,length,file);
229 if(written != length)
233 void factor_vm::primitive_ftell()
235 FILE *file = pop_file_handle();
236 ctx->push(from_signed_8(safe_ftell(file)));
239 void factor_vm::primitive_fseek()
241 int whence = to_fixnum(ctx->pop());
242 FILE *file = pop_file_handle();
243 off_t offset = to_signed_8(ctx->pop());
244 safe_fseek(file,offset,whence);
247 void factor_vm::primitive_fflush()
249 FILE *file = pop_file_handle();
253 void factor_vm::primitive_fclose()
255 FILE *file = pop_file_handle();
259 /* This function is used by FFI I/O. Accessing the errno global directly is
260 not portable, since on some libc's errno is not a global but a funky macro that
261 reads thread-local storage. */
262 VM_C_API int err_no()
267 VM_C_API void set_err_no(int err)