cmdline.c

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

C
859
字号
/****************************************************************************
*
*                            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:  Command line processing for WOMP.
*
****************************************************************************/


#include <ctype.h>
#include <direct.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>      /* for SEEK_SET */
#include <malloc.h>     /* for _fheapshrink/_nheapshrink */
#include <conio.h>
#include "banner.h"
#include "womp.h"
#include "cmdline.h"
#include "memutil.h"
#include "genutil.h"
#include "myassert.h"
#include "watdbg.h"
#include "msdbg.h"
#include "genmsomf.h"
#include "can2txt.h"
#include "genphar.h"
#include "turbodbg.h"
#include "deflib.h"

/*
    THIS MODULE NEEDS A REWRITE!

    The interface to this module sucks bad.  (addFile's hack for
    wildcarding is especially gross.) The processing model
    should have been more along the lines of:

        // in main.c
        while( there_are_more_files_to_do() ) {
            ActionInput( ... );
                ...
            ActionOutput( ... );
                ...
                ...
            ActionRename( ... );
        }

    Main.c should not know about act_grp_t and cmdline_t in cmdline.h.
    There's no need for it.

    Then instead of wasting loads of memory by building all the stupid
    structures that we parse.  We could have simply written a state-machine
    in here.  i.e.,

    there_are_more_files_to_do() {
        if( we_are_wildcarding_a_filename ) {
            advance_to_next_wildcard_match;
            return( TRUE );
        }
        parse_any_switches_and_@includes;
        if( end_of_input ) {
            return( FALSE );
        }
        parse_a_filename;
        if( filename_has_wildcards ) {
            set we_are_wildcarding_a_filename to TRUE;
        }
        return( TRUE );
    }

    22-jul-91   DJG
*/


#define ENVVAR          "WOMP"
#define SWCHAR          '/'
#define INCCHAR         '@'
#define CMTCHAR         '#'
#define WMP_EXTENSION   ".WMP"
#define OBJ_EXTENSION   ".OBJ"
#define WILD_CARDS      "*?"    /* wild cards that may appear in filenames */

/*
    Be careful that none of these enumerated types outgrow their bitfield
    width in struct action_group.
*/

enum dbg_parsers {
    PARSE_NULL,
    PARSE_WATCOM,
    PARSE_WATCOM_70
};

enum dbg_generators {
    DGEN_NULL,
    DGEN_TXT,
    DGEN_MICROSOFT,
    DGEN_METAWARE,
    DGEN_TURBO
};

enum omf_generators {
    OGEN_NULL,
    OGEN_MICROSOFT,
    OGEN_MICROSOFT_OS2,
    OGEN_PHARLAP
};

STATIC cmdline_t    cmdLine;
STATIC act_grp_t    *curAct;    /* stack of actions */
STATIC int          headerDone;
STATIC uint_16      tempFileNum;

int BeQuiet( void ) {
    return( cmdLine.quiet );
}

STATIC void header( void ) {

    if( headerDone ) return;
    headerDone = 1;
    if( cmdLine.quiet ) return;
    PrtFmt(
banner1w( "Object Module Processor", _WOMP_VERSION_ ) "\n"
banner2( "1990" ) "\n"
banner3 "\n"
banner3a "\n"
);
}

static void waitForKey( void ) {

    char                c;

    PrtMsg( MSG_PRESS_KEY );
    c = getch();
}

#pragma aux usage aborts;
STATIC void usage( void ) {

    char        msgbuff[MAX_RESOURCE_SIZE];
    int         previous_null = 0;
    int         i;

    header();
    for( i = MSG_USE_BASE;; i++ ) {
        MsgGet( i, msgbuff );
        if( ( msgbuff[ 0 ] == '.' ) && ( msgbuff[ 1 ] == 0 ) ) break;
        if( previous_null ) {
            if( msgbuff[0] != '\0' ) {
                waitForKey();
                PrtFmt( msgbuff );
                PrtFmt( "\n" );
                previous_null = 0;
            } else break;
        } else if( msgbuff[0] == '\0' ) {
            previous_null = 1;
        } else {
            PrtFmt( msgbuff );
            PrtFmt( "\n" );
        }
    }
    exit( EXIT_FAILURE );
}

