cmdparse.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 486 行
CPP
486 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <errno.h>
#include <wclist.h>
#include <wclistit.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <ctype.h>
#include "assure.h"
#include "chbffile.h"
#include "cmdparse.h"
#include "util.h"
enum TokenVal {
TOK_EOF = '\0',
TOK_Id,
TOK_OpenBrace = '{',
TOK_CloseBrace = '}',
TOK_Comma = ',',
TOK_At = '@',
TOK_NotATok
};
typedef struct fullName {
char path[ _MAX_PATH + 1 ];
char drive[ _MAX_DRIVE + 1 ];
char dir[ _MAX_DIR + 1 ];
char fname[ _MAX_FNAME + 1 ];
char ext[ _MAX_EXT + 1 ];
} FullName;
CommandParser::CommandParser( char * cmdLine, bool optAllowed )
: _cmdLine( cmdLine )
, _command( NULL )
, _database( "" )
, _options( "" )
, _files( NULL )
, _optAllowed( optAllowed )
, _quiet( FALSE )
//-------------------------------------------------------------
{
try {
_files = new WCValSList<String>;
parse();
} catch( FileExcept oops ) {
errMessage( "%s: %s", oops._fileName, oops._message );
}
}
CommandParser::~CommandParser()
//-----------------------------
{
delete _files;
delete _command;
}
void CommandParser::setCommand( const char * name )
//-------------------------------------------------
{
String nameStr( name );
if( _command ) {
errMessage( "Warning: ignoring nested include @%s.", name );
} else {
setExtension( nameStr, ".cbr" );
_command = new CheckedBufferedFile( nameStr );
_command->open( CheckedFile::ReadText, CheckedFile::UserReadWrite );
if( *_cmdLine ) {
_cmdLine--;
}
getNextChar();
}
}
void CommandParser::setDatabase( const char * dbs )
//-------------------------------------------------
{
_database = dbs;
setExtension( _database, ".dbr" );
}
void CommandParser::setSearchPath( const char * path )
//---------------------------------------------------
{
_searchPath = path;
}
void CommandParser::setOptions( const char * opt )
//------------------------------------------------
{
_options = opt;
setExtension( _options, ".obr" );
}
const char * CommandParser::database()
//------------------------------------
{
if( _database.length() > 0 ) {
return _database;
} else {
return NULL;
}
}
const char * CommandParser::searchPath()
//--------------------------------------
{
if( _searchPath.length() > 0 ) {
return _searchPath;
} else {
return NULL;
}
}
const char * CommandParser::options()
//-----------------------------------
{
if( _options.length() > 0 ) {
return _options;
} else {
return NULL;
}
}
bool CommandParser::quiet()
//-------------------------
{
return _quiet;
}
void CommandParser::parse()
//-------------------------
{
int token;
getNextChar();
token = scan();
while( token != TOK_EOF ) {
if( token != TOK_Id && token != '@' ) {
syntaxError();
break;
}
if( token == '@' ) {
token = scan();
if( token != TOK_Id ) {
errMessage( "Missing command file name." );
break;
} else {
setCommand( _token );
token = scan();
continue; // <----------- unusual flow
}
}
if( !strncmp( "database", _token, _token.length() ) ) {
token = scan();
if( token != TOK_Id ) {
errMessage( "Missing database file name." );
break;
} else {
setDatabase( _token );
token = scan();
continue; // <----------- unusual flow
}
}
if( !strncmp( "quiet", _token, _token.length() ) ) {
_quiet = TRUE;
token = scan();
continue; // <----------- unusual flow
}
if( !strncmp( "path", _token, _token.length() ) ) {
token = scan();
if( token != TOK_Id ) {
errMessage( "Missing file search path." );
break;
} else {
setSearchPath( _token );
token = scan();
continue; // <----------- unusual flow
}
}
if( !strncmp( "options", _token, _token.length() ) ) {
token = scan();
if( token != TOK_Id ) {
errMessage( "Missing options file name." );
break;
} else {
setOptions( _token );
token = scan();
continue; // <----------- unusual flow
}
}
if( !strncmp( "file", _token, _token.length() ) ) {
bool error = FALSE;
token = scan();
switch( token ) {
case '{':
token = scan();
while( token == TOK_Id ) {
addFile( _token );
token = scan();
}
if( token != '}' ) {
syntaxError();
error = TRUE;
} else {
token = scan();
}
break;
case TOK_Id:
addFile( _token );
token = scan();
while( token == ',' ) {
token = scan();
if( token != TOK_Id ) {
syntaxError();
error = TRUE;
break;
} else {
addFile( _token );
token = scan();
}
}
break;
default:
syntaxError();
error = TRUE;
}
if( error ) {
break;
} else {
continue;
}
}
// the directive is not database, option, or file
syntaxError();
break;
}
}
void CommandParser::syntaxError()
//-------------------------------
{
if( _token.length() ) {
errMessage( "Syntax error near \"%s\".", (const char *) _token );
} else {
errMessage( "Syntax error near end of input." );
}
}
int CommandParser::scan()
//-----------------------
{
int state = TOK_NotATok;
char buf[ 2 ] = { 0 };
_token = "";
while( 1 ) {
switch( _lookAhead ) {
case '{':
case '}':
case ',':
case '@':
case '\0':
if( state == TOK_NotATok ) {
state = _lookAhead;
buf[ 0 ] = _lookAhead;
_token = buf;
getNextChar();
}
return state;
default:
if( isspace( _lookAhead ) ) {
getNextChar();
if( state != TOK_NotATok ) {
return state;
}
} else {
if( _lookAhead != '\0' ) {
state = TOK_Id;
_token += _lookAhead;
getNextChar();
} else {
return state;
}
}
}
}
}
bool ListContains( WCValSList<String> * list, const String & str )
//----------------------------------------------------------------
{
WCValSListIter<String> iter( *list );
while( ++iter ) {
if( iter.current() == str ) {
return TRUE;
}
}
return FALSE;
}
void CommandParser::addFile( const char * fname )
//-----------------------------------------------
// add all the files specified by the (possibly wild-carded) option
// return TRUE if successful, FALSE on error
{
DIR * dirp;
struct dirent * direntp;
String file( fname );
FullName dirName;
setExtension( file, ".mbr" );
// FIXME -- these error messages have to do something smarter!
if( strchr( file, '?' ) != NULL | strchr( file, '*' ) != NULL ) {
_splitpath( file, dirName.drive, dirName.dir,
dirName.fname, dirName.ext );
dirp = opendir( file );
if( dirp == NULL ) {
errMessage( "No files found matching \"%s\".", fname );
return;
}
for(;;) {
const char AvoidAttribs = _A_HIDDEN | _A_SYSTEM | _A_VOLID |
_A_SUBDIR;
direntp = readdir( dirp );
if( direntp == NULL ) break;
if( (dirp->d_attr & AvoidAttribs) == 0 ) {
String addFile;
addFile = dirName.drive;
addFile += dirName.dir;
addFile += dirp->d_name;
// do NOT do a setExtension here as we only get here
// if user did *.* or *. something.
// setExtension( addFile, ".mbr" );
if( !ListContains( _files, addFile ) ) {
_files->append( addFile );
}
}
}
if( closedir( dirp ) ){
FileExcept oops( FileExcept::Close, errno, file );
throw oops;
}
} else {
if( !ListContains( _files, file ) ) {
_files->append( file );
}
}
return;
}
void CommandParser::setExtension( String & str, const char * ext )
//----------------------------------------------------------------
// split a path apart, set its extension to ext if it is blank,
// stick it back together and return the full path name.
{
FullName name;
char newDir[ _MAX_PATH ];
char * res;
String retStr;
_splitpath( str, name.drive, name.dir, name.fname, name.ext );
if( *name.ext == '\0' ) {
strcpy( name.ext, ext );
}
_makepath( name.path, name.drive, name.dir, name.fname, name.ext );
res = _fullpath( newDir, name.path, _MAX_PATH );
if( res == NULL ) {
FileExcept oops( FileExcept::Read, errno, str );
throw( oops );
}
str = newDir;
}
char CommandParser::getNextChar()
//-------------------------------
{
int nRead;
if( _command == NULL ) {
if( *_cmdLine == '\0' ) {
_lookAhead = '\0';
} else {
_lookAhead = *_cmdLine++;
}
} else {
nRead = _command->read( &_lookAhead, sizeof( char ) );
if( nRead == 0 ) {
_command->close();
delete _command;
_command = NULL;
getNextChar();
}
}
return _lookAhead;
}
#ifdef DEBUG_CMDPARSE
#include <stdio.h>
#include <process.h>
void main()
{
char buf[ 512 ];
CommandParser prs( getcmd( buf ), TRUE );
int i;
WCValSListIter<String> iter( *prs.files() );
printf( " database = \"%s\"\n", prs.database() ? prs.database() : "<NULL>" );
printf( " options = \"%s\"\n", prs.options() ? prs.options() : "<NULL>" );
printf( " files = \n" );
while( ++ iter ) {
printf( " %s\n", (const char *) iter.current() );
}
printf( "--------------" );
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?