cmdutils.c

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

C
1,253
字号
/****************************************************************************
*
*                            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:  Utility routines for the command line parser.
*
****************************************************************************/


#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "walloca.h"
#include "linkstd.h"
#include "loadfile.h"
#include "command.h"
#include "alloc.h"
#include "msg.h"
#include "wlnkmsg.h"
#include "fileio.h"
#include "cmdline.h"
#if !defined( __UNIX__ )
#include <direct.h>
#endif

#define _LinkerPrompt "WLINK>"

cmdfilelist *    CmdFile = NULL;

static  char            *DefExt[] = {           /* see LINK.H */
    ".lnk",
    ".map",
    ".lib",
#if defined( __UNIX__ )
    ".o",
#else
    ".obj",
#endif
    ".exe",
    ".ovl",
    ".dll",
    ".exp",
    ".nlm", /* netware loadable module  */
    ".lan", /* LAN driver               */
    ".dsk", /* disk driver              */
    ".nam", /* name space module        */
    ".msl", /* mirrored server link     */
    ".ham", /* host adapter module      */
    ".cdm", /* custom device module     */
    ".com",
    ".rex",
#if defined( __UNIX__ )
    "",
#else
    ".qnx",
#endif
    ".sym",
    ".lbc",
#if defined( __UNIX__ )
    "",
#else
    ".elf",
#endif
    ".ilk",
    ".hex",
    ".bin"
};

static bool     CheckFence( void );
static bool     MakeToken( tokcontrol, sep_type );
static void     GetNewLine( void );
static void     BackupParser( void );
static void     StartNewFile( void );

static bool WildCard( bool (*rtn)( void ), tokcontrol ctrl )
/**********************************************************/
{
#if defined( __UNIX__ )
    //opendir - readdir wildcarding not supported here.
    ctrl = ctrl;
    return rtn();
#else
    char *              p;
    char *              start;
    DIR *               dir;
    struct dirent *     dirent;
    char                drive[_MAX_DRIVE];
    char                directory[_MAX_DIR];
    char                name[_MAX_FNAME];
    char                extin[_MAX_EXT];
    char                pathin[_MAX_PATH];
    bool                wildcrd;
    bool                retval;

    wildcrd = FALSE;
    if( ctrl & TOK_IS_FILENAME ) {
        p = Token.this;
        for(;;) {               // check if wildcard
            /* end of parm: NULLCHAR or blank */
            if( *p == '\'' ) break;     // don't wildcard a quoted string.
            if( *p == '\0' ) break;
            if( *p == ' ' ) break;
            if( *p == '?' || *p == '*' ) {
                wildcrd = TRUE;
                break;
            }
            p++;
        }
    }
    if( !wildcrd ) {
        retval = rtn();
    } else {
        retval = TRUE;
        /* expand file names */
        start = tostring();
        dir = opendir( start );
        if( dir != NULL ) {
            _splitpath( start, drive, directory, NULL, NULL );
            for(;;) {
                dirent = readdir( dir );
                if( dirent == NULL ) break;
                if( dirent->d_attr &
                  (_A_HIDDEN+_A_SYSTEM+_A_VOLID+_A_SUBDIR) ) continue;
                _splitpath( dirent->d_name, NULL, NULL, name, extin );
                _makepath( pathin, drive, directory, name, extin );
                Token.this = pathin;            // dangerous?
                Token.len = strlen( pathin );
                if( !(*rtn)() ) {
                    Token.this = NULL;
                    Token.thumb = OK;   // make _sure_ we don't use token.this
                    retval = FALSE;
                    break;
                }
            }
            closedir( dir );
        } else {
            retval = rtn();
        }
        _LnkFree( start );
    }
    return retval;
#endif
}

extern bool ProcArgList( bool (*rtn)( void ), tokcontrol ctrl )
{
    return(ProcArgListEx(rtn, ctrl ,NULL));
}

extern bool ProcArgListEx( bool (*rtn)( void ), tokcontrol ctrl ,cmdfilelist *resetpoint)
/*************************************************************/
{
    bool bfilereset = FALSE;    /* did we open a file and get reset ? */

    if( GetTokenEx( SEP_LCURLY, ctrl, resetpoint, &bfilereset) ) {
        for(;;) {
            if( !WildCard( rtn, ctrl ) ) {
                return( FALSE );
            }
            if( CheckFence() ) {
                break;
            } else if( !GetTokenEx( SEP_NO, ctrl ,resetpoint, &bfilereset) ) {
                LnkMsg( LOC+LINE+ERR+MSG_BAD_CURLY_LIST, NULL );
                break;
            }
        }
    } else {
        if(resetpoint && bfilereset)
            return TRUE;
        if( GetTokenEx( SEP_NO, ctrl, resetpoint, &bfilereset) == FALSE )
            return( FALSE );
        do {
            if(resetpoint && bfilereset)
                return TRUE;
            if( !WildCard( rtn, ctrl ) ) {
                return( FALSE );
            }
        } while( GetTokenEx( SEP_COMMA, ctrl , resetpoint, &bfilereset) );
    }
    return( TRUE );
}

