objemit.c

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

C
807
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "disasm.h"
#include "wdismsg.h"


static  char            *RetFMacro[] = {
        "            MACRO   POP_COUNT",
    "                LOCAL   DUMMY",
    "                DUMMY   PROC FAR",
    "                RET     POP_COUNT",
    "                DUMMY   ENDP",
    "                ENDM",
    NULL
};


static char *DOSAlignTxt[] = {
    "SEGMENT", /* used for COMDAT's */
    "BYTE",
    "WORD",
    "PARA",
    "PAGE",
    "DWORD",
    "PAGE4K",
};

static char *UnixAlignTxt[] = {
    "section", /* used for COMDAT's */
    "1",
    "2",
    "16",
    "256",
    "4",
    "4096",
};


static char *MatchTxt[] = {
    "NONE",
    "ANY",
    "SIZE",
    "EXACT",
};

static char *AllocTxt[] = {
    NULL,
    "FAR CODE",
    "FAR DATA",
    "CODE32",
    "DATA32",
};


/*
 * Static function prototypes
 */
static  void            EmitSegAlign( void );
static  void            EmitSegCombine( void );
static  void            EmitOrg( uint_32 origin );
static  void            EmitRetFMacro( void );


void  EmitModule()
/****************/

{
    char                *name;
    import_sym          *imp;
    char                sp_buf[ _MAX_PATH2 ];
    char                *root_name;

    if( ( Options & FORM_ASSEMBLER ) == 0 ) {
        EmitNL();
        DoEmit( MSG_MODULE );
        EmitLine( Mod->name );
        if( Mod->main ) {
            EmitLine( "MAIN MODULE " );
        }
        if( Mod->start != NULL ) {
            DoEmit( MSG_START_ADDR );
            name = GetFixName( Mod->start );
            if( name == NULL ) {
                name = NewName( Mod->start );
            }
            Emit( name );
            EmitNL();
        }
    } else {
        _splitpath2( Mod->name, sp_buf, NULL, NULL, &root_name, NULL );
        if( DO_UNIX ) {
            EmitBlanks( LABEL_LEN );
            EmitSpaced( ".file", OPCODE_LEN );
            Emit( "\"" );
            Emit( root_name );
            Emit( "\"" );
            EmitNL();
        } else {
            if( RetFarUsed ) {
                EmitRetFMacro();
            }
            if( Is32BitObj ) EmitLine( ".386p" );
            EmitBlanks( LABEL_LEN );
            EmitSpaced( "NAME", OPCODE_LEN );
            EmitLine( root_name );
        }
        if( ( Options & FORM_DO_WTK )  &&  HaveWtk() ) {
            Emit( "INCLUDE" );
            EmitBlanks( LABEL_LEN - 7 );
            EmitLine( "67MACROS.EQU" );
        }
    }
    for( imp = Mod->imports; imp != NULL; imp = imp->next_imp ) {
        switch( imp->class ) {
        case TYPE_IMPORT:
            if( !DO_UNIX
                && ( Options & FORM_ASSEMBLER )
                && imp->public
                && !imp->exported
                && strcmp( imp->name, WTLBASEStr ) != 0 ) {
                EmitBlanks( LABEL_LEN );
                EmitSpaced( "EXTRN", OPCODE_LEN );
                EmitSym( imp->name, 0 );
                Emit( ":BYTE" );        // so that output would assemble
                EmitNL();
            }
            break;
        case TYPE_COMDEF:
            if( DO_UNIX ) {
                if( imp->public ) {
                    EmitBlanks( LABEL_LEN );
                    EmitSpaced( ".globl", OPCODE_LEN );
                    EmitLine( imp->name );
                }
                EmitBlanks( LABEL_LEN );
                EmitSpaced( ".lcomm", OPCODE_LEN );
                EmitSym( imp->name, 0 );
                Emit( ", " );
            } else {
                if( imp->public ) {
                    EmitBlanks( LABEL_LEN );
                    EmitSpaced( "COMM", OPCODE_LEN );
                } else {
                    if( Options & FORM_ASSEMBLER ) {
                        DoEmitError( MSG_LCL_COMM_WONT_ASM );
                    }
                    EmitBlanks( LABEL_LEN );
                    EmitSpaced( "LCOMM", OPCODE_LEN );
                }
                if( imp->far_common ) {
                    Emit( "FAR  " );
                } else {
                    Emit( "NEAR " );
                }
                EmitSym( imp->name, 0 );
                Emit( ":BYTE:" );
            }
            EmitHex( imp->u.size );
            EmitNL();
            break;
        }
        FreeSymTranslations();
    }
}


void  EmitEndMod()
/****************/

{
    EmitSrc();
    if( Options & FORM_ASSEMBLER ) {
        if( !DO_UNIX ) {
            EmitBlanks( LABEL_LEN );
            EmitLine( "END" );
        }
    } else {
        DumpSymList();
    }
}


void  EmitGroup( group *grp )
/***************************/

