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 + -
显示快捷键?