extern bool ProcOne( parse_entry *entry, sep_type req, bool suicide )
/*******************************************************************/
/* recognize token out of parse table, with required separator            */
/* return FALSE if no separator, Suicide if not recognized (if suicide is */
/* TRUE) otherwise use return code from action routine in matching entry  */
{
    char                *key;
    char                *ptr;
    int                 plen;
    bool                ret;
    char                keybuff[20];

    ret = GetToken( req, TOK_INCLUDE_DOT );
    if( ret == FALSE ) {
        return( ret );
    }
    while( entry->keyword != NULL ) {
        key = entry->keyword;
        ptr = Token.this;
        plen = Token.len;
        for(;;) {
            if( plen == 0 && !isupper( *key ) ) {
                if( HintFormat( entry->format ) ) {
                    ret = (*entry->rtn)();
                    CmdFlags |= entry->flags;
                } else {
                    strcpy( keybuff, entry->keyword );
                    strlwr( keybuff );
                    LnkMsg( LOC+LINE+WRN+MSG_FORMAT_BAD_OPTION, "s", keybuff );
                    ret = TRUE;
                }
                return( ret );
            }
            if( *key == '\0' || tolower( *ptr ) != tolower( *key ) ) break;
            ptr++;
            key++;
            plen--;
        }
        /* here if this is no match */
        entry++;
    }
    /* here if no match in table */
    if( suicide ) {
        Syntax();
    } else {
        Token.thumb = REJECT;       /*  try again later */
        ret = FALSE;
    }
    return( ret );
}

extern bool MatchOne( parse_entry *entry , sep_type req , char * match, int len )
/*******************************************************************/
/* recognize token out of parse table */
{
    char                *key;
    char                *ptr;
    int                 plen;
    bool                ret = FALSE;

    while( entry->keyword != NULL ) {
        key = entry->keyword;
        ptr = match;
        plen = len;
        for(;;) {
            if( plen == 0 && !isupper( *key ) ) {
                ret = TRUE;
                return ( ret );
            }
            if( *key == '\0' || tolower( *ptr ) != tolower( *key ) )
                break;
            ptr++;
            key++;
            plen--;
        }
        /* here if this is no match */
        entry++;
    }

    /* here if no match in table */
    return( ret );
}

extern ord_state getatoi( unsigned_16 * pnt )
/*******************************************/
{
    unsigned_32 value;
    ord_state   retval;

    retval = getatol( &value );
    if( retval == ST_IS_ORDINAL ) {
        if( value > 0xffff ) {
            return( ST_INVALID_ORDINAL );
        }
        *pnt = (unsigned)value;
    }
    return( retval );
}

extern ord_state getatol( unsigned_32 * pnt )
/*******************************************/
{
    char *          p;
    int             len;
    unsigned long   value;
    unsigned        radix;
    bool            isvalid;
    bool            isdig;
    bool            gotdigit;
    char            ch;

    len = Token.len;
    if( len <= 0 ) return( ST_NOT_ORDINAL );
    p = Token.this;
    gotdigit = FALSE;
    value = 0ul;
    radix = 10;
    if( *p == '0' ) {
        --len;
        if( tolower(*++p) == 'x') {
            radix = 16;
            ++p;
            --len;
        }
    }
    for( ; len != 0; --len ) {
        ch = tolower( *p++ );
        if( ch == 'k' ) {         // constant of the form 64k
            if( len > 1 || !gotdigit ) {
                return( ST_NOT_ORDINAL );
            } else {
                value <<= 10;        // value = value * 1024;
            }
        } else if( ch == 'm' ) {        // constant of the form 64M
            if( len > 1 || !gotdigit ) {
                return( ST_NOT_ORDINAL );
            } else {
                value <<= 20;
            }
        } else {
            isdig = isdigit( ch );
            if( radix == 10 ) {
                isvalid = isdig;
            } else {
                isvalid = isxdigit( ch );
            }
            if( !isvalid ) {
                return( ST_NOT_ORDINAL );
            }
            value *= radix;
            if( isdig ) {
                value += ch - '0';
            } else {
                value += ch - 'a' + 10;
            }
            gotdigit = TRUE;
        }
    }
    *pnt = value;
    return( ST_IS_ORDINAL );
}

extern bool HaveEquals( tokcontrol ctrl )
/***************************************/
{
    if( GetToken( SEP_EQUALS, ctrl ) == FALSE ) {
        Token.this = Token.next;
        /* collect the token that caused the problem */
        GetToken( SEP_NO, ctrl );
        return( FALSE );
    }
    return( TRUE );
}

extern bool GetLong( unsigned_32 *addr )
/**************************************/
{
    unsigned_32     value;
    ord_state       ok;

    if( !HaveEquals(0) ) return( FALSE );
    ok = getatol( &value );
    if( ok != ST_IS_ORDINAL ) {
        return( FALSE );
    } else {
        *addr = value;
    }
    return( TRUE );
}

extern char * tostring( void )
/****************************/
// make the current token into a C string.
{
    char *          src;
    int             len;
    char *          str;

    src = Token.this;
    len = Token.len;
    _ChkAlloc( str, len + 1 );
    memcpy( str, src, len );
    str[ len ] = '\0';
    return( str );
}

extern char * totext()
/********************/
/* get a possiblly quoted string */
{
    Token.thumb = REJECT;
    if( !GetToken( SEP_NO, 0 ) ) {
        GetToken( SEP_NO, TOK_INCLUDE_DOT );
    }

⌨️ 快捷键说明

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