📄 cmac1.c
字号:
tok = NextMToken();
if( tok != T_WHITE_SPACE ) break;
} while( MTokenLen == 0 );
if( tok == T_EOF || tok == T_NULL ) { /* 08-dec-94 */
CErr( ERR_INCOMPLETE_MACRO, mentry->macro_name );
break;
}
if( tok == T_BAD_TOKEN && /* 18-feb-90 */
BadTokenInfo == ERR_MISSING_QUOTE ) {
CErr1( ERR_MISSING_QUOTE );
tok = T_RIGHT_PAREN;
}
if( tok == T_LEFT_PAREN ) {
++bracket;
} else if( tok == T_RIGHT_PAREN ) {
if( bracket == 0 ) break;
--bracket;
} else if( tok == T_COMMA && bracket == 0 &&
( !( (mentry->macro_flags & MACRO_VAR_ARGS ) &&
parm_cnt == mentry->parm_count - 2 ) ) ) {
if( prev_tok == T_WHITE_SPACE ) --MTokenLen;
if( macro_parms != NULL ) { // if expecting parms
SaveParm( mentry, MTokenLen, parm_cnt, macro_parms,
token_head, total );
}
++parm_cnt;
token_tail = &token_head;
token_head = NULL;
total = 0;
MTokenLen = 0;
continue;
}
/* determine size of current token */
j = 1;
switch( tok ) {
case T_WHITE_SPACE:
if( prev_tok == T_WHITE_SPACE ) j = 0;
break;
case T_CONSTANT:
case T_PPNUMBER:
case T_ID:
case T_UNEXPANDABLE_ID:
case T_STRING:
case T_BAD_TOKEN: /* 07-apr-91 */
j += strlen( Buffer );
++j;
break;
default:
break;
}
if( MTokenLen + j >= BufSize ) { /* if not enough space */
EnlargeBuffer( ( MTokenLen + j ) * 2 );
}
if( tok == T_STRING && CompFlags.wide_char_string ) {
tok = T_LSTRING;
}
TokenBuf[MTokenLen++] = tok;
switch( tok ) {
case T_WHITE_SPACE:
if( prev_tok == T_WHITE_SPACE ) --MTokenLen;
break;
case T_BAD_CHAR:
TokenBuf[MTokenLen++] = Buffer[0];
if( Buffer[1] != '\0' ) {
TokenBuf[MTokenLen++] = T_WHITE_SPACE;
}
break;
case T_CONSTANT:
case T_PPNUMBER:
case T_ID:
case T_UNEXPANDABLE_ID:
case T_LSTRING:
case T_STRING:
case T_BAD_TOKEN: /* 07-apr-91 */
j = 0;
while( (TokenBuf[MTokenLen++] = Buffer[j++]) )
/* empty */;
break;
default:
break;
}
}
if( prev_tok == T_WHITE_SPACE ) --MTokenLen;
if( macro_parms != NULL ) { // if expecting parms
SaveParm( mentry, MTokenLen, parm_cnt, macro_parms,
token_head, total );
++parm_cnt;
} else if( MTokenLen + total != 0 ) {
++parm_cnt; // will cause "too many parms" error
}
if( ( (mentry->macro_flags & MACRO_VAR_ARGS ) &&
( parm_cnt < mentry->parm_count - 2 ) )
|| ( !(mentry->macro_flags & MACRO_VAR_ARGS ) &&
( parm_cnt < mentry->parm_count - 1 ) ) ) {
CErr( ERR_TOO_FEW_MACRO_PARMS, mentry->macro_name );
} else if( !(mentry->macro_flags & MACRO_VAR_ARGS ) &&
( parm_cnt > mentry->parm_count - 1 ) ) {
if( mentry->parm_count - 1 != 0 ){
CWarn( WARN_PARM_COUNT_MISMATCH, ERR_TOO_MANY_MACRO_PARMS, mentry->macro_name );
}
} else if( far_strcmp( mentry->macro_name, "va_start", 9 ) == 0 ) {
if( SymLevel != 0 && ! VarParm( CurFunc ) ) {
CErr1( ERR_MUST_BE_VAR_PARM_FUNC );
}
}
FiniPPScan( ppscan_mode ); // disable T_PPNUMBER tokens
}
return( macro_parms );
}
local void SaveParm( MEPTR mentry,
int i,
int parm_cnt,
MACRO_ARG *macro_parms,
struct tokens *token_list,
int total )
{
struct tokens *next_tokens;
char *p;
TokenBuf[i++] = T_NULL;
if( parm_cnt < mentry->parm_count - 1 ) {
p = CMemAlloc( total + i );
macro_parms[ parm_cnt ].arg = p;
if( p != NULL ) {
total = 0;
while( token_list != NULL ) {
memcpy( &p[ total ], token_list->buf, token_list->length );
total += token_list->length;
next_tokens = token_list->next;
CMemFree( token_list );
token_list = next_tokens;
}
memcpy( &p[ total ], TokenBuf, i );
}
}
}
#ifndef NDEBUG
void DumpMDefn( unsigned char *p )
{
int c;
for(; p;) {
if( *p == 0 ) break;
switch( *p ) {
case T_CONSTANT:
case T_PPNUMBER:
case T_ID:
case T_UNEXPANDABLE_ID:
++p;
for(;;) {
c = *p++;
if( c == '\0' ) break;
putchar( c );
}
continue;
case T_LSTRING:
putchar( 'L' );
case T_STRING:
++p;
putchar( '\"' );
for(;;) {
c = *p++;
if( c == '\0' ) break;
putchar( c );
}
putchar( '\"' );
continue;
case T_WHITE_SPACE:
++p;
putchar( ' ' );
continue;
case T_BAD_CHAR:
++p;
putchar( *p++ );
continue;
case T_MACRO_PARM:
++p;
printf( "parm#%c", '1' + *p++ );
continue;
case T_MACRO_VAR_PARM:
++p;
printf( "varparm#%c", '1' + *p++ );
continue;
default:
printf( "%s", Tokens[ *p ] );
++p;
continue;
}
}
putchar( '\n' );
}
void DumpMTokens( MACRO_TOKEN *mtok )
{
while( mtok ) {
printf( "%s\n", mtok->data );
mtok = mtok->next;
}
}
void DumpNestedMacros()
{
NESTED_MACRO *nested;
nested = NestedMacros;
while( nested ) {
printf( "%s\n", nested->mentry->macro_name );
nested = nested->next;
}
}
#endif
static int TokLength( char __FAR *p )
{
int len;
len = 0;
while( *p++ ) ++len;
return( len );
}
static MACRO_TOKEN *BuildAToken( char __FAR *p )
{
int len;
MACRO_TOKEN *mtok;
len = TokLength( p );
mtok = (MACRO_TOKEN *)CMemAlloc( sizeof(MACRO_TOKEN) + len );
mtok->next = NULL;
len = 0;
for(;;) {
mtok->data[len] = *p;
if( *p == '\0' ) break;
++p;
++len;
}
return( mtok );
}
static MACRO_TOKEN *AppendToken( MACRO_TOKEN *head, int token, char *data )
{
MACRO_TOKEN *tail;
MACRO_TOKEN *new;
new = BuildAToken( data );
new->token = token;
if( head == NULL ) {
head = new;
} else {
tail = head;
while( tail->next != NULL ) tail = tail->next;
tail->next = new;
}
return( head );
}
static int Expandable( MACRO_TOKEN *mtok, int macro_parm )
{
int lparen;
if( NextMacro->macro_defn == 0 ) { /* if special macro */
return( 1 );
}
if( NextMacro->parm_count == 0 ) { /* if () not expected */
if( macro_parm ) { /* 20-feb-93 */
if( MacroBeingExpanded( NextMacro ) ) return( 0 );
}
return( 1 );
}
for(;;) {
if( mtok == NULL ) break;
if( mtok->token != T_WHITE_SPACE && mtok->token != T_NULL ) break;
mtok = mtok->next;
}
if( mtok != NULL ) {
if( mtok->token == T_LEFT_PAREN ) {
if( MacroDepth == 1 && !macro_parm ) return( 1 );
lparen = 0;
for(;;) {
mtok = mtok->next;
if( mtok == NULL ) break;
if( mtok->token == T_LEFT_PAREN ) {
++lparen;
} else if( mtok->token == T_RIGHT_PAREN ) {
if( lparen == 0 ) return( 1 );
--lparen;
}
}
}
} else if( ! macro_parm ) {
SkipAhead();
if( CurrChar == '(' ) {
return( 1 );
} else if( CompFlags.cpp_output ) {
return( 2 );
}
}
return( 0 );
}
static int MacroBeingExpanded( MEPTR mentry )
{
NESTED_MACRO *nested;
nested = NestedMacros;
while( nested ) {
if( nested->mentry == mentry ) return( 1 );
if( ! nested->rescanning ) break;
nested = nested->next;
}
return( 0 );
}
static MACRO_TOKEN *ExpandNestedMacros( MACRO_TOKEN *head, int rescanning )
{
MACRO_TOKEN *mtok;
MACRO_TOKEN *toklist;
MACRO_TOKEN *prev_tok;
MACRO_TOKEN *old_tokenlist;
int i;
char *buf;
mtok = head;
++MacroDepth;
prev_tok = NULL;
for(;;) {
if( mtok == NULL ) break;
toklist = NULL;
if( mtok->token == T_ID ) {
// if macro and not being expanded, then expand it
// only tokens available for expansion are those in mtok list
buf = Buffer;
i = 0;
while( (buf[i] = mtok->data[i]) ) i++;
CalcHash( buf, i );
if( IdLookup( buf ) == T_MACRO ) {
if( rescanning ) {
if( MacroBeingExpanded( NextMacro ) ) {
mtok->token = T_UNEXPANDABLE_ID;
} else {
toklist = mtok;
while( toklist->next != NULL ) {
toklist = toklist->next;
}
toklist->next = TokenList;
i = Expandable( mtok->next, 0 );
switch( i ) {
case 0: // macro is currently not expandable
mtok->token = T_MACRO;
toklist->next = NULL;
toklist = NULL;
break;
case 1: // macro is expandable
TokenList = mtok->next;
if( head == mtok ) {
head = NULL;
prev_tok = NULL;
}
CMemFree( mtok );
toklist = MacroExpansion( rescanning );
mtok = TokenList;
TokenList = NULL;
break;
case 2: // we skipped over some white space
mtok->token = T_UNEXPANDABLE_ID;
toklist->next = NULL;
toklist = BuildAToken( " " );
toklist->token = T_WHITE_SPACE;
toklist->next = mtok->next;
mtok->next = toklist;
toklist = NULL;
break;
}
}
} else { // expanding a macro parm
if( Expandable( mtok->next, 1 ) ) {
old_tokenlist = TokenList;
TokenList = mtok->next;
if( head == mtok ) {
head = NULL;
prev_tok = NULL;
}
CMemFree( mtok );
toklist = NestedMacroExpansion( rescanning );
mtok = TokenList;
TokenList = old_tokenlist;
} else {
prev_tok = mtok;
mtok = mtok->next; // advance onto next token
}
}
} else {
mtok->token = T_SAVED_ID; // avoid rechecking this ID
prev_tok = mtok;
mtok = mtok->next; // advance onto next token
}
} else if( mtok->token == T_NULL ) {
toklist = mtok->next;
if( mtok->data[0] == 'Z' ) { // end of a macro
rescanning = NestedMacros->rescanning;
DeleteNestedMacro();
CMemFree( mtok );
mtok = toklist;
} else { // end of a macro parm
if( toklist != NULL ) {
TokenList = toklist;
}
CMemFree( mtok );
mtok = NULL; // will cause us to exit
}
toklist = NULL;
} else { // advance onto next token
prev_tok = mtok;
mtok = mtok->next;
}
if( toklist != NULL ) { // new tokens to insert
if( prev_tok == NULL ) {
head = toklist;
} else {
prev_tok->next = toklist;
}
if( mtok != NULL ) {
while( toklist->next != NULL ) toklist = toklist->next;
toklist->next = mtok;
}
if( prev_tok == NULL ) {
mtok = head;
} else {
mtok = prev_tok->next;
}
} else {
// either no change, or tokens were deleted
if( prev_tok == NULL ) {
head = mtok;
} else {
prev_tok->next = mtok;
}
}
}
for( mtok = head; mtok; mtok = mtok->next ) { /* 02-nov-93 */
// change a temporarily unexpandable ID into an ID because it
// could become expandable in a later rescanning phase
if( mtok->token == T_MACRO ) mtok->token = T_ID;
}
--MacroDepth;
return( head );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -