cmac1.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,383 行 · 第 1/3 页
C
1,383 行
}
FiniPPScan( ppscan_mode );
return( head );
}
static MACRO_TOKEN *glueTokens( MACRO_TOKEN *head )
{
MACRO_TOKEN *mtok;
MACRO_TOKEN *next;
MACRO_TOKEN *new_mtok;
MACRO_TOKEN **ptail, **_ptail;
mtok = head;
_ptail = NULL;
ptail = &head;
for(;;) {
if( mtok == NULL ) break;
if( mtok->token != T_WHITE_SPACE ) {
next = mtok->next;
if( next == NULL ) break;
if( next->token == T_WHITE_SPACE ) next = next->next;
if( next == NULL ) break;
if( next->token == T_MACRO_SHARP_SHARP ) {
next = next->next;
if( next->token == T_WHITE_SPACE ) next = next->next;
// glue mtok->token with next->token to make one token
// create new token
if(next == NULL) break;
if( ( next->token == T_MACRO_EMPTY_VAR_PARM ) ||
( mtok->token == T_MACRO_EMPTY_VAR_PARM ) )
{
MACRO_TOKEN *rem;
if( next->token != T_COMMA &&
mtok->token == T_MACRO_EMPTY_VAR_PARM ) // EMPTY##
{
//keep the next token...
rem = next;
while( mtok->next != rem ){ //free old stuff [mtoken,##,{atok,} next]
next = mtok->next;
CMemFree( mtok );
mtok = next;
}
}
else
{
if( next->token == T_COMMA ||
mtok->token == T_COMMA ) // EMPTY##, or ,##EMPTY
{
// delete whole expression
rem = next->next; // save unseen stuff
next->next = NULL; // break link;
}
else // ##EMPTY
{
// keep the thing after the ##
rem = next->next;
next->next = NULL;
_ptail = ptail;
ptail = &(mtok->next);
mtok = mtok->next; // skip first...
}
while( mtok != NULL ){ //free old stuff [mtoken,##,{atok,} next]
next = mtok->next;
CMemFree( mtok );
mtok = next;
}
}
*ptail = rem;
if( _ptail )
{
// skip back one param..
ptail = _ptail;
mtok = *ptail;
}
else
{
*ptail = rem;
mtok = head;
}
}
else
{
MACRO_TOKEN *last;
last = new_mtok = glue2Tokens( mtok, next );
*ptail = new_mtok;
while( last->next != NULL ) {
last = last->next;
}
if( next != NULL ) {
last->next = next->next;
}
do {
next = mtok->next;
CMemFree( mtok );
mtok = next;
} while( mtok != last->next );
if( !_ptail )
head = new_mtok;
mtok = new_mtok;
}
continue; /* to catch consecutive ##'s */
}
}
_ptail = ptail;
ptail = &(mtok->next);
mtok = mtok->next;
}
return( head );
}
static MACRO_TOKEN **snapString( MACRO_TOKEN **ptail, unsigned i )
{
Buffer[i] = '\0';
TokenLen = i + 1;
CurToken = T_STRING;
ptail = buildTokenOnEnd( ptail, T_STRING, Buffer );
return( ptail );
}
static MACRO_TOKEN **buildString( MACRO_TOKEN **ptail, char *p )
{
MACRO_TOKEN **old_ptail;
char *token_str;
unsigned len;
int i;
int last_non_ws;
int c;
old_ptail = ptail;
i = 0;
last_non_ws = 0;
if( p != NULL ) {
// skip leading whitespace
while( *p == T_WHITE_SPACE ) {
++p;
}
while( *p != T_NULL ) {
if( i >= (BUF_SIZE-8) ) {
DbgAssert( p[0] != T_WHITE_SPACE && p[1] != T_NULL );
ptail = snapString( ptail, i );
i = 0;
last_non_ws = 0;
}
switch( *p ) {
case T_WHITE_SPACE:
++p;
while( *p == T_WHITE_SPACE ) {
++p;
}
Buffer[i++] = ' ';
break;
case T_CONSTANT:
case T_PPNUMBER:
case T_ID:
case T_UNEXPANDABLE_ID:
case T_BAD_TOKEN:
++p;
for(;;) {
c = *p++;
if( c == '\0' ) break;
if( c == '\\' ) {
Buffer[i++] = c;
}
Buffer[i++] = c;
if( i >= (BUF_SIZE-8) ) {
ptail = snapString( ptail, i );
i = 0;
}
}
last_non_ws = i;
break;
case T_LSTRING:
Buffer[i++] = 'L';
case T_STRING:
++p;
Buffer[i++] = '\\';
Buffer[i++] = '"';
for(;;) {
c = *p++;
if( c == '\0' ) break;
if( c == '\\' || c == '"' ) {
Buffer[i++] = '\\';
}
Buffer[i++] = c;
if( i >= (BUF_SIZE-8) ) {
ptail = snapString( ptail, i );
i = 0;
}
}
Buffer[i++] = '\\';
Buffer[i++] = '"';
last_non_ws = i;
break;
case T_BAD_CHAR:
++p;
Buffer[i++] = *p++;
last_non_ws = i;
break;
default:
token_str = Tokens[ *p ];
++p;
len = strlen( token_str );
if( i >= (BUF_SIZE-len) ) {
ptail = snapString( ptail, i );
i = 0;
}
memcpy( &Buffer[i], token_str, len );
i += len;
last_non_ws = i;
}
}
}
if( last_non_ws != 0 || old_ptail == ptail ) {
ptail = snapString( ptail, last_non_ws );
}
return( ptail );
}
static MACRO_TOKEN **buildMTokenList( MACRO_TOKEN **ptail, char *p, MACRO_ARG *macro_parms )
{
unsigned prev_token;
unsigned curr_token;
auto char buf[2];
buf[1] = '\0';
prev_token = T_NULL;
if( p == NULL ) {
return( ptail );
}
for(;;) {
if( *p == 0 ) break;
curr_token = *p;
switch( curr_token ) {
case T_CONSTANT:
case T_PPNUMBER:
case T_ID:
case T_UNEXPANDABLE_ID:
case T_BAD_TOKEN:
case T_LSTRING:
case T_STRING:
ptail = buildTokenOnEnd( ptail, curr_token, p + 1 );
++p;
while( *p++ ) {;}
prev_token = curr_token;
break;
case T_WHITE_SPACE:
++p;
if( prev_token == T_MACRO_SHARP_SHARP ) continue;
ptail = buildTokenOnEnd( ptail, T_WHITE_SPACE, " " );
break;
case T_BAD_CHAR:
++p;
buf[0] = *p++;
ptail = buildTokenOnEnd( ptail, T_BAD_CHAR, buf );
prev_token = T_BAD_CHAR;
break;
case T_MACRO_SHARP:
++p; // skip over T_MACRO_SHARP
while( *p == T_WHITE_SPACE ) ++p;
if( *p != T_MACRO_PARM &&
*p != T_MACRO_VAR_PARM ) {
// we had an error before; handle as T_BAD_CHAR
buf[0] = '#';
ptail = buildTokenOnEnd( ptail, T_BAD_CHAR, buf );
prev_token = T_BAD_CHAR;
break;
}
++p; // skip over T_MACRO_PARM
if( macro_parms ) {
ptail = buildString( ptail, macro_parms[*p].arg );
} else {
Buffer[0] = '\0';
ptail = buildTokenOnEnd( ptail, T_STRING, Buffer );
}
++p;
prev_token = T_STRING;
break;
case T_MACRO_PARM:
++p;
buf[0] = *p++;
ptail = buildTokenOnEnd( ptail, T_MACRO_PARM, buf );
prev_token = T_MACRO_PARM;
break;
case T_MACRO_VAR_PARM:
++p;
buf[0] = *p++;
ptail = buildTokenOnEnd( ptail, T_MACRO_VAR_PARM, buf );
prev_token = T_MACRO_VAR_PARM;
break;
default:
ptail = buildTokenOnEnd( ptail, curr_token, Tokens[*p] );
++p;
prev_token = curr_token;
}
}
return( ptail );
}
static int SharpSharp( MACRO_TOKEN *mtok )
{
for(;;) {
if( mtok == NULL ) break;
if( mtok->token == T_MACRO_SHARP_SHARP ) return( 1 );
if( mtok->token != T_WHITE_SPACE ) break;
mtok = mtok->next;
}
return( 0 );
}
static MACRO_TOKEN *substituteParms( MACRO_TOKEN *head, MACRO_ARG *macro_parms )
{
unsigned prev_non_ws;
MACRO_TOKEN *mtok;
MACRO_TOKEN *list;
MACRO_TOKEN *dummy_list;
MACRO_TOKEN **ptail;
mtok = head;
ptail = &head;
prev_non_ws = T_NULL;
for(;;) {
if( mtok == NULL ) break;
list = NULL;
if( mtok->token == T_MACRO_PARM ||
mtok->token == T_MACRO_VAR_PARM ) {
// replace this ID with a copy of the tokens from
// macro_parms[mtok->data[0]].arg
dummy_list = NULL;
if( mtok->token != T_MACRO_VAR_PARM ||
macro_parms[mtok->data[0]].arg )
{
buildMTokenList( &dummy_list, macro_parms[mtok->data[0]].arg, NULL );
}
else
{
char p[2] = { T_MACRO_EMPTY_VAR_PARM, 0 };
buildMTokenList( &dummy_list, p, NULL );
}
list = dummy_list;
if( prev_non_ws != T_MACRO_SHARP_SHARP && !SharpSharp(mtok->next) ) {
list = expandNestedMacros( list, FALSE );
}
if( list == NULL ) {
list = mtok;
mtok = mtok->next;
CMemFree( list );
list = NULL;
*ptail = mtok;
}
}
if( list != NULL ) {
*ptail = list;
while( list->next != NULL ) {
list = list->next;
}
list->next = mtok->next;
CMemFree( mtok );
mtok = list;
}
if( mtok == NULL ) break;
ptail = &(mtok->next);
if( mtok->token != T_WHITE_SPACE ) {
prev_non_ws = mtok->token;
}
mtok = mtok->next;
}
return( head );
}
static void markUnexpandableIds( MACRO_TOKEN *head )
{
NESTED_MACRO *nested;
MACRO_TOKEN *mtok;
for( mtok = head; mtok; mtok = mtok->next ) {
if( mtok->token == T_ID ) {
for( nested = nestedMacros; nested; nested = nested->next ) {
if( strcmp( nested->fmentry->macro_name, mtok->data ) == 0 ) {
if( ! nested->substituting_parms ) {
// change token so it won't be considered a
// candidate as a macro
mtok->token = T_UNEXPANDABLE_ID;
break;
}
}
}
}
}
}
static MACRO_TOKEN *macroExpansion( MEPTR fmentry, int rescanning )
{
MACRO_ARG *macro_parms;
MACRO_TOKEN *head;
MACRO_TOKEN **ptail;
NESTED_MACRO *nested;
char *tokens;
nested = CarveAlloc( carveNESTED_MACRO );
nested->fmentry = fmentry;
nested->rescanning = rescanning;
nested->substituting_parms = FALSE;
nested->macro_parms = NULL;
head = NULL;
ptail = &head;
if( fmentry->macro_defn == 0 ) { /* if special macro */
CurToken = SpecialMacro( fmentry );
ptail = buildTokenOnEnd( ptail, CurToken, Buffer );
nested->next = nestedMacros;
nestedMacros = nested;
} else {
macro_parms = collectParms( fmentry );
nested->next = nestedMacros;
nestedMacros = nested;
nested->macro_parms = macro_parms;
tokens = ((char*) fmentry) + fmentry->macro_defn;
ptail = buildMTokenList( ptail, tokens, macro_parms );
if( macro_parms != NULL ) {
nested->substituting_parms = TRUE;
head = substituteParms( head, macro_parms );
nested->substituting_parms = FALSE;
}
head = glueTokens( head );
markUnexpandableIds( head );
}
head = appendToken( head, T_NULL, "Z-<end of macro>" );
return( head );
}
static MACRO_TOKEN *nestedMacroExpansion( MEPTR fmentry, boolean rescanning )
{
return( expandNestedMacros( macroExpansion( fmentry, FALSE ), rescanning ) );
}
void DoMacroExpansion( // EXPAND A MACRO
MEPTR fmentry ) // - macro to expand
{
DbgAssert( scannerTokenList == NULL );
macroDepth = 0;
scannerTokenList = nestedMacroExpansion( fmentry, TRUE );
// GetMacroToken will feed back tokens from the tokenList
// when the tokenList is exhausted, then revert back to normal scanning
if( scannerTokenList == NULL ) {
CompFlags.use_macro_tokens = FALSE;
} else {
CompFlags.use_macro_tokens = TRUE;
}
}
void DefineAlternativeTokens( // DEFINE ALTERNATIVE TOKENS
void )
{
SPECIAL_MACRO_NAME *mac;
for( mac = SpcMacros + MACRO_ALT_MARKER + 1; mac->name != NULL; ++mac ) {
MacroSpecialAdd( mac->name, mac->value, mac->flags );
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?