cmdutils.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,253 行 · 第 1/3 页
C
1,253 行
return( tostring() );
}
#define IS_WHITESPACE(ptr) (*(ptr) == ' ' || *(ptr) =='\t' || *(ptr) == '\r')
static void ExpandEnvVariable( void )
/***********************************/
/* parse the specified environment variable & deal with it */
{
char * envname;
char * env;
char * buff;
size_t envlen;
Token.next++;
if( !MakeToken( TOK_INCLUDE_DOT, SEP_PERCENT ) ) {
LnkMsg( LOC+LINE+FTL+MSG_ENV_NAME_INCORRECT, NULL );
}
envname = tostring();
env = GetEnvString( envname );
if( env == NULL ) {
LnkMsg( LOC+LINE+WRN+MSG_ENV_NOT_FOUND, "s", envname );
_LnkFree( envname );
} else {
envlen = strlen( env );
if( !IS_WHITESPACE( Token.next ) ) {
MakeToken( TOK_INCLUDE_DOT, SEP_SPACE );
_ChkAlloc( buff, envlen + Token.len + 1);
memcpy( buff, env, envlen );
memcpy( buff + envlen, Token.this, Token.len );
buff[ Token.len + envlen ] = '\0';
} else {
_ChkAlloc( buff, envlen + 1 );
memcpy( buff, env, envlen );
buff[ envlen ] = '\0';
}
NewCommandSource( envname, buff, ENVIRONMENT );
}
}
static bool CheckFence()
/**********************/
/* check for a "fence", and skip it if it is there */
{
if( Token.thumb == REJECT ) {
if( Token.quoted ) return( FALSE ); /* no fence inside quotes */
if( *Token.this == '}' ) {
Token.this++;
return TRUE;
}
} else {
return GetToken( SEP_RCURLY, 0 );
}
return FALSE;
}
extern bool GetToken( sep_type req, tokcontrol ctrl)
{
return(GetTokenEx(req, ctrl, NULL, NULL));
}
extern bool GetTokenEx( sep_type req, tokcontrol ctrl, cmdfilelist *resetpoint, bool * pbreset)
/***************************************************/
/* return TRUE if no problem */
/* return FALSE if problem */
{
char hmm;
bool ret;
bool need_sep;
if( Token.thumb == REJECT ) {
Token.thumb = OK;
if( Token.quoted ) return( TRUE );
Token.next = Token.this; /* re-process last token */
}
need_sep = TRUE;
for(;;) { /* finite state machine */
/*
// carl.young
// We had a situation where an input file (in this case a Novell
// import or export file) does not have the consistent format
// expected from this FSM code. If the skipToNext flag is set,
// then we just skip to the next token and return rather than
// reporting an error.
// For reference the import files looked like:
// (PREFIX)
// symbol1,
// symbol2,
// symbolnm1,
// symboln
//
// Note the missing comma separator after the prefix token. The
// prefix token(s) may also appear anywhere in the file.
*/
if( (Token.skipToNext) && (req == SEP_COMMA) ) {
Token.skipToNext = 0;
need_sep = FALSE;
}
switch( Token.where ) {
case MIDST:
EatWhite();
hmm = *Token.next;
switch( hmm ) {
case CTRLZ:
Token.where = ENDOFFILE;
break;
case '\0':
if( Token.how == BUFFERED
|| Token.how == ENVIRONMENT
|| Token.how == SYSTEM ) {
Token.where = ENDOFFILE;
break;
} // NOTE the fall through.
case '\n':
if( Token.how == BUFFERED
|| Token.how == ENVIRONMENT
|| Token.how == SYSTEM ) {
Token.next++; // just skip this.
} else if( Token.how == COMMANDLINE ) {
Token.where = ENDOFCMD;
} else {
Token.where = ENDOFLINE;
}
Token.line++;
break;
case '@':
if( req != SEP_SPACE ) {
Token.next++;
GetToken( SEP_NO, TOK_INCLUDE_DOT|TOK_IS_FILENAME );
StartNewFile();
break;
}
Token.next--; /* make a token out of this */
ret = MakeToken( ctrl, req );
Token.quoted = FALSE;
return( ret );
case '#':
Token.where = ENDOFLINE; /* begin comment */
Token.line++;
break;
case '^':
if( req != SEP_SPACE ) { /* if not storing system blocks */
Token.next++;
BackupParser();
break;
}
Token.next--; /* make a token out of this */
ret = MakeToken( ctrl, req );
Token.quoted = FALSE;
return( ret );
case '%':
if( req != SEP_SPACE ) {
ExpandEnvVariable();
break;
}
default:
if( need_sep ) {
Token.quoted = FALSE;
switch( req ) {
case SEP_NO:
if( hmm == ',' || hmm == '=' ) return( FALSE );
break;
case SEP_COMMA:
if(hmm != ',' ) return( FALSE);
Token.next++;
break;
case SEP_EQUALS:
if( hmm != '=' ) return( FALSE );
Token.next++;
break;
case SEP_PERIOD:
case SEP_DOT_EXT:
if( hmm != '.' ) return( FALSE );
Token.next++;
break;
case SEP_PAREN:
if( hmm != '(' ) return( FALSE );
Token.next++;
break;
case SEP_LCURLY:
if( hmm != '{' ) return( FALSE );
Token.next++;
break;
case SEP_QUOTE:
if( hmm != '\'' ) return FALSE;
Token.next++;
Token.quoted = TRUE;
break;
case SEP_RCURLY:
if( hmm != '}' ) return( FALSE );
Token.next++;
return( TRUE );
case SEP_END:
return( FALSE );
}
need_sep = FALSE;
EatWhite();
} else { /* must have good separator here */
if( hmm == '\'' && req != SEP_PAREN && req != SEP_SPACE ) {
req = SEP_QUOTE; /* token has been quoted */
Token.next++; /* don't include the quote */
Token.quoted = TRUE;
}
ret = MakeToken( ctrl, req );
return( ret );
}
break;
}
break;
case ENDOFLINE:
GetNewLine();
break;
case ENDOFFILE:
if( Token.locked ) return( FALSE );
RestoreCmdLine();
if( Token.thumb == REJECT ) {
Token.thumb = OK;
Token.next = Token.this; /* re-process last token */
}
Token.quoted = FALSE;
if( resetpoint && (CmdFile == resetpoint) ) {
if( *Token.next == ',' )
break;
if( pbreset )
*pbreset = TRUE; /* Show we have hit a file end-point for a directive */
return FALSE;
}
break;
case ENDOFCMD:
if( CmdFile->next != NULL ) {
RestoreParser();
break;
}
Token.quoted = FALSE;
ret = ( req == SEP_END ) ? TRUE : FALSE;
return( ret );
}
}
}
static void OutPutPrompt( char *str )
/***********************************/
{
if( QIsDevice( CmdFile->file ) ) {
WriteStdOut( str );
}
}
static void GetNewLine( void )
/****************************/
{
if( Token.how == BUFFERED
|| Token.how == ENVIRONMENT
|| Token.how == SYSTEM ) {
Token.where = MIDST;
while( *Token.next != '\n' ) { //go until next line found;
if( *Token.next == '\0' || *Token.next == CTRLZ ) {
Token.where = ENDOFFILE;
break;
}
Token.next++;
}
Token.next++;
} else if( Token.how == NONBUFFERED ) {
if( QReadStr( CmdFile->file, Token.buff, MAX_REC, CmdFile->name ) ) {
Token.where = ENDOFFILE;
} else {
Token.where = MIDST;
}
Token.next = Token.buff;
} else { // interactive.
OutPutPrompt( _LinkerPrompt );
Token.how = INTERACTIVE;
if( QReadStr( STDIN_HANDLE, Token.buff, MAX_REC, "console" ) ) {
Token.where = ENDOFCMD;
} else {
Token.where = MIDST;
}
Token.next = Token.buff;
}
}
static void BackupParser( void )
/******************************/
/* move the parser temporarily back to a previous input source */
{
if( CmdFile->prev == NULL ) {
LnkMsg( LOC+LINE+WRN + MSG_NO_PREVIOUS_INPUT, NULL );
return;
}
memcpy( &CmdFile->token, &Token, sizeof( tok ) ); // save current state
CmdFile = CmdFile->prev;
memcpy( &Token, &CmdFile->token, sizeof( tok ) ); // restore old state.
}
extern void RestoreParser( void )
/*******************************/
/* return the parser to the previous command state */
{
if( CmdFile->next == NULL ) return;
memcpy( &CmdFile->token, &Token, sizeof( tok ) ); /* save current state */
CmdFile = CmdFile->next;
memcpy( &Token, &CmdFile->token, sizeof( tok ) ); // restore old state.
}
extern void NewCommandSource( char *name, char *buff, method how )
/****************************************************************/
/* start reading from a new command source, and save the old one */
{
cmdfilelist * newfile;
_ChkAlloc( newfile, sizeof( cmdfilelist ) );
newfile->file = STDIN_HANDLE;
if( CmdFile != NULL ) { /* save current state */
memcpy( &CmdFile->token, &Token, sizeof( tok ) );
newfile->next = CmdFile->next;
if( newfile->next != NULL ) {
newfile->next->prev = newfile;
}
} else {
newfile->next = NULL;
}
newfile->prev = CmdFile;
if( newfile->prev != NULL ) {
newfile->prev->next = newfile;
}
CmdFile = newfile;
CmdFile->name = name;
CmdFile->token.buff = buff; /* make sure token is freed */
CmdFile->token.how = how; /* but only if it needs to be */
Token.buff = buff;
Token.next = Token.buff;
Token.where = MIDST;
Token.line = 1;
Token.how = how;
Token.thumb = OK;
Token.locked = FALSE;
Token.quoted = FALSE;
}
extern void SetCommandFile( f_handle file, char *fname )
/******************************************************/
/* read input from given file */
{
unsigned long size;
char * buff;
if( QIsDevice( file ) ) {
size = 0x10000;
} else {
size = QFileSize( file );
}
buff = NULL;
if( size < 65510 ) { // if can alloc a chunk big enough
_LnkAlloc( buff, size + 1 );
if( buff != NULL ) {
size = QRead( file, buff, size, fname );
*(buff + size) = '\0';
NewCommandSource( fname, buff, BUFFERED );
}
}
if( buff == NULL ) { // if couldn't buffer for some reason.
_ChkAlloc( buff, MAX_REC + 1 ); // have to have at least this much RAM
NewCommandSource( fname, buff, NONBUFFERED );
Token.where = ENDOFLINE;
Token.line++;
}
CmdFile->file = file;
}
static void StartNewFile( void )
/******************************/
{
char * fname;
char * envstring;
char * buff;
f_handle file;
size_t envlen;
fname = FileName( Token.this, Token.len, E_COMMAND, FALSE );
file = QObjOpen( fname );
if( file == NIL_HANDLE ) {
_LnkFree( fname );
fname = tostring();
envstring = GetEnvString( fname );
if( envstring != NULL ) {
envlen = strlen( envstring ); // make a copy of envstring
_ChkAlloc( buff, envlen + 1 ); // so we can free it
memcpy( buff, envstring, envlen );
buff[ envlen ] = '\0';
NewCommandSource( fname, buff, ENVIRONMENT );
} else {
LnkMsg( LOC+LINE+ERR+MSG_CANT_OPEN_NO_REASON, "s", fname );
_LnkFree( fname );
Suicide();
}
return;
} else {
SetCommandFile( file, fname );
}
DEBUG(( DBG_OLD, "processing command file %s", CmdFile->name ));
}
extern void EatWhite( void )
/**************************/
{
while( IS_WHITESPACE( Token.next ) ) {
Token.next++;
}
}
static int ParseNumber( char * str, int radix )
/*********************************************/
/* read a (possibly hexadecimal) number */
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?