make asn1 work again
[factor/jcg.git] / vm / io.c
blobbad4854775279ea82c276268c855af9f07237164
1 #include "master.h"
3 /* Simple wrappers for ANSI C I/O functions, used for bootstrapping.
5 Note the ugly loop logic in almost every function; we have to handle EINTR
6 and restart the operation if the system call was interrupted. Naive
7 applications don't do this, but then they quickly fail if one enables
8 itimer()s or other signals.
10 The Factor library provides platform-specific code for Unix and Windows
11 with many more capabilities so these words are not usually used in
12 normal operation. */
14 void init_c_io(void)
16 userenv[STDIN_ENV] = allot_alien(F,(CELL)stdin);
17 userenv[STDOUT_ENV] = allot_alien(F,(CELL)stdout);
18 userenv[STDERR_ENV] = allot_alien(F,(CELL)stderr);
21 void io_error(void)
23 #ifndef WINCE
24 if(errno == EINTR)
25 return;
26 #endif
28 CELL error = tag_object(from_char_string(strerror(errno)));
29 general_error(ERROR_IO,error,F,NULL);
32 void primitive_fopen(void)
34 char *mode = unbox_char_string();
35 REGISTER_C_STRING(mode);
36 char *path = unbox_char_string();
37 UNREGISTER_C_STRING(mode);
39 for(;;)
41 FILE *file = fopen(path,mode);
42 if(file == NULL)
43 io_error();
44 else
46 box_alien(file);
47 break;
52 void primitive_fgetc(void)
54 FILE* file = unbox_alien();
56 for(;;)
58 int c = fgetc(file);
59 if(c == EOF)
61 if(feof(file))
63 dpush(F);
64 break;
66 else
67 io_error();
69 else
71 dpush(tag_fixnum(c));
72 break;
77 void primitive_fread(void)
79 FILE* file = unbox_alien();
80 CELL size = unbox_array_size();
82 if(size == 0)
84 dpush(tag_object(allot_string(0,0)));
85 return;
88 F_BYTE_ARRAY *buf = allot_byte_array(size);
90 for(;;)
92 int c = fread(buf + 1,1,size,file);
93 if(c <= 0)
95 if(feof(file))
97 dpush(F);
98 break;
100 else
101 io_error();
103 else
105 if(c != size)
107 REGISTER_UNTAGGED(buf);
108 F_BYTE_ARRAY *new_buf = allot_byte_array(c);
109 UNREGISTER_UNTAGGED(buf);
110 memcpy(new_buf + 1, buf + 1,c);
111 buf = new_buf;
113 dpush(tag_object(buf));
114 break;
119 void primitive_fputc(void)
121 FILE *file = unbox_alien();
122 F_FIXNUM ch = to_fixnum(dpop());
124 for(;;)
126 if(fputc(ch,file) == EOF)
128 io_error();
130 /* Still here? EINTR */
132 else
133 break;
137 void primitive_fwrite(void)
139 FILE *file = unbox_alien();
140 F_BYTE_ARRAY *text = untag_byte_array(dpop());
141 F_FIXNUM length = array_capacity(text);
142 char *string = (char *)(text + 1);
144 if(length == 0)
145 return;
147 for(;;)
149 size_t written = fwrite(string,1,length,file);
150 if(written == length)
151 break;
152 else
154 if(feof(file))
155 break;
156 else
157 io_error();
159 /* Still here? EINTR */
160 length -= written;
161 string += written;
166 void primitive_fflush(void)
168 FILE *file = unbox_alien();
169 for(;;)
171 if(fflush(file) == EOF)
172 io_error();
173 else
174 break;
178 void primitive_fclose(void)
180 FILE *file = unbox_alien();
181 for(;;)
183 if(fclose(file) == EOF)
184 io_error();
185 else
186 break;
190 /* This function is used by FFI I/O. Accessing the errno global directly is
191 not portable, since on some libc's errno is not a global but a funky macro that
192 reads thread-local storage. */
193 int err_no(void)
195 return errno;
198 void clear_err_no(void)
200 errno = 0;