cmdline.c

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

C
1,052
字号
/****************************************************************************
*
*                            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 Parser
*
****************************************************************************/


#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "linkstd.h"
#include "exeos2.h"
#include "msg.h"
#include "alloc.h"
#include "command.h"
#include "wlnkmsg.h"
#include "cmdall.h"
#include "cmdos2.h"
#include "cmdqnx.h"
#include "cmdnov.h"
#include "cmdelf.h"
#include "cmdphar.h"
#include "cmddos.h"
#include "cmdline.h"
#include "overlays.h"
#include "fileio.h"
#include "symtrace.h"
#include "reloc.h"
// #include "strtab.h"
// #include "carve.h"
// #include "permdata.h"
#include "dbgall.h"

#ifdef _INT_DEBUG
unsigned int            Debug;
#endif

extern void             GetExtraCommands( void );
static void             Crash( bool );
static void             Help( void );
static void             DoCmdParse( void );
static void             DisplayOptions( void );

static bool             ProcDosHelp( void );
static bool             ProcOS2Help( void );
static bool             ProcPharHelp( void );
static bool             ProcNovellHelp( void );
static bool             ProcQNXHelp( void );
static bool             ProcELFHelp( void );
static bool             ProcWindowsHelp( void );
static bool             ProcWinVxdHelp( void );
static bool             ProcNTHelp( void );
static void             WriteHelp( unsigned first_ln, unsigned last_ln, bool prompt );

static  parse_entry   FormatHelp[] = {
    "Dos",          ProcDosHelp,            MK_ALL,     0,
#ifdef _OS2
    "OS2",          ProcOS2Help,            MK_ALL,     0,
    "WINdows",      ProcWindowsHelp,        MK_ALL,     0,
    "VXD",          ProcWinVxdHelp,         MK_ALL,     0,
    "NT",           ProcNTHelp,             MK_ALL,     0,
#endif
#ifdef _PHARLAP
    "PHARlap",      ProcPharHelp,           MK_ALL,     0,
#endif
#ifdef _NOVELL
    "NOVell",       ProcNovellHelp,         MK_ALL,     0,
#endif
#ifdef _QNXLOAD
    "QNX",          ProcQNXHelp,            MK_ALL,     0,
#endif
#ifdef _ELF
    "ELF",          ProcELFHelp,            MK_ALL,     0,
#endif
    NULL
};

byte            Extension;
file_list **    CurrFList;
tok             Token;
commandflag     CmdFlags;
char *          Name;
sysblock *      SysBlocks;
sysblock *      LinkCommands;

static sysblock *       PrevCommand;

#define INIT_FILE_NAME  "wlink.lnk"

extern void InitCmdFile( void )
/******************************/
{
    PrevCommand = NULL;
}

extern void SetSegMask(void)
/***************************/
{
   FmtData.SegShift = 16 - FmtData.Hshift;
   FmtData.SegMask = (1 << FmtData.SegShift) - 1;
}

static void ResetCmdFile( void )
/******************************/
/* do all the initialization necessary for parsing a command file */
{
    SysBlocks = NULL;
    Extension = E_LOAD;
    Name = NULL;
    CmdFlags = CF_UNNAMED;
    Path = NULL;
    memset( &FmtData, 0, sizeof(FmtData) );
    FmtData.base = NO_BASE_SPEC;
    FmtData.objalign = NO_BASE_SPEC;
    FmtData.type = MK_ALL;
    FmtData.def_seg_flags = SEG_LEVEL_3;
    FmtData.output_raw = FALSE;
    FmtData.output_hex = FALSE;
    FmtData.Hshift = 12;   // May want different value for some 32 bit segmented modes
    FmtData.FillChar = 0;  // Default fillchar for segment alignment
    SetSegMask();
    CurrSect = Root;
    CurrFList = &Root->files;
    DBIFlag = 0;        /*  default is only global information */
}

