main.c

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

C
1,316
字号
/****************************************************************************
*
*                            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:  WASM top level module + command line parser
*
****************************************************************************/


#include "asmglob.h"
#include <fcntl.h>
#include <unistd.h>
#ifdef __WATCOMC__
  #include <process.h>
#endif
#include <ctype.h>

#include "asmalloc.h"
#include "asmins.h"
#include "fatal.h"
#include "asmdefs.h"
#include "asmexpnd.h"
#include "objprs.h"
#include "genmsomf.h"
#include "directiv.h"
#include "womputil.h"
#include "swchar.h"
#include "asminput.h"
#include "asmerr.h"

#ifdef __OSI__
  #include "ostype.h"
#endif

extern void             Fatal( unsigned msg, ... );
extern void             ObjRecInit( void );
extern void             DelErrFile( void );
extern void             PrintfUsage( int first_ln );
extern void             MsgPrintf1( int resourceid, char *token );

extern const char       *FingerMsg[];

File_Info               AsmFiles;       // files information
pobj_state              pobjState;      // object file information for WOMP

struct  option {
    char        *option;
    unsigned    value;
    void        (*function)( void );
};

static struct SWData {
    bool register_conventions;
    bool protect_mode;
    int cpu;
    int fpu;
} SWData = {
    TRUE,  // register conventions
    FALSE, // real mode CPU instructions set
    0,     // default CPU 8086
    -1     // unspecified FPU
};

#define MAX_NESTING 15
#define BUF_SIZE 512

static char             ParamBuf[ BUF_SIZE ];
static unsigned char    SwitchChar;
static unsigned         OptValue;
static char             *OptScanPtr;
static char             *OptParm;
static char             *ForceInclude = NULL;

global_options Options = {
    /* sign_value       */          FALSE,
    /* stop_at_end      */          FALSE,
    /* quiet            */          FALSE,
    /* banner_printed   */          FALSE,
    /* debug_flag       */          FALSE,
    /* naming_convention*/          ADD_USCORES,
    /* floating_point   */          DO_FP_EMULATION,
    /* output_comment_data_in_code_records */   TRUE,

    /* error_count      */          0,
    /* warning_count    */          0,
    /* error_limit      */          20,
    /* warning_level    */          2,
    /* warning_error    */          FALSE,
    /* build_target     */          NULL,

    /* code_class       */          NULL,
    /* data_seg         */          NULL,
    /* text_seg         */          NULL,
    /* module_name      */          NULL,

#ifdef DEBUG_OUT
    /* debug            */          FALSE,
#endif
    /* default_name_mangler */      NULL,
    /* allow_c_octals   */          FALSE,
    /* emit_dependencies */         TRUE,
    /* Watcom C name mangler */     TRUE,
    /* stdcall at number */         TRUE,
    /* mangle stdcall   */          TRUE
};

static char *CopyOfParm( void )
/*****************************/
{
    unsigned    len;

    len = OptScanPtr - OptParm;
    memcpy( ParamBuf, OptParm, len );
    ParamBuf[ len ] = '\0';
    return( ParamBuf );
}

static void StripQuotes( char *fname )
/************************************/
{
    char *s;
    char *d;

    if( *fname == '"' ) {
        // string will shrink so we can reduce in place
        d = fname;
        for( s = d + 1; *s && *s != '"'; ++s ) {
            // collapse double backslashes, only then look for escaped quotes
            if( s[0] == '\\' && s[1] == '\\' ) {
                ++s;
            } else if( s[0] == '\\' && s[1] == '"' ) {
                ++s;
            }
            *d++ = *s;
        }
        *d = '\0';
    }
}

static char *GetAFileName( void )
/*******************************/
{
    char *fname;
    fname = CopyOfParm();
    StripQuotes( fname );
    return( fname );
}

static void SetTargName( char *name, unsigned len )
/*************************************************/
{
    char        *p;

    if( Options.build_target != NULL ) {
        AsmFree( Options.build_target );
        Options.build_target = NULL;
    }
    if( name == NULL || len == 0 )
        return;
    Options.build_target = AsmAlloc( len + 1 );
    p = Options.build_target;
    while( len != 0 ) {
        *p++ = toupper( *name++ );
        --len;
    }
    *p++ = '\0';
}

static void SetCPUPMC( void )
/***************************/
{
    char                *tmp;

    for( tmp=OptParm; tmp < OptScanPtr; tmp++ ) {
        if( *tmp == 'p' ) {
            if( SWData.cpu >= 2 ) {         // set protected mode
                SWData.protect_mode = TRUE;
            } else {
                MsgPrintf1( MSG_CPU_OPTION_INVALID, CopyOfParm() );
            }
        } else if( *tmp == 'r' ) {
            if( SWData.cpu >= 3 ) {  // set register calling convention
                SWData.register_conventions = TRUE;
            } else {
                MsgPrintf1( MSG_CPU_OPTION_INVALID, CopyOfParm() );
            }
        } else if( *tmp == 's' ) {
            if( SWData.cpu >= 3 ) {  // set stack calling convention
                SWData.register_conventions = FALSE;
            } else {
                MsgPrintf1( MSG_CPU_OPTION_INVALID, CopyOfParm() );
            }
        } else if( *tmp == '"' ) {                             // set default mangler
            char *dest;
            tmp++;
            dest = strchr(tmp, '"');
            if( Options.default_name_mangler != NULL ) {
                AsmFree( Options.default_name_mangler );
            }
            Options.default_name_mangler = AsmAlloc( dest - tmp + 1 );
            dest = Options.default_name_mangler;
            for( ; *tmp != '"'; dest++, tmp++ ) {
                *dest = *tmp;
            }
            *dest = NULLC;
        } else {
            MsgPrintf1( MSG_UNKNOWN_OPTION, CopyOfParm() );
            exit( 1 );
        }
    }
    if( SWData.cpu < 2 ) {
        SWData.protect_mode = FALSE;
        SWData.register_conventions = TRUE;
    } else if( SWData.cpu < 3 ) {
        SWData.register_conventions = TRUE;
    }
}

