write.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,166 行 · 第 1/3 页

C
1,166
字号
            ObjPutIndex( rec, seg_index );
            write_record( rec, TRUE );
        }
    }
}

static void write_lnames( void )
/******************************/
{
    obj_rec     *objr;
    uint        total_size = 0;
    char        *lname = NULL;

    objr = ObjNewRec( CMD_LNAMES );
    objr->d.lnames.first_idx = 1;
    objr->d.lnames.num_names = LnamesIdx;
    total_size = GetLnameData( &lname );
    if( total_size > 0 ) {
        ObjAttachData( objr, lname, total_size );
    }
    ObjCanFree( objr );
    write_record( objr, TRUE );
}

static void write_global( void )
/******************************/
/* turn the globals into either externs or publics as appropriate */
{
    GetGlobalData();
}

static dir_node *write_extdef( dir_node *start )
/**********************************************/
{
    obj_rec     *objr;
    dir_node    *curr;
    uint        num;
    uint        total_size;
    uint        i;
    char        name[MAX_EXT_LENGTH];
    char        buffer[MAX_LINE_LEN];
    uint        len;

    num = 0;
    total_size = 0;
    i = 0;

    objr = ObjNewRec( CMD_EXTDEF );
    objr->d.extdef.first_idx = 0;

    for( curr = start;
        ( curr != NULL ) && ( curr->e.extinfo->comm == start->e.extinfo->comm );
        curr = curr->next ) {
        Mangle( &curr->sym, buffer );
        len = strlen( buffer );

        if( total_size + len >= MAX_EXT_LENGTH )
            break;
        total_size += len + 2;
        num++;

        name[i] = (char)len;
        i++;
        memcpy( name+i, buffer, len );
        i += len;
        name[i++] = 0;      // for the type index
    }
    ObjAttachData( objr, name, total_size );
    if( num != 0 ) {
        objr->d.extdef.num_names = num;
        write_record( objr, TRUE );
    } else {
        ObjKillRec( objr );
    }
    return( curr );
}

static int opsize( memtype mem_type )
/************************************/
{
    switch( mem_type ) {
    case MT_EMPTY:  return( 0 );
    case MT_SBYTE:
    case MT_BYTE:   return( 1 );
    case MT_SWORD:
    case MT_WORD:   return( 2 );
    case MT_SDWORD:
    case MT_DWORD:  return( 4 );
    case MT_FWORD:  return( 6 );
    case MT_QWORD:  return( 8 );
    case MT_TBYTE:  return( 10 );
    case MT_OWORD:  return( 16 );
    default:        return( 0 );
    }
}

#define THREE_BYTE_MAX ( (1UL << 24) - 1 )

static int get_number_of_bytes_for_size_in_commdef( unsigned long value )
/****************************************************************/
{
    /* The spec allows up to 128 in a one byte size field, but lots
       of software has problems with that, so we'll restrict ourselves
       to 127.
    */
    if( value < 128 ) {
        return( 1 );    /* 1 byte value */
    } else if( value <= USHRT_MAX ) {
        return( 3 );    /* 1 byte flag + 2 byte value */
    } else if( value <= THREE_BYTE_MAX ) {
        return( 4 );    /* 1 byte flag + 3 byte value */
    } else { // if( value <= ULONG_MAX )
        return( 5 );    /* 1 byte flag + 4 byte value */
    }
}

static dir_node *write_comdef( dir_node *start )
/**********************************************/
{
    obj_rec     *objr;
    dir_node    *curr;
    uint        num = 0;
    uint        total_size = 0;
    uint        varsize = 0;
    uint        symsize;
    uint        i = 0;
    uint        j = 0;
    char        *name;
    uint        len;
    unsigned long value;
    char        buffer[MAX_LINE_LEN];
    char        *ptr;


    objr = ObjNewRec( CMD_COMDEF );
    objr->d.comdef.first_idx = 0;

    for( curr = start;
        ( curr != NULL ) && ( curr->e.extinfo->comm == start->e.extinfo->comm );
        curr = curr->next ) {
        ptr = Mangle( &curr->sym, buffer );
        total_size += 3 + strlen( ptr );
        /* 3 = 1 for string len + 1 for type index + 1 for data type */

        varsize = opsize( curr->sym.mem_type );
        if( curr->e.comminfo->distance == T_FAR ) {
            total_size += get_number_of_bytes_for_size_in_commdef( varsize );
            total_size += get_number_of_bytes_for_size_in_commdef( curr->e.comminfo->size );
        } else {
            total_size += get_number_of_bytes_for_size_in_commdef( curr->e.comminfo->size );
        }
        num++;
    }

    if( total_size > 0 ) {
        name = AsmAlloc( total_size * sizeof( char ) );
        for( curr = start;
            ( curr != NULL ) && ( curr->e.extinfo->comm == start->e.extinfo->comm );
            curr = curr->next ) {
            ptr = Mangle( &curr->sym, buffer );
            len = strlen( ptr );
            name[i] = (char)len;
            i++;
            memcpy( name+i, ptr, len );
            i += len;
            name[i++] = 0;      // for the type index

            /* now add the data type & communal length */
            if( curr->e.comminfo->distance == T_FAR ) {
                name[i++] = COMDEF_FAR;
            } else {
                name[i++] = COMDEF_NEAR;
            }

            value = curr->e.comminfo->size;
            varsize = get_number_of_bytes_for_size_in_commdef( value );
            switch( varsize ) {
            case 1:
                break;
            case 3:
                name[i++] = COMDEF_LEAF_2;
                break;
            case 4:
                name[i++] = COMDEF_LEAF_3;
                break;
            case 5:
                name[i++] = COMDEF_LEAF_4;
                break;
            }
            if( varsize > 1 )
                varsize--; /* we already output 1 byte */

            symsize = opsize( curr->sym.mem_type );
            if( curr->e.comminfo->distance != T_FAR ) {
                value *= symsize;
            }

            for( j=0; j < varsize; j++ ) {
                name[i++] = value % ( UCHAR_MAX + 1 );
                value >>= 8;
            }

            if( curr->e.comminfo->distance == T_FAR ) {
                /* mem type always needs <= 1 byte */
                myassert( symsize < UCHAR_MAX );
                name[i++] = symsize;
            }
        }
        ObjAttachData( objr, name, total_size );
    }
    ObjCanFree( objr );
    if( num != 0 ) {
        objr->d.comdef.num_names = num;
        write_record( objr, TRUE );
    } else {
        ObjKillRec( objr );
    }
    return( curr );
}

