#include <ctype.h>
#include "globals.h"
#include "memalloc.h"
#include "parser.h"
#include "reswords.h"
#include "segment.h"
#include "expreval.h"
#include "omf.h"
#include "omfspec.h"
#include "fastpass.h"
#include "coffspec.h"
#include "assume.h"
#include "listing.h"
#include "msgtext.h"
#include "types.h"
#include "fixup.h"
#include "label.h"
#include "myassert.h"
extern ret_code EndstructDirective( int, struct asm_tok tokenarray[] );
struct asym *symCurSeg;
#define INIT_ATTR 0x01
#define INIT_ALIGN 0x02
#define INIT_ALIGN_PARAM (0x80 | INIT_ALIGN)
#define INIT_COMBINE 0x04
#define INIT_COMBINE_AT (0x80 | INIT_COMBINE)
#define INIT_COMBINE_COMDAT (0xC0 | INIT_COMBINE)
#define INIT_OFSSIZE 0x08
#define INIT_OFSSIZE_FLAT (0x80 | INIT_OFSSIZE)
#define INIT_ALIAS 0x10
#define INIT_CHAR 0x20
#define INIT_CHAR_INFO (0x80 | INIT_CHAR)
#define INIT_EXCL_MASK 0x1F
struct typeinfo {
uint_8 value;
uint_8 init;
};
static const char * const SegAttrToken[] = {
#define sitem( text, value, init ) text,
#include "segattr.h"
#undef sitem
};
static const struct typeinfo SegAttrValue[] = {
#define sitem( text, value, init ) { value, init },
#include "segattr.h"
#undef sitem
};
static unsigned grpdefidx;
static struct dsym *SegStack[MAX_SEG_NESTING];
static int stkindex;
static struct dsym *saved_CurrSeg;
static struct dsym **saved_SegStack;
static int saved_stkindex;
static uint_8 codebuf[ 1024 ];
static uint_32 buffer_size;
static const uint_16 min_cpu[] = { P_86, P_386, P_64 };
static int FindToken( const char *token, const char * const *table, int size )
{
int i;
for( i = 0; i < size; i++, table++ ) {
if( _stricmp( *table, token ) == 0 ) {
return( i );
}
}
return( -1 );
}
void UpdateCurPC( struct asym *sym, void *p )
{
if( CurrStruct ) {
sym->mem_type = MT_EMPTY;
sym->segment = NULL;
sym->offset = CurrStruct->sym.offset + (CurrStruct->next ? CurrStruct->next->sym.offset : 0);
} else if ( CurrSeg ) {
sym->mem_type = MT_NEAR;
sym->segment = (struct asym *)CurrSeg;
sym->offset = GetCurrOffset();
} else
EmitErr( MUST_BE_IN_SEGMENT_BLOCK );
}
static void AddLnameItem( struct asym *sym )
{
QAddItem( &ModuleInfo.g.LnameQueue, sym );
return;
}
static void FreeLnameQueue( void )
{
struct qnode *curr;
struct qnode *next;
DebugMsg(("FreeLnameQueue enter\n" ));
for( curr = ModuleInfo.g.LnameQueue.head; curr; curr = next ) {
next = curr->next;
if( curr->sym->state == SYM_CLASS_LNAME ) {
SymFree( curr->sym );
}
LclFree( curr );
}
}
void UpdateCurrSegVars( void )
{
struct assume_info *info;
info = &(SegAssumeTable[ ASSUME_CS ]);
if( CurrSeg == NULL ) {
info->symbol = NULL;
info->is_flat = FALSE;
info->error = TRUE;
symCurSeg->string_ptr = "";
} else {
info->is_flat = FALSE;
info->error = FALSE;
if( CurrSeg->e.seginfo->group != NULL ) {
info->symbol = CurrSeg->e.seginfo->group;
if ( info->symbol == &ModuleInfo.flat_grp->sym )
info->is_flat = TRUE;
} else {
info->symbol = &CurrSeg->sym;
}
symCurSeg->string_ptr = CurrSeg->sym.name;
}
return;
}
void push_seg( struct dsym *seg )
{
if ( stkindex >= MAX_SEG_NESTING ) {
EmitError( NESTING_LEVEL_TOO_DEEP );
return;
}
SegStack[stkindex] = CurrSeg;
stkindex++;
CurrSeg = seg;
UpdateCurrSegVars();
return;
}
void pop_seg( void )
{
if ( stkindex ) {
stkindex--;
CurrSeg = SegStack[stkindex];
UpdateCurrSegVars();
}
return;
}
uint_32 GetCurrOffset( void )
{
return( CurrSeg ? CurrSeg->e.seginfo->current_loc : 0 );
}
uint_32 GetCurrSegAlign( void )
{
if( CurrSeg == NULL )
return( 0 );
if ( CurrSeg->e.seginfo->alignment == MAX_SEGALIGNMENT )
return( 0x40 );
return( 1 << CurrSeg->e.seginfo->alignment );
}
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->numseg = 0;
sym_add_table( &SymTables[TAB_GRP], grp );
grp->sym.list = TRUE;
grp->e.grpinfo->grp_idx = ++grpdefidx;
AddLnameItem( &grp->sym );
} else if( grp->sym.state != SYM_GRP ) {
EmitErr( SYMBOL_REDEFINITION, name );
return( NULL );
}
grp->sym.isdefined = TRUE;
return( grp );
}
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;
seg->e.seginfo->combine = COMB_INVALID;
seg->next = NULL;
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 );
}
void DeleteGroup( struct dsym *dir )
{
#if FASTMEM==0 || defined(DEBUG_OUT)
struct seg_item *curr;
struct seg_item *next;
for( curr = dir->e.grpinfo->seglist; curr; curr = next ) {
next = curr->next;
LclFree( curr );
}
#endif
LclFree( dir->e.grpinfo );
return;
}
ret_code GrpDir( int i, struct asm_tok tokenarray[] )
{
char *name;
struct dsym *grp;
struct dsym *seg;
if( i != 1 ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
if ( Options.output_format == OFORMAT_COFF || Options.output_format == OFORMAT_ELF
|| ( Options.output_format == OFORMAT_BIN && ModuleInfo.sub_format == SFORMAT_PE )) {
return( EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, _strupr( tokenarray[i].string_ptr ) ) );
}
grp = CreateGroup( tokenarray[0].string_ptr );
if( grp == NULL )
return( ERROR );
i++;
do {
if ( tokenarray[i].token != T_ID ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
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 );
if ( grp->e.grpinfo->seglist )
seg->e.seginfo->Ofssize = grp->sym.Ofssize;
} else if( seg->sym.state != SYM_SEG ) {
return( EmitErr( SEGMENT_EXPECTED, name ) );
} else if( seg->e.seginfo->group != NULL &&
seg->e.seginfo->group != &ModuleInfo.flat_grp->sym &&
seg->e.seginfo->group != &grp->sym ) {
return( EmitErr( SEGMENT_IN_ANOTHER_GROUP, name ) );
}
if( grp->e.grpinfo->seglist == NULL ) {
grp->sym.Ofssize = seg->e.seginfo->Ofssize;
} else if ( grp->sym.Ofssize != seg->e.seginfo->Ofssize ) {
return( EmitErr( GROUP_SEGMENT_SIZE_CONFLICT, grp->sym.name, seg->sym.name ) );
}
} else {
if( seg == NULL || seg->sym.state != SYM_SEG || seg->sym.segment == NULL ) {
return( EmitErr( SEGMENT_NOT_DEFINED, name ) );
}
}
if ( seg->e.seginfo->group == NULL ) {
struct seg_item *si;
seg->e.seginfo->group = &grp->sym;
si = LclAlloc( sizeof( struct seg_item ) );
si->seg = seg;
si->next = NULL;
grp->e.grpinfo->numseg++;
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 ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ) );
}
i++;
}
} while ( i < Token_Count );
return( NOT_ERROR );
}
void UpdateWordSize( struct asym *sym, void *p )
{
sym->value = CurrWordSize;
return;
}
ret_code SetOfssize( void )
{
if( CurrSeg == NULL ) {
ModuleInfo.Ofssize = ModuleInfo.defOfssize;
} else {
ModuleInfo.Ofssize = CurrSeg->e.seginfo->Ofssize;
if( (uint_8)ModuleInfo.curr_cpu < min_cpu[ModuleInfo.Ofssize] ) {
return( EmitErr( INCOMPATIBLE_CPU_MODE_FOR_XXBIT_SEGMENT, 16 << ModuleInfo.Ofssize ) );
}
}
CurrWordSize = (2 << ModuleInfo.Ofssize);
Set64Bit( ModuleInfo.Ofssize == USE64 );
return( NOT_ERROR );
}
static ret_code CloseSeg( const char *name )
{
if( CurrSeg == NULL || ( SymCmpFunc( CurrSeg->sym.name, name, CurrSeg->sym.name_size ) != 0 ) ) {
return( EmitErr( BLOCK_NESTING_ERROR, name ) );
}
if ( write_to_file && ( Options.output_format == OFORMAT_OMF ) ) {
omf_FlushCurrSeg();
if ( Options.no_comment_data_in_code_records == FALSE )
omf_OutSelect( FALSE );
}
pop_seg();
return( NOT_ERROR );
}
void DefineFlatGroup( void )
{
if( ModuleInfo.flat_grp == NULL ) {
ModuleInfo.flat_grp = CreateGroup( "FLAT" );
ModuleInfo.flat_grp->sym.Ofssize = ModuleInfo.defOfssize;
}
ModuleInfo.flat_grp->sym.isdefined = TRUE;
}
unsigned GetSegIdx( const struct asym *sym )
{
if( sym )
return( ((struct dsym *)sym)->e.seginfo->seg_idx );
return( 0 );
}
struct asym *GetGroup( const struct asym *sym )
{
struct dsym *curr;
curr = GetSegm( sym );
if( curr != NULL )
return( curr->e.seginfo->group );
return( NULL );
}
int GetSymOfssize( const struct asym *sym )
{
struct dsym *curr;
curr = GetSegm( sym );
if( curr == NULL ) {
if( sym->state == SYM_EXTERNAL )
return( sym->seg_ofssize );
if( sym->state == SYM_STACK || sym->state == SYM_GRP )
return( sym->Ofssize );
if( sym->state == SYM_SEG )
return( ((struct dsym *)sym)->e.seginfo->Ofssize );
if ( sym->mem_type == MT_EMPTY )
return( USE16 );
} else {
return( curr->e.seginfo->Ofssize );
}
return( ModuleInfo.Ofssize );
}
void SetSymSegOfs( struct asym *sym )
{
sym->segment = &CurrSeg->sym;
sym->offset = GetCurrOffset();
}
enum seg_type TypeFromClassName( const struct dsym *seg, const struct asym *clname )
{
int slen;
char uname[MAX_ID_LEN+1];
if ( seg->e.seginfo->alignment == MAX_SEGALIGNMENT )
return( SEGTYPE_ABS );
if ( seg->e.seginfo->combine == COMB_STACK )
return( SEGTYPE_STACK );
if( clname == NULL )
return( SEGTYPE_UNDEF );
if( _stricmp( clname->name, GetCodeClass() ) == 0 )
return( SEGTYPE_CODE );
slen = clname->name_size;
memcpy( uname, clname->name, clname->name_size + 1 );
_strupr( uname );
switch( slen ) {
default:
case 5:
if( memcmp( uname, "CONST", 6 ) == 0 )
return( SEGTYPE_DATA );
if( memcmp( uname, "DBTYP", 6 ) == 0 )
return( SEGTYPE_DATA );
if( memcmp( uname, "DBSYM", 6 ) == 0 )
return( SEGTYPE_DATA );
case 4:
if( memcmp( uname + slen - 4, "CODE", 4 ) == 0 )
return( SEGTYPE_CODE );
if( memcmp( uname + slen - 4, "DATA", 4 ) == 0 )
return( SEGTYPE_DATA );
case 3:
if( memcmp( uname + slen - 3, "BSS", 3 ) == 0 )
return( SEGTYPE_BSS );
case 2:
case 1:
case 0:
return( SEGTYPE_UNDEF );
}
}
static struct asym *FindClass( const char *name, int len )
{
struct qnode *node;
for( node = ModuleInfo.g.LnameQueue.head; node; node = node->next ) {
struct asym *sym = node->sym;
if( sym->state == SYM_CLASS_LNAME && ( SymCmpFunc( sym->name, name, len ) == 0 ) )
return( sym );
}
return( NULL );
}
static struct asym *CreateClassLname( const char *name )
{
struct asym *sym;
int len = strlen( name );
if( len > MAX_LNAME ) {
EmitError( CLASS_NAME_TOO_LONG );
return( NULL );
}
if ( !( sym = FindClass( name, len ) ) ) {
sym = SymAlloc( name );
sym->state = SYM_CLASS_LNAME;
AddLnameItem( sym );
}
return( sym );
}
static ret_code SetSegmentClass( struct dsym *seg, const char *name )
{
struct asym *clsym;
clsym = CreateClassLname( name );
if( clsym == NULL ) {
return( ERROR );
}
seg->e.seginfo->clsym = clsym;
return( NOT_ERROR );
}
struct asym *CreateIntSegment( const char *name, const char *classname, uint_8 alignment, uint_8 Ofssize, bool add_global )
{
struct dsym *seg;
if ( add_global ) {
seg = (struct dsym *)SymSearch( name );
if ( seg == NULL || seg->sym.state == SYM_UNDEFINED )
seg = CreateSegment( seg, name, add_global );
else if ( seg->sym.state != SYM_SEG ) {
EmitErr( SYMBOL_REDEFINITION, name );
return( NULL );
}
} else
seg = CreateSegment( NULL, name, FALSE );
if ( seg ) {
if( seg->sym.isdefined == FALSE ) {
seg->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs;
AddLnameItem( &seg->sym );
seg->sym.isdefined = TRUE;
}
seg->e.seginfo->internal = TRUE;
seg->sym.segment = &seg->sym;
seg->e.seginfo->alignment = alignment;
seg->e.seginfo->Ofssize = Ofssize;
SetSegmentClass( seg, classname );
return( &seg->sym );
}
return( NULL );
}
ret_code EndsDir( int i, struct asm_tok tokenarray[] )
{
if( CurrStruct != NULL ) {
return( EndstructDirective( i, tokenarray ) );
}
if( i != 1 ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
if ( Parse_Pass != PASS_1 ) {
if ( ModuleInfo.list )
LstWrite( LSTTYPE_LABEL, 0, NULL );
}
if ( CloseSeg( tokenarray[0].string_ptr ) == ERROR )
return( ERROR );
i++;
if ( tokenarray[i].token != T_FINAL ) {
EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
}
return( SetOfssize() );
}
static ret_code SetCurrSeg( int i, struct asm_tok tokenarray[] )
{
struct asym *sym;
sym = SymSearch( tokenarray[0].string_ptr );
if ( sym == NULL || sym->state != SYM_SEG ) {
return( EmitErr( SEGMENT_NOT_DEFINED, tokenarray[0].string_ptr ) );
}
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() );
}
static void UnlinkSeg( struct dsym *dir )
{
struct dsym *curr;
struct dsym *prev;
for ( curr = SymTables[TAB_SEG].head, prev = NULL; curr; prev = curr, curr = curr->next )
if ( curr == dir ) {
if ( prev == NULL )
SymTables[TAB_SEG].head = curr->next;
else
prev->next = curr->next;
if ( curr->next == NULL )
SymTables[TAB_SEG].tail = prev;
break;
}
return;
}
struct asym* CV8Label = NULL;
ret_code SegmentDir( int i, struct asm_tok tokenarray[] )
{
char is_old = FALSE;
char *token;
int typeidx;
const struct typeinfo *type;
int newseg = 0;
int temp;
int temp2;
unsigned initstate = 0;
unsigned char oldOfssize;
char oldalign;
char oldcombine;
uint_8 newcharacteristics = 0;
struct dsym *dir;
char *name;
struct asym *sym;
struct expr opndx;
if ( Parse_Pass != PASS_1 )
return( SetCurrSeg( i, tokenarray ) );
if( i != 1 ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
name = tokenarray[0].string_ptr;
sym = SymSearch( name );
if( sym == NULL || sym->state == SYM_UNDEFINED ) {
newseg = 1;
sym = (struct asym *)CreateSegment( (struct dsym *)sym, name, TRUE );
sym->list = TRUE;
dir = (struct dsym *)sym;
} else if ( sym->state == SYM_SEG ) {
dir = (struct dsym *)sym;
if( sym->isdefined == FALSE ) {
UnlinkSeg( dir );
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 {
is_old = TRUE;
oldOfssize = dir->e.seginfo->Ofssize;
oldalign = dir->e.seginfo->alignment;
oldcombine = dir->e.seginfo->combine;
}
} else {
return( EmitErr( SYMBOL_REDEFINITION, name ) );
}
i++;
for( ; i < Token_Count; i++ ) {
token = tokenarray[i].string_ptr;
if( tokenarray[i].token == T_STRING ) {
if ( tokenarray[i].string_delim != '"' &&
tokenarray[i].string_delim != '\'' ) {
EmitErr( SYNTAX_ERROR_EX, token );
continue;
}
token++;
*(token+tokenarray[i].stringlen) = NULLC;
SetSegmentClass( dir, token );
continue;
}
typeidx = FindToken( token, SegAttrToken, sizeof( SegAttrToken )/sizeof( SegAttrToken[0] ) );
if( typeidx < 0 ) {
EmitErr( UNKNOWN_SEGMENT_ATTRIBUTE, token );
continue;
}
type = &SegAttrValue[typeidx];
if( initstate & INIT_EXCL_MASK & type->init ) {
EmitErr( SEGMENT_ATTRIBUTE_DEFINED_ALREADY, token );
continue;
} else {
initstate |= type->init;
}
switch ( type->init ) {
case INIT_ATTR:
dir->e.seginfo->readonly = TRUE;
break;
case INIT_ALIGN:
dir->e.seginfo->alignment = type->value;
break;
case INIT_ALIGN_PARAM:
if ( Options.output_format == OFORMAT_OMF ) {
EmitErr( NOT_SUPPORTED_WITH_OMF_FORMAT, tokenarray[i].string_ptr );
i = Token_Count;
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;
}
for( temp = 1, temp2 = 0; temp < opndx.value && temp < 8192 ; temp <<= 1, temp2++ );
if( temp != opndx.value ) {
EmitErr( POWER_OF_2, opndx.value );
}
dir->e.seginfo->alignment = temp2;
break;
case INIT_COMBINE:
dir->e.seginfo->combine = type->value;
break;
case INIT_COMBINE_AT:
dir->e.seginfo->combine = type->value;
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;
case INIT_COMBINE_COMDAT:
if ( Options.output_format != OFORMAT_COFF && Options.output_format != OFORMAT_OMF ) {
EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr );
i = Token_Count;
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;
break;
}
if ( opndx.value < 1 || opndx.value > 6 ) {
EmitErr( VALUE_NOT_WITHIN_ALLOWED_RANGE, "1-6" );
} else {
if ( opndx.value == 5 ) {
struct asym *sym2;
if ( tokenarray[i].token != T_COMMA ) {
EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos );
i = Token_Count;
break;
}
i++;
if ( tokenarray[i].token != T_ID ) {
EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
i = Token_Count;
break;
}
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;
case INIT_OFSSIZE:
case INIT_OFSSIZE_FLAT:
if ( type->init == INIT_OFSSIZE_FLAT ) {
DefineFlatGroup();
dir->e.seginfo->Ofssize = ( ModuleInfo.defOfssize > USE16 ? ModuleInfo.defOfssize : USE32 );
dir->e.seginfo->group = &ModuleInfo.flat_grp->sym;
} else
dir->e.seginfo->Ofssize = type->value;
break;
case INIT_CHAR_INFO:
dir->e.seginfo->info = TRUE;
break;
case INIT_CHAR:
if ( Options.output_format == OFORMAT_OMF ||
( ModuleInfo.flat == FALSE && Options.output_format == OFORMAT_BIN && ModuleInfo.sub_format != SFORMAT_PE )
) {
EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr );
} else
newcharacteristics |= type->value;
break;
case INIT_ALIAS:
if ( Options.output_format == OFORMAT_OMF
|| ( Options.output_format == OFORMAT_BIN && ModuleInfo.sub_format != SFORMAT_PE )
) {
EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr );
i = Token_Count;
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;
break;
}
temp = i;
i++;
if ( tokenarray[i].token != T_CL_BRACKET ) {
EmitErr( EXPECTED, ")" );
break;
}
if ( is_old ) {
if ( dir->e.seginfo->aliasname == NULL ||
( tokenarray[temp].stringlen != strlen( dir->e.seginfo->aliasname ) ) ||
memcmp( dir->e.seginfo->aliasname, tokenarray[temp].string_ptr + 1, tokenarray[temp].stringlen ) ) {
EmitErr( SEGDEF_CHANGED, dir->sym.name, MsgGetEx( TXT_ALIASNAME ) );
break;
}
} else {
dir->e.seginfo->aliasname = LclAlloc( tokenarray[temp].stringlen + 1 );
memcpy( dir->e.seginfo->aliasname, tokenarray[temp].string_ptr+1, tokenarray[temp].stringlen );
*(dir->e.seginfo->aliasname+tokenarray[temp].stringlen) = NULLC;
}
break;
}
}
if( dir->e.seginfo->segtype != SEGTYPE_CODE ) {
enum seg_type res;
res = TypeFromClassName( dir, dir->e.seginfo->clsym );
if( res != SEGTYPE_UNDEF ) {
dir->e.seginfo->segtype = res;
}
}
if( is_old ) {
int txt = 0;
if ( oldalign != dir->e.seginfo->alignment && !ModuleInfo.flat ) txt = TXT_ALIGNMENT;
else if ( oldcombine != dir->e.seginfo->combine )
txt = TXT_COMBINE;
else if ( oldOfssize != dir->e.seginfo->Ofssize && !ModuleInfo.flat ) txt = TXT_SEG_WORD_SIZE;
else if ( newcharacteristics && ( newcharacteristics != dir->e.seginfo->characteristics ) )
txt = TXT_CHARACTERISTICS;
if ( txt ) {
EmitErr( SEGDEF_CHANGED, dir->sym.name, MsgGetEx( txt ) );
}
} else {
sym->isdefined = TRUE;
sym->segment = sym;
sym->offset = 0;
if ( dir->e.seginfo->comdat_selection && Options.output_format == OFORMAT_OMF )
;
else {
dir->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs;
AddLnameItem( sym );
}
}
if ( newcharacteristics )
dir->e.seginfo->characteristics = newcharacteristics;
push_seg( dir );
if ( ModuleInfo.list )
LstWrite( LSTTYPE_LABEL, 0, NULL );
temp = SetOfssize();
if (Options.debug_symbols == 4 && newseg) {
if (dir->e.seginfo->segtype == SEGTYPE_CODE && CV8Label == NULL) {
CV8Label = CreateLabel("$$000000", MT_NEAR, 0, 0);
}
}
return(temp);
}
void SortSegments( int type )
{
bool changed = TRUE;
bool swap;
struct dsym *curr;
while ( changed == TRUE ) {
struct dsym *prev = NULL;
changed = FALSE;
for( curr = SymTables[TAB_SEG].head; curr && curr->next ; prev = curr, curr = curr->next ) {
swap = FALSE;
switch (type ) {
case 0:
if ( curr->e.seginfo->fileoffset > curr->next->e.seginfo->fileoffset )
swap = TRUE;
break;
case 1:
if ( strcmp( curr->sym.name, curr->next->sym.name ) > 0 )
swap = TRUE;
break;
case 2:
if ( curr->e.seginfo->lname_idx > curr->next->e.seginfo->lname_idx ||
( curr->e.seginfo->lname_idx == curr->next->e.seginfo->lname_idx &&
( _stricmp( curr->sym.name, curr->next->sym.name ) > 0 ) ) )
swap = TRUE;
break;
}
if ( swap ) {
struct dsym *tmp = curr->next;
changed = TRUE;
if ( prev == NULL ) {
SymTables[TAB_SEG].head = tmp;
} else {
prev->next = tmp;
}
curr->next = tmp->next;
tmp->next = curr;
}
}
}
}
ret_code SegmentModuleExit( void )
{
if ( ModuleInfo.model != MODEL_NONE )
ModelSimSegmExit();
if ( CurrSeg ) {
EmitErr( BLOCK_NESTING_ERROR, CurrSeg->sym.name );
while( CurrSeg && ( CloseSeg( CurrSeg->sym.name ) == NOT_ERROR ) );
}
return( NOT_ERROR );
}
void SegmentFini( void )
{
#if FASTPASS
if ( saved_SegStack ) {
LclFree( saved_SegStack );
}
#endif
FreeLnameQueue();
}
void SegmentInit( int pass )
{
struct dsym *curr;
uint_32 i;
char *p;
CurrSeg = NULL;
stkindex = 0;
if ( pass == PASS_1 ) {
grpdefidx = 0;
buffer_size = 0;
CV8Label = NULL;
}
if ( ModuleInfo.pCodeBuff == NULL && Options.output_format != OFORMAT_OMF ) {
for( curr = SymTables[TAB_SEG].head, buffer_size = 0; curr; curr = curr->next ) {
if ( curr->e.seginfo->internal )
continue;
if ( curr->e.seginfo->bytes_written ) {
i = curr->sym.max_offset - curr->e.seginfo->start_loc;
if ( curr->e.seginfo->segtype == SEGTYPE_CODE )
i = i + (i >> 2);
buffer_size += i;
}
}
if ( buffer_size ) {
ModuleInfo.pCodeBuff = LclAlloc( buffer_size );
}
}
for( curr = SymTables[TAB_SEG].head, p = ModuleInfo.pCodeBuff; curr; curr = curr->next ) {
curr->e.seginfo->current_loc = 0;
if ( curr->e.seginfo->internal )
continue;
if ( curr->e.seginfo->bytes_written ) {
if ( Options.output_format == OFORMAT_OMF ) {
curr->e.seginfo->CodeBuffer = codebuf;
} else {
curr->e.seginfo->CodeBuffer = p;
i = curr->sym.max_offset - curr->e.seginfo->start_loc;
p += i;
}
}
if( curr->e.seginfo->combine != COMB_STACK ) {
curr->sym.max_offset = 0;
}
if ( Options.output_format == OFORMAT_OMF ) {
curr->e.seginfo->start_loc = 0;
curr->e.seginfo->data_in_code = FALSE;
}
curr->e.seginfo->bytes_written = 0;
curr->e.seginfo->FixupList.head = NULL;
curr->e.seginfo->FixupList.tail = NULL;
}
ModuleInfo.Ofssize = USE16;
if ( pass != PASS_1 && UseSavedState == TRUE ) {
CurrSeg = saved_CurrSeg;
stkindex = saved_stkindex;
if ( stkindex )
memcpy( &SegStack, saved_SegStack, stkindex * sizeof(struct dsym *) );
UpdateCurrSegVars();
}
}
void SegmentSaveState( void )
{
saved_CurrSeg = CurrSeg;
saved_stkindex = stkindex;
if ( stkindex ) {
saved_SegStack = LclAlloc( stkindex * sizeof(struct dsym *) );
memcpy( saved_SegStack, &SegStack, stkindex * sizeof(struct dsym *) );
}
}