diff options
Diffstat (limited to 'usr/src/common/ficl/fileaccess.c')
| -rw-r--r-- | usr/src/common/ficl/fileaccess.c | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/usr/src/common/ficl/fileaccess.c b/usr/src/common/ficl/fileaccess.c new file mode 100644 index 0000000000..37814eae1c --- /dev/null +++ b/usr/src/common/ficl/fileaccess.c @@ -0,0 +1,400 @@ +#include "ficl.h" + +#if FICL_WANT_FILE +/* + * fileaccess.c + * + * Implements all of the File Access word set that can be implemented in + * portable C. + */ + +static void +pushIor(ficlVm *vm, int success) +{ + int ior; + if (success) + ior = 0; + else + ior = errno; + ficlStackPushInteger(vm->dataStack, ior); +} + +/* ( c-addr u fam -- fileid ior ) */ +static void +ficlFileOpen(ficlVm *vm, char *writeMode) +{ + int fam = ficlStackPopInteger(vm->dataStack); + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); + char mode[4]; + FILE *f; + char *filename = (char *)malloc(length + 1); + memcpy(filename, address, length); + filename[length] = 0; + + *mode = 0; + + switch (FICL_FAM_OPEN_MODE(fam)) { + case 0: + ficlStackPushPointer(vm->dataStack, NULL); + ficlStackPushInteger(vm->dataStack, EINVAL); + goto EXIT; + case FICL_FAM_READ: + strcat(mode, "r"); + break; + case FICL_FAM_WRITE: + strcat(mode, writeMode); + break; + case FICL_FAM_READ | FICL_FAM_WRITE: + strcat(mode, writeMode); + strcat(mode, "+"); + break; + } + + strcat(mode, (fam & FICL_FAM_BINARY) ? "b" : "t"); + + f = fopen(filename, mode); + if (f == NULL) + ficlStackPushPointer(vm->dataStack, NULL); + else { + ficlFile *ff = (ficlFile *)malloc(sizeof (ficlFile)); + strcpy(ff->filename, filename); + ff->f = f; + ficlStackPushPointer(vm->dataStack, ff); + + fseek(f, 0, SEEK_SET); + } + pushIor(vm, f != NULL); + +EXIT: + free(filename); +} + +/* ( c-addr u fam -- fileid ior ) */ +static void +ficlPrimitiveOpenFile(ficlVm *vm) +{ + ficlFileOpen(vm, "a"); +} + +/* ( c-addr u fam -- fileid ior ) */ +static void +ficlPrimitiveCreateFile(ficlVm *vm) +{ + ficlFileOpen(vm, "w"); +} + +/* ( fileid -- ior ) */ +static int +ficlFileClose(ficlFile *ff) +{ + FILE *f = ff->f; + free(ff); + return (!fclose(f)); +} + +/* ( fileid -- ior ) */ +static void +ficlPrimitiveCloseFile(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + pushIor(vm, ficlFileClose(ff)); +} + +/* ( c-addr u -- ior ) */ +static void +ficlPrimitiveDeleteFile(ficlVm *vm) +{ + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); + + char *filename = (char *)malloc(length + 1); + memcpy(filename, address, length); + filename[length] = 0; + + pushIor(vm, !unlink(filename)); + free(filename); +} + +/* ( c-addr1 u1 c-addr2 u2 -- ior ) */ +static void +ficlPrimitiveRenameFile(ficlVm *vm) +{ + int length; + void *address; + char *from; + char *to; + + length = ficlStackPopInteger(vm->dataStack); + address = (void *)ficlStackPopPointer(vm->dataStack); + to = (char *)malloc(length + 1); + memcpy(to, address, length); + to[length] = 0; + + length = ficlStackPopInteger(vm->dataStack); + address = (void *)ficlStackPopPointer(vm->dataStack); + + from = (char *)malloc(length + 1); + memcpy(from, address, length); + from[length] = 0; + + pushIor(vm, !rename(from, to)); + + free(from); + free(to); +} + +/* ( c-addr u -- x ior ) */ +static void +ficlPrimitiveFileStatus(ficlVm *vm) +{ + int status; + int ior; + + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); + + char *filename = (char *)malloc(length + 1); + memcpy(filename, address, length); + filename[length] = 0; + + ior = ficlFileStatus(filename, &status); + free(filename); + + ficlStackPushInteger(vm->dataStack, status); + ficlStackPushInteger(vm->dataStack, ior); +} + +/* ( fileid -- ud ior ) */ +static void +ficlPrimitiveFilePosition(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + long ud = ftell(ff->f); + ficlStackPushInteger(vm->dataStack, ud); + pushIor(vm, ud != -1); +} + +/* ( fileid -- ud ior ) */ +static void +ficlPrimitiveFileSize(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + long ud = ficlFileSize(ff); + ficlStackPushInteger(vm->dataStack, ud); + pushIor(vm, ud != -1); +} + +/* ( i*x fileid -- j*x ) */ +#define nLINEBUF 256 +static void +ficlPrimitiveIncludeFile(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + ficlCell id = vm->sourceId; + int except = FICL_VM_STATUS_OUT_OF_TEXT; + long currentPosition, totalSize; + long size; + ficlString s; + vm->sourceId.p = (void *)ff; + + currentPosition = ftell(ff->f); + totalSize = ficlFileSize(ff); + size = totalSize - currentPosition; + + if ((totalSize != -1) && (currentPosition != -1) && (size > 0)) { + char *buffer = (char *)malloc(size); + long got = fread(buffer, 1, size, ff->f); + if (got == size) { + FICL_STRING_SET_POINTER(s, buffer); + FICL_STRING_SET_LENGTH(s, size); + except = ficlVmExecuteString(vm, s); + } + } + + if ((except < 0) && (except != FICL_VM_STATUS_OUT_OF_TEXT)) + ficlVmThrow(vm, except); + + /* + * Pass an empty line with SOURCE-ID == -1 to flush + * any pending REFILLs (as required by FILE wordset) + */ + vm->sourceId.i = -1; + FICL_STRING_SET_FROM_CSTRING(s, ""); + ficlVmExecuteString(vm, s); + + vm->sourceId = id; + ficlFileClose(ff); +} + +/* ( c-addr u1 fileid -- u2 ior ) */ +static void +ficlPrimitiveReadFile(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); + int result; + + clearerr(ff->f); + result = fread(address, 1, length, ff->f); + + ficlStackPushInteger(vm->dataStack, result); + pushIor(vm, ferror(ff->f) == 0); +} + +/* ( c-addr u1 fileid -- u2 flag ior ) */ +static void +ficlPrimitiveReadLine(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + int length = ficlStackPopInteger(vm->dataStack); + char *address = (char *)ficlStackPopPointer(vm->dataStack); + int error; + int flag; + + if (feof(ff->f)) { + ficlStackPushInteger(vm->dataStack, -1); + ficlStackPushInteger(vm->dataStack, 0); + ficlStackPushInteger(vm->dataStack, 0); + return; + } + + clearerr(ff->f); + *address = 0; + fgets(address, length, ff->f); + + error = ferror(ff->f); + if (error != 0) { + ficlStackPushInteger(vm->dataStack, -1); + ficlStackPushInteger(vm->dataStack, 0); + ficlStackPushInteger(vm->dataStack, error); + return; + } + + length = strlen(address); + flag = (length > 0); + if (length && ((address[length - 1] == '\r') || + (address[length - 1] == '\n'))) + length--; + + ficlStackPushInteger(vm->dataStack, length); + ficlStackPushInteger(vm->dataStack, flag); + ficlStackPushInteger(vm->dataStack, 0); /* ior */ +} + +/* ( c-addr u1 fileid -- ior ) */ +static void +ficlPrimitiveWriteFile(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); + + clearerr(ff->f); + fwrite(address, 1, length, ff->f); + pushIor(vm, ferror(ff->f) == 0); +} + +/* ( c-addr u1 fileid -- ior ) */ +static void +ficlPrimitiveWriteLine(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + size_t length = (size_t)ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); + + clearerr(ff->f); + if (fwrite(address, 1, length, ff->f) == length) + fwrite("\n", 1, 1, ff->f); + pushIor(vm, ferror(ff->f) == 0); +} + +/* ( ud fileid -- ior ) */ +static void +ficlPrimitiveRepositionFile(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + size_t ud = (size_t)ficlStackPopInteger(vm->dataStack); + + pushIor(vm, fseek(ff->f, ud, SEEK_SET) == 0); +} + +/* ( fileid -- ior ) */ +static void +ficlPrimitiveFlushFile(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + pushIor(vm, fflush(ff->f) == 0); +} + +#if FICL_PLATFORM_HAS_FTRUNCATE +/* ( ud fileid -- ior ) */ +static void +ficlPrimitiveResizeFile(ficlVm *vm) +{ + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + size_t ud = (size_t)ficlStackPopInteger(vm->dataStack); + + pushIor(vm, ficlFileTruncate(ff, ud) == 0); +} +#endif /* FICL_PLATFORM_HAS_FTRUNCATE */ +#endif /* FICL_WANT_FILE */ + +void +ficlSystemCompileFile(ficlSystem *system) +{ +#if !FICL_WANT_FILE + FICL_IGNORE(system); +#else + ficlDictionary *dictionary = ficlSystemGetDictionary(system); + ficlDictionary *environment = ficlSystemGetEnvironment(system); + + FICL_SYSTEM_ASSERT(system, dictionary); + FICL_SYSTEM_ASSERT(system, environment); + + ficlDictionarySetPrimitive(dictionary, "create-file", + ficlPrimitiveCreateFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "open-file", + ficlPrimitiveOpenFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "close-file", + ficlPrimitiveCloseFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "include-file", + ficlPrimitiveIncludeFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "read-file", + ficlPrimitiveReadFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "read-line", + ficlPrimitiveReadLine, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "write-file", + ficlPrimitiveWriteFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "write-line", + ficlPrimitiveWriteLine, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "file-position", + ficlPrimitiveFilePosition, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "file-size", + ficlPrimitiveFileSize, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "reposition-file", + ficlPrimitiveRepositionFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "file-status", + ficlPrimitiveFileStatus, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "flush-file", + ficlPrimitiveFlushFile, FICL_WORD_DEFAULT); + + ficlDictionarySetPrimitive(dictionary, "delete-file", + ficlPrimitiveDeleteFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "rename-file", + ficlPrimitiveRenameFile, FICL_WORD_DEFAULT); + +#if FICL_PLATFORM_HAS_FTRUNCATE + ficlDictionarySetPrimitive(dictionary, "resize-file", + ficlPrimitiveResizeFile, FICL_WORD_DEFAULT); + + ficlDictionarySetConstant(environment, "file", FICL_TRUE); + ficlDictionarySetConstant(environment, "file-ext", FICL_TRUE); +#else /* FICL_PLATFORM_HAS_FTRUNCATE */ + ficlDictionarySetConstant(environment, "file", FICL_FALSE); + ficlDictionarySetConstant(environment, "file-ext", FICL_FALSE); +#endif /* FICL_PLATFORM_HAS_FTRUNCATE */ + +#endif /* !FICL_WANT_FILE */ +} |