static void write_ext_comm( void )
/********************************/
{
    dir_node    *next;

    for( next = Tables[TAB_EXT].head; next != NULL; ) {
        if( next->e.extinfo->comm == 0 ) {
            // extdef
            next = write_extdef( next );
        } else {
            // comdef
            next = write_comdef( next );
        }
    }
}

static void write_header( void )
/******************************/
{
    obj_rec     *objr;
    unsigned    len;
    char        *name;

    objr = ObjNewRec( CMD_THEADR );
    if( Options.module_name != NULL ) {
        name = Options.module_name;
    } else {
        name = ModuleInfo.srcfile->fullname;
    }
    len = strlen( name );
    ObjAllocData( objr, len + 1 );
    ObjPutName( objr, name, len );
    ObjTruncRec( objr );
    write_record( objr, TRUE );
}

static int write_modend( void )
/*****************************/
{
    if( ModendRec == NULL ) {
        AsmError( UNEXPECTED_END_OF_FILE );
        return ERROR;
    }
    write_record( ModendRec, TRUE );
    return NOT_ERROR;
}

static int write_autodep( void )
/******************************/
{
    obj_rec         *objr;
    char            buff[2*PATH_MAX + 5];
    unsigned int    len;
    const FNAME     *curr;

    if( !Options.emit_dependencies )
        return NOT_ERROR;

    for( curr = FNames; curr != NULL; curr = curr->next ) {
        objr = ObjNewRec( CMD_COMENT );
        objr->d.coment.attr = 0x80;
        objr->d.coment.class = CMT_DEPENDENCY;

        len = strlen(curr->name);
        *((time_t *)buff) = _timet2dos(curr->mtime);
        *(buff + 4) = (unsigned char)len;
        strcpy(buff + 5, curr->name);
        len += 5;

        ObjAttachData( objr, buff, len );

        write_record( objr, TRUE );
    }
    // one NULL dependency record must be on the end
    objr = ObjNewRec( CMD_COMENT );
    objr->d.coment.attr = 0x80;
    objr->d.coment.class = CMT_DEPENDENCY;
    ObjAttachData( objr, "", 0 );
    write_record( objr, TRUE );
    return NOT_ERROR;
}

void AddLinnumDataRef( void )
/***************************/
/* store a reference for the current line at the current address */
{
    struct line_num_info    *curr;
    unsigned long           line_num;

    if( in_prologue ) {
        line_num = CurrProc->line_num;
    } else {
        line_num = LineNumber;
    }
    if( line_num < 0x8000 )  {
        if( lastLineNumber != line_num ) {
            curr = AsmAlloc( sizeof( struct line_num_info ) );
            curr->number = line_num;
            curr->offset = AsmCodeAddress;
            curr->srcfile = get_curr_srcfile();

            AddLinnumData( curr );
            lastLineNumber = line_num;
        }
    }
}

static void write_linnum( void )
/******************************/
{
    struct linnum_data  *ldata;
    int                 count;
    obj_rec             *objr;
    bool                need_32;

    count = GetLinnumData( &ldata, &need_32 );
    if( count == 0 )
        return;
    if( ldata == NULL ) {
        AsmError( NO_MEMORY );
    } else {
        objr = ObjNewRec( CMD_LINNUM );
        objr->is_32 = need_32;
        objr->d.linnum.num_lines = count;
        objr->d.linnum.lines = ldata;
        objr->d.linnum.d.base.grp_idx = GetGrpIdx( GetGrp( &GetCurrSeg()->sym ) ); // fixme ?
        objr->d.linnum.d.base.seg_idx = CurrSeg->seg->e.seginfo->segrec->d.segdef.idx;
        objr->d.linnum.d.base.frame = 0; // fixme ?

        write_record( objr, TRUE );
    }
}

#ifdef SEPARATE_FIXUPP_16_32

static void divide_fixup_list( struct fixup **fl16, struct fixup **fl32 ) {
/**********************************************/
/* divide fixup record list to the 16-bit or 32-bit list of a fixup record */

    struct fixup *fix;
    struct fixup *fix16;
    struct fixup *fix32;

    fix16 = NULL;
    fix32 = NULL;
    fix = FixupListHead;
    for( fix = FixupListHead; fix != NULL; fix = fix->next ) {
        switch( fix->loc_method ) {
        case FIX_OFFSET386:
        case FIX_POINTER386:
            if( fix32 == NULL ) {
                *fl32 = fix;
            } else {
                fix32->next = fix;
            }
            fix32 = fix;
            break;
        default:
            if( fix16 == NULL ) {
                *fl16 = fix;
            } else {
                fix16->next = fix;
            }
            fix16 = fix;
            break;
        }
    }
    if( fix32 != NULL ) {
        fix32->next = NULL;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?