/** * Interpret a tree. Will deal with initialiazation etc */ int interpreter(t_ast_element *p) { int ret = 0; si_init(); t_object *obj = interpreter_leaf(p); if (OBJECT_IS_NUMERICAL(obj)) { ret = ((t_numerical_object *)(obj))->value; } // @TODO: What should we do with the output of this node? Somehow, return it to the caller or somethign? #ifdef __DEBUG t_hash_iter iter; ht_iter_rewind(&iter, object_hash); while (ht_iter_valid(&iter)) { t_object *obj = ht_iter_value(&iter); if (obj->type != objectTypeCode && obj->type != objectTypeMethod) { DEBUG_PRINT("Object: %20s (%08X) Refcount: %d : %s \n", obj->name, (unsigned int)obj, obj->ref_count, object_debug(obj)); } ht_iter_next(&iter); } #endif si_fini(); return ret; }
/** * Frees a compiler object and all associated memory. * compiler: an instance of Compiler. * TODO: a lot of allocations don't have frees yet. These will be added in when * the program structure becomes final. */ void compiler_free(Compiler * compiler) { assert(compiler != NULL); if(compiler->compiledScripts != NULL) { set_free(compiler->compiledScripts); } if(compiler->symTableStk != NULL) { stk_free(compiler->symTableStk); } if(compiler->functionHT != NULL) { HTIter htIterator; ht_iter_get(compiler->functionHT, &htIterator); while(ht_iter_has_next(&htIterator)) { DSValue value; ht_iter_next(&htIterator, NULL, 0, &value, NULL, true); compilerfunc_free(value.pointerVal); } ht_free(compiler->functionHT); } if(compiler->outBuffer != NULL) { buffer_free(compiler->outBuffer); } free(compiler); }
static const char* vfs_vdir_iter(VFSNode *vdir, void **opaque) { ht_str2ptr_iter_t *iter = *opaque; if(!iter) { iter = *opaque = calloc(1, sizeof(*iter)); ht_iter_begin(VDIR_TABLE(vdir), iter); } else { ht_iter_next(iter); } return iter->has_data ? iter->key : NULL; }
void mem_debug_check(void) { struct ht_iter iter; fprintf(stderr, "*** Memory still in use ***\n"); if (ht_set_iter(mem_ht, &iter) == 0) { do { int pl; void *p = *((void **) ht_iter_getkey(&iter, &pl)); char *s = ht_iter_getval(&iter); fprintf(stderr, "%p %s\n", p, s); } while (!ht_iter_next(&iter)); } ht_clear_iter(&iter); fprintf(stderr, "*** End of used memory ***\n"); }
static ResultCode cmd_help(void) { #ifdef _DEBUG // FIXME: There is no way at the moment to access the serial port. Dump // this through JTAG for now for (HashIterator iter = ht_iter_begin(&commands); !ht_iter_cmp(iter, ht_iter_end(&commands)); iter = ht_iter_next(iter)) { struct CmdTemplate* cmd = (struct CmdTemplate*)ht_iter_get(iter); kprintf("%-20s", cmd->name); for (unsigned j = 0; cmd->arg_fmt[j]; ++j) kprintf("%c ", 'a' + j); kprintf("\r\n"); } #endif return RC_OK; }
static VFSInfo vfs_vdir_query(VFSNode *vdir) { return (VFSInfo) { .exists = true, .is_dir = true, }; } static void vfs_vdir_free(VFSNode *vdir) { ht_str2ptr_t *ht = VDIR_TABLE(vdir); ht_str2ptr_iter_t iter; ht_iter_begin(ht, &iter); for(; iter.has_data; ht_iter_next(&iter)) { vfs_decref(iter.value); } ht_iter_end(&iter); ht_destroy(ht); free(ht); }
/// Hook provided by the parser for matching of command names (TAB completion) for readline const char* parser_rl_match(UNUSED_ARG(void *,dummy), const char *word, int word_len) { HashIterator cur; HashIterator end = ht_iter_end(&commands); const char *found = NULL; for (cur = ht_iter_begin(&commands); !ht_iter_cmp(cur, end); cur = ht_iter_next(cur)) { const struct CmdTemplate* cmdp = (const struct CmdTemplate*)ht_iter_get(cur); if (strncmp(cmdp->name, word, word_len) == 0) { // If there was another matching word, it means that we have a multiple // match: then return NULL. if (found) return NULL; found = cmdp->name; } } return found; }
/** * Run after gunderscript_build_file() to export the compiled bytecode to an * external bytecode file. * instance: a Gunderscript object. * fileName: The name of the file to export to. Caution: file will be overwritten * returns: true upon success, or false if file cannot be opened, * no code has been built, or there was an error building code. */ GSAPI bool gunderscript_export_bytecode(Gunderscript * instance, char * fileName) { FILE * outFile = fopen(fileName, "w"); GSByteCodeHeader header; HTIter functionHTIter; char * byteCodeBuffer; /* check if file open fails */ if(outFile == NULL) { instance->err = GUNDERSCRIPTERR_BAD_FILE_OPEN_WRITE; return false; } /* create header */ strcpy(header.header, GS_BYTECODE_HEADER); strcpy(header.buildDate, __DATE__); header.byteCodeLen = vm_bytecode_size(instance->vm); header.numFunctions = ht_size(vm_functions(instance->vm)); /* write header to file, return false on failure */ if(fwrite(&header, sizeof(GSByteCodeHeader), 1, outFile) != 1) { instance->err = GUNDERSCRIPTERR_BAD_FILE_WRITE; return false; } ht_iter_get(vm_functions(instance->vm), &functionHTIter); /* write exported functions to file */ while(ht_iter_has_next(&functionHTIter)) { DSValue value; char functionName[GS_MAX_FUNCTION_NAME_LEN]; size_t functionNameLen; char outLen; /* get the next item from hashtable */ ht_iter_next(&functionHTIter, functionName, GS_MAX_FUNCTION_NAME_LEN, &value, &functionNameLen, false); /* check if the function should be exported. if so, write it to the file */ if(((VMFunc*)value.pointerVal)->exported) { /* TODO: create an error handler case for this */ assert(functionNameLen < GS_MAX_FUNCTION_NAME_LEN); /* write it's name and length to the file */ outLen = functionNameLen; if(fwrite(&outLen, sizeof(char), 1, outFile) != 1 || fwrite(functionName, sizeof(char), functionNameLen, outFile) != functionNameLen) { instance->err = GUNDERSCRIPTERR_BAD_FILE_WRITE; return false; } /* write its CompilerFunc to the file (stores function call information) */ if(fwrite(value.pointerVal, sizeof(VMFunc), 1, outFile) != 1) { instance->err = GUNDERSCRIPTERR_BAD_FILE_WRITE; return false; } } } byteCodeBuffer = vm_bytecode(instance->vm); if(byteCodeBuffer == NULL) { instance->err = GUNDERSCRIPTERR_NO_SUCCESSFUL_BUILD; return false; } /* write bytecode */ if(fwrite(byteCodeBuffer, vm_bytecode_size(instance->vm), 1, outFile) != 1) { instance->err = GUNDERSCRIPTERR_BAD_FILE_WRITE; return false; } fclose(outFile); return true; }
/** * Processes the given command line according to the configuration of the optin object * * o - The optin object * argc - Pointer to the argument count, should include the program name * argv - Pointer to the arguments, *argv[0] should be the program name * * On exit, argc and argv will be modified to be the arguments left over after option processing * RETURNS: zero if options were parsed successfully, nonzero if there was an error */ int optin_process(optin* o, int* argc, char** argv) { int i, ret; int is_long_option; int next_argv; /* Used to keep track of the next valid argv slot for shuffling non-option args */ char* arg, *opt, *value; _option* option; _option_wrapper* wrapper; hashtable_iter* opt_iter; enum { STATE_NORMAL, STATE_IN_OPTION} state; is_long_option = 0; state = STATE_NORMAL; o->argc = *argc; o->argv = argv; next_argv = 1; ret = 0; i = 1; /* Skip over the program name */ while (i < o->argc) { arg = o->argv[i]; switch(state) { case STATE_NORMAL: if (*arg == '-') { state = STATE_IN_OPTION; opt = arg+1; continue; } argv[next_argv++] = o->argv[i]; break; case STATE_IN_OPTION: (*argc)--; is_long_option = (*opt == '-'); value = 0; if (is_long_option) { opt++; if (*opt == '\0') { /* We have a lone --, that means to stop arg processing NOW */ i++; goto done; } /* We need to check if there's an equal sign in the longopt somewhere */ value = opt; while (*value) { if (*value == '=' && is_long_option) { *value++ = '\0'; /* Modify string so opt ends at where equals sign was */ break; } else if (*value == '=') { fprintf(stderr, "Equals sign not allowed in short option\n"); ret = OPTIN_ERR_INVALID_OPTION; goto done; } value++; } if (!*value) { value = 0; } } if (*opt != '\0') { /* TODO: What do we do if it does? */ option = _query(o->options, opt); if (!option) { fprintf(stderr, "Unrecognized option: '%s'\n", opt); ret = OPTIN_ERR_INVALID_OPTION; goto done; } else if (value && !option->accepts_value) { fprintf(stderr, "Option '%s' does not take a value\n", opt); ret = OPTIN_ERR_INVALID_VALUE; goto done; } if (option->accepts_value && !value) { /* Let's see if our next arg can function as a value */ if ((i + 1) == o->argc || *(o->argv[i+1]) == '-') { fprintf(stderr, "Option '%s' requires a value\n", opt); ret = OPTIN_ERR_VALUE_MISSING; goto done; } else { (*argc)--; } value = o->argv[i+1]; } ret = optin_process_option(o, opt, value); if (ret != 0) { goto done; } } state = STATE_NORMAL; break; } if (value && value == o->argv[i+1]) { /* Need to skip over the value we used */ i += 2; } else { i++; } } done: /* Analyze required options */ opt_iter = ht_iter_begin(o->options); while (opt_iter) { wrapper = ht_value(opt_iter); /* Only consider the real options, ignore aliases so we don't check the same option twice */ if (wrapper && !wrapper->alias) { option = wrapper->o; if (option && option->has_default == OPTIN_REQUIRED && !option->set) { fprintf(stderr, "Missing required option '%s'\n", option->name); ret = OPTIN_ERR_OPTION_MISSING; break; } } opt_iter = ht_iter_next(opt_iter); } /* Reorder any args after the options in the caller's argv array */ for (; i < o->argc; i++) { argv[next_argv++] = o->argv[i]; } return ret; }