/** * 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 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; }
/// 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; }