/******************************************************************* v m C h e c k S t a c k ** Check the parameter stack for underflow or overflow. ** size controls the type of check: if size is zero, ** the function checks the stack state for underflow and overflow. ** If size > 0, checks to see that the stack has room to push ** that many cells. If less than zero, checks to see that the ** stack has room to pop that many cells. If any test fails, ** the function throws (via vmThrow) a VM_ERREXIT exception. *******************************************************************/ void ficlStackCheck(ficlStack *stack, int popCells, int pushCells) #if FICL_ROBUST >= 1 { int nFree = stack->size - STKDEPTH(stack); if (popCells > STKDEPTH(stack)) { ficlVmThrowError(stack->vm, "Error: %s stack underflow", stack->name); } if (nFree < pushCells - popCells) { ficlVmThrowError(stack->vm, "Error: %s stack overflow", stack->name); } return; }
static void ficlPrimitiveTempBase(ficlVm *vm) { int oldbase = vm->base; ficlString number = ficlVmGetWord0(vm); int base = ficlStackPopInteger(vm->dataStack); vm->base = base; if (!ficlVmParseNumber(vm, number)) ficlVmThrowError(vm, "%.*s not recognized", FICL_STRING_GET_LENGTH(number), FICL_STRING_GET_POINTER(number)); vm->base = oldbase; return; }
/* * d e f i n i t i o n s * SEARCH ( -- ) * Make the compilation word list the same as the first word list in the * search order. Specifies that the names of subsequent definitions will * be placed in the compilation word list. Subsequent changes in the search * order will not affect the compilation word list. */ static void ficlPrimitiveDefinitions(ficlVm *vm) { ficlDictionary *dictionary = ficlVmGetDictionary(vm); FICL_VM_ASSERT(vm, dictionary); if (dictionary->wordlistCount < 1) { ficlVmThrowError(vm, "DEFINITIONS error - empty search order"); } dictionary->compilationWordlist = dictionary->wordlists[dictionary->wordlistCount-1]; }
/* * > S E A R C H * Ficl ( wid -- ) * Push wid onto the search order. Error if the search order is full. */ static void ficlPrimitiveSearchPush(ficlVm *vm) { ficlDictionary *dictionary = ficlVmGetDictionary(vm); ficlDictionaryLock(dictionary, FICL_TRUE); if (dictionary->wordlistCount > FICL_MAX_WORDLISTS) { ficlVmThrowError(vm, ">search error: search order overflow"); } dictionary->wordlists[dictionary->wordlistCount++] = ficlStackPopPointer(vm->dataStack); ficlDictionaryLock(dictionary, FICL_FALSE); }
/* * S E A R C H > * Ficl ( -- wid ) * Pop wid off the search order. Error if the search order is empty */ static void ficlPrimitiveSearchPop(ficlVm *vm) { ficlDictionary *dictionary = ficlVmGetDictionary(vm); int wordlistCount; ficlDictionaryLock(dictionary, FICL_TRUE); wordlistCount = dictionary->wordlistCount; if (wordlistCount == 0) { ficlVmThrowError(vm, "search> error: empty search order"); } ficlStackPushPointer(vm->dataStack, dictionary->wordlists[--dictionary->wordlistCount]); ficlDictionaryLock(dictionary, FICL_FALSE); }
static void ficlPrimitiveLoad_(ficlVm *vm, int warn, int icat_special) { char filename[FICL_COUNTED_STRING_MAX]; ficlCountedString *counted = (ficlCountedString *)filename; char *file_data; unsigned size = 0; int line_num; char *line, *c, *end; ficlCell oldSourceId; ficlString s; int result = 0; char *context; int offset; if (icat_special) { int index; FICL_STACK_CHECK(vm->dataStack,1,0); index = ficlStackPopInteger(vm->dataStack); sprintf(filename,"%sicat_config%02d.tbl",ICAT_DEV_PREFIX,index); file_data = find_and_load(filename,&size,&offset); } else { ficlVmGetString(vm, counted, '\n'); if (FICL_COUNTED_STRING_GET_LENGTH(*counted) <= 0) { ficlVmTextOut(vm, "Warning (load): nothing happened\n"); return; } file_data = find_and_load(FICL_COUNTED_STRING_GET_POINTER(*counted),&size,&offset); } /* ** get the file's size and make sure it exists */ if (file_data == NULL) if (warn) { ficlVmTextOut(vm, "Unable to open file "); ficlVmTextOut(vm, FICL_COUNTED_STRING_GET_POINTER(*counted)); ficlVmTextOut(vm, "\n"); ficlVmThrow(vm, FICL_VM_STATUS_QUIT); } else return; oldSourceId = vm->sourceId; vm->sourceId.i = -1; /* feed each line to ficlExec */ for (end = file_data + size + offset, line = file_data + offset, line_num = 1; line < end; line = ++c, line_num++) { int length; for (c = line; *c != '\n' && c<end; c++); length = c-line; if (length > 0) { FICL_STRING_SET_POINTER(s, line); FICL_STRING_SET_LENGTH(s, length); result = ficlVmExecuteString(vm, s); /* handle "bye" in loaded files. --lch */ switch (result) { case FICL_VM_STATUS_OUT_OF_TEXT: case FICL_VM_STATUS_USER_EXIT: break; default: vm->sourceId = oldSourceId; free(file_data); file_data = NULL; ficlVmThrowError(vm, "Error loading file <%s> line %d", FICL_COUNTED_STRING_GET_POINTER(*counted), line_num); break; } } } if (file_data != NULL) free(file_data); vm->sourceId = oldSourceId; /* handle "bye" in loaded files. --lch */ if (result == FICL_VM_STATUS_USER_EXIT) ficlVmThrow(vm, FICL_VM_STATUS_USER_EXIT); return; }
static void ficlPrimitiveLoad(ficlVm *vm) { char buffer[BUFFER_SIZE]; char filename[BUFFER_SIZE]; ficlCountedString *counted = (ficlCountedString *)filename; int line = 0; FILE *f; int result = 0; ficlCell oldSourceId; ficlString s; ficlVmGetString(vm, counted, '\n'); if (FICL_COUNTED_STRING_GET_LENGTH(*counted) <= 0) { ficlVmTextOut(vm, "Warning (load): nothing happened\n"); return; } /* ** get the file's size and make sure it exists */ f = fopen(FICL_COUNTED_STRING_GET_POINTER(*counted), "r"); if (!f) { ficlVmTextOut(vm, "Unable to open file "); ficlVmTextOut(vm, FICL_COUNTED_STRING_GET_POINTER(*counted)); ficlVmTextOut(vm, "\n"); ficlVmThrow(vm, FICL_VM_STATUS_QUIT); } oldSourceId = vm->sourceId; vm->sourceId.p = (void *)f; /* feed each line to ficlExec */ while (fgets(buffer, BUFFER_SIZE, f)) { int length = strlen(buffer) - 1; line++; if (length <= 0) continue; if (buffer[length] == '\n') buffer[length--] = '\0'; FICL_STRING_SET_POINTER(s, buffer); FICL_STRING_SET_LENGTH(s, length + 1); result = ficlVmExecuteString(vm, s); /* handle "bye" in loaded files. --lch */ switch (result) { case FICL_VM_STATUS_OUT_OF_TEXT: case FICL_VM_STATUS_USER_EXIT: break; default: vm->sourceId = oldSourceId; fclose(f); ficlVmThrowError(vm, "Error loading file <%s> line %d", FICL_COUNTED_STRING_GET_POINTER(*counted), line); break; } } /* ** 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 = oldSourceId; fclose(f); /* handle "bye" in loaded files. --lch */ if (result == FICL_VM_STATUS_USER_EXIT) ficlVmThrow(vm, FICL_VM_STATUS_USER_EXIT); return; }