mparse.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,157 行 · 第 1/3 页
C
1,157 行
!doubleQuote ) {
break;
} else if( doubleQuote && intext[*offset] == BACKSLASH ) {
if( intext[*offset + 1] == DOUBLEQUOTE ) {
*offset = *offset + 1;
}
} else if( doubleQuote && intext[*offset] == DOUBLEQUOTE ) {
++(*offset);
break;
}
++(*offset);
}
if( (intext[(*offset) - 1] != DOUBLEQUOTE && doubleQuote) ||
(*offset == 1 && doubleQuote) ) {
/* error */
PrtMsg( ERR | LOC | NON_MATCHING_QUOTE );
ret = NULL;
return( ret );
}
if( !doubleQuote && *offset > 0 ||
doubleQuote && *offset > 1 ) {
tempStr = StartVec();
if( doubleQuote ) {
WriteNVec( tempStr, intext + 1, *offset - 2 );
} else {
WriteNVec( tempStr, intext, *offset );
}
ret = FinishVec( tempStr );
return( ret );
} else {
// if we need a temporary file then give back << as a filename
tempStr = StartVec();
WriteVec( tempStr, INLINE_SYMBOL );
ret = FinishVec( tempStr );
return( ret );
}
}
STATIC void getBody( FLIST *head )
/*********************************
* get the body of the file from the input stream
*/
{
FLIST *current;
TOKEN_T t;
VECSTR buf;
VECSTR bufTemp;
char *temp;
char const *currChar;
current = head;
if( current == NULL ) {
return;
}
/* Inlinelevel == the number of inline files we need to create */
while( inlineLevel > 0 && current != NULL ) {
buf = StartVec();
WriteVec( buf, "" );
for( ;; ) {
t = PreGetCH();
if( t == STRM_END ) {
UnGetCH( t );
PrtMsg( ERR | LOC | UNEXPECTED_EOF );
return;
}
UnGetCH( t );
temp = ignoreWSDeMacro( TRUE, ForceDeMacro() );
if( temp[0] == LESSTHAN ) {
if( temp[1] == LESSTHAN ) {
/* terminator of inline file is found when first
* two characters are <<
*/
currChar = temp + 2;
while( *currChar != NULLCHAR && isws( *currChar ) ) {
++currChar;
}
if( *currChar == NULLCHAR ) {
current->keep = FALSE;
} else if( strnicmp( currChar, NOKEEP, 6 ) == 0 ) {
current->keep = FALSE;
} else if( strnicmp( currChar, KEEP, 4 ) == 0 ) {
current->keep = TRUE;
} else {
/* error only expecting (NO)KEEP */
PrtMsg( ERR | LOC | NOKEEP_ONLY );
}
FreeSafe( temp );
break;
}
}
bufTemp = StartVec();
WriteVec( bufTemp, temp );
FreeSafe( temp );
CatVec( buf, bufTemp );
bufTemp = StartVec();
WriteVec( bufTemp, "\n" );
CatVec( buf, bufTemp );
}
current->body = FinishVec( buf );
current = current->next;
--inlineLevel;
}
if( inlineLevel > 0 ) {
PrtMsg( ERR | LOC | UNEXPECTED_EOF );
}
}
STATIC FLIST *GetInlineFile( char **commandIn )
/**********************************************
* this returns the head of the flist and modifies the command text to
* change << to the actual file name to be used
* also returns an offset so that the calling program would know
* how long the command is in cmdText
* cmdText is also modified it removes the file name information and
* substitutes it with the actual file name that is going to be used
*/
{
size_t offset;
size_t index;
FLIST *head;
FLIST *current;
char *cmdText;
size_t start; // start of cmdText to copy into newCommand
VECSTR newCommand; // stores the new command built by replacing << with
// the actual file name
/* inlinelevel must be initially zero when processing */
assert( inlineLevel == 0 && commandIn != NULL );
cmdText = *commandIn;
head = NULL;
current = NULL;
newCommand = StartVec();
index = 0;
start = 0;
/*
* check for << in the cmdText if found then substitute this
* with a new name the syntax is <<[filename] it is delimited with
* a space/tab or <
* note: the << cannot be part of any macro or else it would not
* be recognized
* this part will remove the << from the command text if the inline file
* is explicitly defined
*/
while( cmdText[index] != NULLCHAR ) {
if( cmdText[index] == LESSTHAN ) {
if( cmdText[index + 1] == LESSTHAN ) {
// Add the current vector into the new command
WriteNVec( newCommand, cmdText + start, index - start );
++inlineLevel;
if( head == NULL ) {
current = NewFList();
head = current;
} else {
assert( current != NULL );
current->next = NewFList();
current = current->next;
}
// Add file Name into new command text
current->fileName = getFileName( cmdText + 2 + index, &offset );
// Check for long file name
if( *(cmdText + 2 + index) == DOUBLEQUOTE ) {
WriteVec( newCommand, "\"" );
WriteVec( newCommand, current->fileName );
WriteVec( newCommand, "\"" );
} else {
WriteVec( newCommand, current->fileName );
}
current->body = NULL;
current->next = NULL;
index = index + offset;
start = index + 2;
}
++index;
}
++index;
}
WriteNVec( newCommand, cmdText + start, index - start );
FreeSafe( cmdText );
*commandIn = FinishVec( newCommand );
getBody( head );
return( head );
}
STATIC char *formatPathName( const char *inPath )
/***********************************************/
{
char buf[_MAX_PATH];
if( inPath != NULL ) {
_makepath( buf, NULL, inPath, NULL, NULL );
return( StrDupSafe( buf ) );
} else {
return( NULL );
}
}
STATIC void getCurTargDepPath( char **cur_targ_path, char **cur_dep_path )
/*************************************************************************
* this is to get the current target path and dependent path
* when sufsuf is created
*/
{
if( *cur_targ_path != NULL ) {
FreeSafe( *cur_targ_path );
}
if( *cur_dep_path != NULL ) {
FreeSafe( *cur_dep_path );
}
if( targ_path != NULL ) {
*cur_targ_path = formatPathName( targ_path );
} else {
*cur_targ_path = StrDupSafe( "" );
}
if( dep_path != NULL ) {
*cur_dep_path = formatPathName( dep_path );
} else {
*cur_dep_path = StrDupSafe( "" );
}
FreeSafe( targ_path );
FreeSafe( dep_path );
targ_path = NULL;
dep_path = NULL;
}
TLIST *Parse( void )
/*******************
* Call LexToken, and dispatch to appropriate routine
*/
{
TOKEN_T t;
CLIST *newclist;
CLIST *bclist;
TLIST *btlist;
BOOLEAN clist_warning_given;
BOOLEAN token_filename;
char *cur_depend_path;
char *cur_target_path;
firstTarget = NULL;
bclist = NULL;
btlist = NULL;
cur_depend_path = NULL;
cur_target_path = NULL;
clist_warning_given = FALSE;
token_filename = FALSE;
for( ;; ) {
/*
* If the current target is a sufsuf then
* we must demacro the text later
* when the actual filenames are resolved
*/
if( btlist != NULL ) {
ImplicitDeMacro = (Glob.microsoft | Glob.unix) && btlist->target->sufsuf;
}
t = LexToken( LEX_PARSER );
ImplicitDeMacro = FALSE;
if( t != TOK_CMD && t != EOL ) {
if( btlist != NULL ) {
/* link the commands to the targets */
linkCList( btlist, bclist, cur_target_path, cur_depend_path );
bclist = NULL;
btlist = NULL;
if( cur_depend_path != NULL ) {
FreeSafe( cur_depend_path );
}
if( cur_target_path != NULL ) {
FreeSafe(cur_target_path);
}
cur_target_path = NULL;
cur_depend_path = NULL;
if( (Glob.microsoft | Glob.unix) && token_filename == TRUE ) {
exPop();
token_filename = FALSE;
}
}
clist_warning_given = FALSE;
}
if( t == STRM_END ) {
break;
}
switch( t ) {
case EOL:
break;
case TOK_CMD:
if( *CurAttr.ptr == NULLCHAR ) {
/* discard blank lines */
FreeSafe( CurAttr.ptr );
} else {
if( btlist == NULL ) {
if( !clist_warning_given ) {
PrtMsg( WRN | LOC | CLIST_HAS_NO_OWNER );
clist_warning_given = TRUE;
}
FreeSafe( CurAttr.ptr );
} else {
newclist = NewCList();
newclist->text = CurAttr.ptr;
/* stack in reverse order */
newclist->next = bclist;
/* look at the command text to see if we need
* to get inline file if we do then create inline
* file information in memory
* note: that if the clist pertains to a implicit
* rule we must deMacro the text the same
* way as wmake does for microsoft option
*/
ImplicitDeMacro = (Glob.microsoft | Glob.unix) &&
btlist->target->sufsuf;
newclist->inlineHead = GetInlineFile( &(newclist->text) );
ImplicitDeMacro = FALSE;
bclist = newclist;
}
}
break;
case TOK_SUF:
parseSuf();
break;
case TOK_SUFSUF:
parseTargDep( t, &btlist );
getCurTargDepPath( &cur_target_path, &cur_depend_path );
if( btlist != NULL ) {
btlist->target->sufsuf = TRUE;
}
break;
case TOK_FILENAME:
parseTargDep( t, &btlist );
if( (Glob.microsoft | Glob.unix) && btlist != NULL ) {
if( btlist->target != NULL && btlist->target->depend != NULL ) {
exPush( btlist->target, btlist->target->depend, NULL );
token_filename = TRUE;
}
}
break;
case TOK_DOTNAME:
parseDotName( t, &btlist );
break;
default:
#ifdef DEVELOPMENT
PrtMsg( FTL | INVALID_TOKEN_IN, "Parse" );
#else
PrtMsg( WRN | LOC | IGNORE_OUT_OF_PLACE_M, M_UNKNOWN_TOKEN );
#endif
}
}
return( firstTarget );
}
void ParseInit( void )
/********************/
{
inlineLevel = 0;
DoingUpdate = FALSE;
}
void ParseFini( void )
/********************/
{
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?