write.c

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

C
1,166
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Write translated object module.
*
****************************************************************************/


#include "asmglob.h"
#include <errno.h>
#include <ctype.h>
#include <time.h>

#include "asmsym.h"
#include "asmins.h"
#include "asmalloc.h"
#include "fatal.h"
#include "asmdefs.h"
#include "asmeval.h"
#include "objio.h"
#include "objprs.h"
#include "fixup.h"
#include "autodept.h"
#include "mangle.h"
#include "namemgr.h"  // WOMP callback NameGet routine declaration
#include "directiv.h"
#include "queues.h"
#include "womputil.h"
#include "asmlabel.h"
#include "asminput.h"

#include "myassert.h"


// use separate fixupp and fixupp32 records
// fixupp32 record is used only for FIX_OFFSET386 and FIX_POINTER386 fixup
// it is for better compatibility with MASM
#define SEPARATE_FIXUPP_16_32 1

extern void             CheckForOpenConditionals( void );
extern void             set_cpu_parameters( void );
extern void             set_fpu_parameters( void );
extern void             CheckProcOpen( void );
extern void             CmdlParamsInit( void );
extern void             PrintStats( void );

extern symbol_queue     Tables[];       // tables of definitions
extern struct fixup     *FixupListHead; // head of list of fixups ( from WOMP )
extern struct fixup     *FixupListTail;
extern uint_32          BufSize;
extern obj_rec          *ModendRec;     // Record for Modend

extern int              MacroExitState;
extern int              in_prologue;

int                     MacroLocalVarCounter = 0; // counter for temp. var names
char                    Parse_Pass;     // phase of parsing
char                    write_to_file;  // write if there is no error
unsigned long           LineNumber;
char                    Modend;         // end of module is reached
int_8                   DefineProc;     // TRUE if the definition of procedure
                                        // has not ended
dir_node                *CurrProc;      // current procedure
int_8                   Use32;          // if 32-bit code is use
unsigned long           PassTotal;      // Total number of ledata bytes generated
int_8                   PhaseError;
char                    EndDirectiveFound = FALSE;

extern uint             segdefidx;      // Number of Segment definition
extern uint             extdefidx;      // Number of Extern definition

static char             **NameArray;

global_vars     Globals = { 0, 0, 0, 0, 0, 0, 0 };

static FNAME            *FNames = NULL;
static unsigned long    lastLineNumber;

const FNAME *AddFlist( char const *name )
/***************************************/
{
    FNAME   *flist;
    FNAME   *last;
    int     index;
    char    *fname;
    char    buff[2*_MAX_PATH];

    index = 0;
    fname = _getFilenameFullPath( buff, name, sizeof( buff ) );
    last = FNames;
    for( flist = last; flist != NULL; flist = flist->next ) {
        if( strcmp( name, flist->name ) == 0 )
            return( flist );
        if( strcmp( fname, flist->fullname ) == 0 )
            return( flist );
        index++;
        last = flist;
    }
    flist = (FNAME *)AsmAlloc( sizeof( FNAME ) );
    flist->name = (char *)AsmAlloc( strlen( name ) + 1 );
    strcpy( flist->name, name );
    flist->fullname = (char *)AsmAlloc( strlen( fname ) + 1 );
    strcpy( flist->fullname, fname );
    flist->mtime = _getFilenameTimeStamp( fname );
    flist->next = NULL;
    if( FNames == NULL ) {
        FNames = flist;
    } else {
        last->next = flist;
    }
    return( flist );
}

static void FreeFlist( void )
/***************************/
{
    const FNAME   *curr;
    const FNAME   *last;

    for( curr = FNames; curr != NULL; ) {
        AsmFree( curr->fullname );
        AsmFree( curr->name );
        last = curr;
        curr = curr->next;
        AsmFree( (void *)last );
    }
    FNames = NULL;
    return;
}

static void write_init( void )
/****************************/
{
    BufSize       = 0;
    FixupListHead = NULL;
    FixupListTail = NULL;
    ModendRec     = NULL;
    CurrProc      = NULL;
    DefineProc    = FALSE;
    Use32         = FALSE;
    write_to_file = TRUE;

    IdxInit();
    LnameInsert( "" );

    ModuleInit();
    FixInit();
}

static void write_fini( void )
/****************************/
{
    FixFini();
    FreeFlist();
}

void OutSelect( bool starts )
/***************************/
{
    obj_rec             *objr;
    unsigned long       curr;

    if( starts ) {
        if( !Options.output_comment_data_in_code_records || Globals.data_in_code
            || !Globals.code_seg )
            return;
        Globals.sel_start = GetCurrAddr();
        Globals.data_in_code = TRUE;
    } else {
        if( !Options.output_comment_data_in_code_records || !Globals.data_in_code )
            return;
        Globals.sel_idx = GetSegIdx( &CurrSeg->seg->sym );
        Globals.data_in_code = FALSE;

        if( (Parse_Pass > PASS_1) && !PhaseError ) {
            objr = ObjNewRec( CMD_COMENT );
            objr->d.coment.attr = 0x80;
            objr->d.coment.class = CMT_DISASM_DIRECTIVE;

            ObjAllocData( objr, 11 );
            curr = GetCurrAddr();
            if( (Globals.sel_start > 0xffffUL) || (curr > 0xffffUL) ) {
                ObjPut8( objr, DDIR_SCAN_TABLE_32 );
                ObjPutIndex( objr, Globals.sel_idx );
                ObjPut32( objr, Globals.sel_start );
                ObjPut32( objr, GetCurrAddr() );
            } else {
                ObjPut8( objr, DDIR_SCAN_TABLE );
                ObjPutIndex( objr, Globals.sel_idx );
                ObjPut16( objr, Globals.sel_start );
                ObjPut16( objr, GetCurrAddr() );
            }
            ObjTruncRec( objr );
            write_record( objr, TRUE );
        }
        Globals.sel_idx = 0;
        Globals.sel_start = 0;
    }
}

