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

📄 cmac1.c

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