⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmac1.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
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 + -