STATIC int isBreakChar( char x ) {

    if( isspace( x ) ) return( 1 );
    switch( x ) {
    case '-':
    case SWCHAR:
    case INCCHAR:
    case CMTCHAR:
    case 0:
        return( 1 );
    }
    return( 0 );
}

STATIC void getAct( int mk_new ) {

    act_grp_t   *act;

    act = curAct;
    if( act == NULL ) {
        /*
            Build the default action group
        */
        act = curAct = MemAlloc( sizeof( act_grp_t ) );
        act->next = NULL;
        act->dbg_parser = PARSE_WATCOM;
        act->dbg_generator = DGEN_METAWARE;
        act->omf_generator = OGEN_MICROSOFT;
        act->deflib = 1;
        act->quiet = 0;
        act->batch = 0;
        act->output = NULL;
        act->num_files = 0;
    } else if( act->num_files > 0 && mk_new ) {
        /* gotta create a new act_grp_t */
        act = MemAlloc( sizeof( act_grp_t ) );
        *act = *curAct;             /* copy the old info */
        act->next = curAct;         /* stack it up */
        curAct = act;
        act->num_files = 0;         /* no files in this group yet */
    }
}

STATIC char *getFile( const char ** pstr ) {

    const char  *start;
    const char  *str;
    size_t      len;
    char        *copy;

/**/myassert( pstr != NULL && *pstr != NULL );
    str = *pstr;
/**/myassert( !isBreakChar( *str ) );
    start = str;
    for(;;) {
        ++str;
        if( *str == '\0' ) break;
        if( isspace( *str ) ) break;
    }
    *pstr = str;
    len = str - start;
    copy = MemAlloc( len + 1 );
    memcpy( copy, start, len );
    copy[ len ] = 0;
    return( copy );
}

#pragma aux unrecognized aborts;
STATIC void unrecognized( char opt ) {
    char        msgbuff[MAX_RESOURCE_SIZE];

    header();
    MsgGet( MSG_SYNTAX_ERR_IN_OPT, msgbuff );
    PrtFmt( msgbuff, opt );
    PrtFmt( "\n" );
    usage();
}

STATIC const char *doParse( const char *str ) {

/**/myassert( str != NULL );
    getAct( 1 );
    switch( tolower( *str ) ) {
    case 'w':   curAct->dbg_parser = PARSE_WATCOM;      break;
    case '7':   curAct->dbg_parser = PARSE_WATCOM_70;   break;
    case '-':   curAct->dbg_parser = PARSE_NULL;        break;
    default:    unrecognized( 'p' );
    }
    return( str + 1 );
}

STATIC const char *doDebug( const char *str ) {

/**/myassert( str != NULL );
    getAct( 1 );
    switch( tolower( *str ) ) {
    case 'm':   curAct->dbg_generator = DGEN_MICROSOFT; break;
    case 'p':   curAct->dbg_generator = DGEN_METAWARE;  break;
    case 't':   curAct->dbg_generator = DGEN_TURBO;     break;
    case 'x':   curAct->dbg_generator = DGEN_TXT;       break;
    case '-':   curAct->dbg_generator = DGEN_NULL;      break;
    default:    unrecognized( 'd' );
    }
    return( str + 1 );
}

STATIC const char *doFile( const char *str ) {

/**/myassert( str != NULL );
    getAct( 1 );
    switch( tolower( *str ) ) {
    case 'm':
        curAct->omf_generator = OGEN_MICROSOFT;
        if( str[1] == '2' ) {
            curAct->omf_generator = OGEN_MICROSOFT_OS2;
            ++str;
        }
        break;
    case 'p':
        curAct->omf_generator = OGEN_PHARLAP;
        break;
    case '-':
        curAct->omf_generator = OGEN_NULL;
        break;
    default:
        unrecognized( 'f' );
    }
    return( str + 1 );
}

