Type* StabDebugInfo::get_type2(const char* &p, StringIn name, int file_num, int type_num) { Type* pType = nullptr; char typeDescriptor = *p++; // TRACE("%c", typeDescriptor); switch (typeDescriptor) { case 's': // struct { ClassType* pClass = new ClassType(); pType = pClass; //pClass->AddRef(); pClass->m_kwType = ClassKey_struct; pClass->m_name = name; ASSERT(pType != NULL); //ASSERT(m_types[file_num*100 + type_num] == NULL); //Class* pClass2 = (Class*)m_types[file_num*100 + type_num]; //if (pClass2 == NULL) m_types[file_num*100 + type_num] = pType; // TRACE("struct"); int size = get_number(p); pClass->m_sizeof = size;// / 8; if (*p == '!') { p++; int nbases = get_number(p); eat(p, ','); for (int i = 0; i < nbases; i++) { char virtualChar = *p++; char visibilityChar = *p++; long offset = get_number(p); eat(p, ','); System::Type* baseType = get_type(p, nullptr); eat(p, ';'); } } while (*p != ';') { Declarator* pMemberDecl = new Declarator; pMemberDecl->m_name = get_name(p); if (*p == '/') { p++; char visibility = *p++; ASSERT(isdigit(visibility)); } if (pMemberDecl->m_name.GetLength() && pMemberDecl->m_name.LeftOf(3) == "$vb") { System::Type* pType = get_type(p, nullptr); eat(p, ','); pMemberDecl->m_offset = get_number(p) / 8; } else if (pMemberDecl->m_name.GetLength() && pMemberDecl->m_name.LeftOf(3) == "$vf") { System::Type* pType = get_type(p, nullptr); eat(p, ','); pMemberDecl->m_offset = get_number(p) / 8; } else if (*p == ':') // Method { p++; do { System::Type* pType = get_type(p, nullptr); eat(p, ':'); while (*p) { if (*p == ';') break; p++; } eat(p, ';'); char number = *p++; ASSERT(isdigit(number)); char letter = *p++; //ASSERT(isalpha(letter)); ASSERT(letter == 'A' || letter == 'B' || letter == 'C' || letter == 'D'); int next = *p++; switch (next) { case '.': // normal break; case '*': // virtual { get_number(p); //ASSERT(0); eat(p, ';'); get_type(p, nullptr); eat(p, ';'); } break; case '?': // static; break; default: ASSERT(0); } } while (*p != ';'); /* if (*p != ';') { Type* pType = get_type(p, StringA()); eat(p, ':'); while (*p) { if (*p == ';') break; p++; } eat(p, ';'); char number = *p++; ASSERT(isdigit(number)); char letter = *p++; //ASSERT(isalpha(letter)); ASSERT(letter == 'A' || letter == 'B' || letter == 'C' || letter == 'D'); int next = *p++; ASSERT(next == '.' || next == '*'); ASSERT(next == '.'); } */ } else { pMemberDecl->m_pType = get_type(p, nullptr); if (*p == ':') // static member { p++; while (*p) { if (*p == ';') break; p++; } // get_name(p); } else { eat(p, ','); pMemberDecl->m_offset = get_number(p) / 8; eat(p, ','); int numbits = get_number(p) / 8; pClass->m_pScope->AddDeclarator(pMemberDecl); } } eat(p, ';'); } eat(p, ';'); // For classes containing virtual functions the very last section of the string part of the stab holds a type reference to the first base class. if (*p == '~') { p++; eat(p, '%'); get_type(p, nullptr); eat(p, ';'); } /* if (pClass2) { if (!pClass->Equals(pClass2)) { ASSERT(0); } } */ } break; case 'u': // union { ClassType* pClass = new ClassType(); pType = pClass; // pClass->AddRef(); pClass->m_kwType = ClassKey_union; pClass->m_name = name; ASSERT(pType != NULL); // ASSERT(m_types[file_num*100 + type_num] == NULL); m_types[file_num*100 + type_num] = pType; // TRACE("union"); int size = get_number(p); pClass->m_sizeof = size;// / 8; while (*p != ';') { Declarator* pMemberDecl = new Declarator; pMemberDecl->m_name = get_name(p); if (*p == ':') // Method { p++; do { System::Type* pType = get_type(p, nullptr); eat(p, ':'); while (*p) { if (*p == ';') break; p++; } eat(p, ';'); char number = *p++; ASSERT(isdigit(number)); char letter = *p++; ASSERT(isalpha(letter)); int next = *p++; ASSERT(next == '.' || next == '*'); ASSERT(next == '.'); } while (*p != ';'); } else { pMemberDecl->m_pType = get_type(p, nullptr); eat(p, ','); pMemberDecl->m_offset = get_number(p) / 8; eat(p, ','); int numbits = get_number(p) / 8; pClass->m_pScope->AddDeclarator(pMemberDecl); } eat(p, ';'); } eat(p, ';'); } break; case 'e': // enum { NamedType* pType2 = m_pReceiver->LookupNamedType(name); EnumType* pEnum = new EnumType; pEnum->m_name = name; while (*p != ';') { String name = get_name(p); long value = get_number(p); //EnumDef& enumDef = new ; pEnum->m_deflist.push_back(EnumDef(name, value)); eat(p, ','); } eat(p, ';'); if (pType2) { #if 0 if (!pType2->Equals(*pEnum)) { // ASSERT(0); } #endif pType = pType2; } else { pType = pEnum; } m_types[file_num*100 + type_num] = pType; } break; case 'a': // array { get_type2(p, nullptr, -1, -1); // index type get_type(p, nullptr); // element type } break; case 'f': // function type { pType = new FunctionType;//new Type(type_function); //pType->m_pFunction = ; pType->AsFunction()->m_pReturnType = get_type(p, nullptr); } break; #if 0 case 'f': /* || typeDescriptor == 'F' */ { Type* pReturnType = get_type(p); // TODO /* if (*p == ',') { p++; } eatchar(';'); */ } break; #endif case 'r': // subrange type { /* pType = new PrimitiveType;//(type_int, 4); ASSERT(pType); ASSERT(m_types[file_num*100 + type_num] == NULL); m_types[file_num*100 + type_num] = pType; */ Type* pType2 = get_type(p, nullptr); eat(p, ';'); int lower = get_number(p); eat(p, ';'); int upper = get_number(p); eat(p, ';'); //Type_type type; LONGLONG range = (LONGLONG)upper - (LONGLONG)lower; if (range <= 255) { pType = &Types::type_char; // pType->m_sizeof = 1; } else if (range <= 65535) { pType = &Types::type_short; // pType->m_sizeof = 2; } else// if (range <= MAX_INT) { pType = &Types::type_int; // pType->m_sizeof = 4; } //pType = System::PrimitiveType(type);//(type_int, 4); if (type_num != -1) { if (m_types[file_num*100 + type_num] != NULL) { /* if (!m_types[file_num*100 + type_num]->Equals(pType)) { ASSERT(0); } */ } //ASSERT(m_types[file_num*100 + type_num] == NULL); m_types[file_num*100 + type_num] = pType; } } break; case 'R': { char fp_type = *p++; if (fp_type == '1') pType = &Types::type_float; else if (fp_type == '2') pType = &Types::type_double; else ASSERT(0); // TODO eat(p, ';'); int /*pType->m_*/ _sizeof = get_number(p); VERIFY(pType->get_sizeof() == _sizeof); // ASSERT(m_types[file_num*100 + type_num] == NULL || m_types[file_num*100 + type_num]->Equals(pType)); m_types[file_num*100 + type_num] = pType; } break; case '*': { pType = new PointerType(get_type(p, nullptr)); // ASSERT(m_types[file_num*100 + type_num] == NULL || m_types[file_num*100 + type_num]->Equals(pType)); m_types[file_num*100 + type_num] = pType; } break; case '&': { pType = new ReferenceType(get_type(p, nullptr)); // ASSERT(m_types[file_num*100 + type_num] == NULL); m_types[file_num*100 + type_num] = pType; } break; case 'k': { pType = new ModifierType(get_type(p, nullptr), true, false); // ((CVType*)pType)->m_bConst = true; // ASSERT(m_types[file_num*100 + type_num] == NULL || m_types[file_num*100 + type_num]->Equals(pType)); m_types[file_num*100 + type_num] = pType; } break; case 'B': { pType = new ModifierType(get_type(p, nullptr), false, true); // ((CVType*)pType)->m_bVolatile = true; // ASSERT(m_types[file_num*100 + type_num] == NULL || m_types[file_num*100 + type_num]->Equals(pType)); m_types[file_num*100 + type_num] = pType; } break; case '#': { if (*p == '#') { p++; Type* returnType = get_type(p, nullptr); eat(p, ';'); // the class and argument types are not specified, specified, and must be // determined by demangling the name of the method if it is available } else { Type* classType = get_type(p, nullptr); eat(p, ','); Type* returnType = get_type(p, nullptr); //eat(p, ','); while (*p == ',') { p++; Type* paramType = get_type(p, nullptr); } eat(p, ';'); } } break; case '-': // negative type descriptor { int num = -get_number(p); eat(p, ';'); switch (num) { case -16: pType = &Types::type_int; // 32bit boolean break; default: ASSERT(0); throw new Exception(L"parse error"); } // pType = new Type(type_pointer, sizeof_pointer); // pType->m_pPointerTo = get_type(p); // ASSERT(m_types[file_num*100 + type_num] == NULL || m_types[file_num*100 + type_num]->Equals(pType)); m_types[file_num*100 + type_num] = pType; } break; case 'x': // forward reference { char type = *p++; ASSERT(type == 's' || type == 'u' || type == 'e'); String name = get_name(p); } break; default: { ASSERT(0); // TODO pType = &Types::type_int; ASSERT(pType != NULL); // ASSERT(m_types[file_num*100 + type_num] == NULL); m_types[file_num*100 + type_num] = pType; } } return pType; }