void _parseFieldList (const char *str, StringPool &props, StringPool &columns) { QS_DEF(Array<char>, prop); QS_DEF(Array<char>, column); BufferScanner scanner(str); props.clear(); columns.clear(); scanner.skipSpace(); while (!scanner.isEOF()) { scanner.readWord(prop, " ,"); scanner.skipSpace(); scanner.readWord(column, " ,"); scanner.skipSpace(); props.add(prop.ptr()); columns.add(column.ptr()); if (scanner.isEOF()) break; if (scanner.readChar() != ',') throw BingoError("_parseFieldList(): comma expected"); scanner.skipSpace(); } }
TypeManager::TypeManager(StringPool &strings) : strings_(strings), voidType_(nullptr), implicitVoidType_(nullptr), uncheckedType_(nullptr), metaFunctionType_(nullptr), overloadedFunctionType_(nullptr), primitiveTypes_(), char_type_(nullptr), char_array_(nullptr), const_char_array_(nullptr), float_type_(nullptr), float3_array_(nullptr), const_float3_array_(nullptr) { atom_String_ = strings.add("String"); atom_Float_ = strings.add("Float"); atom_any_ = strings.add("any"); atom_Function_ = strings.add("Function"); atom_bool_ = strings.add("bool"); }
int VirtualMachine::runFile(ByteCodeFileReader& reader){ int header = reader.readHeader(); if(header != ('E' + 'D' + 'D' + 'I')){ cout << "Not an EDDI compiled file" << endl; return 1; } StringPool pool; int strings = reader.readInt(); cout << "String pool size = " << strings << endl; for(int i = 0; i < strings; i++){ int index = reader.readInt(); string value = reader.readLitteral(); pool.add(index, value); } vector<Instruction> instructions; int current = 0; map<int, int> branches; while(reader.hasMore()){ ByteCode bytecode = reader.readByteCode(); if(bytecode == LABEL){ int branche = reader.readInt(); branches[branche] = current; } else { Instruction instruction; instruction.bytecode = bytecode; if(instruction.bytecode > LABEL && instruction.bytecode <= JUMP_IF_NOT){ instruction.operand = reader.readInt(); } instructions.push_back(instruction); ++current; } } Stack stack; Variables variables; int programCounter = 0; while(true){ Instruction instruction = instructions[programCounter]; ByteCode bytecode = instruction.bytecode; programCounter++; switch(bytecode){ case LDCS: case LDCI: stack.push(instruction.operand); break; case PRINTI: cout << stack.pop() << endl; break; case PRINTS: cout << pool.get(stack.pop()) << endl; break; case SSTORE: case ISTORE:{ unsigned int variable = (unsigned int) instruction.operand; variables.assign(variable, stack.pop()); break; } case SLOAD: case ILOAD:{ unsigned int variable = (unsigned int) instruction.operand; stack.push(variables.get(variable)); break; } case IADD:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs + rhs); break; } case ISUB:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs - rhs); break; } case IMUL:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs * rhs); break; } case IDIV:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs / rhs); break; } case IMOD:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs % rhs); break; } case SADD:{ string rhs = pool.get(stack.pop()); string lhs = pool.get(stack.pop()); int index = pool.addNew(lhs + rhs); stack.push(index); break; } case JUMP: { programCounter = branches[instruction.operand]; break; } case JUMP_IF: { int result = stack.pop(); if(result == 1){ programCounter = branches[instruction.operand]; } break; } case JUMP_IF_NOT: { int result = stack.pop(); if(result == 0){ programCounter = branches[instruction.operand]; } break; } case EQUALS: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs == rhs){ stack.push(1); } else { stack.push(0); } break; } case NOT_EQUALS: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs != rhs){ stack.push(1); } else { stack.push(0); } break; } case GREATER_THAN: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs > rhs){ stack.push(1); } else { stack.push(0); } break; } case LESS_THAN: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs < rhs){ stack.push(1); } else { stack.push(0); } break; } case GREATER_THAN_EQUALS: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs >= rhs){ stack.push(1); } else { stack.push(0); } break; } case LESS_THAN_EQUALS: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs <= rhs){ stack.push(1); } else { stack.push(0); } break; } case END: return 0; } } return 1; }
static void append_debug_tables(SmxBuilder *builder, StringPool &pool, RefPtr<SmxNameTable> names, SymbolList &nativeList) { // We use a separate name table for historical reasons that are no longer // necessary. In the future we should just alias this to ".names". RefPtr<SmxNameTable> dbgnames = new SmxNameTable(".dbg.strings"); RefPtr<SmxDebugInfoSection> info = new SmxDebugInfoSection(".dbg.info"); RefPtr<SmxDebugLineSection> lines = new SmxDebugLineSection(".dbg.lines"); RefPtr<SmxDebugFileSection> files = new SmxDebugFileSection(".dbg.files"); RefPtr<SmxDebugSymbolsSection> symbols = new SmxDebugSymbolsSection(".dbg.symbols"); RefPtr<SmxDebugNativesSection> natives = new SmxDebugNativesSection(".dbg.natives"); RefPtr<SmxTagSection> tags = new SmxTagSection(".tags"); stringlist *dbgstrs = get_dbgstrings(); // State for tracking which file we're on. We replicate the original AMXDBG // behavior here which excludes duplicate addresses. ucell prev_file_addr = 0; const char *prev_file_name = nullptr; // Add debug data. for (stringlist *iter = dbgstrs; iter; iter = iter->next) { if (iter->line[0] == '\0') continue; DebugString str(iter->line); switch (str.kind()) { case 'F': { ucell codeidx = str.parse(); if (codeidx != prev_file_addr) { if (prev_file_name) { sp_fdbg_file_t &entry = files->add(); entry.addr = prev_file_addr; entry.name = dbgnames->add(pool, prev_file_name); } prev_file_addr = codeidx; } prev_file_name = str.skipspaces(); break; } case 'L': { sp_fdbg_line_t &entry = lines->add(); entry.addr = str.parse(); entry.line = str.parse(); break; } case 'S': { sp_fdbg_symbol_t sym; sp_fdbg_arraydim_t dims[sDIMEN_MAX]; sym.addr = str.parse(); sym.tagid = str.parse(); str.skipspaces(); str.expect(':'); char *name = str.skipspaces(); char *nameend = str.skipto(' '); Atom *atom = pool.add(name, nameend - name); sym.codestart = str.parse(); sym.codeend = str.parse(); sym.ident = (char)str.parse(); sym.vclass = (char)str.parse(); sym.dimcount = 0; sym.name = dbgnames->add(atom); info->header().num_syms++; str.skipspaces(); if (str.getc() == '[') { info->header().num_arrays++; for (char *ptr = str.skipspaces(); *ptr != ']'; ptr = str.skipspaces()) { dims[sym.dimcount].tagid = str.parse(); str.skipspaces(); str.expect(':'); dims[sym.dimcount].size = str.parse(); sym.dimcount++; } } symbols->add(&sym, sizeof(sym)); symbols->add(dims, sizeof(dims[0]) * sym.dimcount); break; } } } // Add the last file. if (prev_file_name) { sp_fdbg_file_t &entry = files->add(); entry.addr = prev_file_addr; entry.name = dbgnames->add(pool, prev_file_name); } // Build the tags table. for (constvalue *constptr = tagname_tab.next; constptr; constptr = constptr->next) { assert(strlen(constptr->name)>0); sp_file_tag_t &tag = tags->add(); tag.tag_id = constptr->value; tag.name = names->add(pool, constptr->name); } // Finish up debug header statistics. info->header().num_files = files->count(); info->header().num_lines = lines->count(); // Write natives. sp_fdbg_ntvtab_t natives_header; natives_header.num_entries = nativeList.length(); natives->add(&natives_header, sizeof(natives_header)); for (size_t i = 0; i < nativeList.length(); i++) { symbol *sym = nativeList[i]; sp_fdbg_native_t info; info.index = i; info.name = dbgnames->add(pool, sym->name); info.tagid = sym->tag; info.nargs = 0; for (arginfo *arg = sym->dim.arglist; arg->ident; arg++) info.nargs++; natives->add(&info, sizeof(info)); for (arginfo *arg = sym->dim.arglist; arg->ident; arg++) { sp_fdbg_ntvarg_t argout; argout.ident = arg->ident; argout.tagid = arg->tag; argout.dimcount = arg->numdim; argout.name = dbgnames->add(pool, arg->name); natives->add(&argout, sizeof(argout)); for (int j = 0; j < argout.dimcount; j++) { sp_fdbg_arraydim_t dim; dim.tagid = arg->idxtag[j]; dim.size = arg->dim[j]; natives->add(&dim, sizeof(dim)); } } } // Add these in the same order SourceMod 1.6 added them. builder->add(files); builder->add(symbols); builder->add(lines); builder->add(natives); builder->add(dbgnames); builder->add(info); builder->add(tags); }