void rewrite_jumps(uint8_t *code_ref, jump_type *jump_list, hashtable_type *labels) { vm_int target = 0; vm_int *label_addr = 0; /* rewrite jumps */ while(jump_list) { /* look up label */ if(!hash_get(labels, jump_list->label, (void **)&label_addr)) { printf("Undefined jump to '%s' @ %" PRIi64 " on line %" PRIi64 "\n", jump_list->label, jump_list->addr, jump_list->lineno); assert(0); } /* convert to relative address */ target = *label_addr - jump_list->addr; target -= 8; /* adjust for addr field */ /* get bytes, there should be 8 */ uint8_t addr[] = { INT_64(target)}; /* write bytes into code_ref */ for(int i=0; i < 8; i++) { code_ref[jump_list->addr + i] = addr[i]; } jump_list = jump_list->next; } }
void asm_jump(gc_type *gc, buffer_type *buf, yyscan_t *scanner, jump_type **jump_list) { static int init = 0; static gc_type_def jump_def = 0; jump_type *jump = 0; char *label = 0; /* TODO: This is a hack */ if(!init) { init = 1; jump_def = gc_register_type(gc, sizeof(jump_type)); gc_register_pointer(gc, jump_def, offsetof(jump_type, label)); gc_register_pointer(gc, jump_def, offsetof(jump_type, next)); } gc_register_root(gc, (void **)&jump); /* allocate a new jump */ gc_alloc_type(gc, 0, jump_def, (void **)&jump); /* save location of jump addr field */ jump->addr = buffer_size(buf); /* save the line number for this jump */ jump->lineno = yyget_lineno(scanner); /* make sure we have a label */ if(yylex(scanner) != LABEL_TOKEN) { assert(0); } /* save a copy of the label */ label = get_text(scanner); gc_alloc(gc, 0, strlen(label)+1, (void **)&(jump->label)); strcpy(jump->label, label); /* put this jump at the head of the list */ jump->next = *jump_list; *jump_list = jump; gc_unregister_root(gc, (void **)&jump); /* Make sure we have space to write target */ EMIT(buf, INT_64(0),8); }
// // Handler // INT_32 FnCast::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // 2 arguments need if (iArgNum != 2) { oLogger.Emerg("Usage: CAST(flag, x)"); return -1; } // Arg 1: destination type const STLW::string & sWhat = aArguments[1].GetString(); if (sWhat.length() == 0) { oLogger.Error("The last argument should be 's', 'S', 'o', 'O', 'd', 'D', 'i', 'I', 'h', 'H', 'f' or 'F', but is `%s`", sWhat.c_str()); return -1; } CDT & oTMP = aArguments[0]; switch(sWhat[0]) { // S[tring] case 'S': case 's': oCDTRetVal = oTMP.GetString(); return 0; // O[ct[al]] case 'o': case 'O': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetInt(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { unsigned long long iLL = 0; sscanf(oTMP.GetString().c_str(), "%llo", &iLL); oCDTRetVal = INT_64(iLL); return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // D[ec[imal]] case 'd': case 'D': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetInt(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { long long iLL = 0; sscanf(oTMP.GetString().c_str(), "%lld", &iLL); oCDTRetVal = INT_64(iLL); return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // I[nt[eger]] case 'i': case 'I': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetInt(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { long long iLL = 0; sscanf(oTMP.GetString().c_str(), "%lli", &iLL); oCDTRetVal = INT_64(iLL); return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // H[ex[adecimal]] case 'H': case 'h': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetInt(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { unsigned long long iLL = 0; sscanf(oTMP.GetString().c_str(), "%llx", &iLL); oCDTRetVal = INT_64(iLL); return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // F[loat] case 'F': case 'f': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetFloat(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { double dVal = 0; sscanf(oTMP.GetString().c_str(), "%lg", &dVal); oCDTRetVal = dVal; return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // Error default: oLogger.Error("The last argument should be 's', 'S', 'o', 'O', 'd', 'D', 'i', 'I', 'h', 'H', 'f' or 'F', but is `%s`", sWhat.c_str()); return -1; } }
// // Handler // INT_32 FnRandom::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // 0 .. MAX(unsigned long) if (iArgNum == 0) { oCDTRetVal = UINT_64(random()); return 0; } // RAND(x) -> 0 .. RAND(x) else if (iArgNum == 1) { const CDT & oFirstArg = aArguments[0]; // Integer value if (oFirstArg.GetType() == CDT::INT_VAL) { oCDTRetVal = INT_64(random() % oFirstArg.GetInt()); return 0; } // Floating point value else if (oFirstArg.GetType() == CDT::REAL_VAL) { oCDTRetVal = W_FLOAT(oFirstArg.GetFloat() * (random() % UINT_64(RAND_MAX)) / UINT_64(RAND_MAX)); return 0; } // Invalid data type, just return 0 oCDTRetVal = 0; return 0; } // RAND(x, y) -> x .. y else if (iArgNum == 2) { const CDT & oFirstArg = aArguments[1]; const CDT & oSecondArg = aArguments[0]; // x and y is integer values if (oFirstArg.GetType() == CDT::INT_VAL && oSecondArg.GetType() == CDT::INT_VAL) { const UINT_64 iFirst = oFirstArg.GetInt(); const UINT_64 iInterval = oSecondArg.GetInt() - iFirst; oCDTRetVal = INT_64(random() % iInterval + iFirst); return 0; } // x or y (or both) are floating point value else if ((oFirstArg.GetType() == CDT::REAL_VAL && oSecondArg.GetType() == CDT::INT_VAL) || (oFirstArg.GetType() == CDT::INT_VAL && oSecondArg.GetType() == CDT::REAL_VAL) || (oFirstArg.GetType() == CDT::REAL_VAL && oSecondArg.GetType() == CDT::REAL_VAL)) { const W_FLOAT dFirst = oFirstArg.GetFloat(); const W_FLOAT dInterval = oSecondArg.GetFloat() - dFirst; oCDTRetVal = W_FLOAT(dInterval * (random() % UINT_64(RAND_MAX)) / UINT_64(RAND_MAX) + dFirst); return 0; } // Invalid data type, just return 0 oCDTRetVal = 0; return 0; } oLogger.Emerg("Usage: RANDOM([[min,] max])"); return -1; }