STATIC const char *doOutput( const char * str ) {

/**/myassert( str != NULL );
    if( *str != '=' && *str != '#' ) unrecognized( 'o' );
    ++str;
    getAct( 1 );
    if( curAct->output != NULL ) {
        MemFree( curAct->output );
    }
    if( isBreakChar( *str ) ) unrecognized( 'o' );
    curAct->output = getFile( &str );
    return( str );
}

STATIC const char *doToggle( const char *str ) {

/**/myassert( str != NULL );
    getAct( 1 );
    switch( tolower( str[-1] ) ) {
    case 'q':   curAct->quiet = ! curAct->quiet;        break;
#if 0
    case 'l':   curAct->deflib = ! curAct->deflib;      break;
#endif
    case 'b':   curAct->batch = ! curAct->batch;        break;
    default:    unrecognized( str[-1] );                break;
    }
    return( str );
}

STATIC const char *addFile( const char *str ) {

    DIR                 *parent;
    struct dirent       *direntp;
    char                sp_buf[ _MAX_PATH2 ];
    char                *drive;
    char                *dir;
    char                path[ _MAX_PATH ];
    char                *p;
    size_t              len;
    size_t              files_in_dir;

/**/myassert( str != NULL );
    getAct( 0 );
    p = getFile( &str );
    if( strpbrk( p, WILD_CARDS ) == NULL ) {
        curAct = MemRealloc( curAct, sizeof( act_grp_t ) +
            sizeof( const char * ) * curAct->num_files );
        curAct->files[ curAct->num_files ] = p;
        ++curAct->num_files;
        return( str );
    }
    /* process a wildcarded name */
    parent = opendir( p );
    if( parent == NULL ) {
        Fatal( MSG_UNABLE_TO_OPEN_FILE, p );
    }
    /*
        Since we must allocate memory for the filenames we shouldn't
        MemRealloc the curAct to a larger size at the same time.  So
        we count the number of files in the directory.
    */
    files_in_dir = 0;
    for(;;) {           /* count number of directory entries */
        direntp = readdir( parent );
        if( direntp == NULL ) break;
        ++files_in_dir;
    }
    closedir( parent );
    if( files_in_dir == 0 ) {
        Fatal( MSG_UNABLE_TO_OPEN_FILE, p );
    }
    curAct = MemRealloc( curAct, sizeof( act_grp_t ) +
        sizeof( const char * ) * ( curAct->num_files + files_in_dir - 1 ) );
    parent = opendir( p );
    if( parent == NULL ) {
        Fatal( MSG_UNABLE_TO_OPEN_FILE, p );
    }
    _splitpath2( p, sp_buf, &drive, &dir, NULL, NULL );
    MemFree( p );               /* no longer need this */
    for(;;) {
        /* we ignore any difference between the number of times we can
          loop here, and file_in_dir calc'd above */
        direntp = readdir( parent );
        if( direntp == NULL ) break;
        _makepath( path, drive, dir, direntp->d_name, NULL );
        len = strlen( path ) + 1;
        curAct->files[ curAct->num_files ] =
                                        memcpy( MemAlloc( len ), path, len );
        ++curAct->num_files;
        --files_in_dir;
        if( files_in_dir == 0 ) break;
    }
    closedir( parent );
    return( str );
}

STATIC const char *doComment( const char *str ) {

/**/myassert( str != NULL );
    while( *str != '\n' && *str != 0 ) ++str;
    return( str );
}

/*
    The next three functions (openIncludeFile, readIncludeFile, doInclude)
    require stack checking.
*/
#pragma on( check_stack );
STATIC int openIncludeFile( const char * file_name ) {

⌨️ 快捷键说明

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