bool VMTapeParser :: parseMessage(ident_t message, IdentifierString& reference) { int paramCounter = 0; size_t length = getlength(message); length = message.find('['); if (length != NOTFOUND_POS) { reference.copy(message + length + 1); if (reference[reference.Length() - 1] == ']') { reference.truncate(reference.Length() - 1); //if (emptystr(reference)) { // paramCounter = OPEN_ARG_COUNT; //} /*else */paramCounter = reference.ident().toInt(); } else return false; } else return false; reference.clear(); reference.append('0' + (char)paramCounter); reference.append(message, length); return true; }
bool VMTapeParser :: writeExtension(TapeWriter& writer, ident_t message, int command) { IdentifierString reference; size_t dotPos = message.find('.'); if (parseMessage(message + dotPos + 1, reference)) { reference.insert(message, 0, dotPos + 1); writer.writeCommand(command, reference); return true; } else return false; }
void parseMessageConstant(IdentifierString& message, ident_t reference) { // message constant: nverb&signature int verbId = 0; int signatureId = 0; // read the param counter int count = reference[0] - '0'; // skip the param counter reference+=1; int index = reference.find('&'); //HOTFIX: for generic GET message we have to ignore ampresand if (reference[index + 1] == 0) index = -1; if (index != -1) { //HOTFIX: for GET message we have &&, so the second ampersand should be used if (reference[index + 1] == 0 || reference[index + 1] == '&') index++; IdentifierString verb(reference, index); ident_t signature = reference + index + 1; // if it is a predefined verb if (verb[0] == '#') { verbId = verb[1] - 0x20; } message.append(signature); } else { message.append(reference); } }
void printMethod(_Module* module, ident_t methodReference, int pageSize) { methodReference = trim(methodReference); int separator = methodReference.find('.'); if (separator == -1) { printf("Invalid command"); return; } IdentifierString className(methodReference, separator); ident_t methodName = methodReference + separator + 1; ref_t message = 0; // resolve method if (methodName[0] >= '0' && methodName[0] <= '9') { message = resolveMessageByIndex(module, className.ident(), methodName.toInt()); } else message = resolveMessage(module, methodName); if (message == 0) return; // find class VMT _Memory* vmt = findClassVMT(module, className); _Memory* code = findClassCode(module, className); if (vmt == NULL || code == NULL) { printLine("Class not found: ", className); return; } // find method entry MemoryReader vmtReader(vmt); // read tape record size size_t size = vmtReader.getDWord(); // read VMT header ClassHeader header; vmtReader.read((void*)&header, sizeof(ClassHeader)); VMTEntry entry; // read VMT while the entry not found size -= sizeof(ClassHeader); bool found = false; while (size > 0) { vmtReader.read((void*)&entry, sizeof(VMTEntry)); if (entry.message == message) { found = true; IdentifierString temp; temp.copy(className); temp.append('.'); printMessage(temp, module, entry.message); printLine("@method ", temp); printByteCodes(module, code, entry.address, 4, pageSize); print("@end\n"); break; } size -= sizeof(VMTEntry); } if (!found) { printLine("Method not found:", methodName); } }
ref_t resolveMessage(_Module* module, ident_t method) { int paramCount = 0; ref_t actionRef = 0; ref_t flags = 0; if (method.startsWith("params#")) { flags |= VARIADIC_MESSAGE; method = method.c_str() + getlength("params#"); } if (method.startsWith("prop#")) { flags |= PROPERTY_MESSAGE; method = method.c_str() + getlength("prop#"); } if (method.startsWith("#invoke")) { flags |= SPECIAL_MESSAGE; } if (method.startsWith("#private&")) { flags |= STATIC_MESSAGE; method = method.c_str() + getlength("#private&"); } if (method.compare("#init")) { flags |= SPECIAL_MESSAGE; } IdentifierString actionName; int paramIndex = method.find('[', -1); if (paramIndex != -1) { actionName.copy(method, paramIndex); IdentifierString countStr(method + paramIndex + 1, getlength(method) - paramIndex - 2); paramCount = countStr.ident().toInt(); } else actionName.copy(method); //if (actionName.compare("dispatch")) { // actionRef = DISPATCH_MESSAGE_ID; //} //else if (actionName.compare("#new")) { // actionRef = NEWOBJECT_MESSAGE_ID; //} ///*else */if (actionName.compare("#init")) { // actionRef = INIT_MESSAGE_ID; //} //else { // if (method.find("set&") != NOTFOUND_POS) { // actionName.cut(0, 4); // flags = PROPSET_MESSAGE; // } // else if (method.startsWith("#cast<") && paramCount > 0) { // flags = SPECIAL_MESSAGE; // } //// else if (actionName.compare("set")) { //// flags = PROPSET_MESSAGE; //// } ref_t signature = 0; size_t index = actionName.ident().find('<'); if (index != NOTFOUND_POS) { ref_t references[ARG_COUNT]; size_t end = actionName.ident().find('>'); size_t len = 0; size_t i = index + 1; while (i < end) { size_t j = actionName.ident().find(i, ',', end); IdentifierString temp(actionName.c_str() + i, j-i); references[len++] = module->mapReference(temp, true); i = j + 1; } signature = module->mapSignature(references, len, true); actionName.truncate(index); } actionRef = module->mapAction(actionName, signature, true); if (actionRef == 0) { printLine("Unknown subject ", actionName); return 0; } //} return encodeMessage(actionRef, paramCount, flags); }