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 + -
显示快捷键?