objprs.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 848 行 · 第 1/2 页
C
848 行
STATIC int pass1Comdef( obj_rec *objr ) {
uint_8 len;
uint_16 count;
uint_8 far_near;
uint_8 byte;
/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_COMDEF ||
objr->command == CMD_STATIC_COMDEF );
objr->d.comdef.first_idx = loc.extdef_idx + 1;
count = 0;
while( !ObjEOR( objr ) ) {
len = ObjGet8( objr );
ObjGet( objr, len );
ObjGetIndex( objr );
far_near = ObjGet8( objr );
if( far_near == COMDEF_FAR ) { /* read the extra field for FAR */
byte = ObjGet8( objr );
if( byte <= COMDEF_LEAF_SIZE ) {
/* all done */
} else if( byte == COMDEF_LEAF_2 ) {
ObjGet( objr, 2 );
} else if( byte == COMDEF_LEAF_3 ) {
ObjGet( objr, 3 );
} else if( byte == COMDEF_LEAF_4 ) {
ObjGet( objr, 4 );
} else {
Fatal( MSG_UNK_COMDEF_LEAF, byte );
}
}
byte = ObjGet8( objr );
if( byte <= COMDEF_LEAF_SIZE ) {
/* all done */
} else if( byte == COMDEF_LEAF_2 ) {
ObjGet( objr, 2 );
} else if( byte == COMDEF_LEAF_3 ) {
ObjGet( objr, 3 );
} else if( byte == COMDEF_LEAF_4 ) {
ObjGet( objr, 4 );
} else {
Fatal( MSG_UNK_COMDEF_LEAF, byte );
}
++count;
}
objr->d.comdef.num_names = count;
loc.extdef_idx += count;
return( 0 );
}
STATIC int pass1Base( obj_rec *objr ) {
uint_16 grp_idx;
uint_16 seg_idx;
/**/myassert( objr != NULL );
grp_idx = objr->d.base.grp_idx = ObjGetIndex( objr );
seg_idx = objr->d.base.seg_idx = ObjGetIndex( objr );
if( grp_idx == 0 && seg_idx == 0 ) {
objr->d.base.frame = ObjGet16( objr );
}
return( 0 );
}
STATIC int pass1Comdat( obj_rec *objr ) {
/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_COMDAT );
loc.last_data_rec = objr;
objr->d.comdat.flags = ObjGet8( objr );
objr->d.comdat.attributes = ObjGet8( objr );
objr->d.comdat.align = ObjGet8( objr );
objr->d.comdat.offset = ObjGetEither( objr );
objr->d.comdat.type_idx = ObjGetIndex( objr );
if( ( objr->d.comdat.attributes & COMDAT_ALLOC_MASK ) == COMDAT_EXPLICIT ) {
pass1Base( objr );
}
objr->d.comdat.public_name_idx = ObjGetIndex( objr );
return( 0 );
}
STATIC int pass1LinnumData( obj_rec *objr ) {
linnum_data *linedata;
div_t res;
uint_16 line;
int is32;
uint_16 len;
/**/myassert( objr != NULL );
is32 = objr->is_32 || objr->is_phar;
len = ObjRemain( objr );
res = div( len, is32 ? 6 : 4 );
/**/myassert( res.rem == 0 );
if( res.quot == 0 ) {
/* no point in keeping this record if no lines in it */
return( 1 );
}
objr->d.linnum.num_lines = res.quot;
linedata = objr->d.linnum.lines =
MemAlloc( res.quot * sizeof( linnum_data ) );
#if defined( __BIG_ENDIAN__ )
for( line = 0; line < res.quot; ++line ) {
linedata[ line ].number = ObjGet16( objr );
linedata[ line ].offset = ObjGetEither( objr );
}
ObjDetachData( objr );
#else
if( is32 ) {
memcpy( linedata, ObjGet( objr, len ), len );
/**/ myassert( sizeof( linnum_data ) == 6 );
} else {
for( line = 0; line < res.quot; ++line ) {
linedata[ line ].number = ObjGet16( objr );
linedata[ line ].offset = (uint_32)ObjGet16( objr );
}
}
ObjDetachData( objr );
#endif
return( 0 );
}
STATIC int pass1Linnum( obj_rec *objr ) {
/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_LINNUM );
pass1Base( objr );
return( pass1LinnumData( objr ) );
}
STATIC int pass1Linsym( obj_rec *objr ) {
/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_LINSYM );
objr->d.linsym.d.linsym.flags = ObjGet8( objr );
objr->d.linsym.d.linsym.public_name_idx = ObjGetIndex( objr );
return( pass1LinnumData( objr ) );
}
STATIC int pass1Pubdef( obj_rec *objr ) {
pubdef_data *pubdata;
uint_16 num_pubs;
uint_8 name_len;
/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_PUBDEF ||
objr->command == CMD_STATIC_PUBDEF );
pass1Base( objr );
pubdata = MemAlloc( 16 * sizeof( pubdef_data ) );
num_pubs = 0;
if( !ObjEOR( objr ) ) {
for(;;) {
name_len = ObjGet8( objr );
pubdata[ num_pubs ].name = NameAdd( ObjGet( objr, name_len ),
name_len );
pubdata[ num_pubs ].offset = ObjGetEither( objr );
pubdata[ num_pubs ].type.idx = ObjGetIndex( objr );
++num_pubs;
if( ObjEOR( objr ) ) break;
if( ( num_pubs & 0xf ) == 0 ) {
/* we've used a multiple of 16 pubs, realloc for 16 more */
pubdata = MemRealloc( pubdata,
( num_pubs + 16 ) * sizeof( pubdef_data ) );
}
}
}
ObjDetachData( objr );
objr->d.pubdef.num_pubs = num_pubs;
if( num_pubs > 0 ) {
objr->d.pubdef.pubs = MemRealloc( pubdata,
num_pubs * sizeof( pubdef_data ) );
objr->d.pubdef.free_pubs = 1;
} else {
MemFree( pubdata );
objr->d.pubdef.pubs = NULL;
objr->d.pubdef.free_pubs = 0;
}
objr->d.pubdef.processed = 0;
return( 0 );
}
STATIC void doPass1( OBJ_RFILE *file_in, pobj_lib_info *pli ) {
obj_rec *objr;
jlist *func;
jlist *next;
int cont;
QInit( &loc.records );
QInit( &loc.pub );
objr = ObjReadRec( file_in );
switch( objr->command ) {
case LIB_HEADER_REC:
pli->page_len = ObjRemain( objr ) + 4;
pli->is_lib = 1;
objr = ObjReadRec( file_in );
break;
case LIB_TRAILER_REC:
return;
}
if( objr->command != CMD_THEADR ) {
Fatal( MSG_THEADR_MISSING );
}
for(;;) {
objr->is_phar = loc.is_phar;
objr->is_32 = objr->command & 1;
objr->command &= ~1;
/* handle those records we must preprocess */
cont = 0;
switch( objr->command ) {
case CMD_COMENT: cont = pass1Coment( objr ); break;
case CMD_MODEND: cont = pass1Modend( objr ); break;
case CMD_STATIC_EXTDEF: /* fall through */
case CMD_EXTDEF: cont = pass1Extdef( objr ); break;
case CMD_LLNAMES: /* fall through */
case CMD_LNAMES: cont = pass1Lnames( objr ); break;
case CMD_SEGDEF: cont = pass1Segdef( objr ); break;
case CMD_GRPDEF: cont = pass1Grpdef( objr ); break;
case CMD_FIXUP: cont = pass1Fixup( objr ); break;
case CMD_LEDATA: /* fall through */
case CMD_LIDATA: cont = pass1Ledata( objr ); break;
case CMD_STATIC_COMDEF: /* fall through */
case CMD_COMDEF: cont = pass1Comdef( objr ); break;
case CMD_LINNUM: cont = pass1Linnum( objr ); break;
case CMD_STATIC_PUBDEF: /* fall through */
case CMD_PUBDEF: cont = pass1Pubdef( objr ); break;
case CMD_CEXTDF: cont = pass1Cextdf( objr ); break;
case CMD_COMDAT: cont = pass1Comdat( objr ); break;
case CMD_LINSYM: cont = pass1Linsym( objr ); break;
}
/* pass record to registered routines */
func = readJump[ JUMP_OFFSET( objr->command ) ];
while( func != NULL && cont != -1 ) {
next = func->next; /* filters are allowed to unregister themself */
cont = func->func( objr, &loc.state );
func = next;
}
if( cont == 0 ) {
switch( objr->command ) {
case CMD_PUBDEF:
case CMD_STATIC_PUBDEF:
QEnqueue( &loc.pub, objr );
break;
default:
QEnqueue( &loc.records, objr );
break;
}
}
if( objr->command == CMD_MODEND ) {
if( pli->is_lib ) {
ObjRSkipPage( file_in, pli->page_len );
}
break;
}
objr = ObjReadRec( file_in );
}
}
STATIC void pass2Lnames( obj_rec *objr ) {
/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_LNAMES || objr->command == CMD_LLNAMES );
loc.lnames_idx = objr->d.lnames.first_idx + objr->d.lnames.num_names - 1;
}
STATIC void pass2Segdef( obj_rec *objr ) {
/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_SEGDEF );
loc.segdef_idx = objr->d.segdef.idx;
}
STATIC void pass2Grpdef( obj_rec *objr ) {
/**/myassert( objr != NULL );
/**/myassert( objr->command == CMD_GRPDEF );
loc.grpdef_idx = objr->d.grpdef.idx;
}
STATIC void doPass2( void ) {
obj_rec *objr;
obj_rec *objr_next;
obj_rec *stale_objrs;
jlist *func;
jlist *func_next;
int cont;
objr = loc.records.head;
/**/myassert( objr != NULL );
if( objr->command != CMD_THEADR ) {
Fatal( MSG_THEADR_MISSING );
}
stale_objrs = NULL;
do {
QInit( &loc.insert ); /* set up for inserted records */
switch( objr->command ) {
case CMD_LLNAMES: /* fall through */
case CMD_LNAMES: pass2Lnames( objr ); break;
case CMD_SEGDEF: pass2Segdef( objr ); break;
case CMD_GRPDEF: pass2Grpdef( objr ); break;
}
/* pass record to registered routines */
cont = 0;
func = writeJump[ JUMP_OFFSET( objr->command ) ];
while( func != NULL && cont != -1 ) {
func_next = func->next;
cont = func->func( objr, &loc.state );
func = func_next;
}
objr_next = objr->next;
if( objr == loc.last_defn ) {
if( loc.pub.head != NULL ) {
PObjJoinQueue( &loc.pub );
}
func = writeJump[ JUMP_OFFSET( CMD_LAST_DEFN ) ];
while( func != NULL && cont != -1 ) {
func_next = func->next;
cont = func->func( objr, &loc.state );
func = func_next;
}
}
objr_next = objr->next;
if( loc.insert.head != NULL ) {
((obj_rec *)loc.insert.tail)->next = objr_next;
objr_next = loc.insert.head;
}
/* we don't want any records recycled during the 2nd pass */
objr->next = stale_objrs;
stale_objrs = objr;
objr = objr_next;
} while( objr != NULL );
/* clean up stale object records */
while( stale_objrs != NULL ) {
objr_next = stale_objrs->next;
ObjKillRec( stale_objrs );
stale_objrs = objr_next;
}
}
int PObj( OBJ_RFILE *file_in, OBJ_WFILE *file_out, pobj_lib_info *pli ) {
/***********************************************************************/
int more_data;
memset( &loc, 0, sizeof( loc ) );
ObjDGROUPIndex = 0;
ObjFLATIndex = 0;
loc.fix_info = FixBegin();
loc.state.file_out = file_out;
loc.state.pass = POBJ_READ_PASS;
doPass1( file_in, pli );
if( loc.records.head == NULL && pli->is_lib ) {
FixEnd( loc.fix_info );
return( 0 );
}
/**/myassert( loc.records.head != NULL );
if( loc.last_defn == NULL ) {
Fatal( MSG_INVALID_OBJECT );
}
loc.state.pass = POBJ_WRITE_PASS;
loc.segdef_idx = 0;
loc.grpdef_idx = 0;
loc.extdef_idx = 0;
loc.lnames_idx = 0;
doPass2();
FixEnd( loc.fix_info );
more_data = ObjRMoreData( file_in );
if( more_data ) {
return( 1 );
}
return( ObjRMoreData( file_in ) );
}
obj_rec *PObjNewLnames( uint_16 num ) {
/***********************************/
obj_rec *new;
/**/myassert( loc.state.pass == POBJ_WRITE_PASS );
new = ObjNewRec( CMD_LNAMES );
new->d.lnames.first_idx = loc.lnames_idx + 1;
new->d.lnames.num_names = num;
loc.lnames_idx += num;
PObjEnqueue( new );
return( new );
}
obj_rec *PObjNewSegdef( void ) {
/****************************/
obj_rec *new;
/**/myassert( loc.state.pass == POBJ_WRITE_PASS );
new = ObjNewRec( CMD_SEGDEF );
new->d.segdef.idx = loc.segdef_idx + 1;
++loc.segdef_idx;
PObjEnqueue( new );
return( new );
}
obj_rec *PObjNewGrpdef( void ) {
/****************************/
obj_rec *new;
/**/myassert( loc.state.pass == POBJ_WRITE_PASS );
new = ObjNewRec( CMD_GRPDEF );
new->d.grpdef.idx = loc.grpdef_idx + 1;
++loc.grpdef_idx;
PObjEnqueue( new );
return( new );
}
qdesc *PObjPubdefQueue( void ) {
/****************************/
/*
This is used by pubdef.c to get the queue of PUBDEF records. It is possible
for pubdef.c to munch this queue any way it likes. Of course, a call to
this must be made BEFORE the last_defn record is stumbled on in the
WRITE_PASS.
*/
/**/myassert( loc.state.pass == POBJ_WRITE_PASS );
return( &loc.pub );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?