{
    handle              *entry;
    segment             *seg;
    bool                found;

    if( grp->name != NULL ) {
        entry = grp->list;
        found = FALSE;
        while( entry != NULL ) {
            seg = (segment *)entry->data;
            if( !found ) {
                found = TRUE;
                if( Options & FORM_ASSEMBLER ) {
                    EmitSpaced( grp->name, LABEL_LEN );
                    EmitSpaced( "GROUP", OPCODE_LEN );
                } else {
                    DoEmit( MSG_GROUP );
                    Emit( "'" );
                    Emit( grp->name );
                    Emit( "' " );
                }
            } else {
                Emit( "," );
            }
            Emit( seg->name );
            entry = entry->next_hndl;
        }
        if( found ) EmitNL();
    }
}


void  EmitSegment()
/*****************/

{
    export_sym          *exp;
    char                numbuff[ 16 ];
    group               *grp;

    if( Segment->name != NULL ) {
        if( Options & FORM_ASSEMBLER ) {
            if( DO_UNIX ) {
                if( !Segment->data_seg ) {
                    EmitLine( ".text" );
                } else if( stricmp( Segment->name, "_BSS" ) == 0 ) {
                    EmitLine( ".bss" );
                } else {
                    EmitLine( ".data" );
                }
                if( Segment->class == TYPE_SEGMENT ) {
                    EmitBlanks( LABEL_LEN );
                    Emit( ".align " );
                    EmitLine( UnixAlignTxt[ _SegAlign( Segment ) ] );
                } else {
                    //NYI: don't know what to do with comdat's
                    EmitNL();
                }
            } else {
                if( Segment->class == TYPE_COMDAT ) {
                    if( Options & FORM_ASSEMBLER ) {
                        DoEmitError( MSG_COMDAT_WONT_ASM );
                    }
                    EmitSym( Segment->name, LABEL_LEN );
                    EmitSpaced( "COMDAT", OPCODE_LEN );
                } else {
                    EmitSpaced( Segment->name, LABEL_LEN );
                    EmitSpaced( "SEGMENT", OPCODE_LEN );
                }
                EmitSegAlign();
                EmitSegCombine();
                EmitSegUse();
                EmitSegAccess();
                if( Segment->class == TYPE_SEGMENT ) {
                    Emit( "'" );
                    Emit( Segment->u.seg.class_name );
                    Emit( "'" );
                }
                EmitNL();
                if( !Segment->data_seg ) {
                    EmitBlanks( LABEL_LEN );
                    Emit( "ASSUME  CS:" );
                    grp = Segment->grouped;
                    if( grp != NULL ) {
                        Emit( grp->name );
                    } else {
                        EmitSegName( Segment, 0 );
                    }
                    EmitLine( ",DS:DGROUP,SS:DGROUP" );
                }
            }
            exp = Segment->exports;
            while( exp != NULL ) {
                if( exp->public ) {
                    EmitBlanks( LABEL_LEN );
                    if( DO_UNIX ) {
                        EmitSpaced( ".globl", OPCODE_LEN );
                    } else {
                        EmitSpaced( "PUBLIC", OPCODE_LEN );
                    }
                    EmitSym( exp->name, 0 );
                    EmitNL();
                }
                exp = exp->next_exp;
            }
        } else {
            EmitNL();
            if( Segment->class == TYPE_COMDAT ) {
                DoEmit( MSG_COMDAT );
            } else {
                DoEmit( MSG_SEGMENT );
            }
            EmitSegName( Segment, 0 );
            Emit( " " );
            EmitSegAlign();
            EmitSegUse();
            EmitSegAccess();
            if( _Size64K( Segment ) ) {
                strcpy( numbuff, "10000" );
            } else {
                EmitAddr( Segment->size, WORD_SIZE, numbuff );
            }
            SubStrEmit( MSG_BYTES, numbuff, 's' );
            if( Segment->offset != BAD_OFFSET ) {
                DoEmit( MSG_LOCATION );
                EmitAddr( Segment->address, WORD_SIZE, NULL );
                IToHS( numbuff, Segment->offset, 1 );
                numbuff[1] = NULLCHAR;
                Emit( numbuff );
            }
            EmitNL();
        }
    }
}


static  void  EmitSegAlign( void )
/********************************/

{
    unsigned    align;

    align = (Segment->class == TYPE_COMDAT)
                        ? _ComdatAlign( Segment ) : _SegAlign( Segment );
    Emit( DOSAlignTxt[ align ] );
    Emit( " " );
}


static  void  EmitSegUse( void )
/******************************/

{
    if( Segment->class == TYPE_COMDAT ) {
        Emit( MatchTxt[ _ComdatMatch( Segment ) ] );
        Emit( " " );
        if( Segment->u.com.grp != NULL ) {
            Emit( "'" );
            Emit( Segment->u.com.grp->name );
            if( Segment->u.com.seg != NULL ) {
                Emit( ":" );
                Emit( Segment->u.com.seg->name );
            }
            Emit( "'" );
        } else if( Segment->u.com.seg != NULL ) {
            Emit( "'" );
            Emit( Segment->u.com.seg->name );
            Emit( "'" );
        } else {
            Emit( AllocTxt[ _ComdatAlloc( Segment ) ] );
        }
    } else if( Segment->use_32 ) {
        Emit( "USE32" );
    } else if( Is32BitObj ) {
        Emit( "USE16" );
    }
    Emit( " " );
}


static void EmitSegAccess( void )
/*******************************/
{
    if( IsPharLap && Segment->access_valid ) {
        switch( Segment->access_attr ) {
        case EASY_READ_ONLY:    Emit( "RO " );  break;

⌨️ 快捷键说明

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