mpreproc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,112 行 · 第 1/4 页
C
2,112 行
* aborts: if not nested
* errors: if elseFound
*/
{
if( nestLevel == 0 ) {
PrtMsg( FTL | LOC | UNMATCHED_WITH_IF, directives[D_ELSE] );
}
if( curNest.elseFound ) {
PrtMsg( WRN | LOC | SKIPPING_AFTER_ELSE, directives[D_ELSE],
directives[D_ELSE] );
// must set these because we may not have been skipping previous block
curNest.skip2endif = TRUE;
curNest.skip = TRUE;
return;
}
curNest.elseFound = TRUE;
if( !curNest.skip2endif ) {
// check we're not skipping. if !skip then we should skip the else part.
if( !curNest.skip ) {
// skip to the end - we've done a block in this nesting
curNest.skip = TRUE;
curNest.skip2endif = TRUE;
} else {
// we still haven't done block in this nesting, do the else portion
curNest.skip = FALSE;
}
}
if( curNest.skip ) {
PrtMsg( DBG | INF | LOC | SKIPPING_BLOCK, directives[D_ELSE] );
} else {
PrtMsg( DBG | INF | LOC | ENTERING_BLOCK, directives[D_ELSE] );
}
}
#ifdef __WATCOMC__
#pragma on (check_stack);
#endif
STATIC void doElIf( BOOLEAN (*logical)(void), enum directiveTok tok )
/********************************************************************
* post: skip if !logical || skip2endif
* aborts: if not nested
* errors: if elseFound
*/
{
char buf[MAX_DIR_LEN * 2];
FmtStr( buf, "%s %s", directives[D_ELSE], directives[tok] );
if( nestLevel == 0 ) {
PrtMsg( FTL | LOC | UNMATCHED_WITH_IF, buf );
}
if( curNest.elseFound ) {
PrtMsg( WRN | LOC | SKIPPING_AFTER_ELSE, buf, directives[D_ELSE] );
// must set these because we may not have been skipping previous block
curNest.skip2endif = TRUE;
curNest.skip = TRUE;
(void)eatToEOL();
return;
}
if( !curNest.skip2endif ) {
// check we're not skipping. if !skip, we should skip the else if part
if( !curNest.skip ) {
// skip to the end - we've done a block in this nesting
curNest.skip = TRUE;
curNest.skip2endif = TRUE;
(void)eatToEOL();
} else {
// we still haven't done block in this nesting, try this logical.
curNest.skip = !logical();
}
} else {
(void)eatToEOL();
}
if( curNest.skip ) {
PrtMsg( DBG | INF | LOC | SKIPPING_BLOCK, buf );
} else {
PrtMsg( DBG | INF | LOC | ENTERING_BLOCK, buf );
}
}
#ifdef __WATCOMC__
#pragma off(check_stack);
#endif
STATIC void bangElse( void )
/***************************
* pre: next character of input is first after 'else' token
* post: atStartOfLine == EOL; skip may be modified
* aborts: if illegal directive
*/
{
enum directiveTok tok;
tok = getPreTok();
switch( tok ) {
case D_BLANK:
(void)eatToEOL();
doElse();
break;
case D_IFDEF: doElIf( ifDef, D_IFDEF ); break;
case D_IFEQ: doElIf( ifEq, D_IFEQ ); break;
case D_IFEQI: doElIf( ifEqi, D_IFEQI ); break;
case D_IFNDEF: doElIf( ifNDef, D_IFNDEF ); break;
case D_IF: doElIf( ifOp, D_IF ); break;
case D_IFNEQ: doElIf( ifNEq, D_IFNEQ ); break;
case D_IFNEQI: doElIf( ifNEqi, D_IFNEQI ); break;
default:
(void)eatToEOL();
PrtMsg( FTL | LOC | NOT_ALLOWED_AFTER_ELSE, directives[tok],
directives[D_ELSE] );
}
}
STATIC void bangDefine( void )
/*****************************
* post: atStartOfLine == EOL; macro may be defined
* errors: if !IsMacroName
*/
{
char *name;
assert( !curNest.skip );
name = DeMacro( MAC_PUNC ); /* decode name */
if( !IsMacroName( name ) ) {
(void)eatToEOL();
} else {
DefMacro( name );
}
FreeSafe( name );
}
static char *skipWhileWS( char *p )
/*********************************/
{
while( isws( *p ) ) {
++p;
}
return( p );
}
static char *skipUntilWS( char *p )
/*********************************/
{
while( *p != '\0' && !isws( *p ) ) {
++p;
}
return( p );
}
STATIC void bangInject( void )
/*****************************
* !inject <text> <mac-name1> <mac-name2> ... <mac-nameN>
* post: atStartOfLine == EOL
* errors: none
*/
{
char *text;
char *contents;
char *end_contents;
char *curr;
char *mac_name;
char *value;
assert( !curNest.skip );
text = DeMacro( EOL );
(void)eatToEOL();
contents = skipWhileWS( text );
if( *contents == '\0' ) {
FreeSafe( text );
return;
}
end_contents = skipUntilWS( contents );
if( *end_contents == '\0' ) {
FreeSafe( text );
return;
}
*end_contents = '\0';
curr = end_contents + 1;
for( ;; ) {
curr = skipWhileWS( curr );
if( *curr == '\0' ) break;
mac_name = curr;
curr = skipUntilWS( curr );
if( *curr != '\0' ) {
*curr = '\0';
++curr;
}
if( !IsMacroName( mac_name ) ) {
break;
}
UnGetCH( EOL );
InsString( contents, FALSE );
value = GetMacroValue( mac_name );
if( value != NULL ) {
InsString( " ", FALSE );
InsString( value, TRUE );
}
DefMacro( mac_name );
}
FreeSafe( text );
}
STATIC void bangLoadDLL( void )
/******************************
* !loaddll <cmd-name> <dll-name> [<entry-pt>]
* post: atStartOfLine == EOL
* errors: none
*/
{
char *text;
char *cmd_name;
char *end_cmd_name;
char *dll_name;
char *end_dll_name;
char *ent_name;
char *end_ent_name;
assert( !curNest.skip );
text = DeMacro( EOL );
(void)eatToEOL();
cmd_name = skipWhileWS( text );
if( *cmd_name == '\0' ) {
FreeSafe( text );
return;
}
end_cmd_name = skipUntilWS( cmd_name );
if( *end_cmd_name == '\0' ) {
FreeSafe( text );
return;
}
*end_cmd_name = '\0';
dll_name = skipWhileWS( end_cmd_name + 1 );
if( *dll_name == '\0' ) {
FreeSafe( text );
return;
}
end_dll_name = skipUntilWS( dll_name );
if( *end_dll_name == '\0' ) {
OSLoadDLL( cmd_name, dll_name, NULL );
FreeSafe( text );
return;
}
*end_dll_name = '\0';
ent_name = skipWhileWS( end_dll_name + 1 );
if( *ent_name == '\0' ) {
OSLoadDLL( cmd_name, dll_name, NULL );
FreeSafe( text );
return;
}
end_ent_name = skipUntilWS( ent_name );
if( *end_ent_name == '\0' ) {
OSLoadDLL( cmd_name, dll_name, ent_name );
FreeSafe( text );
return;
}
*end_ent_name = '\0';
OSLoadDLL( cmd_name, dll_name, ent_name );
FreeSafe( text );
}
STATIC void bangUnDef( void )
/****************************
* post: atStartOfLine == EOL; macro may be undefined
* errors: if env_variable || !IsMacroName || not-defined
*/
{
char *name;
char *value;
assert( !curNest.skip );
name = DeMacro( MAC_PUNC );
(void)eatToEOL();
if( !IsMacroName( name ) ) {
FreeSafe( name );
return;
}
value = GetMacroValue( name );
if( value == NULL ) {
PrtMsg( WRN | LOC | TRYING_UNDEF_UNDEF, directives[D_UNDEF] );
FreeSafe( name );
return;
}
UnDefMacro( name );
FreeSafe( name );
FreeSafe( value );
}
STATIC char *formatLongFileName( char *text )
/*******************************************/
{
char *ret;
char *currentRet;
char *currentTxt;
assert( text != NULL );
ret = StrDupSafe( text );
currentRet = ret;
currentTxt = text;
if( currentTxt[0] == DOUBLEQUOTE ) {
++currentTxt;
}
while( *currentTxt != NULLCHAR && *currentTxt != DOUBLEQUOTE ) {
if( *currentTxt == '\\' ) {
if( *(currentTxt + 1) == DOUBLEQUOTE ) {
++currentTxt;
}
}
*(currentRet++) = *(currentTxt++);
}
*currentRet = NULLCHAR;
if( *currentTxt == DOUBLEQUOTE ) {
if( *(currentTxt + 1) != NULLCHAR ) {
PrtMsg( ERR | LOC | UNABLE_TO_INCLUDE, text );
FreeSafe( ret );
return( NULL );
}
}
return( ret );
}
STATIC void bangInclude( void )
/******************************
* post: atStartOfLine == EOL; maybe( new file in stream )
* errors: if unable to InsertFile()
* for MS-Compatability we add <> angular bracket support to look
* for the file in the INCLUDE directory
*/
{
char *text;
char *temp = NULL;
#ifdef __WATCOMC__
char *current;
char full_path[_MAX_PATH];
RET_T ret;
#endif
assert( !curNest.skip );
text = DeMacro( EOL );
(void)eatToEOL();
chopTrailWS( text ); /* get rid of trailing ws */
#ifdef __WATCOMC__
if( *text == LESSTHAN ) {
current = text;
while( *current != GREATERTHAN && *current != NULLCHAR ) {
++current;
}
if( *current == GREATERTHAN ) {
*current = NULLCHAR;
temp = text;
text = formatLongFileName( temp + 1 );
if( text == NULL ) {
FreeSafe( temp );
return;
}
for( ;; ) {
if( *current == NULLCHAR ) {
_searchenv( text, INCLUDE, full_path );
ret = RET_ERROR;
if( *full_path != NULLCHAR ) {
ret = InsFile( full_path, FALSE );
}
if( ret == RET_ERROR ) {
PrtMsg( ERR | LOC | UNABLE_TO_INCLUDE, text );
}
break;
}
// check if there are any trailing characters if there are
// then error
if( !isws( *current ) ) {
PrtMsg( ERR | LOC | UNABLE_TO_INCLUDE, text );
break;
}
++current;
}
} else {
PrtMsg( ERR | LOC | UNABLE_TO_INCLUDE, text );
}
} else
#endif
{
temp = text;
text = formatLongFileName( text );
if( text == NULL ) {
FreeSafe( temp );
return;
}
if( InsFile( text, FALSE ) != RET_SUCCESS ) {
PrtMsg( ERR | LOC | UNABLE_TO_INCLUDE, text );
}
}
FreeSafe( temp );
FreeSafe( text );
}
STATIC void bangMessage( void )
/******************************
* post: atStartOfLine == EOL
*/
{
char *text;
assert( !curNest.skip );
text = DeMacro( EOL );
(void)eatToEOL();
chopTrailWS( text );
PrtMsg( PRNTSTR, text );
FreeSafe( text );
}
STATIC void bangError( void )
/****************************
* post: atStartOfLine == EOL
*/
{
char *text;
assert( !curNest.skip );
text = DeMacro( EOL );
(void)eatToEOL();
chopTrailWS( text );
PrtMsg( ERR | LOC | NEOL | USER_ERROR );
PrtMsg( ERR | PRNTSTR, text );
FreeSafe( text );
}
STATIC void handleBang( void )
/*****************************
* post: atStartOfLine == EOL
*/
{
enum directiveTok tok;
tok = getPreTok();
/* these are executed regardless of skip */
switch( tok ) {
case D_BLANK: (void)eatToEOL(); break;
case D_ELSE: bangElse(); break;
case D_ENDIF: bangEndIf(); break;
case D_IF: bangIf( ifOp, D_IF ); break;
case D_IFDEF: bangIf( ifDef, D_IFDEF ); break;
case D_IFEQ: bangIf( ifEq, D_IFEQ ); break;
case D_IFEQI: bangIf( ifEqi, D_IFEQI ); break;
case D_IFNDEF: bangIf( ifNDef, D_IFNDEF ); break;
case D_IFNEQ: bangIf( ifNEq, D_IFNEQ ); break;
case D_IFNEQI: bangIf( ifNEqi, D_IFNEQI ); break;
default:
if( !curNest.skip ) {
/* these are only executed if !skip */
switch( tok ) {
case D_DEFINE: bangDefine(); break;
case D_ERROR: bangError(); break;
case D_MESSAGE: bangMessage(); break;
case D_INCLUDE: bangInclude(); break;
case D_INJECT: bangInject(); break;
case D_LOADDLL: bangLoadDLL(); break;
case D_UNDEF: bangUnDef(); break;
default:
break;
}
} else {
(void)eatToEOL(); /* otherwise, we just eat it up */
}
}
}
static int PreTestString( const char *str )
/******************************************
* Test if 'str' is the next sequence of characters in stream.
* If not, push back any characters read.
*/
{
const char *s = str;
STRM_T t;
int rc = FALSE;
for( ;; ) {
t = GetCHR();
if( t != *s ) {
UnGetCH( t );
while( s-- > str ) {
UnGetCH( *s );
}
break;
}
++s;
if( *s == '\0' ) {
rc = TRUE;
break;
}
}
return( rc );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?