static ret_code CloseSeg( const char *name ) /******************************************/ { //struct asym *sym; DebugMsg1(("CloseSeg(%s) enter\n", name)); if( CurrSeg == NULL || ( SymCmpFunc( CurrSeg->sym.name, name, CurrSeg->sym.name_size ) != 0 ) ) { DebugMsg(("CloseSeg(%s): nesting error, CurrSeg=%s\n", name, CurrSeg ? CurrSeg->sym.name : "(null)" )); EmitErr( BLOCK_NESTING_ERROR, name ); return( ERROR ); } DebugMsg1(("CloseSeg(%s): current ofs=%" FX32 "\n", name, CurrSeg->e.seginfo->current_loc)); if ( write_to_file && ( Options.output_format == OFORMAT_OMF ) ) { //if ( !omf_FlushCurrSeg() ) /* v2: error check is obsolete */ // EmitErr( INTERNAL_ERROR, "CloseSeg", 1 ); /* coding error! */ omf_FlushCurrSeg(); if ( Options.no_comment_data_in_code_records == FALSE ) omf_OutSelect( FALSE ); } pop_seg(); return( NOT_ERROR ); }
/* Called by SetModel() [.MODEL directive]. * Initializes simplified segment directives. * NewLineQueue() has already been called, * and the caller will run RunLineQueue() later. * Called for each pass. */ ret_code ModelSimSegmInit( int model ) /************************************/ { char buffer[20]; if ( Parse_Pass == PASS_1 ) { DebugMsg1(("ModelSimSegmInit() enter, pass one\n" )); /* create default code segment (_TEXT) */ SetSimSeg( SIM_CODE, NULL ); EndSimSeg( SIM_CODE ); /* create default data segment (_DATA) */ SetSimSeg( SIM_DATA, NULL ) ; EndSimSeg( SIM_DATA ); /* create DGROUP for BIN/OMF if model isn't FLAT */ if( model != MODEL_FLAT && ( Options.output_format == OFORMAT_OMF || Options.output_format == OFORMAT_BIN )) { strcpy( buffer, "%s %r %s" ); if( model == MODEL_TINY ) { strcat( buffer, ", %s" ); AddLineQueueX( buffer, szDgroup, T_GROUP, SegmNames[SIM_CODE], SegmNames[SIM_DATA] ); } else AddLineQueueX( buffer, szDgroup, T_GROUP, SegmNames[SIM_DATA] ); } DebugMsg1(("ModelSimSegmInit() exit\n" )); } return( NOT_ERROR ); }
static ret_code SetCurrSeg( int i, struct asm_tok tokenarray[] ) /**************************************************************/ { struct asym *sym; sym = SymSearch( tokenarray[0].string_ptr ); DebugMsg1(("SetCurrSeg(%s) sym=%p\n", tokenarray[0].string_ptr, sym)); if ( sym == NULL || sym->state != SYM_SEG ) { EmitErr( SEG_NOT_DEFINED, tokenarray[0].string_ptr ); return( ERROR ); } /* v2.04: added */ sym->isdefined = TRUE; if ( CurrSeg && Options.output_format == OFORMAT_OMF ) { omf_FlushCurrSeg(); if ( Options.no_comment_data_in_code_records == FALSE ) omf_OutSelect( FALSE ); } push_seg( (struct dsym *)sym ); if ( ModuleInfo.list ) LstWrite( LSTTYPE_LABEL, 0, NULL ); return( SetOfssize() ); }
void PushMacro( struct macro_instance *mi ) /*****************************************/ { DebugMsg1(( "PushMacro(%s)\n", mi->macro->name )); PushSrcItem( SIT_MACRO, mi ); return; }
struct asm_tok *PushInputStatus( struct input_status *oldstat ) /*************************************************************/ { oldstat->token_stringbuf = token_stringbuf; oldstat->token_count = Token_Count; oldstat->currsource = CurrSource; /* if there's a comment, attach it to current source */ if ( ModuleInfo.CurrComment ) { int i = strlen( CurrSource ); oldstat->CurrComment = CurrSource + i; strcpy( oldstat->CurrComment, ModuleInfo.CurrComment ); } else oldstat->CurrComment = NULL; oldstat->line_flags = ModuleInfo.line_flags; /* v2.08 */ #ifdef __I86__ oldstat->tokenarray = ModuleInfo.tokenarray; oldstat->stringbufferend = StringBufferEnd; CurrSource = MemAlloc( MAX_LINE_LEN + SIZE_TOKENARRAY + SIZE_STRINGBUFFER ); ModuleInfo.tokenarray = (struct asm_tok *)( CurrSource + MAX_LINE_LEN ); token_stringbuf = CurrSource + MAX_LINE_LEN + SIZE_TOKENARRAY; #else token_stringbuf = StringBufferEnd; ModuleInfo.tokenarray += Token_Count + 1; CurrSource = GetAlignedPointer( CurrSource, strlen( CurrSource ) ); /**/myassert( ( CurrSource + MAX_LINE_LEN ) <= (char *)ModuleInfo.tokenarray ); /**/myassert( ( ModuleInfo.tokenarray + sizeof( struct asm_tok ) * MAX_TOKEN ) <= end_tokenarray ); /**/myassert( ( token_stringbuf + 2 * MAX_LINE_LEN ) <= end_stringbuf ); #endif DebugMsg1(("PushInputStatus() stringbuf-tokencnt-currsrc old=%X-%u-%X new=%X-%X-%X\n", oldstat->token_stringbuf, oldstat->token_count, oldstat->currsource, token_stringbuf, ModuleInfo.tokenarray, CurrSource )); return( ModuleInfo.tokenarray ); }
void PopInputStatus( struct input_status *newstat ) /*************************************************/ { DebugMsg1(("PopInputStatus() old=%X-%u-%X new=%X-%u-%X\n", token_stringbuf, Token_Count, CurrSource, newstat->token_stringbuf, newstat->token_count, newstat->currsource )); #ifdef __I86__ MemFree( CurrSource ); #else StringBufferEnd = token_stringbuf; #endif token_stringbuf = newstat->token_stringbuf; Token_Count = newstat->token_count; CurrSource = newstat->currsource; if ( newstat->CurrComment ) { ModuleInfo.CurrComment = commentbuffer; strcpy( ModuleInfo.CurrComment, newstat->CurrComment ); *newstat->CurrComment = NULLC; } else ModuleInfo.CurrComment = NULL; #ifdef __I86__ StringBufferEnd = newstat->stringbufferend; ModuleInfo.tokenarray = newstat->tokenarray; #else ModuleInfo.tokenarray -= Token_Count + 1; #endif ModuleInfo.line_flags = newstat->line_flags; /* v2.08 */ return; }
static void UpdateCurrSegVars( void ) /***********************************/ { struct assume_info *info; DebugMsg1(("UpdateCurrSegVars(%s)\n", CurrSeg ? CurrSeg->sym.name : "NULL" )); info = &(SegAssumeTable[ ASSUME_CS ]); if( CurrSeg == NULL ) { info->symbol = NULL; info->flat = FALSE; info->error = TRUE; symCurSeg->string_ptr = ""; //symPC.segment = NULL; /* v2.05: removed */ } else { info->flat = FALSE; info->error = FALSE; /* fixme: OPTION OFFSET:SEGMENT? */ if( CurrSeg->e.seginfo->group != NULL ) { info->symbol = CurrSeg->e.seginfo->group; if ( info->symbol == &ModuleInfo.flat_grp->sym ) info->flat = TRUE; } else { info->symbol = &CurrSeg->sym; } symCurSeg->string_ptr = CurrSeg->sym.name; //symPC.segment = &CurrSeg->sym; /* v2.05: removed */ } return; }
static void close_currseg( void ) /*******************************/ { if ( CurrSeg ) { DebugMsg1(("close_currseg: current seg=%s\n", CurrSeg->sym.name)); AddLineQueueX( "%s %r", CurrSeg->sym.name, T_ENDS ); } }
/* function to get value of @FileCur. * won't work, because text macros don't use asym.sfunc_ptr */ static void GetFileCur( struct asym *sym ) /****************************************/ { struct src_item *curr; for( curr = src_stack; curr && curr->type != SIT_FILE; curr = curr->next ); sym->string_ptr = GetFName( curr->srcfile )->name; DebugMsg1(("GetFileCur: curr value=%s\n", sym->string_ptr )); }
char *GetTextLine( char *buffer ) /*******************************/ { struct src_item *curr = src_stack; if ( curr->type == SIT_FILE ) { if( my_fgets( buffer, MAX_LINE_LEN, curr->file ) ) { curr->line_num++; #ifdef DEBUG_OUT if ( Parse_Pass == PASS_1 ) cntlines++; #endif return( buffer ); } DebugCmd( ModuleInfo.g.FNames[curr->srcfile].lines = curr->line_num ); DebugMsg1(("GetTextLine: ***** EOF file %s (idx=%u) *****\n", GetFName( curr->srcfile )->fname, curr->srcfile )); /* don't close and remove main source file */ if ( curr->next ) { fclose( curr->file ); src_stack = curr->next; curr->next = SrcFree; SrcFree = curr; } /* update value of @FileCur variable */ for( curr = src_stack; curr->type != SIT_FILE; curr = curr->next ); FileCur->string_ptr = GetFName( curr->srcfile)->fname; #if FILESEQ if ( Options.line_numbers && Parse_Pass == PASS_1 ) AddFileSeq( curr->srcfile ); #endif } else { curr->mi->currline = ( curr->mi->currline ? curr->mi->currline->next : curr->mi->startline ); if ( curr->mi->currline ) { /* if line contains placeholders, replace them by current values */ if ( curr->mi->currline->ph_count ) { fill_placeholders( buffer, curr->mi->currline->line, curr->mi->parmcnt, curr->mi->localstart, curr->mi->parm_array ); } else { strcpy( buffer, curr->mi->currline->line ); } curr->line_num++; #ifdef DEBUG_OUT if ( Parse_Pass == PASS_1 ) cntlines++; #endif return( buffer ); } src_stack = curr->next; curr->next = SrcFree; SrcFree = curr; } return( NULL ); /* end of file or macro reached */ }
static ret_code SubStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] ) /************************************************************************************************/ { int pos; int size; char *src = mi->parm_array[0]; DebugMsg1(("@SubStr( %s, %s, %s)\n", src ? src : "", mi->parm_array[1] ? mi->parm_array[1] : "", mi->parm_array[2] ? mi->parm_array[2] : "" )); if ( GetNumber( mi->parm_array[1], &pos, tokenarray ) == ERROR ) return( ERROR ); if ( pos <= 0 ) { /* Masm doesn't check if index is < 0; * might cause an "internal assembler error". * v2.09: negative index no longer silently changed to 1. */ if ( pos ) { return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) ); } DebugMsg(( "@SubStr(): index value 0 changed to 1\n", pos )); pos = 1; } size = strlen( src ); if ( pos > size ) { return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) ); } size = size - pos + 1; if ( mi->parm_array[2] ) { int sizereq; if ( GetNumber( mi->parm_array[2], &sizereq, tokenarray ) == ERROR ) return( ERROR ); if ( sizereq < 0 ) { return( EmitError( COUNT_MUST_BE_POSITIVE_OR_ZERO ) ); } if ( sizereq > size ) { return( EmitError( COUNT_VALUE_TOO_LARGE ) ); } size = sizereq; } #if 1 memcpy( buffer, src + pos - 1, size ); *(buffer+size) = NULLC; #else for( src += pos - 1; size; size-- ) *buffer++ = *src++; *buffer = NULLC; #endif return( NOT_ERROR ); }
/* internal @InStr macro function * syntax: @InStr( [num], literal, literal ) * the result is returned as string in current radix */ static ret_code InStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] ) /***********************************************************************************************/ { int pos = 1; char *p; uint_32 found; DebugMsg1(("@InStr( %s, %s, %s)\n", mi->parm_array[0] ? mi->parm_array[0] : "", mi->parm_array[1] ? mi->parm_array[1] : "", mi->parm_array[2] ? mi->parm_array[2] : "" )); /* init buffer with "0" */ *buffer = '0'; *(buffer+1) = NULLC; if ( mi->parm_array[0] ) { if ( GetNumber( mi->parm_array[0], &pos, tokenarray ) == ERROR ) return( ERROR ); if ( pos == 0 ) { /* adjust index 0. Masm also accepts 0 (and any negative index), * but the result will always be 0 then */ DebugMsg(( "@InStr(): index value is 0, changed to 1\n" )); pos++; } } if ( pos > strlen( mi->parm_array[1] ) ) { return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) ); } /* v2.08: if() added, empty searchstr is to return 0 */ if ( *(mi->parm_array[2]) != NULLC ) { p = strstr( mi->parm_array[1] + pos - 1, mi->parm_array[2] ); if ( p ) { found = p - mi->parm_array[1] + 1; myltoa( found, buffer, ModuleInfo.radix, FALSE, TRUE ); } } DebugMsg1(( "@InStr()=>%s<\n", buffer )); return( NOT_ERROR ); }
static struct asym *CreateProto( int i, struct asm_tok tokenarray[], const char *name, enum lang_type langtype ) /**************************************************************************************************************/ { struct asym *sym; struct dsym *dir; DebugMsg1(("CreateProto( i=%u, name=%s, lang=%u )\n", i, name ? name : "NULL", langtype )); sym = SymSearch( name ); /* the symbol must be either NULL or state * - SYM_UNDEFINED * - SYM_EXTERNAL + isproc == FALSE ( previous EXTERNDEF ) * - SYM_EXTERNAL + isproc == TRUE ( previous PROTO ) * - SYM_INTERNAL + isproc == TRUE ( previous PROC ) */ if( sym == NULL || sym->state == SYM_UNDEFINED || ( sym->state == SYM_EXTERNAL && sym->weak == TRUE && sym->isproc == FALSE )) { if ( NULL == ( sym = CreateProc( sym, name, SYM_EXTERNAL ) ) ) return( NULL ); /* name was probably invalid */ } else if ( sym->isproc == FALSE ) { EmitErr( SYMBOL_REDEFINITION, sym->name ); return( NULL ); } dir = (struct dsym *)sym; /* a PROTO typedef may be used */ if ( tokenarray[i].token == T_ID ) { struct asym * sym2; sym2 = SymSearch( tokenarray[i].string_ptr ); if ( sym2 && sym2->state == SYM_TYPE && sym2->mem_type == MT_PROC ) { i++; if ( tokenarray[i].token != T_FINAL ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( NULL ); } CopyPrototype( dir, (struct dsym *)sym2->target_type ); return( sym ); } } /* sym->isproc is set inside ParseProc() */ //sym->isproc = TRUE; if ( Parse_Pass == PASS_1 ) { if ( ParseProc( dir, i, tokenarray, FALSE, langtype ) == ERROR ) return( NULL ); #if DLLIMPORT sym->dll = ModuleInfo.CurrDll; #endif } else { sym->isdefined = TRUE; } return( sym ); }
static ret_code CatStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] ) /************************************************************************************************/ { #ifdef DEBUG_OUT int cnt = 0; #endif int i; char *p; DebugMsg1(("@CatStr( %s )\n", mi->parm_array[0] ? mi->parm_array[0] : "NULL" )); for ( p = mi->parm_array[0]; mi->parmcnt; mi->parmcnt-- ) { DebugMsg1(("@CatStr.%u: >%s<\n", cnt++, p )); i = strlen( p ); memcpy( buffer, p, i ); p = GetAlignedPointer( p, i ); buffer += i; } *buffer = NULLC; return( NOT_ERROR ); }
/* internal @SizeStr macro function * syntax: @SizeStr( literal ) * the result is returned as string in current radix */ static ret_code SizeStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] ) /*************************************************************************************************/ { DebugMsg1(("@SizeStr(%s)\n", mi->parm_array[0] ? mi->parm_array[0] : "" )); if ( mi->parm_array[0] ) myltoa( strlen( mi->parm_array[0] ), buffer, ModuleInfo. radix, FALSE, TRUE ); else { buffer[0] = '0'; buffer[1] = NULLC; } return( NOT_ERROR ); }
/* SizeStr() * defines a numeric variable which contains size of a string */ ret_code SizeStrDir( int i, struct asm_tok tokenarray[] ) /*******************************************************/ { struct asym *sym; int sizestr; DebugMsg1(("SizeStrDir entry\n")); DebugCmd( sizstrcnt++ ); if ( i != 1 ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } #if 0 /* this is checked in ParseLine() */ if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } #endif if ( tokenarray[2].token != T_STRING || tokenarray[2].string_delim != '<' ) { return( TextItemError( &tokenarray[2] ) ); } if ( Token_Count > 3 ) { DebugMsg(("SizeStrDir: syntax error, name=%s, Token_Count=%u\n", tokenarray[0].string_ptr, Token_Count)); return( EmitErr( SYNTAX_ERROR_EX, tokenarray[3].string_ptr ) ); } //sizestr = GetLiteralValue( StringBufferEnd, tokenarray[2].string_ptr ); sizestr = tokenarray[2].stringlen; if ( sym = CreateVariable( tokenarray[0].string_ptr, sizestr ) ) { DebugMsg1(("SizeStrDir(%s) exit, value=%u\n", tokenarray[0].string_ptr, sizestr)); LstWrite( LSTTYPE_EQUATE, 0, sym ); return( NOT_ERROR ); } return( ERROR ); }
void SetCurPC( struct asym *sym ) /*******************************/ { if( CurrStruct ) { //symPC.segment = NULL; //symPC.mem_type = MT_ABS; symPC.mem_type = MT_EMPTY; symPC.segment = NULL; /* v2.07: needed again */ symPC.offset = CurrStruct->sym.offset + (CurrStruct->next ? CurrStruct->next->sym.offset : 0); } else { symPC.mem_type = MT_NEAR; symPC.segment = (struct asym *)CurrSeg; symPC.offset = GetCurrOffset(); } DebugMsg1(("SetCurPC: curr value=%" FX32 "h\n", symPC.offset )); }
/* create a (predefined) text macro. * used to create @code, @data, ... * there are 2 more locations where predefined text macros may be defined: * - assemble.c, add_cmdline_tmacros() * - symbols.c, SymInit() * this should be changed eventually. */ struct asym *AddPredefinedText( const char *name, const char *value ) /*******************************************************************/ { struct asym *sym; DebugMsg1(("AddPredefinedText(%s): >%s<\n", name, value )); /* v2.08: ignore previous setting */ if ( NULL == ( sym = SymSearch( name ) ) ) sym = SymCreate( name ); sym->state = SYM_TMACRO; sym->isdefined = TRUE; sym->predefined = TRUE; sym->string_ptr = (char *)value; /* to ensure that a new buffer is used if the string is modified */ sym->total_size = 0; return( sym ); }
/* check if a file is in the array of known files. * if no, store the file at the array's end. * returns array index. * used for the main source and all INCLUDEd files. * the array is stored in the standard C heap! * the filenames are stored in the "local" heap. */ static unsigned AddFile( char const *fname ) /******************************************/ { unsigned index; DebugMsg1(("AddFile(%s) enter, curr index=%u\n", fname, ModuleInfo.g.cnt_fnames )); for( index = 0; index < ModuleInfo.g.cnt_fnames; index++ ) { if( filecmp( fname, ModuleInfo.g.FNames[index].fname ) == 0 ) { #ifdef DEBUG_OUT if ( Parse_Pass == PASS_1 ) ModuleInfo.g.FNames[index].included++; #endif return( index ); } } if ( ( index % 64 ) == 0 ) { struct fname_item *newfn; newfn = (struct fname_item *)MemAlloc( ( index + 64 ) * sizeof( struct fname_item ) ); if ( ModuleInfo.g.FNames ) { memcpy( newfn, ModuleInfo.g.FNames, index * sizeof( struct fname_item ) ); MemFree( ModuleInfo.g.FNames ); } ModuleInfo.g.FNames = newfn; } ModuleInfo.g.cnt_fnames++; /* v2.11: use name directly - allows COFF .file entries with relative paths */ //_splitpath( fname, NULL, NULL, name, ext ); ModuleInfo.g.FNames[index].fname = (char *)LclAlloc( strlen( fname ) + 1 ); strcpy( ModuleInfo.g.FNames[index].fname, fname ); /* v2.11: field fullname removed */ //ModuleInfo.g.FNames[index].fullname = (char *)LclAlloc( strlen( fullname ) + 1 ); //strcpy( ModuleInfo.g.FNames[index].fullname, fullname ); DebugCmd( ModuleInfo.g.FNames[index].included = 1 ); return( index ); }
ret_code CommDirective( int i, struct asm_tok tokenarray[] ) /**********************************************************/ { char *token; #if MANGLERSUPP char *mangle_type = NULL; #endif bool isfar; //int distance; int tmp; uint_32 size; /* v2.12: changed from 'int' to 'uint_32' */ uint_32 count; /* v2.12: changed from 'int' to 'uint_32' */ struct asym *sym; struct expr opndx; enum lang_type langtype; DebugMsg1(("CommDirective(%u) enter\n", i)); i++; /* skip COMM token */ for( ; i < Token_Count; i++ ) { #if MANGLERSUPP mangle_type = Check4Mangler( &i, tokenarray ); #endif /* get the symbol language type if present */ langtype = ModuleInfo.langtype; GetLangType( &i, tokenarray, &langtype ); /* get the -optional- distance ( near or far ) */ isfar = FALSE; if ( tokenarray[i].token == T_STYPE ) switch ( tokenarray[i].tokval ) { case T_FAR: case T_FAR16: case T_FAR32: if ( ModuleInfo.model == MODEL_FLAT ) { EmitError( FAR_NOT_ALLOWED_IN_FLAT_MODEL_COMM_VARIABLES ); } else isfar = TRUE; /* no break */ case T_NEAR: case T_NEAR16: case T_NEAR32: i++; } /* v2.08: ensure token is a valid id */ if( tokenarray[i].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } /* get the symbol name */ token = tokenarray[i++].string_ptr; /* go past the colon */ if( tokenarray[i].token != T_COLON ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } i++; /* the evaluator cannot handle a ':' so scan for one first */ for ( tmp = i; tmp < Token_Count;tmp++ ) if ( tokenarray[tmp].token == T_COLON ) break; /* v2.10: expression evaluator isn't to accept forward references */ //if ( EvalOperand( &i, tokenarray, tmp, &opndx, 0 ) == ERROR ) if ( EvalOperand( &i, tokenarray, tmp, &opndx, EXPF_NOUNDEF ) == ERROR ) return( ERROR ); /* v2.03: a string constant is accepted by Masm */ /* v2.11: don't accept NEAR or FAR */ /* v2.12: check for too large value added */ //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) { if ( opndx.kind != EXPR_CONST ) EmitError( CONSTANT_EXPECTED ); else if ( ( opndx.mem_type & MT_SPECIAL_MASK) == MT_ADDRESS ) EmitErr( INVALID_TYPE_FOR_DATA_DECLARATION, token ); else if ( opndx.hvalue != 0 && opndx.hvalue != -1 ) EmitConstError( &opndx ); else if ( opndx.uvalue == 0 ) EmitError( POSITIVE_VALUE_EXPECTED ); size = opndx.uvalue; count = 1; if( tokenarray[i].token == T_COLON ) { i++; /* get optional count argument */ /* v2.10: expression evaluator isn't to accept forward references */ //if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR ) if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) return( ERROR ); /* v2.03: a string constant is acceptable! */ /* v2.12: check for too large value added */ //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) { if ( opndx.kind != EXPR_CONST ) EmitError( CONSTANT_EXPECTED ); else if ( opndx.hvalue != 0 && opndx.hvalue != -1 ) EmitConstError( &opndx ); else if ( opndx.uvalue == 0 ) EmitError( POSITIVE_VALUE_EXPECTED ); count = opndx.uvalue; } sym = SymSearch( token ); if( sym == NULL || sym->state == SYM_UNDEFINED ) { sym = MakeComm( token, sym, size, count, isfar ); if ( sym == NULL ) return( ERROR ); } else if ( sym->state != SYM_EXTERNAL || sym->iscomm != TRUE ) { return( EmitErr( SYMBOL_REDEFINITION, sym->name ) ); } else { tmp = sym->total_size / sym->total_length; if( count != sym->total_length || size != tmp ) { return( EmitErr( NON_BENIGN_XXX_REDEFINITION, szCOMM, sym->name ) ); } } sym->isdefined = TRUE; SetMangler( sym, langtype, mangle_type ); if ( tokenarray[i].token != T_FINAL && tokenarray[i].token != T_COMMA ) { return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) ); } } 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 ); }
static ret_code HandleAltname( char *altname, struct asym *sym ) /**************************************************************/ { struct asym *symalt; if ( altname && sym->state == SYM_EXTERNAL ) { symalt = SymSearch( altname ); /* altname symbol changed? */ if ( sym->altname && sym->altname != symalt ) { return( EmitErr( SYMBOL_REDEFINITION, sym->name ) ); } if ( Parse_Pass > PASS_1 ) { if ( symalt->state == SYM_UNDEFINED ) { EmitErr( SYMBOL_NOT_DEFINED, altname ); } else if (symalt->state != SYM_INTERNAL && symalt->state != SYM_EXTERNAL ) { EmitErr( SYMBOL_TYPE_CONFLICT, altname ); } else { #if COFF_SUPPORT || ELF_SUPPORT if ( symalt->state == SYM_INTERNAL && symalt->ispublic == FALSE ) if ( Options.output_format == OFORMAT_COFF #if ELF_SUPPORT || Options.output_format == OFORMAT_ELF #endif ) { EmitErr( MUST_BE_PUBLIC_OR_EXTERNAL, altname ); } #endif if ( sym->mem_type != symalt->mem_type ) EmitErr( SYMBOL_TYPE_CONFLICT, altname ); } } else { if ( symalt ) { DebugMsg(("HandleAltname: symbol '%s' found, state=%u\n", altname, symalt->state )); if ( symalt->state != SYM_INTERNAL && symalt->state != SYM_EXTERNAL && symalt->state != SYM_UNDEFINED ) { return( EmitErr( SYMBOL_TYPE_CONFLICT, altname ) ); } } else { symalt = SymCreate( altname ); sym_add_table( &SymTables[TAB_UNDEF], (struct dsym *)symalt ); } /* make sure the alt symbol becomes strong if it is an external * v2.11: don't do this for OMF ( maybe neither for COFF/ELF? ) */ if ( Options.output_format != OFORMAT_OMF ) symalt->used = TRUE; /* symbol inserted in the "weak external" queue? * currently needed for OMF only. */ if ( sym->altname == NULL ) { sym->altname = symalt; #if 0 /* v2.11: removed. Member nextext wasn't free to use */ DebugMsg1(("HandleAltname: symbol '%s' added to AltQueue\n", sym->name )); ((struct dsym *)sym)->nextext = NULL; if ( ModuleInfo.g.AltQueue.head == NULL ) ModuleInfo.g.AltQueue.head = ModuleInfo.g.AltQueue.tail = (struct dsym *)sym; else { ((struct dsym *)ModuleInfo.g.AltQueue.tail)->nextext = (struct dsym *)sym; ModuleInfo.g.AltQueue.tail = (struct dsym *)sym; } #endif } } } return( NOT_ERROR ); }
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 SetCPU( enum cpu_info newcpu ) /*************************************/ { int temp; DebugMsg1(("SetCPU(%X) enter\n", newcpu )); if ( newcpu == P_86 || ( newcpu & P_CPU_MASK ) ) { /* reset CPU and EXT bits */ ModuleInfo.curr_cpu &= ~( P_CPU_MASK | P_EXT_MASK | P_PM ); /* set CPU bits */ ModuleInfo.curr_cpu |= newcpu & ( P_CPU_MASK | P_PM ); /* set default FPU bits if nothing is given and .NO87 not active */ if ( (ModuleInfo.curr_cpu & P_FPU_MASK) != P_NO87 && ( newcpu & P_FPU_MASK ) == 0 ) { ModuleInfo.curr_cpu &= ~P_FPU_MASK; if ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_286 ) ModuleInfo.curr_cpu |= P_87; else if ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_386 ) ModuleInfo.curr_cpu |= P_287; else ModuleInfo.curr_cpu |= P_387; } } if( newcpu & P_FPU_MASK ) { ModuleInfo.curr_cpu &= ~P_FPU_MASK; ModuleInfo.curr_cpu |= (newcpu & P_FPU_MASK); } #if AMD64_SUPPORT /* enable MMX, K3D, SSEx for 64bit cpus */ if ( ( newcpu & P_CPU_MASK ) == P_64 ) ModuleInfo.curr_cpu |= P_EXT_ALL; #endif if( newcpu & P_EXT_MASK ) { ModuleInfo.curr_cpu &= ~P_EXT_MASK; ModuleInfo.curr_cpu |= (newcpu & P_EXT_MASK); } /* set the Masm compatible @Cpu value */ temp = ModuleInfo.curr_cpu & P_CPU_MASK; switch ( temp ) { case P_186: ModuleInfo.cpu = M_8086 | M_186; break; case P_286: ModuleInfo.cpu = M_8086 | M_186 | M_286; break; case P_386: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386; break; case P_486: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386 | M_486; break; case P_586: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386 | M_486 | M_586; break; /* Masm's .686 directive doesn't set the Pentium flag! A bug? */ //case P_686: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386 | M_486 | M_586 | M_686; break; #if AMD64_SUPPORT case P_64: #endif case P_686: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386 | M_486 | M_686; break; default: ModuleInfo.cpu = M_8086; break; } if ( ModuleInfo.curr_cpu & P_PM ) ModuleInfo.cpu = ModuleInfo.cpu | M_PROT; temp = ModuleInfo.curr_cpu & P_FPU_MASK; switch (temp) { case P_87: ModuleInfo.cpu = ModuleInfo.cpu | M_8087; break; case P_287: ModuleInfo.cpu = ModuleInfo.cpu | M_8087 | M_287; break; case P_387: ModuleInfo.cpu = ModuleInfo.cpu | M_8087 | M_287 | M_387; break; } DebugMsg1(("SetCPU: ModuleInfo.curr_cpu=%X, @Cpu=%X\n", ModuleInfo.curr_cpu, ModuleInfo.cpu )); //MakeCPUConstant( newcpu ); if ( ModuleInfo.model == MODEL_NONE ) #if AMD64_SUPPORT if ( ( ModuleInfo.curr_cpu & P_CPU_MASK) >= P_64 ) { SetDefaultOfssize( USE64 ); } else #endif SetDefaultOfssize( ((ModuleInfo.curr_cpu & P_CPU_MASK) >= P_386) ? USE32 : USE16 ); /* Set @Cpu */ /* differs from Codeinfo cpu setting */ sym_Cpu = CreateVariable( "@Cpu", ModuleInfo.cpu ); return( NOT_ERROR ); }
void AddPublicData( struct asym *sym ) /************************************/ { DebugMsg1(("AddPublicData(%s)\n", sym->name )); QAddItem( &ModuleInfo.g.PubQueue, sym ); }
void LstWrite( enum lsttype type, uint_32 oldofs, void *value ) /*************************************************************/ { uint_32 newofs; struct asym *sym = value; int len; int len2; int idx; int srcfile; char *p1; char *p2; char *pSrcline; struct lstleft *pll; struct lstleft ll; //char buffer2[MAX_LINE_LEN]; /* stores text macro value */ if ( ModuleInfo.list == FALSE || CurrFile[LST] == NULL || ( ModuleInfo.line_flags & LOF_LISTED ) ) return; if ( ModuleInfo.GeneratedCode && ( ModuleInfo.list_generated_code == FALSE ) ) return; if ( MacroLevel ) { switch ( ModuleInfo.list_macro ) { case LM_NOLISTMACRO: return; case LM_LISTMACRO: /* todo: filter certain macro lines */ break; } } ModuleInfo.line_flags |= LOF_LISTED; DebugMsg1(("LstWrite( %u, %" I32_SPEC "u ): enter [ pos=%" I32_SPEC "u, GeneratedCode=%u, MacroLevel=%u ]\n", type, oldofs, list_pos, ModuleInfo.GeneratedCode, MacroLevel )); pSrcline = CurrSource; #if FASTPASS if ( ( Parse_Pass > PASS_1 ) && UseSavedState ) { if ( ModuleInfo.GeneratedCode == 0 ) { if ( !( ModuleInfo.line_flags & LOF_SKIPPOS ) ) list_pos = LineStoreCurr->list_pos; #if USELSLINE /* either use CurrSource + CurrComment or LineStoreCurr->line (see assemble.c, OnePass() */ pSrcline = LineStoreCurr->line; if ( ModuleInfo.CurrComment ) { /* if comment was removed, readd it! */ *( LineStoreCurr->line + strlen( LineStoreCurr->line ) ) = ';'; ModuleInfo.CurrComment = NULL; } #endif DebugMsg1(("LstWrite: Pass=%u, stored pos=%" I32_SPEC "u\n", Parse_Pass+1, list_pos )); } fseek( CurrFile[LST], list_pos, SEEK_SET ); } #endif ll.next = NULL; memset( ll.buffer, ' ', sizeof( ll.buffer ) ); srcfile = get_curr_srcfile(); switch ( type ) { case LSTTYPE_DATA: if ( Parse_Pass == PASS_1 && Options.first_pass_listing == FALSE ) { break; } /* no break */ case LSTTYPE_CODE: newofs = GetCurrOffset(); sprintf( ll.buffer, "%08" I32_SPEC "X", oldofs ); ll.buffer[OFSSIZE] = ' '; if ( CurrSeg == NULL ) break; //if ( write_to_file == FALSE ) if ( Options.first_pass_listing ) { if ( Parse_Pass > PASS_1 ) break; #ifdef DEBUG_OUT } else if ( Options.max_passes == 1 ) { ; /* write a listing in pass 1 */ #endif } else if ( Parse_Pass == PASS_1 ) /* changed v1.96 */ break; len = CODEBYTES; p2 = ll.buffer + OFSSIZE + 2; if ( CurrSeg->e.seginfo->CodeBuffer == NULL || CurrSeg->e.seginfo->written == FALSE ) { while ( oldofs < newofs && len ) { *p2++ = '0'; *p2++ = '0'; oldofs++; len--; } break; } /* OMF hold just a small buffer for one LEDATA record */ /* if it has been flushed, use LastCodeBufSize */ idx = (CurrSeg->e.seginfo->current_loc - CurrSeg->e.seginfo->start_loc) - (newofs - oldofs); if ( Options.output_format == OFORMAT_OMF ) { /* v2.11: additional check to make the hack more robust [ test case: db 800000h dup (0) ] */ if ( ( idx+LastCodeBufSize ) < 0 ) break; /* just exit. The code bytes area will remain empty */ while ( idx < 0 && len ) { sprintf( p2, "%02X", CurrSeg->e.seginfo->CodeBuffer[idx+LastCodeBufSize] ); p2 += 2; idx++; oldofs++; len--; } } else if (idx < 0) idx = 0; while ( oldofs < newofs && len ) { sprintf( p2, "%02X", CurrSeg->e.seginfo->CodeBuffer[idx] ); p2 += 2; idx++; oldofs++; len--; } *p2 = ' '; break; case LSTTYPE_EQUATE: /* v2.10: display current offset if equate is an alias for a label in this segment */ idx = 1; if ( sym->segment && sym->segment == &CurrSeg->sym ) { sprintf( ll.buffer, "%08" I32_SPEC "X", GetCurrOffset() ); idx = 10; } ll.buffer[idx] = '='; #if AMD64_SUPPORT if ( sym->value3264 != 0 && ( sym->value3264 != -1 || sym->value >= 0 ) ) sprintf( &ll.buffer[idx+2], "%-" PREFFMTSTR I64_SPEC "X", (uint_64)sym->value + ( (uint_64)sym->value3264 << 32 ) ); else #endif sprintf( &ll.buffer[idx+2], "%-" PREFFMTSTR I32_SPEC "X", sym->value ); ll.buffer[28] = ' '; break; case LSTTYPE_TMACRO: ll.buffer[1] = '='; //GetLiteralValue( buffer2, sym->string_ptr ); //strcpy( buffer2, sym->string_ptr ); for ( p1 = sym->string_ptr, p2 = &ll.buffer[3], pll = ≪ *p1; ) { if ( p2 >= &pll->buffer[28] ) { struct lstleft *next = myalloca( sizeof( struct lstleft ) ); pll->next = next; pll = next; pll->next = NULL; memset( pll->buffer, ' ', sizeof( pll->buffer) ); p2 = &pll->buffer[3]; } *p2++ = *p1++; } break; case LSTTYPE_MACROLINE: ll.buffer[1] = '>'; pSrcline = value; break; case LSTTYPE_LABEL: oldofs = GetCurrOffset(); /* no break */ case LSTTYPE_STRUCT: sprintf( ll.buffer, "%08" I32_SPEC "X", oldofs ); ll.buffer[8] = ' '; break; case LSTTYPE_DIRECTIVE: if ( CurrSeg || value ) { sprintf( ll.buffer, "%08" I32_SPEC "X", oldofs ); ll.buffer[8] = ' '; } break; default: /* LSTTYPE_MACRO */ if ( *pSrcline == NULLC && ModuleInfo.CurrComment == NULL && srcfile == ModuleInfo.srcfile ) { DebugMsg1(("LstWrite: type=%u, writing CRLF\n", type )); fwrite( NLSTR, 1, NLSIZ, CurrFile[LST] ); list_pos += NLSIZ; return; } break; } #if FASTPASS if ( Parse_Pass == PASS_1 || UseSavedState == FALSE ) { #endif idx = sizeof( ll.buffer ); if ( ModuleInfo.GeneratedCode ) ll.buffer[28] = '*'; if ( MacroLevel ) { len = sprintf( &ll.buffer[29], "%u", MacroLevel ); ll.buffer[29+len] = ' '; } if ( srcfile != ModuleInfo.srcfile ) { ll.buffer[30] = 'C'; } #ifdef DEBUG_OUT ll.last = NULLC; #endif #if FASTPASS } else { idx = OFSSIZE + 2 + 2 * CODEBYTES; #ifdef DEBUG_OUT ll.buffer[idx] = NULLC; #endif } #endif fwrite( ll.buffer, 1, idx, CurrFile[LST] ); len = strlen( pSrcline ); len2 = ( ModuleInfo.CurrComment ? strlen( ModuleInfo.CurrComment ) : 0 ); list_pos += sizeof( ll.buffer ) + len + len2 + NLSIZ; DebugMsg1(("LstWrite: writing (%u b) >%s< [%u/%u], new pos=%" I32_SPEC "u\n", idx, ll.buffer, len, len2, list_pos )); /* write source and comment part */ #if FASTPASS if ( Parse_Pass == PASS_1 || UseSavedState == FALSE ) { #endif if ( len ) fwrite( pSrcline, 1, len, CurrFile[LST] ); if ( len2 ) { fwrite( ModuleInfo.CurrComment, 1, len2, CurrFile[LST] ); DebugMsg1(("LstWrite: writing (%u b) >%s%s<\n", len + len2 + NLSIZ, pSrcline, ModuleInfo.CurrComment )); } #ifdef DEBUG_OUT else DebugMsg1(("LstWrite: writing (%u b) >%s<\n", len + NLSIZ, pSrcline )); #endif fwrite( NLSTR, 1, NLSIZ, CurrFile[LST] ); #if FASTPASS } #endif /* write optional additional lines. * currently works in pass one only. */ for ( pll = ll.next; pll; pll = pll->next ) { fwrite( pll->buffer, 1, 32, CurrFile[LST] ); fwrite( NLSTR, 1, NLSIZ, CurrFile[LST] ); list_pos += 32 + NLSIZ; DebugMsg1(("LstWrite: additional line >%s<, new pos=%" I32_SPEC "u\n", pll->buffer, list_pos )); } return; }
ret_code PublicDirective( int i, struct asm_tok tokenarray[] ) /************************************************************/ { #if MANGLERSUPP char *mangle_type = NULL; #endif char *token; struct asym *sym; //struct dsym *dir; char skipitem; enum lang_type langtype; DebugMsg1(("PublicDirective(%u) enter\n", i)); i++; /* skip PUBLIC directive */ #if MANGLERSUPP mangle_type = Check4Mangler( &i, tokenarray ); #endif do { /* read the optional language type */ langtype = ModuleInfo.langtype; GetLangType( &i, tokenarray, &langtype ); if ( tokenarray[i].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } /* get the symbol name */ token = tokenarray[i++].string_ptr; DebugMsg1(("PublicDirective: sym=%s\n", token )); /* Add the public name */ sym = SymSearch( token ); if ( Parse_Pass == PASS_1 ) { if ( sym == NULL ) { if ( sym = SymCreate( token ) ) { sym_add_table( &SymTables[TAB_UNDEF], (struct dsym *)sym ); DebugMsg1(("PublicDirective(%s): new symbol\n", sym->name )); } else return( ERROR ); /* name was too long */ } skipitem = FALSE; } else { if ( sym == NULL || sym->state == SYM_UNDEFINED ) { EmitErr( SYMBOL_NOT_DEFINED, token ); //return( ERROR ); /* v2.04: dont exit */ } } if ( sym ) { switch ( sym->state ) { case SYM_UNDEFINED: break; case SYM_INTERNAL: if ( sym->scoped == TRUE ) { EmitErr( CANNOT_DECLARE_SCOPED_CODE_LABEL_AS_PUBLIC, sym->name ); skipitem = TRUE; //return( ERROR ); } break; case SYM_EXTERNAL: if ( sym->iscomm == TRUE ) { EmitErr( CANNOT_DEFINE_AS_PUBLIC_OR_EXTERNAL, sym->name ); skipitem = TRUE; //return( ERROR ); } else if ( sym->weak == FALSE ) { /* for EXTERNs, emit a different error msg */ EmitErr( SYMBOL_REDEFINITION, sym->name ); skipitem = TRUE; //return( ERROR ); } break; default: EmitErr( CANNOT_DEFINE_AS_PUBLIC_OR_EXTERNAL, sym->name ); skipitem = TRUE; //return( ERROR ); } if( Parse_Pass == PASS_1 && skipitem == FALSE ) { if ( sym->ispublic == FALSE ) { sym->ispublic = TRUE; AddPublicData( sym ); /* put it into the public table */ } SetMangler( sym, langtype, mangle_type ); } } if ( tokenarray[i].token != T_FINAL ) if ( tokenarray[i].token == T_COMMA ) { if ( (i + 1) < Token_Count ) i++; } else { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ) ); } } while ( i < Token_Count ); return( NOT_ERROR ); }
/* set memory model, called by ModelDirective() * also set predefined symbols: * - @CodeSize (numeric) * - @code (text) * - @DataSize (numeric) * - @data (text) * - @stack (text) * - @Model (numeric) * - @Interface (numeric) * inactive: * - @fardata (text) * - @fardata? (text) * Win64 only: * - @ReservedStack (numeric) */ static void SetModel( void ) /**************************/ { int value; const char *textvalue; //struct asym *sym; DebugMsg1(("SetModel() enter (model=%u)\n", ModuleInfo.model )); /* if model is set, it disables OT_SEGMENT of -Zm switch */ if ( ModuleInfo.model == MODEL_FLAT ) { ModuleInfo.offsettype = OT_FLAT; #if AMD64_SUPPORT SetDefaultOfssize( ((ModuleInfo.curr_cpu & P_CPU_MASK) >= P_64 ) ? USE64 : USE32 ); #else SetDefaultOfssize( USE32 ); #endif } else ModuleInfo.offsettype = OT_GROUP; NewLineQueue(); ModelSimSegmInit( ModuleInfo.model ); /* create segments in first pass */ ModelAssumeInit(); if ( ModuleInfo.list ) LstWriteSrcLine(); RunLineQueue(); if ( Parse_Pass != PASS_1 ) return; /* Set @CodeSize */ if ( SIZE_CODEPTR & ( 1 << ModuleInfo.model ) ) { value = 1; /* v2.06: SimpleType[] is obsolete */ //SimpleType[ST_PROC].mem_type = MT_FAR; } else { value = 0; // SimpleType[ST_PROC].mem_type = MT_NEAR; /* this is default */ } sym_CodeSize = AddPredefinedConstant( "@CodeSize", value ); AddPredefinedText( "@code", SimGetSegName( SIM_CODE ) ); /* Set @DataSize */ switch( ModuleInfo.model ) { case MODEL_COMPACT: case MODEL_LARGE: value = 1; break; case MODEL_HUGE: value = 2; break; default: value = 0; break; } sym_DataSize = AddPredefinedConstant( "@DataSize", value ); textvalue = ( ModuleInfo.model == MODEL_FLAT ? "FLAT" : szDgroup ); AddPredefinedText( "@data", textvalue ); if ( ModuleInfo.distance == STACK_FAR ) textvalue = "STACK"; AddPredefinedText( "@stack", textvalue ); #if 0 AddPredefinedText( "@fardata", ( ModuleInfo.model == MODEL_FLAT ? "FLAT" : SimGetSegName( SIM_FARDATA ) ) ); AddPredefinedText( "@fardata?", ( ModuleInfo.model == MODEL_FLAT ? "FLAT" : SimGetSegName( SIM_FARDATA_UN ) ) ); #endif /* Set @Model and @Interface */ sym_Model = AddPredefinedConstant( "@Model", ModuleInfo.model ); sym_Interface = AddPredefinedConstant( "@Interface", ModuleInfo.langtype ); #if AMD64_SUPPORT if ( ModuleInfo.defOfssize == USE64 && ModuleInfo.fctype == FCT_WIN64 ) { ReservedStack.mem_type = MT_EMPTY; ReservedStack.state = SYM_INTERNAL; ReservedStack.isdefined = TRUE; ReservedStack.predefined = TRUE; #if FASTMEM==0 ReservedStack.staticmem = TRUE; #endif ReservedStack.variable = TRUE; ReservedStack.name_size = 14; /* sizeof( "@ReservedStack" ) */ SymAddGlobal( &ReservedStack ); } #endif }
/* PreprocessLine() is the "preprocessor". * 1. the line is tokenized with Tokenize(), Token_Count set * 2. (text) macros are expanded by ExpandLine() * 3. "preprocessor" directives are executed */ int PreprocessLine( char *line, struct asm_tok tokenarray[] ) /***********************************************************/ { int i; /* v2.11: GetTextLine() removed - this is now done in ProcessFile() */ /* v2.08: moved here from GetTextLine() */ ModuleInfo.CurrComment = NULL; /* v2.06: moved here from Tokenize() */ ModuleInfo.line_flags = 0; /* Token_Count is the number of tokens scanned */ Token_Count = Tokenize( line, 0, tokenarray, TOK_DEFAULT ); #ifdef DEBUG_OUT cntppl0++; if ( ModuleInfo.GeneratedCode ) DebugMsg1(("PreprocessLine: >%s<\n", line )); else DebugMsg1(("PreprocessLine(%s): >%s< cmt=%s\n", GetTopSrcName(), line, ModuleInfo.CurrComment ? ModuleInfo.CurrComment : "" )); #endif #if REMOVECOMENT == 0 if ( Token_Count == 0 && ( CurrIfState == BLOCK_ACTIVE || ModuleInfo.listif ) ) LstWriteSrcLine(); #endif if ( Token_Count == 0 ) return( 0 ); #ifdef DEBUG_OUT /* option -np, skip preprocessor? */ if ( Options.skip_preprocessor ) return( Token_Count ); #endif /* CurrIfState != BLOCK_ACTIVE && Token_Count == 1 | 3 may happen * if a conditional assembly directive has been detected by Tokenize(). * However, it's important NOT to expand then */ if ( CurrIfState == BLOCK_ACTIVE ) { if ( ( tokenarray[Token_Count].bytval & TF3_EXPANSION ? ExpandText( line, tokenarray, TRUE ) : ExpandLine( line, tokenarray ) ) < NOT_ERROR ) return( 0 ); } DebugCmd( cntppl1++ ); i = 0; if ( Token_Count > 2 && ( tokenarray[1].token == T_COLON || tokenarray[1].token == T_DBL_COLON ) ) i = 2; /* handle "preprocessor" directives: * IF, ELSE, ENDIF, ... * FOR, REPEAT, WHILE, ... * PURGE * INCLUDE * since v2.05, error directives are no longer handled here! */ if ( tokenarray[i].token == T_DIRECTIVE && tokenarray[i].dirtype <= DRT_INCLUDE ) { /* if i != 0, then a code label is located before the directive */ if ( i > 1 ) { if ( ERROR == WriteCodeLabel( line, tokenarray ) ) return( 0 ); } directive_tab[tokenarray[i].dirtype]( i, tokenarray ); return( 0 ); } /* handle preprocessor directives which need a label */ if ( tokenarray[0].token == T_ID && tokenarray[1].token == T_DIRECTIVE ) { struct asym *sym; switch ( tokenarray[1].dirtype ) { case DRT_EQU: /* * EQU is a special case: * If an EQU directive defines a text equate * it MUST be handled HERE and 0 must be returned to the caller. * This will prevent further processing, nothing will be stored * if FASTPASS is on. * Since one cannot decide whether EQU defines a text equate or * a number before it has scanned its argument, we'll have to * handle it in ANY case and if it defines a number, the line * must be stored and, if -EP is set, written to stdout. */ if ( sym = CreateConstant( tokenarray ) ) { if ( sym->state != SYM_TMACRO ) { #if FASTPASS if ( StoreState ) FStoreLine( 0 ); #endif if ( Options.preprocessor_stdout == TRUE ) WritePreprocessedLine( line ); } /* v2.03: LstWrite() must be called AFTER StoreLine()! */ if ( ModuleInfo.list == TRUE ) { LstWrite( sym->state == SYM_INTERNAL ? LSTTYPE_EQUATE : LSTTYPE_TMACRO, 0, sym ); } } return( 0 ); case DRT_MACRO: case DRT_CATSTR: /* CATSTR + TEXTEQU directives */ case DRT_SUBSTR: directive_tab[tokenarray[1].dirtype]( 1, tokenarray ); return( 0 ); } } DebugCmd( cntppl2++ ); return( Token_Count ); }
/* handle .model directive * syntax: .MODEL <FLAT|TINY|SMALL...> [,<C|PASCAL|STDCALL...>][,<NEARSTACK|FARSTACK>][,<OS_DOS|OS_OS2>] * sets fields * - ModuleInfo.model * - ModuleInfo.language * - ModuleInfo.distance * - ModuleInfo.ostype * if model is FLAT, defines FLAT pseudo-group * set default segment names for code and data */ ret_code ModelDirective( int i, struct asm_tok tokenarray[] ) /***********************************************************/ { enum model_type model; enum lang_type language; enum dist_type distance; enum os_type ostype; int index; uint_8 init; uint_8 initv; DebugMsg1(("ModelDirective enter\n")); /* v2.03: it may occur that "code" is defined BEFORE the MODEL * directive (i.e. DB directives in AT-segments). For FASTPASS, * this may have caused errors because contents of the ModuleInfo * structure was saved before the .MODEL directive. */ //if( Parse_Pass != PASS_1 ) { if( Parse_Pass != PASS_1 && ModuleInfo.model != MODEL_NONE ) { /* just set the model with SetModel() if pass is != 1. * This won't set the language ( which can be modified by * OPTION LANGUAGE directive ), but the language in ModuleInfo * isn't needed anymore once pass one is done. */ SetModel(); return( NOT_ERROR ); } i++; if ( tokenarray[i].token == T_FINAL ) { EmitError( EXPECTED_MEMORY_MODEL ); return( ERROR ); } /* get the model argument */ index = FindToken( tokenarray[i].string_ptr, ModelToken, sizeof( ModelToken )/sizeof( ModelToken[0] ) ); if( index >= 0 ) { if( ModuleInfo.model != MODEL_NONE ) { EmitWarn( 2, MODEL_DECLARED_ALREADY ); return( NOT_ERROR ); } model = index + 1; i++; } else { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( ERROR ); } /* get the optional arguments: language, stack distance, os */ init = 0; while ( i < ( Token_Count - 1 ) && tokenarray[i].token == T_COMMA ) { i++; if ( tokenarray[i].token != T_COMMA ) { if ( GetLangType( &i, tokenarray, &language ) == NOT_ERROR ) { initv = INIT_LANG; } else { index = FindToken( tokenarray[i].string_ptr, ModelAttr, sizeof( ModelAttr )/sizeof( ModelAttr[0] ) ); if ( index < 0 ) break; initv = ModelAttrValue[index].init; switch ( initv ) { case INIT_STACK: if ( model == MODEL_FLAT ) { EmitError( INVALID_MODEL_PARAM_FOR_FLAT ); return( ERROR ); } distance = ModelAttrValue[index].value; break; case INIT_OS: ostype = ModelAttrValue[index].value; break; } i++; } /* attribute set already? */ if ( initv & init ) { i--; break; } init |= initv; } } /* everything parsed successfully? */ if ( tokenarray[i].token != T_FINAL ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ); return( ERROR ); } if ( model == MODEL_FLAT ) { if ( ( ModuleInfo.curr_cpu & P_CPU_MASK) < P_386 ) { EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE ); return( ERROR ); } DefineFlatGroup(); } ModuleInfo.model = model; if ( init & INIT_LANG ) { ModuleInfo.langtype = language; #if AMD64_SUPPORT /* v2.03: set header and fastcall type to win64 if x64 is active. * This is rather hackish, but currently there's no other possibility * to enable the win64 ABI from the source. */ if ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) == P_64 ) if ( language == LANG_FASTCALL && model == MODEL_FLAT && Options.output_format != OFORMAT_ELF ) { DebugMsg(("ModelDirective: FASTCALL type set to WIN64\n")); ModuleInfo.header_format = HFORMAT_WIN64; ModuleInfo.fctype = FCT_WIN64; } #endif } if ( init & INIT_STACK ) ModuleInfo.distance = distance; if ( init & INIT_OS ) ModuleInfo.ostype = ostype; SetModelDefaultSegNames(); SetModel(); return( NOT_ERROR ); }