ret_code ExterndefDirective( int i, struct asm_tok tokenarray[] ) /***************************************************************/ { char *token; #if MANGLERSUPP char *mangle_type = NULL; #endif struct asym *sym; enum lang_type langtype; char isnew; struct qualified_type ti; DebugMsg1(("ExterndefDirective(%u) enter\n", i)); i++; /* skip EXTERNDEF token */ #if MANGLERSUPP mangle_type = Check4Mangler( &i, tokenarray ); #endif do { ti.Ofssize = ModuleInfo.Ofssize; /* get the symbol language type if present */ langtype = ModuleInfo.langtype; GetLangType( &i, tokenarray, &langtype ); /* get the symbol name */ if( tokenarray[i].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } token = tokenarray[i++].string_ptr; /* go past the colon */ if( tokenarray[i].token != T_COLON ) { return( EmitError( COLON_EXPECTED ) ); } i++; sym = SymSearch( token ); //typetoken = tokenarray[i].string_ptr; ti.mem_type = MT_EMPTY; ti.size = 0; ti.is_ptr = 0; ti.is_far = FALSE; ti.ptr_memtype = MT_EMPTY; ti.symtype = NULL; ti.Ofssize = ModuleInfo.Ofssize; if ( tokenarray[i].token == T_ID && ( 0 == _stricmp( tokenarray[i].string_ptr, "ABS" ) ) ) { /* v2.07: MT_ABS is obsolete */ //ti.mem_type = MT_ABS; i++; } else if ( tokenarray[i].token == T_DIRECTIVE && tokenarray[i].tokval == T_PROTO ) { /* dont scan this line further! * CreateProto() will either define a SYM_EXTERNAL or fail * if there's a syntax error or symbol redefinition. */ sym = CreateProto( i + 1, tokenarray, token, langtype ); #if 0 /* global queue is obsolete */ if ( sym && sym->isglobal == FALSE ) { sym->isglobal = TRUE; QAddItem( &ModuleInfo.g.GlobalQueue, sym ); } #endif return( sym ? NOT_ERROR : ERROR ); } else if ( tokenarray[i].token != T_FINAL && tokenarray[i].token != T_COMMA ) { if ( GetQualifiedType( &i, tokenarray, &ti ) == ERROR ) return( ERROR ); } isnew = FALSE; if ( sym == NULL || sym->state == SYM_UNDEFINED ) { sym = CreateExternal( sym, token, TRUE ); isnew = TRUE; } /* new symbol? */ if ( isnew ) { DebugMsg1(("ExterndefDirective(%s): memtype=%X set, ofssize=%X\n", token, ti.mem_type, ti.Ofssize )); /* v2.05: added to accept type prototypes */ if ( ti.is_ptr == 0 && ti.symtype && ti.symtype->isproc ) { CreateProc( sym, NULL, SYM_EXTERNAL ); CopyPrototype( (struct dsym *)sym, (struct dsym *)ti.symtype ); ti.mem_type = ti.symtype->mem_type; ti.symtype = NULL; } switch ( ti.mem_type ) { //case MT_ABS: case MT_EMPTY: /* v2.04: hack no longer necessary */ //if ( sym->weak == TRUE ) // sym->equate = TRUE; /* allow redefinition by EQU, = */ break; case MT_FAR: /* v2.04: don't inherit current segment for FAR externals * if -Zg is set. */ if ( Options.masm_compat_gencode ) break; /* fall through */ default: //SetSymSegOfs( sym ); sym->segment = &CurrSeg->sym; } sym->Ofssize = ti.Ofssize; if ( ti.is_ptr == 0 && ti.Ofssize != ModuleInfo.Ofssize ) { sym->seg_ofssize = ti.Ofssize; if ( sym->segment && ((struct dsym *)sym->segment)->e.seginfo->Ofssize != sym->seg_ofssize ) sym->segment = NULL; } sym->mem_type = ti.mem_type; sym->is_ptr = ti.is_ptr; sym->isfar = ti.is_far; sym->ptr_memtype = ti.ptr_memtype; if ( ti.mem_type == MT_TYPE ) sym->type = ti.symtype; else sym->target_type = ti.symtype; /* v2.04: only set language if there was no previous definition */ SetMangler( sym, langtype, mangle_type ); } else if ( Parse_Pass == PASS_1 ) { /* v2.05: added to accept type prototypes */ if ( ti.is_ptr == 0 && ti.symtype && ti.symtype->isproc ) { ti.mem_type = ti.symtype->mem_type; ti.symtype = NULL; } /* ensure that the type of the symbol won't change */ if ( sym->mem_type != ti.mem_type ) { /* if the symbol is already defined (as SYM_INTERNAL), Masm won't display an error. The other way, first externdef and then the definition, will make Masm complain, however */ DebugMsg(("ExterndefDirective: type conflict for %s. mem_types old-new: %X-%X\n", sym->name, sym->mem_type, ti.mem_type)); EmitWarn( 1, SYMBOL_TYPE_CONFLICT, sym->name ); } else if ( sym->mem_type == MT_TYPE && sym->type != ti.symtype ) { struct asym *sym2 = sym; /* skip alias types and compare the base types */ DebugMsg(("ExterndefDirective(%s): types differ: %X (%s) - %X (%s)\n", sym->name, sym->type, sym->type->name, ti.symtype, ti.symtype->name)); while ( sym2->type ) sym2 = sym2->type; while ( ti.symtype->type ) ti.symtype = ti.symtype->type; if ( sym2 != ti.symtype ) { DebugMsg(("ExterndefDirective(%s): type conflict old-new: %X (%s) - %X (%s)\n", sym->name, sym2, sym2->name, ti.symtype, ti.symtype->name)); EmitWarn( 1, SYMBOL_TYPE_CONFLICT, sym->name ); } } /* v2.04: emit a - weak - warning if language differs. * Masm doesn't warn. */ if ( langtype != LANG_NONE && sym->langtype != langtype ) EmitWarn( 3, LANGUAGE_ATTRIBUTE_CONFLICT, sym->name ); } sym->isdefined = TRUE; #if 0 /* write a global entry if none has been written yet */ if ( sym->state == SYM_EXTERNAL && sym->weak == FALSE ) ;/* skip EXTERNDEF if a real EXTERN/COMM was done */ else if ( sym->isglobal == FALSE ) { sym->isglobal = TRUE; DebugMsg1(("ExterndefDirective(%s): writing a global entry\n", sym->name)); QAddItem( &ModuleInfo.g.GlobalQueue, sym ); } #else if ( sym->state == SYM_INTERNAL && sym->ispublic == FALSE ) { sym->ispublic = TRUE; AddPublicData( sym ); } #endif if ( tokenarray[i].token != T_FINAL ) if ( tokenarray[i].token == T_COMMA ) { if ( (i + 1) < Token_Count ) i++; } else { return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) ); } } while ( i < Token_Count ); return( NOT_ERROR ); }
ret_code ExternDirective( int i, struct asm_tok tokenarray[] ) /************************************************************/ { char *token; #if MANGLERSUPP char *mangle_type = NULL; #endif char *altname; struct asym *sym; enum lang_type langtype; struct qualified_type ti; DebugMsg1(("ExternDirective(%u) enter\n", i)); i++; /* skip EXT[E]RN token */ #if MANGLERSUPP mangle_type = Check4Mangler( &i, tokenarray ); #endif do { altname = NULL; /* get the symbol language type if present */ langtype = ModuleInfo.langtype; GetLangType( &i, tokenarray, &langtype ); /* get the symbol name */ if( tokenarray[i].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } token = tokenarray[i++].string_ptr; /* go past the optional alternative name (weak ext, default resolution) */ if( tokenarray[i].token == T_OP_BRACKET ) { i++; if ( tokenarray[i].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } altname = tokenarray[i].string_ptr; i++; if( tokenarray[i].token != T_CL_BRACKET ) { return( EmitErr( EXPECTED, ")" ) ); } i++; } /* go past the colon */ if( tokenarray[i].token != T_COLON ) { return( EmitError( COLON_EXPECTED ) ); } i++; sym = SymSearch( token ); ti.mem_type = MT_EMPTY; ti.size = 0; ti.is_ptr = 0; ti.is_far = FALSE; ti.ptr_memtype = MT_EMPTY; ti.symtype = NULL; ti.Ofssize = ModuleInfo.Ofssize; if ( tokenarray[i].token == T_ID && ( 0 == _stricmp( tokenarray[i].string_ptr, "ABS" ) ) ) { //ti.mem_type = MT_ABS; i++; } else if ( tokenarray[i].token == T_DIRECTIVE && tokenarray[i].tokval == T_PROTO ) { /* dont scan this line further */ /* CreateProto() will define a SYM_EXTERNAL */ sym = CreateProto( i + 1, tokenarray, token, langtype ); DebugMsg1(("ExternDirective(%s): CreateProto()=%X\n", token, sym)); if ( sym == NULL ) return( ERROR ); if ( sym->state == SYM_EXTERNAL ) { sym->weak = FALSE; return( HandleAltname( altname, sym ) ); } else { /* unlike EXTERNDEF, EXTERN doesn't allow a PROC for the same name */ return( EmitErr( SYMBOL_REDEFINITION, sym->name ) ); } } else if ( tokenarray[i].token != T_FINAL && tokenarray[i].token != T_COMMA ) { if ( GetQualifiedType( &i, tokenarray, &ti ) == ERROR ) return( ERROR ); } DebugMsg1(("ExternDirective(%s): mem_type=%Xh\n", token, ti.mem_type )); if( sym == NULL || sym->state == SYM_UNDEFINED ) { /* v2.04: emit the error at the PUBLIC directive */ //if ( sym && sym->public == TRUE ) { // EmitErr( CANNOT_DEFINE_AS_PUBLIC_OR_EXTERNAL, sym->name ); // return( ERROR ); //} if(( sym = MakeExtern( token, ti.mem_type, ti.mem_type == MT_TYPE ? ti.symtype : NULL, sym, ti.is_ptr ? ModuleInfo.Ofssize : ti.Ofssize )) == NULL ) return( ERROR ); /* v2.05: added to accept type prototypes */ if ( ti.is_ptr == 0 && ti.symtype && ti.symtype->isproc ) { CreateProc( sym, NULL, SYM_EXTERNAL ); sym->weak = FALSE; /* v2.09: reset the weak bit that has been set inside CreateProc() */ CopyPrototype( (struct dsym *)sym, (struct dsym *)ti.symtype ); ti.mem_type = ti.symtype->mem_type; ti.symtype = NULL; DebugMsg1(("ExternDirective(%s): prototype copied, memtype=%X\n", token, ti.mem_type )); } } else { #if MASM_EXTCOND /* allow internal AND external definitions for equates */ //if ( sym->state == SYM_INTERNAL && sym->mem_type == MT_ABS ) if ( sym->state == SYM_INTERNAL && sym->mem_type == MT_EMPTY ) ; else #endif if ( sym->state != SYM_EXTERNAL ) { DebugMsg(("ExternDirective: symbol %s redefinition, state=%u\n", token, sym->state )); return( EmitErr( SYMBOL_REDEFINITION, token ) ); } /* v2.05: added to accept type prototypes */ if ( ti.is_ptr == 0 && ti.symtype && ti.symtype->isproc ) { ti.mem_type = ti.symtype->mem_type; ti.symtype = NULL; } if( sym->mem_type != ti.mem_type || sym->is_ptr != ti.is_ptr || sym->isfar != ti.is_far || ( sym->is_ptr && sym->ptr_memtype != ti.ptr_memtype ) || ((sym->mem_type == MT_TYPE) ? sym->type : sym->target_type) != ti.symtype || ( langtype != LANG_NONE && sym->langtype != LANG_NONE && sym->langtype != langtype )) { DebugMsg(("ExternDirective: memtype:%X-%X ptr=%X-%X far=%X-%X ptr_memtype=%X-%X lang=%u-%u\n", sym->mem_type, ti.mem_type, sym->is_ptr, ti.is_ptr, sym->isfar, ti.is_far, sym->ptr_memtype, ti.ptr_memtype, sym->langtype, langtype )); return( EmitErr( SYMBOL_TYPE_CONFLICT, token ) ); } } sym->isdefined = TRUE; sym->Ofssize = ti.Ofssize; if ( ti.is_ptr == 0 && ti.Ofssize != ModuleInfo.Ofssize ) { sym->seg_ofssize = ti.Ofssize; if ( sym->segment && ((struct dsym *)sym->segment)->e.seginfo->Ofssize != sym->seg_ofssize ) sym->segment = NULL; } sym->mem_type = ti.mem_type; sym->is_ptr = ti.is_ptr; sym->isfar = ti.is_far; sym->ptr_memtype = ti.ptr_memtype; if ( ti.mem_type == MT_TYPE ) sym->type = ti.symtype; else sym->target_type = ti.symtype; HandleAltname( altname, sym ); SetMangler( sym, langtype, mangle_type ); if ( tokenarray[i].token != T_FINAL ) if ( tokenarray[i].token == T_COMMA && ( (i + 1) < Token_Count ) ) { i++; } else { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } } while ( i < Token_Count ); return( NOT_ERROR ); }
ret_code AssumeDirective( int i, struct asm_tok tokenarray[] ) /************************************************************/ /* Handles ASSUME * syntax is : * - ASSUME * - ASSUME NOTHING * - ASSUME segregister : seglocation [, segregister : seglocation ] * - ASSUME dataregister : qualified type [, dataregister : qualified type ] * - ASSUME register : ERROR | NOTHING | FLAT */ { int reg; int j; int size; uint_32 flags; struct assume_info *info; bool segtable; struct qualified_type ti; DebugMsg1(( "AssumeDirective enter, pass=%u\n", Parse_Pass+1 )); for( i++; i < Token_Count; i++ ) { if( ( tokenarray[i].token == T_ID ) && (0 == _stricmp( tokenarray[i].string_ptr, szNothing )) ) { AssumeInit(); i++; break; } /*---- get the info ptr for the register ----*/ info = NULL; if ( tokenarray[i].token == T_REG ) { reg = tokenarray[i].tokval; j = GetRegNo( reg ); flags = GetValueSp( reg ); if ( flags & OP_SR ) { info = &SegAssumeTable[j]; segtable = TRUE; } else if ( flags & OP_R ) { info = &StdAssumeTable[j]; segtable = FALSE; } } if ( info == NULL ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( ERROR ); } if( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < GetCpuSp( reg ) ) { EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE ); return( ERROR ); } i++; /* go past register */ if( tokenarray[i].token != T_COLON ) { EmitError( COLON_EXPECTED ); return( ERROR ); } i++; if( tokenarray[i].token == T_FINAL ) { EmitError( SYNTAX_ERROR ); return( ERROR ); } /* check for ERROR and NOTHING */ if( 0 == _stricmp( tokenarray[i].string_ptr, szError )) { if ( segtable ) { info->flat = FALSE; info->error = TRUE; } else info->error |= (( reg >= T_AH && reg <= T_BH ) ? RH_ERROR : ( flags & OP_R )); info->symbol = NULL; i++; } else if( 0 == _stricmp( tokenarray[i].string_ptr, szNothing )) { if ( segtable ) { info->flat = FALSE; info->error = FALSE; } else info->error &= ~(( reg >= T_AH && reg <= T_BH ) ? RH_ERROR : ( flags & OP_R )); info->symbol = NULL; i++; } else if ( segtable == FALSE ) { /* v2.05: changed to use new GetQualifiedType() function */ ti.size = 0; ti.is_ptr = 0; ti.is_far = FALSE; ti.mem_type = MT_EMPTY; ti.ptr_memtype = MT_EMPTY; ti.symtype = NULL; ti.Ofssize = ModuleInfo.Ofssize; if ( GetQualifiedType( &i, tokenarray, &ti ) == ERROR ) return( ERROR ); /* v2.04: check size of argument! */ size = OperandSize( flags, NULL ); if ( ( ti.is_ptr == 0 && size != ti.size ) || ( ti.is_ptr > 0 && size < CurrWordSize ) ) { EmitError( TYPE_IS_WRONG_SIZE_FOR_REGISTER ); return( ERROR ); } info->error &= ~(( reg >= T_AH && reg <= T_BH ) ? RH_ERROR : ( flags & OP_R )); if ( stdsym[j] == NULL ) { stdsym[j] = CreateTypeSymbol( NULL, "", FALSE ); stdsym[j]->typekind = TYPE_TYPEDEF; } stdsym[j]->total_size = ti.size; stdsym[j]->mem_type = ti.mem_type; stdsym[j]->is_ptr = ti.is_ptr; stdsym[j]->isfar = ti.is_far; stdsym[j]->Ofssize = ti.Ofssize; stdsym[j]->ptr_memtype = ti.ptr_memtype; /* added v2.05 rc13 */ if ( ti.mem_type == MT_TYPE ) stdsym[j]->type = ti.symtype; else stdsym[j]->target_type = ti.symtype; info->symbol = stdsym[j]; } else { /* segment register */ struct expr opnd; /* v2.08: read expression with standard evaluator */ if( EvalOperand( &i, tokenarray, Token_Count, &opnd, 0 ) == ERROR ) return( ERROR ); switch ( opnd.kind ) { case EXPR_ADDR: if ( opnd.sym == NULL || opnd.indirect == TRUE || opnd.value ) { EmitError( SEGMENT_GROUP_OR_SEGREG_EXPECTED ); return( ERROR ); } else if ( opnd.sym->state == SYM_UNDEFINED ) { /* ensure that directive is rerun in pass 2 * so an error msg can be emitted. */ FStoreLine(0); info->symbol = opnd.sym; } else if ( ( opnd.sym->state == SYM_SEG || opnd.sym->state == SYM_GRP ) && opnd.instr == EMPTY ) { info->symbol = opnd.sym; } else if ( opnd.instr == T_SEG ) { info->symbol = opnd.sym->segment; } else { EmitError( SEGMENT_GROUP_OR_SEGREG_EXPECTED ); return( ERROR ); } info->flat = ( info->symbol == &ModuleInfo.flat_grp->sym ); break; case EXPR_REG: if ( GetValueSp( opnd.base_reg->tokval ) & OP_SR ) { info->symbol = SegAssumeTable[ GetRegNo( opnd.base_reg->tokval ) ].symbol; info->flat = SegAssumeTable[ GetRegNo( opnd.base_reg->tokval ) ].flat; break; } default: EmitError( SEGMENT_GROUP_OR_SEGREG_EXPECTED ); return( ERROR ); } info->error = FALSE; } /* comma expected */ if( i < Token_Count && tokenarray[i].token != T_COMMA ) break; } if ( i < Token_Count ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ); return( ERROR ); } return( NOT_ERROR ); }