extern void DoCmdFile( char *fname )
/**********************************/
/* start parsing the command */
{
    exe_format  possible;
    f_handle    file;
    size_t      namelen;
    unsigned    extension;

    ResetCmdFile();
    if( fname == NULL || *fname == '\0' ) {
        _ChkAlloc( fname, (10*1024) );  // arbitrarily large buffer that won't
        GetCmdLine( fname );            // be overflowed
        NewCommandSource( NULL, fname, COMMANDLINE );
    } else {
        NewCommandSource( NULL, fname, ENVIRONMENT );
    }
    if( IsStdOutConsole() ) {
        CmdFlags |= CF_TO_STDOUT;
    }
    while( *fname == ' ' ) {
        fname++;
    }
    if( QSysHelp( &Token.next ) ) {
        Help();
    }
    if( *fname == '?' ) {
        Token.next = fname + 1;       // skip question mark.
        Help();
#if defined( __UNIX__ )
    } else if( *fname == '-' ) {
#else
    } else if( *fname == '-' || *fname == '/' ) {
#endif
        if( *(fname + 1) == '?' ) {
            Token.next = fname + 2;     // skip /?
            Help();
        }
    }
    if( *fname == '\0' ) {       // go into interactive mode.
        Token.how = INTERACTIVE;
        Token.where = ENDOFLINE;
        LnkMsg( INF+MSG_PRESS_CTRL_Z, NULL );
    }
#if _DEVELOPMENT == _ON
    file = SearchPath( "nwlink.lnk" );
    if( file == NIL_HANDLE ) {
        file = SearchPath( INIT_FILE_NAME );
    }
#else
    file = SearchPath( INIT_FILE_NAME );
#endif
    if( file != NIL_HANDLE ) {
        _ChkAlloc( fname, sizeof(INIT_FILE_NAME));
        memcpy( fname, INIT_FILE_NAME, sizeof(INIT_FILE_NAME) );
        SetCommandFile( file, fname );
    }
    if( Spawn( DoCmdParse ) ) {
        Ignite();
        Suicide();
    }
    GetExtraCommands();
    if( !(LinkState & FMT_DECIDED) ) {
        /* restrict set to automatically decided ones */
#if defined( __QNX__ )
#define LAST_CHANCE ( MK_OS2_LX | MK_OS2_LE | MK_OS2_NE | MK_QNX )
#elif defined( __LINUX__ )
#define LAST_CHANCE ( MK_OS2_LX | MK_OS2_LE | MK_OS2_NE | MK_ELF )
#elif defined( __NT__ )
#define LAST_CHANCE ( MK_OS2_LX             | MK_OS2_NE | MK_WINDOWS | MK_PE | MK_DOS_EXE | MK_WIN_VXD )
#else
#define LAST_CHANCE ( MK_OS2_LX | MK_OS2_LE | MK_OS2_NE | MK_DOS_EXE | MK_PHAR_SIMPLE )
#endif
        HintFormat( LAST_CHANCE );
    } else {
        /* restrict to a unique type */
        for( possible = 1; possible != 0; possible *= 2 ) {
            if( FmtData.type & possible ) {
                FmtData.type = possible;
                break;
            }
        }
    }
    if( FmtData.type & (MK_NOVELL | MK_DOS) && LinkFlags & INC_LINK_FLAG ) {
        LnkMsg( FTL+MSG_FORMAT_BAD_OPTION, "s", "incremental" );
    }
#ifdef _NOVELL
    if( FmtData.type & MK_NOVELL ) {
        CmdNovFini();
    } else
#endif
    if( FmtData.type & MK_OVERLAYS ) {
        CmdOvlFini();
        AddObjLib( "wovl.lib", 0 );     // add a reference to wovl.lib
    }
    if( Name == NULL || !(CmdFlags & CF_HAVE_FILES) ) {
        Ignite();
        LnkMsg( FTL+MSG_NO_FILES_FOUND, NULL );
    }
    namelen = strlen( Name );
    if( MapFlags & MAP_FLAG ) {
        if( MapFName == NULL ) {
            MapFName = FileName( Name, (int) namelen, E_MAP, TRUE );
        }
    } else {
        MapFlags = 0;   // if main isn't set, don't set anything.
    }
    if( SymFileName == NULL && (CmdFlags & CF_SEPARATE_SYM ||
                   (LinkFlags & OLD_DBI_FLAG && FmtData.type & MK_COM)) ) {
        SymFileName = FileName( Name, (int) namelen, E_SYM, TRUE );
    }
    if( FmtData.make_implib && FmtData.implibname == NULL ) {
        if( FmtData.make_impfile ) {
            extension = E_LBC;
        } else {
            extension = E_LIBRARY;
        }
        FmtData.implibname = FileName( Name, (int) namelen, (byte) extension, TRUE );
    }
    CheckTraces();
    BurnUtils();
    PruneSystemList();
    NumberSections();
    DBIInit();
}

