2 * $FreeBSD: src/sys/boot/ficl/fileaccess.c,v 1.1 2002/04/09 17:45:11 dcs Exp $
3 * $DragonFly: src/sys/boot/ficl/fileaccess.c,v 1.1 2003/11/10 06:08:33 dillon Exp $
19 ** Implements all of the File Access word set that can be implemented in portable C.
23 static void pushIor(FICL_VM
*pVM
, int success
)
30 stackPushINT(pVM
->pStack
, ior
);
35 static void ficlFopen(FICL_VM
*pVM
, char *writeMode
) /* ( c-addr u fam -- fileid ior ) */
37 int fam
= stackPopINT(pVM
->pStack
);
38 int length
= stackPopINT(pVM
->pStack
);
39 void *address
= (void *)stackPopPtr(pVM
->pStack
);
43 char *filename
= (char *)alloca(length
+ 1);
44 memcpy(filename
, address
, length
);
49 switch (FICL_FAM_OPEN_MODE(fam
))
52 stackPushPtr(pVM
->pStack
, NULL
);
53 stackPushINT(pVM
->pStack
, EINVAL
);
59 strcat(mode
, writeMode
);
61 case FICL_FAM_READ
| FICL_FAM_WRITE
:
62 strcat(mode
, writeMode
);
67 strcat(mode
, (fam
& FICL_FAM_BINARY
) ? "b" : "t");
69 f
= fopen(filename
, mode
);
71 stackPushPtr(pVM
->pStack
, NULL
);
74 ficlFILE
*ff
= (ficlFILE
*)malloc(sizeof(ficlFILE
));
75 strcpy(ff
->filename
, filename
);
77 stackPushPtr(pVM
->pStack
, ff
);
79 fseek(f
, 0, SEEK_SET
);
81 pushIor(pVM
, f
!= NULL
);
86 static void ficlOpenFile(FICL_VM
*pVM
) /* ( c-addr u fam -- fileid ior ) */
92 static void ficlCreateFile(FICL_VM
*pVM
) /* ( c-addr u fam -- fileid ior ) */
98 static int closeFiclFILE(ficlFILE
*ff
) /* ( fileid -- ior ) */
105 static void ficlCloseFile(FICL_VM
*pVM
) /* ( fileid -- ior ) */
107 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
108 pushIor(pVM
, closeFiclFILE(ff
));
111 static void ficlDeleteFile(FICL_VM
*pVM
) /* ( c-addr u -- ior ) */
113 int length
= stackPopINT(pVM
->pStack
);
114 void *address
= (void *)stackPopPtr(pVM
->pStack
);
116 char *filename
= (char *)alloca(length
+ 1);
117 memcpy(filename
, address
, length
);
118 filename
[length
] = 0;
120 pushIor(pVM
, !unlink(filename
));
123 static void ficlRenameFile(FICL_VM
*pVM
) /* ( c-addr1 u1 c-addr2 u2 -- ior ) */
130 length
= stackPopINT(pVM
->pStack
);
131 address
= (void *)stackPopPtr(pVM
->pStack
);
132 to
= (char *)alloca(length
+ 1);
133 memcpy(to
, address
, length
);
136 length
= stackPopINT(pVM
->pStack
);
137 address
= (void *)stackPopPtr(pVM
->pStack
);
139 from
= (char *)alloca(length
+ 1);
140 memcpy(from
, address
, length
);
143 pushIor(pVM
, !rename(from
, to
));
146 static void ficlFileStatus(FICL_VM
*pVM
) /* ( c-addr u -- x ior ) */
150 int length
= stackPopINT(pVM
->pStack
);
151 void *address
= (void *)stackPopPtr(pVM
->pStack
);
153 char *filename
= (char *)alloca(length
+ 1);
154 memcpy(filename
, address
, length
);
155 filename
[length
] = 0;
157 if (stat(filename
, &statbuf
) == 0)
160 ** the "x" left on the stack is implementation-defined.
161 ** I push the file's access mode (readable, writeable, is directory, etc)
162 ** as defined by ANSI C.
164 stackPushINT(pVM
->pStack
, statbuf
.st_mode
);
165 stackPushINT(pVM
->pStack
, 0);
169 stackPushINT(pVM
->pStack
, -1);
170 stackPushINT(pVM
->pStack
, ENOENT
);
175 static void ficlFilePosition(FICL_VM
*pVM
) /* ( fileid -- ud ior ) */
177 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
178 long ud
= ftell(ff
->f
);
179 stackPushINT(pVM
->pStack
, ud
);
180 pushIor(pVM
, ud
!= -1);
185 static long fileSize(FILE *f
)
188 statbuf
.st_size
= -1;
189 if (fstat(fileno(f
), &statbuf
) != 0)
191 return statbuf
.st_size
;
196 static void ficlFileSize(FICL_VM
*pVM
) /* ( fileid -- ud ior ) */
198 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
199 long ud
= fileSize(ff
->f
);
200 stackPushINT(pVM
->pStack
, ud
);
201 pushIor(pVM
, ud
!= -1);
207 static void ficlIncludeFile(FICL_VM
*pVM
) /* ( i*x fileid -- j*x ) */
209 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
210 CELL id
= pVM
->sourceID
;
211 int result
= VM_OUTOFTEXT
;
212 long currentPosition
, totalSize
;
214 pVM
->sourceID
.p
= (void *)ff
;
216 currentPosition
= ftell(ff
->f
);
217 totalSize
= fileSize(ff
->f
);
218 size
= totalSize
- currentPosition
;
220 if ((totalSize
!= -1) && (currentPosition
!= -1) && (size
> 0))
222 char *buffer
= (char *)malloc(size
);
223 long got
= fread(buffer
, 1, size
, ff
->f
);
225 result
= ficlExecC(pVM
, buffer
, size
);
229 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
230 CELL id
= pVM
->sourceID
;
235 pVM
->sourceID
.p
= (void *)ff
;
237 /* feed each line to ficlExec */
239 while (keepGoing
&& fgets(cp
, nLINEBUF
, ff
->f
))
241 int len
= strlen(cp
) - 1;
250 result
= ficlExec(pVM
, cp
);
266 ** Pass an empty line with SOURCE-ID == -1 to flush
267 ** any pending REFILLs (as required by FILE wordset)
269 pVM
->sourceID
.i
= -1;
278 static void ficlReadFile(FICL_VM
*pVM
) /* ( c-addr u1 fileid -- u2 ior ) */
280 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
281 int length
= stackPopINT(pVM
->pStack
);
282 void *address
= (void *)stackPopPtr(pVM
->pStack
);
286 result
= fread(address
, 1, length
, ff
->f
);
288 stackPushINT(pVM
->pStack
, result
);
289 pushIor(pVM
, ferror(ff
->f
) == 0);
294 static void ficlReadLine(FICL_VM
*pVM
) /* ( c-addr u1 fileid -- u2 flag ior ) */
296 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
297 int length
= stackPopINT(pVM
->pStack
);
298 char *address
= (char *)stackPopPtr(pVM
->pStack
);
304 stackPushINT(pVM
->pStack
, -1);
305 stackPushINT(pVM
->pStack
, 0);
306 stackPushINT(pVM
->pStack
, 0);
312 fgets(address
, length
, ff
->f
);
314 error
= ferror(ff
->f
);
317 stackPushINT(pVM
->pStack
, -1);
318 stackPushINT(pVM
->pStack
, 0);
319 stackPushINT(pVM
->pStack
, error
);
323 length
= strlen(address
);
325 if (length
&& ((address
[length
- 1] == '\r') || (address
[length
- 1] == '\n')))
328 stackPushINT(pVM
->pStack
, length
);
329 stackPushINT(pVM
->pStack
, flag
);
330 stackPushINT(pVM
->pStack
, 0); /* ior */
335 static void ficlWriteFile(FICL_VM
*pVM
) /* ( c-addr u1 fileid -- ior ) */
337 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
338 int length
= stackPopINT(pVM
->pStack
);
339 void *address
= (void *)stackPopPtr(pVM
->pStack
);
342 fwrite(address
, 1, length
, ff
->f
);
343 pushIor(pVM
, ferror(ff
->f
) == 0);
348 static void ficlWriteLine(FICL_VM
*pVM
) /* ( c-addr u1 fileid -- ior ) */
350 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
351 size_t length
= (size_t)stackPopINT(pVM
->pStack
);
352 void *address
= (void *)stackPopPtr(pVM
->pStack
);
355 if (fwrite(address
, 1, length
, ff
->f
) == length
)
356 fwrite("\n", 1, 1, ff
->f
);
357 pushIor(pVM
, ferror(ff
->f
) == 0);
362 static void ficlRepositionFile(FICL_VM
*pVM
) /* ( ud fileid -- ior ) */
364 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
365 size_t ud
= (size_t)stackPopINT(pVM
->pStack
);
367 pushIor(pVM
, fseek(ff
->f
, ud
, SEEK_SET
) == 0);
372 static void ficlFlushFile(FICL_VM
*pVM
) /* ( fileid -- ior ) */
374 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
375 pushIor(pVM
, fflush(ff
->f
) == 0);
380 #if FICL_HAVE_FTRUNCATE
382 static void ficlResizeFile(FICL_VM
*pVM
) /* ( ud fileid -- ior ) */
384 ficlFILE
*ff
= (ficlFILE
*)stackPopPtr(pVM
->pStack
);
385 size_t ud
= (size_t)stackPopINT(pVM
->pStack
);
387 pushIor(pVM
, ftruncate(fileno(ff
->f
), ud
) == 0);
390 #endif /* FICL_HAVE_FTRUNCATE */
392 #endif /* FICL_WANT_FILE */
396 void ficlCompileFile(FICL_SYSTEM
*pSys
)
399 FICL_DICT
*dp
= pSys
->dp
;
402 dictAppendWord(dp
, "create-file", ficlCreateFile
, FW_DEFAULT
);
403 dictAppendWord(dp
, "open-file", ficlOpenFile
, FW_DEFAULT
);
404 dictAppendWord(dp
, "close-file", ficlCloseFile
, FW_DEFAULT
);
405 dictAppendWord(dp
, "include-file", ficlIncludeFile
, FW_DEFAULT
);
406 dictAppendWord(dp
, "read-file", ficlReadFile
, FW_DEFAULT
);
407 dictAppendWord(dp
, "read-line", ficlReadLine
, FW_DEFAULT
);
408 dictAppendWord(dp
, "write-file", ficlWriteFile
, FW_DEFAULT
);
409 dictAppendWord(dp
, "write-line", ficlWriteLine
, FW_DEFAULT
);
410 dictAppendWord(dp
, "file-position", ficlFilePosition
, FW_DEFAULT
);
411 dictAppendWord(dp
, "file-size", ficlFileSize
, FW_DEFAULT
);
412 dictAppendWord(dp
, "reposition-file", ficlRepositionFile
, FW_DEFAULT
);
413 dictAppendWord(dp
, "file-status", ficlFileStatus
, FW_DEFAULT
);
414 dictAppendWord(dp
, "flush-file", ficlFlushFile
, FW_DEFAULT
);
416 dictAppendWord(dp
, "delete-file", ficlDeleteFile
, FW_DEFAULT
);
417 dictAppendWord(dp
, "rename-file", ficlRenameFile
, FW_DEFAULT
);
419 #ifdef FICL_HAVE_FTRUNCATE
420 dictAppendWord(dp
, "resize-file", ficlResizeFile
, FW_DEFAULT
);
422 ficlSetEnv(pSys
, "file", FICL_TRUE
);
423 ficlSetEnv(pSys
, "file-ext", FICL_TRUE
);
424 #endif /* FICL_HAVE_FTRUNCATE */
427 #endif /* FICL_WANT_FILE */