static void write_end_of_pass1( void )
/************************************/
{
    obj_rec     *objr;

    objr = ObjNewRec( CMD_COMENT );
    objr->d.coment.attr = 0x00;
    objr->d.coment.class = CMT_MS_END_PASS_1;
    ObjAttachData( objr, "\x001", 1 );
    write_record( objr, TRUE );
}

static void write_dosseg( void )
/******************************/
{
    obj_rec     *objr;

    objr = ObjNewRec( CMD_COMENT );
    objr->d.coment.attr = 0x80;
    objr->d.coment.class = CMT_DOSSEG;
    ObjAttachData( objr, "", 0 );
    write_record( objr, TRUE );
}

static void write_lib( void )
/***************************/
{
    obj_rec             *objr;
    struct dir_node     *curr;
    char                *name;

    for( curr = Tables[TAB_LIB].head; curr; curr = curr->next ) {
        name = curr->sym.name;
        objr = ObjNewRec( CMD_COMENT );
        objr->d.coment.attr = 0x80;
        objr->d.coment.class = CMT_DEFAULT_LIBRARY;
        ObjAttachData( objr, name, strlen( name ) );
        write_record( objr, TRUE );
    }
}

static void write_one_export( dir_node *dir )
/*******************************************/
{
    obj_rec     *objr;
    char        *name;
    proc_info   *info;

    info = dir->e.procinfo;
    if( info->visibility == VIS_EXPORT ) {
        objr = ObjNewRec( CMD_COMENT );
        objr->d.coment.attr = 0x00;
        objr->d.coment.class = CMT_DLL_ENTRY;

        name = Mangle( &dir->sym, NULL );

        ObjAllocData( objr, 4 + strlen( name )  );
        ObjPut8( objr, 2 );
        ObjPut8( objr, 0 );             // temporary
        ObjPutName( objr, name, strlen( name ) );
        ObjPut8( objr, 0 );
        write_record( objr, TRUE );

        AsmFree( name );
    }
}

static void write_export( void )
/******************************/
{
    dir_node    *dir;

    for( dir = Tables[TAB_PROC].head; dir != NULL; dir = dir->next ) {
        write_one_export( dir );
    }
}


static void write_grp( void )
/***************************/
{
    dir_node        *curr;
    dir_node        *segminfo;
    seg_list        *seg;
    obj_rec         *grp;
    unsigned long   line_num;
    char            writeseg;
    unsigned        i = 1;

    line_num = LineNumber;

    for( curr = Tables[TAB_GRP].head; curr; curr = curr->next, i++ ) {

        grp = ObjNewRec( CMD_GRPDEF );
        /**/myassert( grp != NULL );

        grp->d.grpdef.idx = curr->e.grpinfo->idx;

        /* we might need up to 3 bytes for each seg in dgroup and 1 byte for
           the group name index */
        ObjAllocData( grp, 1 + 3 * curr->e.grpinfo->numseg );
        ObjPut8( grp, GetLnameIdx( curr->sym.name ) );

        for( seg = curr->e.grpinfo->seglist; seg; seg = seg->next ) {
            writeseg = TRUE;
            segminfo = (dir_node *)(seg->seg);
            if( ( segminfo->sym.state != SYM_SEG ) || ( segminfo->sym.segment == NULL ) ) {
                LineNumber = curr->line_num;
                AsmErr( SEG_NOT_DEFINED, segminfo->sym.name );
                write_to_file = FALSE;
                LineNumber = line_num;
            } else {
                ObjPut8( grp, GRP_SEGIDX );
                ObjPutIndex( grp, segminfo->e.seginfo->segrec->d.segdef.idx);
            }
        }
        if( write_to_file ) {
            ObjTruncRec( grp );
            write_record( grp, TRUE );
        } else {
            ObjKillRec( grp );
        }
    }
}

static void write_seg( void )
/***************************/
{
    dir_node    *curr;
    obj_rec     *objr;
    uint        seg_index;
    uint        total_segs = 0;

    for( curr = Tables[TAB_SEG].head; curr; curr = curr->next ) {
        if( ( curr->sym.segment == NULL )
          && ( curr->e.seginfo->group == NULL ) )
            AsmErr( SEG_NOT_DEFINED, curr->sym.name );
        total_segs++;
    }

    for( seg_index = 1; seg_index <= total_segs; seg_index++ ) {
        /* find segment by index */
        for( curr = Tables[TAB_SEG].head; curr; curr = curr->next ) {
            if( GetSegIdx( curr->sym.segment ) == seg_index ) {
                break;
            }
        }
        if( curr == NULL )
            continue;
        if( curr->sym.state != SYM_SEG ) {
            AsmErr( SEG_NOT_DEFINED, curr->sym.name );
            continue;
        }
        objr = curr->e.seginfo->segrec;
        objr->is_32 = TRUE;
        objr->d.segdef.ovl_name_idx = 1;
        objr->d.segdef.seg_name_idx = GetLnameIdx( curr->sym.name );
        write_record( objr, FALSE );
        if( curr->e.seginfo->iscode == SEGTYPE_ISCODE ) {
            obj_rec     *rec;

            rec = ObjNewRec( CMD_COMENT );
            rec->d.coment.attr = CMT_TNP;
            rec->d.coment.class = CMT_LINKER_DIRECTIVE;
            ObjAllocData( rec, 3  );
            ObjPut8( rec, LDIR_OPT_FAR_CALLS );

⌨️ 快捷键说明

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