extern char * GetNextLink( void )
/*******************************/
{
    char *      cmd;

    cmd = NULL;
    _LnkFree( PrevCommand );
    if( LinkCommands != NULL ) {
        PrevCommand = LinkCommands;
        LinkCommands = LinkCommands->next;
        cmd = PrevCommand->commands;
    }
    return cmd;
}

#define PREFIX_SIZE 8

struct extra_cmd_info {
    unsigned    type;
    char        prefix[PREFIX_SIZE+1];
    bool        retry;
};

static struct extra_cmd_info ExtraCmds[] = {
        EXTRA_NAME_DIR, "name    ",     FALSE,
        EXTRA_OBJ_FILE, "file    ",     TRUE,
        EXTRA_LIB_FILE, "lib     ",     TRUE,
        EXTRA_RES_FILE, "opt res=",     FALSE,
        0,              "\0",           FALSE
};

extern void GetExtraCommands( void )
/**********************************/
{
    struct extra_cmd_info const        *cmd;
    char                                buff[ _MAX_PATH + PREFIX_SIZE ];

    cmd = ExtraCmds;
    while( cmd->prefix[0] != '\0' ) {
        for(;;) {
            memcpy( buff, cmd->prefix, PREFIX_SIZE );
            if( !GetAddtlCommand( cmd->type, buff + PREFIX_SIZE ) ) break;
            NewCommandSource( NULL, buff, COMMANDLINE );
            if( Spawn( DoCmdParse ) ) break;
            if( !cmd->retry ) break;
        }
        cmd++;
    }

}

extern void Syntax( void )
/************************/
{
    if( Token.this == NULL ) {
        LnkMsg( LOC+LINE+FTL+MSG_DIRECTIVE_ERR_BEGINNING, NULL );
    } else {
        Token.this[Token.len] = '\0';
        LnkMsg( LOC+LINE+FTL+MSG_DIRECTIVE_ERR, "s", Token.this );
    }
}

static void Crash( bool check_file )
/**********************************/
{
    char        buff[81];
    unsigned    len;
    f_handle    fp;

    if( check_file ) {
        fp = SearchPath( "wlink.hlp" );
        if( fp != NIL_HANDLE ) {
            WLPrtBanner();
            for( ;; ) {
                len = QRead( fp, buff, 80, "wlink.hlp" );
                if( len == 0 ) break;
                buff[len] = '\0';
                WriteStdOut( buff );
            }
            QClose( fp, "wlink.hlp" );
            Ignite();
            Suicide();
        }
    }
    DisplayOptions();
    Ignite();
    Suicide();
}

static void Help( void )
/**********************/
// display help, optionally allowing the user to specifiy the format he/she
// wants the help for.
{
    EatWhite();
    if( *Token.next == '?' ) {
        Crash( FALSE );
    } else if( *Token.next == '\0' || !ProcOne( FormatHelp, SEP_NO, FALSE ) ) {
        Crash( TRUE );
    } else {
        Ignite();
        Suicide();
    }
}

static void DoCmdParse( void )
/****************************/
{
    while( GetToken( SEP_END, TOK_INCLUDE_DOT ) == FALSE ) {
        if( ProcOne( Directives, SEP_NO, TRUE ) == FALSE ) {
            Syntax();
        }
        RestoreParser();
    }
}

static void WriteGenHelp( void )
/******************************/
{
    WLPrtBanner();
    WriteHelp( MSG_GENERAL_HELP_0, MSG_GENERAL_HELP_51, FALSE );
}

