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 size_t safe_fread(void *ptr, size_t size, size_t nitems, FILE *stream)
36 size_t items_read = 0;
39 items_read += fread((void*)((int*)ptr+items_read*size),size,nitems-items_read,stream);
40 } while(items_read != nitems && errno == EINTR);
45 size_t safe_fwrite(void *ptr, size_t size, size_t nitems, FILE *stream)
47 size_t items_written = 0;
50 items_written += fwrite((void*)((int*)ptr+items_written*size),size,nitems-items_written,stream);
51 } while(items_written != nitems && errno == EINTR);
56 int safe_fclose(FILE *stream)
62 } while(ret != 0 && errno == EINTR);
67 void factor_vm::primitive_fopen()
69 data_root<byte_array> mode(ctx->pop(),this);
70 data_root<byte_array> path(ctx->pop(),this);
71 mode.untag_check(this);
72 path.untag_check(this);
76 file = fopen((char *)(path.untagged() + 1),
77 (char *)(mode.untagged() + 1));
80 } while(errno == EINTR);
82 ctx->push(allot_alien(file));
85 FILE *factor_vm::pop_file_handle()
87 return (FILE *)alien_offset(ctx->pop());
90 void factor_vm::primitive_fgetc()
92 FILE *file = pop_file_handle();
100 ctx->push(false_object);
108 ctx->push(tag_fixnum(c));
111 } while(errno == EINTR);
114 void factor_vm::primitive_fread()
116 FILE *file = pop_file_handle();
117 fixnum size = unbox_array_size();
121 ctx->push(tag<string>(allot_string(0,0)));
125 data_root<byte_array> buf(allot_uninitialized_array<byte_array>(size),this);
129 int c = safe_fread(buf.untagged() + 1,1,size,file);
134 ctx->push(false_object);
144 byte_array *new_buf = allot_byte_array(c);
145 memcpy(new_buf + 1, buf.untagged() + 1,c);
149 ctx->push(buf.value());
155 void factor_vm::primitive_fputc()
157 FILE *file = pop_file_handle();
158 fixnum ch = to_fixnum(ctx->pop());
161 if(fputc(ch,file) == EOF)
165 } while(errno == EINTR);
168 void factor_vm::primitive_fwrite()
170 FILE *file = pop_file_handle();
171 byte_array *text = untag_check<byte_array>(ctx->pop());
172 cell length = array_capacity(text);
173 char *string = (char *)(text + 1);
178 size_t written = safe_fwrite(string,1,length,file);
179 if(written != length)
183 void factor_vm::primitive_ftell()
185 FILE *file = pop_file_handle();
189 if((offset = FTELL(file)) == -1)
193 } while(errno == EINTR);
195 ctx->push(from_signed_8(offset));
198 void factor_vm::primitive_fseek()
200 int whence = to_fixnum(ctx->pop());
201 FILE *file = pop_file_handle();
202 off_t offset = to_signed_8(ctx->pop());
206 case 0: whence = SEEK_SET; break;
207 case 1: whence = SEEK_CUR; break;
208 case 2: whence = SEEK_END; break;
210 critical_error("Bad value for whence",whence);
215 if(FSEEK(file,offset,whence) == -1)
219 } while(errno == EINTR);
222 void factor_vm::primitive_fflush()
224 FILE *file = pop_file_handle();
226 if(fflush(file) == EOF)
230 } while(errno == EINTR);
233 void factor_vm::primitive_fclose()
235 FILE *file = pop_file_handle();
236 if(safe_fclose(file) == EOF)
240 /* This function is used by FFI I/O. Accessing the errno global directly is
241 not portable, since on some libc's errno is not a global but a funky macro that
242 reads thread-local storage. */
243 VM_C_API int err_no()
248 VM_C_API void clear_err_no()