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 + -
显示快捷键?