static void DisplayOptions( void )
/********************************/
{
    bool    isout;

    isout = FALSE;
    if( CmdFlags & CF_TO_STDOUT ) {
        isout = TRUE;
    }
    WriteGenHelp();
#if defined( _QNXLOAD ) && defined( __QNX__ )
    WriteHelp( MSG_QNX_HELP_0, MSG_QNX_HELP_15, isout );
#endif
#ifdef _EXE
    WriteHelp( MSG_DOS_HELP_0, MSG_DOS_HELP_15, isout );
#endif
#ifdef _OS2
    WriteHelp( MSG_OS2_HELP_0, MSG_OS2_HELP_31, isout );
    WriteHelp( MSG_WINDOWS_HELP_0, MSG_WINDOWS_HELP_31, isout );
    WriteHelp( MSG_WIN_VXD_HELP_0, MSG_WIN_VXD_HELP_31, isout );
    WriteHelp( MSG_NT_HELP_0, MSG_NT_HELP_31, isout );
#endif
#ifdef _PHARLAP
    WriteHelp( MSG_PHAR_HELP_0, MSG_PHAR_HELP_15, isout );
#endif
#ifdef _NOVELL
    WriteHelp( MSG_NOVELL_HELP_0, MSG_NOVELL_HELP_31, isout );
#endif
#if defined( _QNXLOAD ) && !defined( __QNX__ )
    WriteHelp( MSG_QNX_HELP_0, MSG_QNX_HELP_15, isout );
#endif
#ifdef _ELF
    WriteHelp( MSG_ELF_HELP_0, MSG_ELF_HELP_15, isout );
#endif
}

#ifdef _EXE
static bool ProcDosHelp( void )
/*****************************/
{
    WriteGenHelp();
    WriteHelp( MSG_DOS_HELP_0, MSG_DOS_HELP_15, CmdFlags & CF_TO_STDOUT );
    return( TRUE );
}
#endif
#ifdef _OS2
static bool ProcOS2Help( void )
/*****************************/
{
    WriteGenHelp();
    WriteHelp( MSG_OS2_HELP_0, MSG_OS2_HELP_31, CmdFlags & CF_TO_STDOUT );
    return( TRUE );
}

static bool ProcWindowsHelp( void )
/*********************************/
{
    WriteGenHelp();
    WriteHelp( MSG_WINDOWS_HELP_0, MSG_WINDOWS_HELP_31,
                                                CmdFlags & CF_TO_STDOUT );
    return( TRUE );
}

static bool ProcWinVxdHelp( void )
/*********************************/
{
    WriteGenHelp();
    WriteHelp( MSG_WIN_VXD_HELP_0, MSG_WIN_VXD_HELP_31,
                                                CmdFlags & CF_TO_STDOUT );
    return( TRUE );
}

static bool ProcNTHelp( void )
/****************************/
{
    WriteGenHelp();
    WriteHelp( MSG_NT_HELP_0, MSG_NT_HELP_31, CmdFlags & CF_TO_STDOUT );
    return( TRUE );
}
#endif
#ifdef _PHARLAP
static bool ProcPharHelp( void )
/******************************/
{
    WriteGenHelp();
    WriteHelp( MSG_PHAR_HELP_0, MSG_PHAR_HELP_15, CmdFlags & CF_TO_STDOUT );
    return( TRUE );
}
#endif
#ifdef _NOVELL
static bool ProcNovellHelp( void )
/********************************/
{
    WriteGenHelp();
    WriteHelp( MSG_NOVELL_HELP_0, MSG_NOVELL_HELP_31,
                                                CmdFlags & CF_TO_STDOUT );
    return( TRUE );
}
#endif
#ifdef _QNXLOAD
static bool ProcQNXHelp( void )
/*******************************/
{
    WriteGenHelp();
    WriteHelp( MSG_QNX_HELP_0, MSG_QNX_HELP_15, CmdFlags & CF_TO_STDOUT );
    return( TRUE );
}
#endif

#ifdef _ELF
static bool ProcELFHelp( void )
/*******************************/
{
    WriteGenHelp();
    WriteHelp( MSG_ELF_HELP_0, MSG_ELF_HELP_15, CmdFlags & CF_TO_STDOUT );
    return( TRUE );
}
#endif

static void PressKey( void );
static void WriteMsg( char msg_buffer[] );

static void WriteHelp( unsigned first_ln, unsigned last_ln, bool prompt )
/***********************************************************************/
{
    char        msg_buffer[RESOURCE_MAX_SIZE];
    int         previous_null = 0;

⌨️ 快捷键说明

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