int directive( int i, long direct ) /* Handle all directives */ { int ret; /* no expansion on the following */ switch( direct ) { case T_MASM: Options.mode &= ~MODE_IDEAL; return( NOT_ERROR ); case T_IDEAL: Options.mode |= MODE_IDEAL; return( NOT_ERROR ); case T_DOT_286C: direct = T_DOT_286; case T_DOT_8086: case T_DOT_186: case T_DOT_286: case T_DOT_286P: case T_DOT_386: case T_DOT_386P: case T_DOT_486: case T_DOT_486P: case T_DOT_586: case T_DOT_586P: case T_DOT_686: case T_DOT_686P: case T_DOT_8087: case T_DOT_287: case T_DOT_387: case T_DOT_NO87: case T_DOT_K3D: case T_DOT_MMX: case T_DOT_XMM: case T_DOT_XMM2: case T_DOT_XMM3: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } else { ret = cpu_directive(direct); if( Parse_Pass != PASS_1 ) ret = NOT_ERROR; return( ret ); } case T_P286N: direct = T_P286; case T_P8086: case T_P186: case T_P286: case T_P286P: case T_P386: case T_P386P: case T_P486: case T_P486P: case T_P586: case T_P586P: case T_P686: case T_P686P: case T_P8087: case T_P287: case T_P387: case T_PK3D: case T_PMMX: case T_PXMM: case T_PXMM2: case T_PXMM3: ret = cpu_directive(direct); if( Parse_Pass != PASS_1 ) ret = NOT_ERROR; return( ret ); case T_DOT_DOSSEG: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_DOSSEG: Globals.dosseg = TRUE; return( NOT_ERROR ); case T_PUBLIC: /* special case - expanded inside iff it is an EQU to a symbol */ return( Parse_Pass == PASS_1 ? PubDef(i+1) : NOT_ERROR ); case T_ELSE: case T_ELSEIF: case T_ELSEIF1: case T_ELSEIF2: case T_ELSEIFB: case T_ELSEIFDEF: case T_ELSEIFE: case T_ELSEIFNB: case T_ELSEIFNDEF: case T_ELSEIFDIF: case T_ELSEIFDIFI: case T_ELSEIFIDN: case T_ELSEIFIDNI: case T_ENDIF: case T_IF: case T_IF1: case T_IF2: case T_IFB: case T_IFDEF: case T_IFE: case T_IFNB: case T_IFNDEF: case T_IFDIF: case T_IFDIFI: case T_IFIDN: case T_IFIDNI: return( conditional_assembly_directive( i ) ); case T_DOT_ERR: case T_DOT_ERRB: case T_DOT_ERRDEF: case T_DOT_ERRDIF: case T_DOT_ERRDIFI: case T_DOT_ERRE: case T_DOT_ERRIDN: case T_DOT_ERRIDNI: case T_DOT_ERRNB: case T_DOT_ERRNDEF: case T_DOT_ERRNZ: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_ERR: case T_ERRIFB: case T_ERRIFDEF: case T_ERRIFDIF: case T_ERRIFDIFI: case T_ERRIFE: case T_ERRIFIDN: case T_ERRIFIDNI: case T_ERRIFNDEF: return( conditional_error_directive( i ) ); case T_ENDS: if( Definition.struct_depth != 0 ) return( StructDef( i ) ); // else fall through to T_SEGMENT case T_SEGMENT: return( Parse_Pass == PASS_1 ? SegDef(i) : SetCurrSeg(i) ); case T_GROUP: return( Parse_Pass == PASS_1 ? GrpDef(i) : NOT_ERROR ); case T_PROC: return( ProcDef( i, TRUE ) ); case T_ENDP: return( ProcEnd(i) ); case T_ENUM: return( EnumDef( i ) ); case T_DOT_CODE: case T_DOT_STACK: case T_DOT_DATA: case T_DOT_DATA_UN: case T_DOT_FARDATA: case T_DOT_FARDATA_UN: case T_DOT_CONST: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_CODESEG: case T_STACK: case T_DATASEG: case T_UDATASEG: case T_FARDATA: case T_UFARDATA: case T_CONST: return( SimSeg(i) ); case T_WARN: case T_NOWARN: return( NOT_ERROR ); /* Not implemented yet */ case T_DOT_ALPHA: case T_DOT_SEQ: case T_DOT_LIST: case T_DOT_LISTALL: case T_DOT_LISTIF: case T_DOT_LISTMACRO: case T_DOT_LISTMACROALL: case T_DOT_NOLIST: case T_DOT_XLIST: case T_DOT_TFCOND: case T_DOT_SFCOND: case T_DOT_LFCOND: case T_DOT_CREF: case T_DOT_XCREF: case T_DOT_NOCREF: case T_DOT_SALL: case T_PAGE: case T_TITLE: case T_SUBTITLE: case T_SUBTTL: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } AsmWarn( 4, IGNORING_DIRECTIVE ); return( NOT_ERROR ); case T_DOT_BREAK: case T_DOT_CONTINUE: case T_DOT_ELSE: case T_DOT_ENDIF: case T_DOT_ENDW: case T_DOT_IF: case T_DOT_RADIX: case T_DOT_REPEAT: case T_DOT_UNTIL: case T_DOT_WHILE: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_ECHO: case T_HIGH: case T_HIGHWORD: case T_LOW: case T_LOWWORD: case T_ADDR: case T_BOUND: case T_CASEMAP: case T_INVOKE: case T_LROFFSET: case T_OPATTR: case T_OPTION: case T_POPCONTEXT: case T_PUSHCONTEXT: case T_PROTO: case T_THIS: case T_WIDTH: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_CATSTR: case T_MASK: case T_PURGE: case T_RECORD: case T_TYPEDEF: case T_UNION: AsmError( NOT_SUPPORTED ); return( ERROR ); case T_ORG: ExpandTheWorld( 0, FALSE, TRUE ); break; case T_TEXTEQU: /* TEXTEQU */ if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_EQU2: /* = */ case T_EQU: /* EQU */ /* expand any constants and simplify any expressions */ ExpandTheConstant( 0, FALSE, TRUE ); break; case T_NAME: /* no expand parameters */ break; case T_DOT_STARTUP: case T_DOT_EXIT: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_STARTUPCODE: case T_EXITCODE: default: /* expand any constants in all other directives */ ExpandAllConsts( 0, FALSE ); break; } switch( direct ) { case T_ALIAS: if( Parse_Pass == PASS_1 ) return( AddAlias( i ) ); return( NOT_ERROR ); case T_EXTERN: if( Options.mode & MODE_IDEAL ) { break; } case T_EXTRN: return( Parse_Pass == PASS_1 ? ExtDef( i+1, FALSE ) : NOT_ERROR ); case T_COMM: return( Parse_Pass == PASS_1 ? CommDef(i+1) : NOT_ERROR ); case T_EXTERNDEF: if( Options.mode & MODE_IDEAL ) { break; } case T_GLOBAL: return( Parse_Pass == PASS_1 ? ExtDef( i+1, TRUE ) : NOT_ERROR ); case T_DOT_MODEL: if( Options.mode & MODE_IDEAL ) { break; } case T_MODEL: return( Model(i) ); case T_INCLUDE: return( Include(i+1) ); case T_INCLUDELIB: return( Parse_Pass == PASS_1 ? IncludeLib(i+1) : NOT_ERROR ); case T_ASSUME: return( SetAssume(i) ); case T_END: return( ModuleEnd(Token_Count) ); case T_EQU: return( DefineConstant( i-1, FALSE, FALSE ) ); case T_EQU2: return( DefineConstant( i-1, TRUE, FALSE ) ); case T_TEXTEQU: return( DefineConstant( i-1, TRUE, TRUE ) ); case T_MACRO: return( MacroDef(i, FALSE ) ); case T_ENDM: return( MacroEnd( FALSE ) ); case T_EXITM: return( MacroEnd( TRUE ) ); case T_ARG: return( Parse_Pass == PASS_1 ? ArgDef(i) : NOT_ERROR ); case T_USES: return( Parse_Pass == PASS_1 ? UsesDef(i) : NOT_ERROR ); case T_LOCAL: return( Parse_Pass == PASS_1 ? LocalDef(i) : NOT_ERROR ); case T_COMMENT: if( Options.mode & MODE_IDEAL ) break; return( Comment( START_COMMENT, i ) ); case T_STRUCT: if( Options.mode & MODE_IDEAL ) { break; } case T_STRUC: return( StructDef( i ) ); case T_NAME: return( Parse_Pass == PASS_1 ? NameDirective(i) : NOT_ERROR ); case T_LABEL: return( LabelDirective( i ) ); case T_ORG: return( OrgDirective( i ) ); case T_ALIGN: case T_EVEN: return( AlignDirective( direct, i ) ); case T_FOR: if( Options.mode & MODE_IDEAL ) { break; } case T_IRP: return( ForDirective ( i+1, IRP_WORD ) ); case T_FORC: if( Options.mode & MODE_IDEAL ) { break; } case T_IRPC: return( ForDirective ( i+1, IRP_CHAR ) ); case T_REPEAT: if( Options.mode & MODE_IDEAL ) { break; } case T_REPT: return( ForDirective ( i+1, IRP_REPEAT ) ); case T_DOT_STARTUP: case T_DOT_EXIT: case T_STARTUPCODE: case T_EXITCODE: return( Startup ( i ) ); case T_LOCALS: case T_NOLOCALS: return( Locals( i ) ); } AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); }
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; }