15 ** Implements all of the File Access word set that can be implemented in portable C.
19 static void pushIor(FICL_VM
*pVM
, int success
)
26 stackPushINT(pVM
->pStack
, ior
);
31 static void ficlFopen(FICL_VM
*pVM
, char *writeMode
) /* ( c-addr u fam -- fileid ior ) */
33 int fam
= stackPopINT(pVM
->pStack
);
34 int length
= stackPopINT(pVM
->pStack
);
35 void *address
= (void *)stackPopPtr(pVM
->pStack
);
39 char *filename
= (char *)alloca(length
+ 1);
40 memcpy(filename
, address
, length
);
45 switch (FICL_FAM_OPEN_MODE(fam
))
48 stackPushPtr(pVM
->pStack
, NULL
);
49 stackPushINT(pVM
->pStack
, EINVAL
);
55 strcat(mode
, writeMode
);
57 case FICL_FAM_READ
| FICL_FAM_WRITE
:
58 strcat(mode
, writeMode
);
63 strcat(mode
, (fam
& FICL_FAM_BINARY
) ? "b" : "t");
65 f
= fopen(filename
, mode
);
67 stackPushPtr(pVM
->pStack
, NULL
);
69 #ifdef LOADER_VERIEXEC
71 verify_file(fileno(f
), filename
, 0, VE_GUESS
, __func__
) < 0) {
73 stackPushPtr(pVM
->pStack
, NULL
);
77 ficlFILE
*ff
= (ficlFILE
*)malloc(sizeof(ficlFILE
));
78 strcpy(ff
->filename
, filename
);
80 stackPushPtr(pVM
->pStack
, ff
);
82 fseek(f
, 0, SEEK_SET
);
84 pushIor(pVM
, f
!= NULL
);
89 static void ficlOpenFile(FICL_VM
*pVM
) /* ( c-addr u fam -- fileid ior ) */
95 static void ficlCreateFile(FICL_VM
*pVM
) /* ( c-addr u fam -- fileid ior ) */
101 static int closeFiclFILE(ficlFILE
*ff
) /* ( fileid -- ior ) */
108 static void ficlCloseFile(FICL_VM
*pVM
) /* ( fileid -- ior ) */
110 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
111 pushIor(pVM
, closeFiclFILE(ff
));
114 static void ficlDeleteFile(FICL_VM
*pVM
) /* ( c-addr u -- ior ) */
116 int length
= stackPopINT(pVM
->pStack
);
117 void *address
= (void *)stackPopPtr(pVM
->pStack
);
119 char *filename
= (char *)alloca(length
+ 1);
120 memcpy(filename
, address
, length
);
121 filename
[length
] = 0;
123 pushIor(pVM
, !unlink(filename
));
126 static void ficlRenameFile(FICL_VM
*pVM
) /* ( c-addr1 u1 c-addr2 u2 -- ior ) */
133 length
= stackPopINT(pVM
->pStack
);
134 address
= (void *)stackPopPtr(pVM
->pStack
);
135 to
= (char *)alloca(length
+ 1);
136 memcpy(to
, address
, length
);
139 length
= stackPopINT(pVM
->pStack
);
140 address
= (void *)stackPopPtr(pVM
->pStack
);
142 from
= (char *)alloca(length
+ 1);
143 memcpy(from
, address
, length
);
146 pushIor(pVM
, !rename(from
, to
));
149 static void ficlFileStatus(FICL_VM
*pVM
) /* ( c-addr u -- x ior ) */
153 int length
= stackPopINT(pVM
->pStack
);
154 void *address
= (void *)stackPopPtr(pVM
->pStack
);
156 char *filename
= (char *)alloca(length
+ 1);
157 memcpy(filename
, address
, length
);
158 filename
[length
] = 0;
160 if (stat(filename
, &statbuf
) == 0)
163 ** the "x" left on the stack is implementation-defined.
164 ** I push the file's access mode (readable, writeable, is directory, etc)
165 ** as defined by ANSI C.
167 stackPushINT(pVM
->pStack
, statbuf
.st_mode
);
168 stackPushINT(pVM
->pStack
, 0);
172 stackPushINT(pVM
->pStack
, -1);
173 stackPushINT(pVM
->pStack
, ENOENT
);
178 static void ficlFilePosition(FICL_VM
*pVM
) /* ( fileid -- ud ior ) */
180 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
181 long ud
= ftell(ff
->f
);
182 stackPushINT(pVM
->pStack
, ud
);
183 pushIor(pVM
, ud
!= -1);
188 static long fileSize(FILE *f
)
191 statbuf
.st_size
= -1;
192 if (fstat(fileno(f
), &statbuf
) != 0)
194 return statbuf
.st_size
;
199 static void ficlFileSize(FICL_VM
*pVM
) /* ( fileid -- ud ior ) */
201 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
202 long ud
= fileSize(ff
->f
);
203 stackPushINT(pVM
->pStack
, ud
);
204 pushIor(pVM
, ud
!= -1);
210 static void ficlIncludeFile(FICL_VM
*pVM
) /* ( i*x fileid -- j*x ) */
212 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
213 CELL id
= pVM
->sourceID
;
214 int result
= VM_OUTOFTEXT
;
215 long currentPosition
, totalSize
;
217 pVM
->sourceID
.p
= (void *)ff
;
219 currentPosition
= ftell(ff
->f
);
220 totalSize
= fileSize(ff
->f
);
221 size
= totalSize
- currentPosition
;
223 if ((totalSize
!= -1) && (currentPosition
!= -1) && (size
> 0))
225 char *buffer
= (char *)malloc(size
);
226 long got
= fread(buffer
, 1, size
, ff
->f
);
228 result
= ficlExecC(pVM
, buffer
, size
);
232 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
233 CELL id
= pVM
->sourceID
;
238 pVM
->sourceID
.p
= (void *)ff
;
240 /* feed each line to ficlExec */
242 while (keepGoing
&& fgets(cp
, nLINEBUF
, ff
->f
))
244 int len
= strlen(cp
) - 1;
253 result
= ficlExec(pVM
, cp
);
269 ** Pass an empty line with SOURCE-ID == -1 to flush
270 ** any pending REFILLs (as required by FILE wordset)
272 pVM
->sourceID
.i
= -1;
281 static void ficlReadFile(FICL_VM
*pVM
) /* ( c-addr u1 fileid -- u2 ior ) */
283 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
284 int length
= stackPopINT(pVM
->pStack
);
285 void *address
= (void *)stackPopPtr(pVM
->pStack
);
289 result
= fread(address
, 1, length
, ff
->f
);
291 stackPushINT(pVM
->pStack
, result
);
292 pushIor(pVM
, ferror(ff
->f
) == 0);
297 static void ficlReadLine(FICL_VM
*pVM
) /* ( c-addr u1 fileid -- u2 flag ior ) */
299 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
300 int length
= stackPopINT(pVM
->pStack
);
301 char *address
= (char *)stackPopPtr(pVM
->pStack
);
307 stackPushINT(pVM
->pStack
, -1);
308 stackPushINT(pVM
->pStack
, 0);
309 stackPushINT(pVM
->pStack
, 0);
315 fgets(address
, length
, ff
->f
);
317 error
= ferror(ff
->f
);
320 stackPushINT(pVM
->pStack
, -1);
321 stackPushINT(pVM
->pStack
, 0);
322 stackPushINT(pVM
->pStack
, error
);
326 length
= strlen(address
);
328 if (length
&& ((address
[length
- 1] == '\r') || (address
[length
- 1] == '\n')))
331 stackPushINT(pVM
->pStack
, length
);
332 stackPushINT(pVM
->pStack
, flag
);
333 stackPushINT(pVM
->pStack
, 0); /* ior */
338 static void ficlWriteFile(FICL_VM
*pVM
) /* ( c-addr u1 fileid -- ior ) */
340 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
341 int length
= stackPopINT(pVM
->pStack
);
342 void *address
= (void *)stackPopPtr(pVM
->pStack
);
345 fwrite(address
, 1, length
, ff
->f
);
346 pushIor(pVM
, ferror(ff
->f
) == 0);
351 static void ficlWriteLine(FICL_VM
*pVM
) /* ( c-addr u1 fileid -- ior ) */
353 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
354 size_t length
= (size_t)stackPopINT(pVM
->pStack
);
355 void *address
= (void *)stackPopPtr(pVM
->pStack
);
358 if (fwrite(address
, 1, length
, ff
->f
) == length
)
359 fwrite("\n", 1, 1, ff
->f
);
360 pushIor(pVM
, ferror(ff
->f
) == 0);
365 static void ficlRepositionFile(FICL_VM
*pVM
) /* ( ud fileid -- ior ) */
367 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
368 size_t ud
= (size_t)stackPopINT(pVM
->pStack
);
370 pushIor(pVM
, fseek(ff
->f
, ud
, SEEK_SET
) == 0);
375 static void ficlFlushFile(FICL_VM
*pVM
) /* ( fileid -- ior ) */
377 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
378 pushIor(pVM
, fflush(ff
->f
) == 0);
383 #if FICL_HAVE_FTRUNCATE
385 static void ficlResizeFile(FICL_VM
*pVM
) /* ( ud fileid -- ior ) */
387 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
388 size_t ud
= (size_t)stackPopINT(pVM
->pStack
);
390 pushIor(pVM
, ftruncate(fileno(ff
->f
), ud
) == 0);
393 #endif /* FICL_HAVE_FTRUNCATE */
395 #endif /* FICL_WANT_FILE */
399 void ficlCompileFile(FICL_SYSTEM
*pSys
)
402 FICL_DICT
*dp
= pSys
->dp
;
405 dictAppendWord(dp
, "create-file", ficlCreateFile
, FW_DEFAULT
);
406 dictAppendWord(dp
, "open-file", ficlOpenFile
, FW_DEFAULT
);
407 dictAppendWord(dp
, "close-file", ficlCloseFile
, FW_DEFAULT
);
408 dictAppendWord(dp
, "include-file", ficlIncludeFile
, FW_DEFAULT
);
409 dictAppendWord(dp
, "read-file", ficlReadFile
, FW_DEFAULT
);
410 dictAppendWord(dp
, "read-line", ficlReadLine
, FW_DEFAULT
);
411 dictAppendWord(dp
, "write-file", ficlWriteFile
, FW_DEFAULT
);
412 dictAppendWord(dp
, "write-line", ficlWriteLine
, FW_DEFAULT
);
413 dictAppendWord(dp
, "file-position", ficlFilePosition
, FW_DEFAULT
);
414 dictAppendWord(dp
, "file-size", ficlFileSize
, FW_DEFAULT
);
415 dictAppendWord(dp
, "reposition-file", ficlRepositionFile
, FW_DEFAULT
);
416 dictAppendWord(dp
, "file-status", ficlFileStatus
, FW_DEFAULT
);
417 dictAppendWord(dp
, "flush-file", ficlFlushFile
, FW_DEFAULT
);
419 dictAppendWord(dp
, "delete-file", ficlDeleteFile
, FW_DEFAULT
);
420 dictAppendWord(dp
, "rename-file", ficlRenameFile
, FW_DEFAULT
);
422 #ifdef FICL_HAVE_FTRUNCATE
423 dictAppendWord(dp
, "resize-file", ficlResizeFile
, FW_DEFAULT
);
425 ficlSetEnv(pSys
, "file", FICL_TRUE
);
426 ficlSetEnv(pSys
, "file-ext", FICL_TRUE
);
427 #endif /* FICL_HAVE_FTRUNCATE */
430 #endif /* FICL_WANT_FILE */