void SetModelDefaultSegNames( void ) /**********************************/ { /* init segment names with default values */ memcpy( SegmNames, SegmNamesDef, sizeof(SegmNames) ); /* option -nt set? */ if( Options.names[OPTN_TEXT_SEG] ) { SegmNames[SIM_CODE] = LclAlloc( strlen( Options.names[OPTN_TEXT_SEG] ) + 1 ); strcpy( SegmNames[SIM_CODE], Options.names[OPTN_TEXT_SEG] ); } else { if ( SIZE_CODEPTR & ( 1 << ModuleInfo.model ) ) { /* for some models, the code segment contains the module name */ SegmNames[SIM_CODE] = LclAlloc( strlen( SegmNamesDef[SIM_CODE] ) + strlen( ModuleInfo.name ) + 1 ); strcpy( SegmNames[SIM_CODE], ModuleInfo.name ); strcat( SegmNames[SIM_CODE], SegmNamesDef[SIM_CODE] ); } } /* option -nd set? */ if ( Options.names[OPTN_DATA_SEG] ) { SegmNames[SIM_DATA] = LclAlloc( strlen( Options.names[OPTN_DATA_SEG] ) + 1 ); strcpy( SegmNames[SIM_DATA], Options.names[OPTN_DATA_SEG] ); } return; }
static struct dsym *CreateSegment( struct dsym *seg, const char *name, bool add_global ) /**************************************************************************************/ { if ( seg == NULL ) seg = ( add_global ? (struct dsym *)SymCreate( name ) : (struct dsym *)SymAlloc( name ) ); else if ( seg->sym.state == SYM_UNDEFINED ) sym_remove_table( &SymTables[TAB_UNDEF], seg ); if ( seg ) { seg->sym.state = SYM_SEG; seg->e.seginfo = LclAlloc( sizeof( struct seg_info ) ); memset( seg->e.seginfo, 0, sizeof( struct seg_info ) ); seg->e.seginfo->Ofssize = ModuleInfo.defOfssize; seg->e.seginfo->alignment = 4; /* this is PARA (2^4) */ seg->e.seginfo->combine = COMB_INVALID; /* null class name, in case none is mentioned */ seg->e.seginfo->class_name_idx = 1; seg->next = NULL; /* don't use sym_add_table(). Thus the "prev" member * becomes free for another use. */ if ( SymTables[TAB_SEG].head == NULL ) SymTables[TAB_SEG].head = SymTables[TAB_SEG].tail = seg; else { SymTables[TAB_SEG].tail->next = seg; SymTables[TAB_SEG].tail = seg; } } return( seg ); }
static struct dsym *CreateGroup( const char *name ) /*************************************************/ { struct dsym *grp; grp = (struct dsym *)SymSearch( name ); if( grp == NULL || grp->sym.state == SYM_UNDEFINED ) { if ( grp == NULL ) grp = (struct dsym *)SymCreate( name ); else sym_remove_table( &SymTables[TAB_UNDEF], grp ); grp->sym.state = SYM_GRP; grp->e.grpinfo = LclAlloc( sizeof( struct grp_info ) ); grp->e.grpinfo->seglist = NULL; //grp->e.grpinfo->grp_idx = 0; //grp->e.grpinfo->lname_idx = 0; grp->e.grpinfo->numseg = 0; sym_add_table( &SymTables[TAB_GRP], grp ); grp->sym.list = TRUE; grp->e.grpinfo->grp_idx = ++grpdefidx; grp->e.grpinfo->lname_idx = ++LnamesIdx; AddLnameData( &grp->sym ); } else if( grp->sym.state != SYM_GRP ) { EmitErr( SYMBOL_REDEFINITION, name ); return( NULL ); } grp->sym.isdefined = TRUE; return( grp ); }
void InputInit( void ) /********************/ { struct src_item *fl; #if 0 char path[FILENAME_MAX]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; #endif DebugMsg(( "InputInit() enter\n" )); //ModuleInfo.g.cnt_fnames = 0; //ModuleInfo.g.FNames = NULL; //IncludePath = NULL; //src_stack = NULL; SrcFree = NULL; /* v2.11 */ #if FILESEQ FileSeq.head = NULL; #endif #ifdef DEBUG_OUT cntppl0 = 0; cntppl1 = 0; cntppl2 = 0; cnttok0 = 0; cnttok1 = 0; cntflines = 0; cntlines = 0; #endif /* add path of main module to the include path. * v2.12: unnecessary since v2.10, since the directory part of the * current source is added if a file is to be included; see SearchFile(). */ //_splitpath( CurrFName[ASM], drive, dir, NULL, NULL ); //if ( drive[0] || dir[0] ) { // _makepath( path, drive, dir, NULL, NULL ); // AddStringToIncludePath( path ); //} srclinebuffer = LclAlloc( SIZE_SRCLINES + SIZE_TOKENARRAY + SIZE_STRINGBUFFER ); /* the comment buffer is at the end of the source line buffer */ commentbuffer = srclinebuffer + SIZE_SRCLINES - MAX_LINE_LEN; /* behind the comment buffer is the token buffer */ ModuleInfo.tokenarray = (struct asm_tok *)( srclinebuffer + SIZE_SRCLINES ); token_stringbuf = srclinebuffer + SIZE_SRCLINES + SIZE_TOKENARRAY; #ifdef DEBUG_OUT end_tokenarray = (struct asm_tok *)token_stringbuf; end_stringbuf = token_stringbuf + SIZE_STRINGBUFFER; DebugMsg(( "InputInit: srclinebuffer=%p, tokenarray=%p, token_stringbuf=%p end_stringbuf=%p\n", srclinebuffer, ModuleInfo.tokenarray, token_stringbuf, end_stringbuf )); #endif fl = PushSrcItem( SIT_FILE, CurrFile[ASM] ); fl->srcfile = ModuleInfo.srcfile = AddFile( CurrFName[ASM] ); /* setting a function pointer won't work for text macros! */ //FileCur->sfunc_ptr = &GetFileCur; FileCur->string_ptr = GetFName( fl->srcfile )->fname; DebugMsg(( "InputInit() exit\n" )); }
void AddFileSeq( unsigned file ) /******************************/ { struct file_seq *node; node = LclAlloc( sizeof( struct file_seq ) ); node->next = NULL; node->file = file; if ( FileSeq.head == NULL ) FileSeq.head = FileSeq.tail = node; else { ((struct file_seq *)FileSeq.tail)->next = node; FileSeq.tail = node; } }
/* push a new item onto the source stack. * type: SIT_FILE or SIT_MACRO */ static struct src_item *PushSrcItem( char type, void *pv ) /********************************************************/ { struct src_item *curr; if ( SrcFree ) { curr = SrcFree; SrcFree = curr->next; } else curr = LclAlloc( sizeof( struct src_item ) ); curr->next = src_stack; src_stack = curr; curr->type = type; curr->content = pv; curr->line_num = 0; return( curr ); }
static uint_8 *checkflush( struct dsym *seg, uint_8 *buffer, uint_8 *curr, int size ) /***********************************************************************************/ { #if COFF_SUPPORT uint_8 *p; #endif if ( ( curr - buffer ) && ( ( curr - buffer ) + size ) > ( 1024 - 8 ) ) { switch ( Options.output_format ) { #if COFF_SUPPORT case OFORMAT_COFF: p = LclAlloc( (curr - buffer) + sizeof( struct qditem ) ); ((struct qditem *)p)->next = NULL; ((struct qditem *)p)->size = curr - buffer; memcpy( p + sizeof( struct qditem ), buffer, curr - buffer ); if ( seg->sym.name[7] == 'S' ) { /* .debug$S or .debug$T ? */ if ( DebugS.head == NULL ) DebugS.head = DebugS.tail = p; else { ((struct qditem *)(DebugS.tail))->next = p; DebugS.tail = p; } } else { if ( DebugT.head == NULL ) DebugT.head = DebugT.tail = p; else { ((struct qditem *)(DebugT.tail))->next = p; DebugT.tail = p; } } seg->e.seginfo->current_loc = seg->e.seginfo->start_loc + ( curr - buffer ); seg->e.seginfo->start_loc = seg->e.seginfo->current_loc; break; #endif case OFORMAT_OMF: seg->e.seginfo->current_loc = seg->e.seginfo->start_loc + ( curr - buffer ); omf_write_ledata( seg ); break; } return( buffer ); } return( curr ); }
/* 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 ); }
static void AddLinnumData( struct line_num_info *data ) /*****************************************************/ { struct qdesc *q; #if COFF_SUPPORT if ( Options.output_format == OFORMAT_COFF ) { q = (struct qdesc *)CurrSeg->e.seginfo->LinnumQueue; if ( q == NULL ) { q = LclAlloc( sizeof( struct qdesc ) ); CurrSeg->e.seginfo->LinnumQueue = q; q->head = NULL; } } else #endif q = &LinnumQueue; data->next = NULL; if ( q->head == NULL) q->head = q->tail = data; else { ((struct line_num_info *)q->tail)->next = data; q->tail = data; } }
/* * used by EQU if the value to be assigned to a symbol is text. * - sym: text macro name, may be NULL * - name: identifer ( if sym == NULL ) * - value: value of text macro ( original line, BEFORE expansion ) */ struct asym *SetTextMacro( struct asm_tok tokenarray[], struct asym *sym, const char *name, const char *value ) /*************************************************************************************************************/ { int count; //char *p; DebugCmd( equcnt++ ); if ( sym == NULL ) sym = SymCreate( name ); else if ( sym->state == SYM_UNDEFINED ) { sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym ); #if FASTPASS /* the text macro was referenced before being defined. * this is valid usage, but it requires a full second pass. * just simply deactivate the fastpass feature for this module! */ SkipSavedState(); #endif EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name ); } else if ( sym->state != SYM_TMACRO ) { EmitErr( SYMBOL_REDEFINITION, name ); return( NULL ); } sym->state = SYM_TMACRO; sym->isdefined = TRUE; if ( tokenarray[2].token == T_STRING && tokenarray[2].string_delim == '<' ) { /* the simplest case: value is a literal. define a text macro! */ /* just ONE literal is allowed */ if ( tokenarray[3].token != T_FINAL ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[3].tokpos ); return( NULL ); } value = tokenarray[2].string_ptr; count = tokenarray[2].stringlen; } else { /* * the original source is used, since the tokenizer has * deleted some information. */ //while ( isspace( *value ) ) value++; /* probably obsolete */ count = strlen( value ); /* skip trailing spaces */ for ( ; count; count-- ) if ( isspace( *( value + count - 1 ) ) == FALSE ) break; } #if FASTMEM==0 if ( sym->string_ptr ) LclFree( sym->string_ptr ); sym->string_ptr = (char *)LclAlloc( count + 1 ); #else if ( sym->total_size < ( count + 1 ) ) { LclFree( sym->string_ptr ); /* is a noop if fastmem is on */ sym->string_ptr = (char *)LclAlloc( count + 1 ); sym->total_size = count + 1; } #endif memcpy( sym->string_ptr, value, count ); *(sym->string_ptr + count) = NULLC; DebugMsg1(( "SetTextMacro(%s): value is >%s<, exit\n", sym->name, sym->string_ptr )); return( sym ); }
ret_code GrpDir( int i, struct asm_tok tokenarray[] ) /***************************************************/ { char *name; struct dsym *grp; struct dsym *seg; /* GROUP directive must be at pos 1, needs a name at pos 0 */ if( i != 1 ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( ERROR ); } #if COFF_SUPPORT || ELF_SUPPORT /* GROUP valid for OMF + BIN only */ if ( Options.output_format == OFORMAT_COFF #if ELF_SUPPORT || Options.output_format == OFORMAT_ELF #endif ) { EmitError( GROUP_DIRECTIVE_INVALID_FOR_COFF ); return( ERROR ); } #endif grp = CreateGroup( tokenarray[0].string_ptr ); if( grp == NULL ) return( ERROR ); i++; /* go past GROUP */ do { /* get segment name */ if ( tokenarray[i].token != T_ID ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( ERROR ); } name = tokenarray[i].string_ptr; i++; seg = (struct dsym *)SymSearch( name ); if ( Parse_Pass == PASS_1 ) { if( seg == NULL || seg->sym.state == SYM_UNDEFINED ) { seg = CreateSegment( seg, name, TRUE ); /* inherit the offset magnitude from the group */ if ( grp->e.grpinfo->seglist ) seg->e.seginfo->Ofssize = grp->sym.Ofssize; } else if( seg->sym.state != SYM_SEG ) { EmitErr( SEGMENT_EXPECTED, name ); return( ERROR ); } else if( seg->e.seginfo->group != NULL && seg->e.seginfo->group != &grp->sym ) { /* segment is in another group */ DebugMsg(("GrpDir: segment >%s< is in group >%s< already\n", name, seg->e.seginfo->group->name)); EmitErr( SEGMENT_IN_ANOTHER_GROUP, name ); return( ERROR ); } /* the first segment will define the group's word size */ if( grp->e.grpinfo->seglist == NULL ) { grp->sym.Ofssize = seg->e.seginfo->Ofssize; } else if ( grp->sym.Ofssize != seg->e.seginfo->Ofssize ) { EmitErr( GROUP_SEGMENT_SIZE_CONFLICT, grp->sym.name, seg->sym.name ); return( ERROR ); } } else { /* v2.04: don't check the "defined" flag. It's for IFDEF only! */ //if( seg == NULL || seg->sym.state != SYM_SEG || seg->sym.defined == FALSE ) { /* v2.07: check the "segment" field instead of "defined" flag! */ //if( seg == NULL || seg->sym.state != SYM_SEG ) { if( seg == NULL || seg->sym.state != SYM_SEG || seg->sym.segment == NULL ) { EmitErr( SEG_NOT_DEFINED, name ); return( ERROR ); } } /* insert segment in group if it's not there already */ if ( seg->e.seginfo->group == NULL ) { struct seg_item *si; /* set the segment's grp */ seg->e.seginfo->group = &grp->sym; si = LclAlloc( sizeof( struct seg_item ) ); si->seg = seg; si->next = NULL; grp->e.grpinfo->numseg++; /* insert the segment at the end of linked list */ if( grp->e.grpinfo->seglist == NULL ) { grp->e.grpinfo->seglist = si; } else { struct seg_item *curr; curr = grp->e.grpinfo->seglist; while( curr->next != NULL ) { curr = curr->next; } curr->next = si; } } if ( i < Token_Count ) { if ( tokenarray[i].token != T_COMMA || tokenarray[i+1].token == T_FINAL ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ); return( ERROR ); } i++; } } while ( i < Token_Count ); return( NOT_ERROR ); }
void SegmentInit( int pass ) /**************************/ { struct dsym *curr; uint_32 i; #ifdef __I86__ char __huge *p; #else char *p; #endif //struct fixup *fix; DebugMsg(("SegmentInit(%u) enter\n", pass )); CurrSeg = NULL; stkindex = 0; if ( pass == PASS_1 ) { grpdefidx = 0; LnamesIdx = 1; /* the first Lname is a null-string */ //pCodeBuff = NULL; buffer_size = 0; //flat_grp = NULL; symPC.sfunc_ptr = &SetCurPC; symPC.mem_type = MT_NEAR; symPC.state = SYM_INTERNAL; symPC.isdefined = TRUE; symPC.predefined = TRUE; symPC.variable = TRUE; /* added v1.96. Important for fixup creation */ #if FASTMEM==0 symPC.staticmem = TRUE; #endif symPC.name_size = 1; /* sizeof("$") */ symPC.list = FALSE; /* don't display the '$' symbol in symbol list */ SymAddGlobal( &symPC ); #if 0 /* v2.03: obsolete, also belongs to simplified segment handling */ /* set ModuleInfo.code_class */ if( Options.code_class ) size = strlen( Options.code_class ) + 1; else size = 4 + 1; ModuleInfo.code_class = LclAlloc( size ); if ( Options.code_class ) strcpy( ModuleInfo.code_class, Options.code_class ); else strcpy( ModuleInfo.code_class, "CODE" ); #endif } /* * alloc a buffer for the contents */ if ( ModuleInfo.pCodeBuff == NULL && Options.output_format != OFORMAT_OMF ) { for( curr = SymTables[TAB_SEG].head, buffer_size = 0; curr; curr = curr->next ) { /* v2.04: can't happen */ //if( ( curr->sym.state != SYM_SEG ) || ( curr->sym.segment == NULL ) ) // continue; if ( curr->e.seginfo->bytes_written ) { i = curr->sym.max_offset - curr->e.seginfo->start_loc; /* the segment can grow in step 2-n due to forward references. * for a quick solution just add 25% to the size if segment * is a code segment. (v2.02: previously if was added only if * code segment contained labels, but this isn't sufficient.) */ //if ( curr->e.seginfo->labels ) /* v2.02: changed */ if ( curr->e.seginfo->segtype == SEGTYPE_CODE ) i = i + (i >> 2); DebugMsg(("SegmentInit(%u), %s: max_ofs=%" FX32 ", alloc_size=%" FX32 "h\n", pass, curr->sym.name, curr->sym.max_offset, i )); buffer_size += i; } } if ( buffer_size ) { ModuleInfo.pCodeBuff = LclAlloc( buffer_size ); DebugMsg(("SegmentInit(%u): total buffer size=%" FX32 ", start=%p\n", pass, buffer_size, ModuleInfo.pCodeBuff )); } }
/* string macro initialization * this proc is called once per module */ void StringInit( void ) /*********************/ { int i; struct dsym *macro; DebugMsg(( "StringInit() enter\n" )); #ifdef DEBUG_OUT catstrcnt = 0; substrcnt = 0; sizstrcnt = 0; instrcnt = 0; equcnt = 0; #endif /* add @CatStr() macro func */ macro = CreateMacro( "@CatStr" ); macro->sym.isdefined = TRUE; macro->sym.predefined = TRUE; macro->sym.func_ptr = CatStrFunc; macro->sym.isfunc = TRUE; /* v2.08: @CatStr() changed to VARARG */ macro->sym.mac_vararg = TRUE; macro->e.macroinfo->parmcnt = 1; macro->e.macroinfo->parmlist = LclAlloc( sizeof( struct mparm_list ) * 1 ); macro->e.macroinfo->parmlist[0].deflt = NULL; macro->e.macroinfo->parmlist[0].required = FALSE; /* add @InStr() macro func */ macro = CreateMacro( "@InStr" ); macro->sym.isdefined = TRUE; macro->sym.predefined = TRUE; macro->sym.func_ptr = InStrFunc; macro->sym.isfunc = TRUE; macro->e.macroinfo->parmcnt = 3; macro->e.macroinfo->autoexp = 1; /* param 1 (pos) is expanded */ macro->e.macroinfo->parmlist = LclAlloc(sizeof( struct mparm_list) * 3); for (i = 0; i < 3; i++) { macro->e.macroinfo->parmlist[i].deflt = NULL; //macro->e.macroinfo->parmlist[i].label = parmnames[i]; macro->e.macroinfo->parmlist[i].required = (i != 0); } /* add @SizeStr() macro func */ macro = CreateMacro( "@SizeStr" ); macro->sym.isdefined = TRUE; macro->sym.predefined = TRUE; macro->sym.func_ptr = SizeStrFunc; macro->sym.isfunc = TRUE; macro->e.macroinfo->parmcnt = 1; macro->e.macroinfo->parmlist = LclAlloc(sizeof( struct mparm_list)); macro->e.macroinfo->parmlist[0].deflt = NULL; //macro->e.macroinfo->parmlist[0].label = parmnames[0]; /* macro->e.macroinfo->parmlist[0].required = TRUE; */ /* the string parameter is NOT required, '@SizeStr()' is valid */ macro->e.macroinfo->parmlist[0].required = FALSE; /* add @SubStr() macro func */ macro = CreateMacro( "@SubStr" ); macro->sym.isdefined = TRUE; macro->sym.predefined = TRUE; macro->sym.func_ptr = SubStrFunc; macro->sym.isfunc = TRUE; macro->e.macroinfo->parmcnt = 3; macro->e.macroinfo->autoexp = 2 + 4; /* param 2 (pos) and 3 (size) are expanded */ macro->e.macroinfo->parmlist = LclAlloc(sizeof( struct mparm_list) * 3); for (i = 0; i < 3; i++) { macro->e.macroinfo->parmlist[i].deflt = NULL; //macro->e.macroinfo->parmlist[i].label = parmnames[i]; macro->e.macroinfo->parmlist[i].required = (i < 2); } return; }
ret_code CatStrDir( int i, struct asm_tok tokenarray[] ) /******************************************************/ { struct asym *sym; int count; char *p; /* struct expr opndx; */ DebugMsg1(("CatStrDir(%u) enter\n", i )); DebugCmd( catstrcnt++ ); #if 0 /* can't happen */ /* syntax must be <id> CATSTR textitem[,textitem,...] */ if ( i != 1 ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } #endif i++; /* go past CATSTR/TEXTEQU */ /* v2.08: don't copy to temp buffer */ //*StringBufferEnd = NULLC; /* check correct syntax and length of items */ for ( count = 0; i < Token_Count; ) { DebugMsg1(("CatStrDir(%s): item[%u]=%s delim=0x%x\n", tokenarray[0].string_ptr, i, tokenarray[i].string_ptr, tokenarray[i].string_delim )); if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) { DebugMsg(("CatStrDir: error, not a <>-literal: %s\n", tokenarray[i].tokpos )); return( TextItemError( &tokenarray[i] ) ); } /* v2.08: using tokenarray.stringlen is not quite correct, since some chars * are stored in 2 bytes (!) */ if ( ( count + tokenarray[i].stringlen ) >= MAX_LINE_LEN ) { DebugMsg(("CatStrDir: error, literal too long: %u + %u >= %u\n", count, tokenarray[i].stringlen, MAX_LINE_LEN )); return( EmitError( STRING_OR_TEXT_LITERAL_TOO_LONG ) ); } /* v2.08: don't copy to temp buffer */ //strcpy( StringBufferEnd + count, tokenarray[i].string_ptr ); count = count + tokenarray[i].stringlen; i++; if ( ( tokenarray[i].token != T_COMMA ) && ( tokenarray[i].token != T_FINAL ) ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } i++; } sym = SymSearch( tokenarray[0].string_ptr ); if ( sym == NULL ) { sym = SymCreate( tokenarray[0].string_ptr ); DebugMsg1(( "CatStrDir: new symbol %s created\n", sym->name)); } else if( sym->state == SYM_UNDEFINED ) { /* v2.01: symbol has been used already. Using * a textmacro before it has been defined is * somewhat problematic. */ sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym ); #if FASTPASS SkipSavedState(); /* further passes must be FULL! */ #endif EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name ); } else if( sym->state != SYM_TMACRO ) { /* it is defined as something else, get out */ DebugMsg(( "CatStrDir(%s) exit, symbol redefinition\n", sym->name)); return( EmitErr( SYMBOL_REDEFINITION, sym->name ) ); } sym->state = SYM_TMACRO; sym->isdefined = TRUE; #if FASTMEM==0 if ( sym->string_ptr ) LclFree( sym->string_ptr ); sym->string_ptr = (char *)LclAlloc( count + 1 ); #else /* v2.08: reuse string space if fastmem is on */ if ( sym->total_size < ( count+1 ) ) { LclFree( sym->string_ptr ); /* is a noop if fastmem is on */ sym->string_ptr = (char *)LclAlloc( count + 1 ); sym->total_size = count + 1; } #endif /* v2.08: don't use temp buffer */ //memcpy( sym->string_ptr, StringBufferEnd, count + 1 ); for ( i = 2, p = sym->string_ptr; i < Token_Count; i += 2 ) { memcpy( p, tokenarray[i].string_ptr, tokenarray[i].stringlen ); p += tokenarray[i].stringlen; } *p = NULLC; DebugMsg1(("CatStrDir(%s) (new) value: >%s<\n", sym->name, sym->string_ptr )); if ( ModuleInfo.list ) LstWrite( LSTTYPE_TMACRO, 0, sym ); return( NOT_ERROR ); }
/* SubStr() * defines a text equate. * syntax: name SUBSTR <string>, pos [, size] */ ret_code SubStrDir( int i, struct asm_tok tokenarray[] ) /******************************************************/ { struct asym *sym; char *name; char *p; //char *newvalue; int pos; int size; int cnt; bool chksize; struct expr opndx; DebugMsg1(("SubStrDir enter\n")); DebugCmd( substrcnt++ ); /* at least 5 items are needed * 0 1 2 3 4 5 6 * ID SUBSTR SRC_ID , POS [, LENGTH] */ #if 0 /* can't happen */ if ( i != 1 ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } #endif name = tokenarray[0].string_ptr; i++; /* go past SUBSTR */ /* third item must be a string */ if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) { DebugMsg(("SubStrDir: error, no text item\n")); return( TextItemError( &tokenarray[i] ) ); } p = tokenarray[i].string_ptr; cnt = tokenarray[i].stringlen; i++; DebugMsg1(("SubStrDir(%s): src=>%s<\n", name, p)); if ( tokenarray[i].token != T_COMMA ) { return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) ); } i++; /* get pos, must be a numeric value and > 0 */ /* v2.11: flag NOUNDEF added - no forward ref possible */ if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) { DebugMsg(("SubStrDir(%s): invalid pos value\n", name)); return( ERROR ); } /* v2.04: "string" constant allowed as second argument */ //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) { if ( opndx.kind != EXPR_CONST ) { DebugMsg(("SubStrDir(%s): pos value is not a constant\n", name)); return( EmitError( CONSTANT_EXPECTED ) ); } /* pos is expected to be 1-based */ pos = opndx.value; if ( pos <= 0 ) { return( EmitError( POSITIVE_VALUE_EXPECTED ) ); } if ( tokenarray[i].token != T_FINAL ) { if ( tokenarray[i].token != T_COMMA ) { return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) ); } i++; /* get size, must be a constant */ /* v2.11: flag NOUNDEF added - no forward ref possible */ if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) { DebugMsg(("SubStrDir(%s): invalid size value\n", name)); return( ERROR ); } /* v2.04: string constant ok */ //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) { if ( opndx.kind != EXPR_CONST ) { DebugMsg(("SubStrDir(%s): size value is not a constant\n", name)); return( EmitError( CONSTANT_EXPECTED ) ); } size = opndx.value; if ( tokenarray[i].token != T_FINAL ) { DebugMsg(("SubStrDir(%s): additional items found\n", name)); return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } if ( size < 0 ) { return( EmitError( COUNT_MUST_BE_POSITIVE_OR_ZERO ) ); } chksize = TRUE; } else { size = -1; chksize = FALSE; } #if 0 cnt = pos; /* position p to start of substring */ for ( pos--; pos > 0 && *p ; pos--, p++ ) if ( *p == '!' && *(p+1) != NULLC ) p++; if ( *p == NULLC ) { return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, cnt ) ); } if ( *p == '!' && *(p+1) != NULLC ) p++; for ( newvalue = p, cnt = size; *p && cnt; cnt--, p++ ) if ( *p == '!' && *(p+1) != NULLC ) p++; /* v2.04: check added */ if ( chksize && cnt ) { return( EmitError( COUNT_VALUE_TOO_LARGE ) ); } size = p - newvalue; p = newvalue; #else if ( pos > cnt ) { return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) ); } if ( chksize && (pos+size-1) > cnt ) { return( EmitError( COUNT_VALUE_TOO_LARGE ) ); } p += pos - 1; if ( size == -1 ) size = cnt - pos + 1; #endif sym = SymSearch( name ); /* if we've never seen it before, put it in */ if( sym == NULL ) { sym = SymCreate( name ); } else if( sym->state == SYM_UNDEFINED ) { /* it was referenced before being defined. This is * a bad idea for preprocessor text items, because it * will require a full second pass! */ sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym ); #if FASTPASS SkipSavedState(); EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name ); #endif } else if( sym->state != SYM_TMACRO ) { /* it is defined as something incompatible, get out */ DebugMsg(( "SubStrDir(%s) error, incompatible type\n", sym->name)); return( EmitErr( SYMBOL_REDEFINITION, sym->name ) ); } sym->state = SYM_TMACRO; sym->isdefined = TRUE; #if FASTMEM==0 if ( sym->string_ptr ) LclFree( sym->string_ptr ); sym->string_ptr = (char *)LclAlloc( size + 1 ); #else if ( sym->total_size < ( size + 1 ) ) { LclFree( sym->string_ptr ); sym->string_ptr = LclAlloc ( size + 1 ); sym->total_size = size + 1; } #endif memcpy( sym->string_ptr, p, size ); *(sym->string_ptr + size) = NULLC; DebugMsg1(("SubStrDir(%s): result=>%s<\n", sym->name, sym->string_ptr )); LstWrite( LSTTYPE_TMACRO, 0, sym ); return( NOT_ERROR ); }
void AddLinnumDataRef( unsigned srcfile, uint_32 line_num ) /*********************************************************/ { struct line_num_info *curr; #if COFF_SUPPORT /* COFF line number info is related to functions/procedures. Since * assembly allows code lines outside of procs, "dummy" procs must * be generated. A dummy proc lasts until * - a true PROC is detected or * - the source file changes or * - the segment/section changes ( added in v2.11 ) */ if ( Options.output_format == OFORMAT_COFF && CurrProc == NULL && ( dmyproc == NULL || dmyproc->debuginfo->file != srcfile || dmyproc->segment != (struct asym *)CurrSeg ) ) { char procname[12]; if ( dmyproc ) { /**/myassert( dmyproc->segment ); dmyproc->total_size = ((struct dsym *)dmyproc->segment)->e.seginfo->current_loc - dmyproc->offset; } sprintf( procname, "$$$%05u", procidx ); DebugMsg1(("AddLinnumDataRef(src=%u.%u): CurrProc==NULL, dmyproc=%s searching proc=%s\n", srcfile, line_num, dmyproc ? dmyproc->name : "NULL", procname )); dmyproc = SymSearch( procname ); /* in pass 1, create the proc */ if ( dmyproc == NULL ) { dmyproc = CreateProc( NULL, procname, SYM_INTERNAL ); DebugMsg1(("AddLinnumDataRef: new proc %s created\n", procname )); dmyproc->isproc = TRUE; /* flag is usually set inside ParseProc() */ dmyproc->included = TRUE; AddPublicData( dmyproc ); } else procidx++; /* for passes > 1, adjust procidx */ /* if the symbols isn't a PROC, the symbol name has been used * by the user - bad! A warning should be displayed */ if ( dmyproc->isproc == TRUE ) { SetSymSegOfs( dmyproc ); dmyproc->Ofssize = ModuleInfo.Ofssize; dmyproc->langtype = ModuleInfo.langtype; if ( write_to_file == TRUE ) { curr = LclAlloc( sizeof( struct line_num_info ) ); curr->sym = dmyproc; curr->line_number = GetLineNumber(); curr->file = srcfile; curr->number = 0; DebugMsg1(("AddLinnumDataRef: CURRPROC=NULL, sym=%s, calling AddLinnumData(src=%u.%u)\n", curr->sym->name, curr->file, curr->line_number )); AddLinnumData( curr ); } } } #endif if( line_num && ( write_to_file == FALSE || lastLineNumber == line_num )) { #ifdef DEBUG_OUT if ( write_to_file == TRUE ) DebugMsg1(("AddLinnumDataRef(src=%u.%u) line skipped, lastline=%u\n", srcfile, line_num, lastLineNumber )); #endif return; } DebugMsg1(("AddLinnumDataRef(src=%u.%u): currofs=%Xh, CurrProc=%s, GeneratedCode=%u\n", srcfile, line_num, GetCurrOffset(), CurrProc ? CurrProc->sym.name : "NULL", ModuleInfo.GeneratedCode )); curr = LclAlloc( sizeof( struct line_num_info ) ); curr->number = line_num; #if COFF_SUPPORT if ( line_num == 0 ) { /* happens for COFF only */ /* changed v2.03 (CurrProc might have been NULL) */ /* if ( Options.output_format == OFORMAT_COFF && CurrProc->sym.public == FALSE ) { */ /* v2.09: avoid duplicates, check for pass 1 */ //if ( Options.output_format == OFORMAT_COFF && CurrProc && CurrProc->sym.public == FALSE ) { if ( Parse_Pass == PASS_1 && Options.output_format == OFORMAT_COFF && CurrProc && CurrProc->sym.ispublic == FALSE ) { CurrProc->sym.included = TRUE; AddPublicData( (struct asym *)CurrProc ); } /* changed v2.03 */ /* curr->sym = (struct asym *)CurrProc; */ curr->sym = ( CurrProc ? (struct asym *)CurrProc : dmyproc ); curr->line_number = GetLineNumber(); curr->file = srcfile; /* set the function's size! */ if ( dmyproc ) { /**/myassert( dmyproc->segment ); dmyproc->total_size = ((struct dsym *)dmyproc->segment)->e.seginfo->current_loc - dmyproc->offset; dmyproc = NULL; } /* v2.11: write a 0x7fff line item if prologue exists */ if ( CurrProc && CurrProc->e.procinfo->size_prolog ) { DebugMsg1(("AddLinnumDataRef: calling AddLinnumData(src=%u.%u) sym=%s\n", curr->file, curr->line_number, curr->sym->name )); AddLinnumData( curr ); curr = LclAlloc( sizeof( struct line_num_info ) ); curr->number = GetLineNumber(); curr->offset = GetCurrOffset(); curr->srcfile = srcfile; } } else { #endif curr->offset = GetCurrOffset(); curr->srcfile = srcfile; #if COFF_SUPPORT } #endif lastLineNumber = line_num; /* v2.11: added, improved multi source support for CV. * Also, the size of line number info could have become > 1024, * ( even > 4096, thus causing an "internal error in omfint.c" ) */ if ( Options.output_format == OFORMAT_OMF ) omf_check_flush( curr ); /* v2.10: warning if line-numbers for segments without class code! */ if ( CurrSeg->e.seginfo->linnum_init == FALSE ) { CurrSeg->e.seginfo->linnum_init = TRUE; if ( TypeFromClassName( CurrSeg, CurrSeg->e.seginfo->clsym ) != SEGTYPE_CODE ) { EmitWarn( 2, LINNUM_INFO_FOR_SEGMENT_WITHOUT_CLASS_CODE, CurrSeg->sym.name ); } } DebugMsg1(("AddLinnumDataRef: calling AddLinnumData(src=%u.%u ofs=%X)\n", curr->number == 0 ? curr->file : curr->srcfile, curr->number, curr->offset )); AddLinnumData( curr ); return; }
ret_code SafeSEHDirective( int i, struct asm_tok tokenarray[] ) /*************************************************************/ { struct asym *sym; struct qnode *node; if ( Options.output_format != OFORMAT_COFF ) { if ( Parse_Pass == PASS_1) EmitWarn( 2, DIRECTIVE_IGNORED_WITHOUT_X, "coff" ); return( NOT_ERROR ); } if ( Options.safeseh == FALSE ) { if ( Parse_Pass == PASS_1) EmitWarn( 2, DIRECTIVE_IGNORED_WITHOUT_X, "safeseh" ); return( NOT_ERROR ); } i++; if ( tokenarray[i].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } sym = SymSearch( tokenarray[i].string_ptr ); /* make sure the argument is a true PROC */ if ( sym == NULL || sym->state == SYM_UNDEFINED ) { if ( Parse_Pass != PASS_1 ) { return( EmitErr( SYMBOL_NOT_DEFINED, tokenarray[i].string_ptr ) ); } } else if ( sym->isproc == FALSE ) { return( EmitErr( SAFESEH_ARGUMENT_MUST_BE_A_PROC, tokenarray[i].string_ptr ) ); } if ( Parse_Pass == PASS_1 ) { if ( sym ) { for ( node = ModuleInfo.g.SafeSEHQueue.head; node; node = node->next ) if ( node->elmt == sym ) break; } else { sym = SymCreate( tokenarray[i].string_ptr ); node = NULL; } if ( node == NULL ) { sym->used = TRUE; /* make sure an external reference will become strong */ #if 0 /* v2.11: use QAddItem() */ node = LclAlloc( sizeof( struct qnode ) ); node->elmt = sym; node->next = NULL; if ( ModuleInfo.g.SafeSEHQueue.head == 0 ) ModuleInfo.g.SafeSEHQueue.head = ModuleInfo.g.SafeSEHQueue.tail = node; else { ((struct qnode *)ModuleInfo.g.SafeSEHQueue.tail)->next = node; ModuleInfo.g.SafeSEHQueue.tail = node; } #else QAddItem( &ModuleInfo.g.SafeSEHQueue, sym ); #endif } } i++; if ( tokenarray[i].token != T_FINAL ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } return( NOT_ERROR ); }
ret_code SegmentDir( int i, struct asm_tok tokenarray[] ) /*******************************************************/ { char is_old; char *token; int typeidx; const struct typeinfo *type; /* type of option */ int temp; int temp2; uint initstate = 0; /* flags for attribute initialization */ unsigned char oldreadonly; /* readonly value of a defined segment */ //unsigned char oldsegtype; unsigned char oldOfssize; char oldalign; char oldcombine; uint oldclassidx; uint_8 oldcharacteristics; struct dsym *dir; char *name; struct asym *sym; struct expr opndx; if ( Parse_Pass != PASS_1 ) return( SetCurrSeg( i, tokenarray ) ); if( i != 1 ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( ERROR ); } name = tokenarray[0].string_ptr; DebugMsg1(("SegmentDir(%s) enter: ModuleInfo.Ofssize=%u, num_seg=%u\n", name, ModuleInfo.Ofssize, ModuleInfo.g.num_segs )); /* See if the segment is already defined */ sym = SymSearch( name ); if( sym == NULL || sym->state == SYM_UNDEFINED ) { /* segment is not defined (yet) */ sym = (struct asym *)CreateSegment( (struct dsym *)sym, name, TRUE ); sym->list = TRUE; /* always list segments */ dir = (struct dsym *)sym; dir->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs; is_old = FALSE; /* * initialize segment with values from the one without suffix */ #if COFF_SUPPORT || ELF_SUPPORT if (Options.output_format == OFORMAT_COFF #if ELF_SUPPORT || Options.output_format == OFORMAT_ELF #endif ) { char *p; if ( p = strchr(sym->name, '$') ) { char buffer[MAX_ID_LEN+1]; struct dsym *dir2; memcpy(buffer, sym->name, p - sym->name); buffer[p - sym->name] = NULLC; if ((dir2 = (struct dsym *)SymSearch(buffer)) && dir2->sym.state == SYM_SEG) { dir->e.seginfo->readonly = dir2->e.seginfo->readonly; dir->e.seginfo->segtype = dir2->e.seginfo->segtype; dir->e.seginfo->Ofssize = dir2->e.seginfo->Ofssize; dir->e.seginfo->alignment= dir2->e.seginfo->alignment; dir->e.seginfo->characteristics = dir2->e.seginfo->characteristics; dir->e.seginfo->combine = dir2->e.seginfo->combine; dir->e.seginfo->class_name_idx = dir2->e.seginfo->class_name_idx; } } } #endif } else if ( sym->state == SYM_SEG ) { /* segment already defined */ dir = (struct dsym *)sym; is_old = TRUE; oldreadonly = dir->e.seginfo->readonly; //oldsegtype = dir->e.seginfo->segtype; oldOfssize = dir->e.seginfo->Ofssize; oldalign = dir->e.seginfo->alignment; oldcharacteristics = dir->e.seginfo->characteristics; oldcombine = dir->e.seginfo->combine; oldclassidx = dir->e.seginfo->class_name_idx; if( dir->e.seginfo->lname_idx == 0 ) { /* segment was mentioned in a group statement, but not really set up */ is_old = FALSE; /* the segment list is to be sorted. * So unlink the segment and add it at the end. */ UnlinkSeg( dir ); dir->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs; dir->next = NULL; if ( SymTables[TAB_SEG].head == NULL ) SymTables[TAB_SEG].head = SymTables[TAB_SEG].tail = dir; else { SymTables[TAB_SEG].tail->next = dir; SymTables[TAB_SEG].tail = dir; } } } else { /* symbol is different kind, error */ DebugMsg(("SegmentDir(%s): symbol redefinition\n", name )); EmitErr( SYMBOL_REDEFINITION, name ); return( ERROR ); } i++; /* go past SEGMENT */ for( ; i < Token_Count; i++ ) { token = tokenarray[i].string_ptr; DebugMsg1(("SegmentDir(%s): i=%u, string=%s token=%X\n", name, i, token, tokenarray[i].token )); if( tokenarray[i].token == T_STRING ) { /* the class name - the only token which is of type STRING */ /* string must be delimited by [double]quotes */ if ( tokenarray[i].string_delim != '"' && tokenarray[i].string_delim != '\'' ) { EmitErr( SYNTAX_ERROR_EX, token ); continue; } /* remove the quote delimiters */ token++; *(token+tokenarray[i].stringlen) = NULLC; SetSegmentClass( &dir->sym, token ); DebugMsg1(("SegmentDir(%s): class found: %s\n", name, token )); continue; } /* check the rest of segment attributes. */ typeidx = FindToken( token, SegAttrToken, sizeof( SegAttrToken )/sizeof( SegAttrToken[0] ) ); if( typeidx < 0 ) { EmitErr( UNKNOWN_SEGMENT_ATTRIBUTE, token ); continue; } type = &SegAttrValue[typeidx]; /* initstate is used to check if any field is already * initialized */ if( initstate & INIT_EXCL_MASK & type->init ) { EmitErr( SEGMENT_ATTRIBUTE_DEFINED_ALREADY, token ); continue; } else { initstate |= type->init; /* mark it initialized */ } switch ( type->init ) { case INIT_ATTR: dir->e.seginfo->readonly = TRUE; break; case INIT_ALIGN: DebugMsg1(("SegmentDir(%s): align attribute found\n", name )); dir->e.seginfo->alignment = type->value; break; case INIT_ALIGN_PARAM: DebugMsg1(("SegmentDir(%s): ALIGN() found\n", name )); if ( Options.output_format == OFORMAT_OMF ) { EmitErr( NOT_SUPPORTED_WITH_OMF_FORMAT, tokenarray[i].string_ptr ); i = Token_Count; /* stop further parsing of this line */ break; } i++; if ( tokenarray[i].token != T_OP_BRACKET ) { EmitErr( EXPECTED, "(" ); break; } i++; if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR ) break; if ( tokenarray[i].token != T_CL_BRACKET ) { EmitErr( EXPECTED, ")" ); break; } if ( opndx.kind != EXPR_CONST ) { EmitError( CONSTANT_EXPECTED ); break; } /* COFF allows alignment values 1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192 */ for( temp = 1, temp2 = 0; temp < opndx.value && temp < 8192 ; temp <<= 1, temp2++ ); if( temp != opndx.value ) { EmitError( POWER_OF_2 ); } dir->e.seginfo->alignment = temp2; break; case INIT_COMBINE: DebugMsg1(("SegmentDir(%s): combine attribute found\n", name )); dir->e.seginfo->combine = type->value; break; case INIT_COMBINE_AT: DebugMsg1(("SegmentDir(%s): AT found\n", name )); dir->e.seginfo->combine = type->value; /* v2.05: always use MAX_SEGALIGNMENT */ //dir->e.seginfo->alignment = -1; dir->e.seginfo->alignment = MAX_SEGALIGNMENT; i++; if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) != ERROR ) { if ( opndx.kind == EXPR_CONST ) { dir->e.seginfo->abs_frame = opndx.value; dir->e.seginfo->abs_offset = 0; } else { EmitError( CONSTANT_EXPECTED ); } } break; #if COMDATSUPP case INIT_COMBINE_COMDAT: DebugMsg1(("SegmentDir(%s): COMDAT found\n", name )); if ( Options.output_format != OFORMAT_COFF ) { EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr ); i = Token_Count; /* stop further parsing of this line */ break; } i++; if ( tokenarray[i].token != T_OP_BRACKET ) { EmitErr( EXPECTED, "(" ); break; } i++; if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR ) break; if ( opndx.kind != EXPR_CONST ) { EmitError( CONSTANT_EXPECTED ); i = Token_Count; /* stop further parsing of this line */ break; } if ( opndx.value < 1 || opndx.value > 6 ) { EmitErr( VALUE_NOT_WITHIN_ALLOWED_RANGE, "1-6" ); } else { /* if value is IMAGE_COMDAT_SELECT_ASSOCIATIVE, * get the associated segment name argument. */ if ( opndx.value == 5 ) { struct asym *sym2; if ( tokenarray[i].token != T_COMMA ) { EmitError( EXPECTING_COMMA ); i = Token_Count; /* stop further parsing of this line */ break; } i++; if ( tokenarray[i].token != T_ID ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); i = Token_Count; /* stop further parsing of this line */ break; } /* associated segment must be COMDAT, but not associative */ sym2 = SymSearch( tokenarray[i].string_ptr ); if ( sym2 == NULL || sym2->state != SYM_SEG || ((struct dsym *)sym2)->e.seginfo->comdat_selection == 0 || ((struct dsym *)sym2)->e.seginfo->comdat_selection == 5 ) EmitErr( INVALID_ASSOCIATED_SEGMENT, tokenarray[i].string_ptr ); else dir->e.seginfo->comdat_number = ((struct dsym *)sym2)->e.seginfo->seg_idx; i++; } } if ( tokenarray[i].token != T_CL_BRACKET ) { EmitErr( EXPECTED, ")" ); break; } dir->e.seginfo->comdat_selection = opndx.value; dir->e.seginfo->combine = type->value; break; #endif case INIT_OFSSIZE: case INIT_OFSSIZE_FLAT: /* v2.07: check for compatible cpu mode */ if ( type->value == USE32 && ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_386 ) #if AMD64_SUPPORT || type->value == USE64 && ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_64 ) #endif ) { EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE ); break; } if ( type->init == INIT_OFSSIZE_FLAT ) { DefineFlatGroup(); #if AMD64_SUPPORT dir->e.seginfo->Ofssize = ModuleInfo.defOfssize; #else dir->e.seginfo->Ofssize = USE32; #endif /* put the segment into the FLAT group. * this is not quite Masm-compatible, because trying to put * the segment into another group will cause an error. */ dir->e.seginfo->group = &ModuleInfo.flat_grp->sym; } else dir->e.seginfo->Ofssize = type->value; break; #if COFF_SUPPORT || ELF_SUPPORT case INIT_CHAR_INFO: dir->e.seginfo->info = TRUE; break; case INIT_CHAR: DebugMsg1(("SegmentDir(%s): characteristics found\n", name )); ; /* characteristics are restricted to COFF/ELF */ if ( Options.output_format == OFORMAT_OMF || Options.output_format == OFORMAT_BIN ) { EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr ); } else dir->e.seginfo->characteristics |= type->value; break; case INIT_ALIAS: DebugMsg1(("SegmentDir(%s): ALIAS found\n", name )); if ( Options.output_format != OFORMAT_COFF && Options.output_format != OFORMAT_ELF ) { EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr ); i = Token_Count; /* stop further parsing of this line */ break; } i++; if ( tokenarray[i].token != T_OP_BRACKET ) { EmitErr( EXPECTED, "(" ); break; } i++; if ( tokenarray[i].token != T_STRING || ( tokenarray[i].string_delim != '"' && tokenarray[i].string_delim != '\'' ) ) { EmitErr( SYNTAX_ERROR_EX, token ); i = Token_Count; /* stop further parsing of this line */ break; } temp = i; i++; if ( tokenarray[i].token != T_CL_BRACKET ) { EmitErr( EXPECTED, ")" ); break; } dir->e.seginfo->aliasname = LclAlloc( tokenarray[temp].stringlen ); memcpy( dir->e.seginfo->aliasname, tokenarray[temp].string_ptr+1, tokenarray[temp].stringlen ); *(dir->e.seginfo->aliasname+tokenarray[temp].stringlen) = NULLC; break; #endif #ifdef DEBUG_OUT default: /* shouldn't happen */ myassert( 0 ); break; #endif } } /* end for */ /* make a guess about the segment's type */ if( dir->e.seginfo->segtype != SEGTYPE_CODE ) { enum seg_type res; token = GetLname( dir->e.seginfo->class_name_idx ); res = TypeFromClassName( dir, token ); if( res != SEGTYPE_UNDEF ) { dir->e.seginfo->segtype = res; } #if 0 /* v2.03: removed */ else { res = TypeFromSegmentName( name ); dir->e.seginfo->segtype = res; } #endif } if( is_old ) { int txt = 0; /* Check if new definition is different from previous one */ // oldobj = dir->e.seginfo->segrec; if( oldreadonly != dir->e.seginfo->readonly ) txt = TXT_READONLY; else if ( oldalign != dir->e.seginfo->alignment ) txt = TXT_ALIGNMENT; else if ( oldcombine != dir->e.seginfo->combine ) txt = TXT_COMBINE; else if ( oldOfssize != dir->e.seginfo->Ofssize ) txt = TXT_SEG_WORD_SIZE; else if ( oldclassidx != dir->e.seginfo->class_name_idx ) txt = TXT_CLASS; /* Masm warns only! */ else if ( oldcharacteristics != dir->e.seginfo->characteristics ) txt = TXT_CHARACTERISTICS; if ( txt ) { EmitErr( SEGDEF_CHANGED, dir->sym.name, MsgGetEx( txt ) ); //return( ERROR ); /* v2: display error, but continue */ } } else { /* A new definition */ sym = &dir->sym; sym->isdefined = TRUE; sym->segment = sym; sym->offset = 0; if( dir->e.seginfo->lname_idx == 0 ) { dir->e.seginfo->lname_idx = ++LnamesIdx; AddLnameData( sym ); } } push_seg( dir ); /* set CurrSeg */ if ( ModuleInfo.list ) LstWrite( LSTTYPE_LABEL, 0, NULL ); return( SetOfssize() ); }