static void SetCPU( void )
/************************/
{
    SWData.cpu = OptValue;
    SetCPUPMC();
}

static void SetFPU( void )
/************************/
{
    switch( OptValue ) {
    case 'i':
        Options.floating_point = DO_FP_EMULATION;
        break;
    case '7':
        Options.floating_point = NO_FP_EMULATION;
        break;
    case 'c':
        Options.floating_point = NO_FP_ALLOWED;
        break;
    case 0:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
        SWData.fpu = OptValue;
        break;
    }
}

static char memory_model = 0;

static void SetMM( void )
/***********************/
{
    char buffer[20];

    switch( OptValue ) {
    case 'c':
    case 'f':
    case 'h':
    case 'l':
    case 'm':
    case 's':
    case 't':
        break;
    default:
        strcpy( buffer, "/m" );
        strcat( buffer, (char *)&OptValue );
        MsgPrintf1( MSG_UNKNOWN_OPTION, buffer );
        exit( 1 );
    }

    memory_model = OptValue;
}

static void SetMemoryModel( void )
/********************************/
{
    char buffer[20];
    char *model;

    switch( memory_model ) {
    case 'c':
        model = "COMPACT";
        break;
    case 'f':
        model = "FLAT";
        break;
    case 'h':
        model = "HUGE";
        break;
    case 'l':
        model = "LARGE";
        break;
    case 'm':
        model = "MEDIUM";
        break;
    case 's':
        model = "SMALL";
        break;
    case 't':
        model = "TINY";
        break;
    default:
        return;
    }

    strcpy( buffer, ".MODEL " );
    strcat( buffer, model );
    InputQueueLine( buffer );
}

static int isvalidident( char *id )
/*********************************/
{
    char *s;
    char lwr_char;

    if( isdigit( *id ) )
        return( ERROR ); /* can't start with a number */
    for( s = id; *s != '\0'; s++ ) {
        lwr_char = tolower( *s );
        if( !( lwr_char == '_' || lwr_char == '.' || lwr_char == '$'
                || lwr_char == '@' || lwr_char == '?'
                || isdigit( lwr_char )
                || islower( lwr_char ) ) ) {
            return( ERROR );
        }
    }
    return( NOT_ERROR );
}

static void add_constant( char *string )
/**************************************/
{
    char *tmp;
    char *one = "1";

    tmp = strchr( string, '=' );
    if( tmp == NULL ) {
        tmp = strchr( string, '#' );
        if( tmp == NULL ) {
            tmp = one;
        } else {
            *tmp = '\0';
            tmp++;
        }
    } else {
        *tmp = '\0';
        tmp++;
    }

    if( isvalidident( string ) == ERROR ) {
        AsmError( SYNTAX_ERROR ); // fixme
        return;
    }

    StoreConstant( string, tmp, FALSE ); // don't allow it to be redef'd
}

static void get_fname( char *token, int type )
/********************************************/
/*
 * figure out the source file name & store it in AsmFiles
 * fill in default object file name if it is null
 */
{
    char        *def_drive, *def_dir, *def_fname, *def_ext;
    char        *drive, *dir, *fname, *ext;
    char        buffer[ _MAX_PATH2 ];
    char        buffer2[ _MAX_PATH2 ];
    char        name [ _MAX_PATH  ];
    char        msgbuf[80];

    /* get filename for source file */

    if( type == ASM ) {
        if( token == NULL ) {
            MsgGet( SOURCE_FILE, msgbuf );
            Fatal( MSG_CANNOT_OPEN_FILE, msgbuf );
        }
        if( AsmFiles.fname[ASM] != NULL ) {
            Fatal( MSG_TOO_MANY_FILES );
        }

        _splitpath2( token, buffer, &drive, &dir, &fname, &ext );
        if( *ext == '\0' ) {
            ext = ASM_EXT;
        }
        _makepath( name, drive, dir, fname, ext );
        AsmFiles.fname[ASM] = AsmAlloc( strlen( name ) + 1 );
        strcpy( AsmFiles.fname[ASM], name );

        _makepath( name, drive, dir, NULL, NULL );
        /* add the source path to the include path */
        AddStringToIncludePath( name );

        if( AsmFiles.fname[OBJ] == NULL ) {
            /* set up default object and error filename */
            ext = OBJ_EXT;
            _makepath( name, NULL, NULL, fname, ext );
        } else {
            _splitpath2( AsmFiles.fname[OBJ], buffer2, &def_drive,
                         &def_dir, &def_fname, &def_ext );
            if( *def_fname == NULLC )
                def_fname = fname;
            if( *def_ext == NULLC )
                def_ext = OBJ_EXT;

            _makepath( name, def_drive, def_dir, def_fname, def_ext );
            AsmFree( AsmFiles.fname[OBJ] );
        }
        AsmFiles.fname[OBJ] = AsmAlloc( strlen( name ) + 1 );
        strcpy( AsmFiles.fname[OBJ], name );

        if( AsmFiles.fname[ERR] == NULL ) {

⌨️ 快捷键说明

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