📄 cmac1.c
字号:
static char *GlueTokenToBuffer( MACRO_TOKEN *first, char *gluebuf )
{
size_t gluelen;
char *buf;
buf = NULL;
if( first != NULL ) { /* 19-apr-93 */
MacroPtr = &first->token;
buf = ExpandMacroToken();
}
if ( buf == NULL )
buf = gluebuf;
else if ( gluebuf != NULL ) {
/* now do a "strcat( gluebuf, buf )" */
gluelen = strlen( gluebuf );
gluebuf = CMemRealloc( gluebuf, gluelen + strlen( buf ) + 1 );
strcpy( gluebuf + gluelen, buf );
CMemFree( buf );
buf = gluebuf;
}
return( buf );
}
static MACRO_TOKEN *ReTokenGlueBuffer( char *gluebuf )
{ // retokenize starting at gluebuf
MACRO_TOKEN *head;
MACRO_TOKEN **lnk;
MACRO_TOKEN *new;
int ppscan_mode;
ppscan_mode = InitPPScan();
if ( gluebuf == NULL )
gluebuf = "";
ReScanInit( gluebuf );
head = NULL;
lnk = &head;
for(;;) {
ReScanToken();
new = BuildAToken( Buffer );
new->token = CurToken;
*lnk = new;
lnk = &new->next;
if( CompFlags.rescan_buffer_done ) break;
}
FiniPPScan( ppscan_mode );
return( head );
}
static MACRO_TOKEN *GlueTokens( MACRO_TOKEN *head )
{
MACRO_TOKEN *mtok;
MACRO_TOKEN **lnk,**_lnk;// prior lnk
MACRO_TOKEN *next;
char *buf;
char *gluebuf;
_lnk= NULL;
lnk = &head;
mtok = *lnk;
buf = Buffer;
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 ) { // let's paste
int pos;
MACRO_TOKEN *rem;
next = next->next;
pos = 0;
// glue mtok->token with next->token to make one token
if( ( mtok->token == T_COMMA && next->token == T_MACRO_EMPTY_VAR_PARM ) ||
( mtok->token == T_MACRO_EMPTY_VAR_PARM && next->token == T_COMMA ) )
{
// delete [mtoken(a comma),##,empty __VA_ARGS__]
// delete [empty __VA_ARGS__,##,mtoken(a comma)]
buf[10] = '\0';
pos = -1;
}
else
{
if( mtok->token == T_MACRO_EMPTY_VAR_PARM )
{
// well should never be in this state if no next - since ## cannot
// appear at the end of a macro
gluebuf = GlueTokenToBuffer( next, NULL );
}
else
{
gluebuf = GlueTokenToBuffer( mtok, NULL );
if( next != NULL &&
next->token != T_MACRO_EMPTY_VAR_PARM ){
gluebuf = GlueTokenToBuffer( next, gluebuf ); //paste in next
}
}
}
rem = next->next; // save unseen stuff
next->next = NULL; // break link;
while( mtok != NULL ){ //free old stuff [mtoken,##,{atok,} next]
next = mtok->next;
CMemFree( mtok );
mtok = next;
}
if( pos >= 0 )
{
mtok = ReTokenGlueBuffer( gluebuf );
if( gluebuf != NULL ) CMemFree( gluebuf );
*lnk = mtok; // link in new mtok to mtok's link
while( mtok && mtok->next != NULL ){ //position mtok & lnk to last token
_lnk = lnk;
lnk = &mtok->next;
mtok = *lnk;
if( mtok == mtok->next )
{
return head;
}
}
// mtok == last token of retokenizing
// lnk == the pointer which references mtok
mtok->next = rem;
}
else
{
if( _lnk )
{
*lnk = rem;
lnk = _lnk;
mtok = *lnk;
}
else
{
*lnk = rem;
mtok = head;
}
}
continue; //ready to go
}
}
_lnk = lnk;
lnk = &mtok->next;
mtok = *lnk;
}
return( head );
}
static MACRO_TOKEN **NextString( MACRO_TOKEN **lnk, char *buf, unsigned i )
{
MACRO_TOKEN *mtok;
buf[i] = '\0';
CLitLength = i + 1;
CurToken = T_STRING;
mtok = BuildAToken( buf );
mtok->token = T_STRING;
*lnk = mtok;
lnk = &mtok->next;
return( lnk );
}
local MACRO_TOKEN *BuildString( byte *p )
{
MACRO_TOKEN *head;
MACRO_TOKEN **lnk;
int i;
int c;
char *tokenstr;
int len;
char *buf;
size_t bufsize;
head = NULL;
lnk = &head;
i = 0;
if( p != NULL ) {
bufsize = BUF_SIZE;
buf = CMemAlloc( bufsize );
while( *p == T_WHITE_SPACE ) ++p; //eat leading wspace
while( *p != T_NULL ) {
if( i >= (bufsize-8) ) buf = CMemRealloc( buf, 2 * i );
switch( *p ) {
case T_CONSTANT:
case T_PPNUMBER:
case T_ID:
case T_UNEXPANDABLE_ID:
case T_BAD_TOKEN: /* 07-apr-91 */
++p;
for(;;) {
c = *p++;
if( c == '\0' ) break;
if( c == '\\' ) buf[i++] = c; /* 15-mar-88 */
buf[i++] = c;
if( i >= (bufsize-8) ) buf = CMemRealloc( buf, 2 * i );
}
break;
case T_LSTRING:
buf[i++] = 'L';
case T_STRING:
++p;
buf[i++] = '\\';
buf[i++] = '"';
for(;;) {
c = *p++;
if( c == '\0' ) break;
if( c == '\\' || c == '"' ) buf[i++] = '\\';
buf[i++] = c;
if( i >= (bufsize-8) ) buf = CMemRealloc( buf, 2 * i );
}
buf[i++] = '\\';
buf[i++] = '"';
break;
case T_WHITE_SPACE:
while( *p == T_WHITE_SPACE )++p;
if( *p != T_NULL ){
buf[i++] = ' ';
}
break;
case T_BAD_CHAR:
++p;
if( *p == '\\' && p[1] == T_NULL ) { /* 17-nov-94 */
CErr1( ERR_INVALID_STRING_LITERAL );
}
buf[i++] = *p++;
break;
default:
tokenstr = Tokens[ *p ];
++p;
len = strlen( tokenstr );
if( i >= (bufsize-len) ) buf = CMemRealloc( buf, 2 * i );
memcpy( &buf[i], tokenstr, len );
i += len;
break;
}
}
if( i > 0 ) {
lnk = NextString( lnk, buf, i );
i = 0;
}
CMemFree( buf );
}
return( head );
}
static MACRO_TOKEN *BuildMTokenList( byte __FAR *p, MACRO_ARG *macro_parms )
{
MACRO_TOKEN *mtok;
MACRO_TOKEN *head;
MACRO_TOKEN **lnk;
NESTED_MACRO *nested;
byte __FAR *p2;
byte buf[2];
enum TOKEN prev_token;
head = NULL;
lnk = &head;
nested = NestedMacros;
buf[1] = '\0';
prev_token = T_NULL;
if( p == NULL ) return( NULL ); /* 12-nov-92 */
for(;;) {
if( *p == 0 ) break;
switch( *p ) {
case T_CONSTANT:
case T_PPNUMBER:
case T_ID:
case T_UNEXPANDABLE_ID:
case T_BAD_TOKEN:
mtok = BuildAToken( p + 1 );
mtok->token = *p++;
while( *p++ ) {;}
break;
case T_LSTRING:
case T_STRING:
mtok = BuildAToken( p + 1 );
mtok->token = *p++;
while( *p++ ) {;}
break;
case T_WHITE_SPACE:
++p;
if( prev_token == T_MACRO_SHARP_SHARP ) continue;
mtok = BuildAToken( " " );
mtok->token = T_WHITE_SPACE;
break;
case T_BAD_CHAR:
++p;
buf[0] = *p++;
mtok = BuildAToken( buf );
mtok->token = T_BAD_CHAR;
break;
case T_MACRO_SHARP:
++p; // skip over T_MACRO_SHARP
while( *p == T_WHITE_SPACE ) ++p;
++p; // skip over T_MACRO_PARM
// If no macro arg given, result must be "", not empty
if( macro_parms && macro_parms[*p].arg && !(*(macro_parms[*p].arg) == '\0') ) {
mtok = BuildString( macro_parms[*p].arg );
} else {
mtok = BuildAToken( "" );
mtok->token = T_STRING;
}
++p;
break;
case T_MACRO_PARM:
++p;
buf[0] = *p++;
p2 = p;
while( *p2 == T_WHITE_SPACE ) ++p2;
nested->substituting_parms = 1; /* 09-nov-93 */
if( macro_parms ) {
mtok = BuildMTokenList( macro_parms[buf[0]].arg, NULL );
if( mtok == NULL ) { // deal with empty arguments
mtok = BuildAToken( "" );
mtok->token = T_UNEXPANDABLE_ID;
}
} else {
mtok = BuildAToken( "" );
mtok->token = T_WHITE_SPACE;
}
if( *p2 != T_MACRO_SHARP_SHARP &&
prev_token != T_MACRO_SHARP_SHARP ) {
if( mtok != NULL ) {
mtok = AppendToken( mtok, T_NULL, "P-<end of parm>" );
mtok = ExpandNestedMacros( mtok, 0 );
}
}
nested->substituting_parms = 0;
break;
case T_MACRO_VAR_PARM:
++p;
buf[0] = *p++;
p2 = p;
while( *p2 == T_WHITE_SPACE ) ++p2;
nested->substituting_parms = 1; /* 09-nov-93 */
if( macro_parms ) {
if( macro_parms[buf[0]].arg )
{
mtok = BuildMTokenList( macro_parms[buf[0]].arg, NULL );
}
else
{
if( prev_token == T_MACRO_SHARP_SHARP ||
*p2 == T_MACRO_SHARP_SHARP )
{
mtok = BuildAToken( "" );
mtok->token = T_MACRO_EMPTY_VAR_PARM;
}
else
{
mtok = BuildAToken( "" );
mtok->token = T_WHITE_SPACE;
}
}
} else {
mtok = BuildAToken( "" );
mtok->token = T_WHITE_SPACE;
}
if( *p2 != T_MACRO_SHARP_SHARP &&
prev_token != T_MACRO_SHARP_SHARP ) {
if( mtok != NULL ) {
mtok = AppendToken( mtok, T_NULL, "P-<end of parm>" );
mtok = ExpandNestedMacros( mtok, 0 );
}
}
nested->substituting_parms = 0;
break;
default:
mtok = BuildAToken( Tokens[*p] );
mtok->token = *p++;
break;
}
if( mtok != NULL ) {
if( mtok->token != T_WHITE_SPACE ) prev_token = mtok->token;
*lnk = mtok;
while( *lnk != NULL ) lnk = &(*lnk)->next;
}
}
head = GlueTokens( head );
return( head );
}
MACRO_TOKEN *MacroExpansion( int rescanning )
{
MEPTR mentry;
MACRO_ARG *macro_parms;
MACRO_TOKEN *head;
MACRO_TOKEN *mtok;
NESTED_MACRO *nested;
char __FAR *tokens;
int len;
mentry = NextMacro;
nested = (NESTED_MACRO *)CMemAlloc( sizeof( NESTED_MACRO ) );
nested->mentry = mentry;
nested->rescanning = rescanning;
nested->substituting_parms = 0;
nested->macro_parms = NULL;
if( mentry->macro_defn == 0 ) { /* if special macro */
CurToken = SpecialMacro( mentry );
head = BuildAToken( Buffer );
head->token = CurToken;
nested->next = NestedMacros;
NestedMacros = nested;
} else {
macro_parms = CollectParms();
nested->next = NestedMacros;
NestedMacros = nested;
nested->macro_parms = macro_parms;
tokens = (char *)mentry + mentry->macro_defn;
head = BuildMTokenList( tokens, macro_parms );
for( mtok = head; mtok; mtok = mtok->next ) { /* 26-oct-93 */
if( mtok->token == T_ID ) {
len = strlen( mtok->data ) + 1;
for( nested = NestedMacros; nested; nested = nested->next ) {
if( far_strcmp( nested->mentry->macro_name,
mtok->data, len ) == 0 ) {
if( nested->substituting_parms == 0 ) { /* 09-nov-93*/
// change token so it won't be considered a
// candidate as a macro
mtok->token = T_UNEXPANDABLE_ID;
break;
}
}
}
}
}
}
head = AppendToken( head, T_NULL, "Z-<end of macro>" );
return( head );
}
MACRO_TOKEN *NestedMacroExpansion( int rescanning )
{
return( ExpandNestedMacros( MacroExpansion( 0 ), rescanning ) );
}
void DoMacroExpansion(void) // called from cscan
{
MacroDepth = 0;
TokenList = NestedMacroExpansion( 1 );
// GetMacroToken will feed back tokens from the TokenList
// when the TokenList is exhausted, then revert back to normal scanning
if( TokenList == NULL ) {
MacroPtr = NULL;
} else {
MacroPtr = "";
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -