cmac2.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 856 行 · 第 1/2 页

C
856
字号
    int ppscan_mode;            // - previous ppnumber scan mode
    unsigned mlen;              // - current length of macro def'n
    TOKEN_LOCN locn;            // - location for definition

    SrcFileGuardStateSig();
    NextToken();
    if( CurToken != T_ID ) {
        Expecting( "identifier" );
        return( NULL );
    } else {
        SrcFileGetTokenLocn( &locn );
    }
    name_len = TokenLen;
    mlen = offsetof( MEDEFN, macro_name );
    parm_names = NULL;
    MacroOffsetAddMem( &mlen, Buffer, TokenLen + 1 );
    if( CurrChar == '(' ) {         /* parms present */
        if( ! ( defn & MSCAN_MANY ) ) {
            BadCmdLine( ERR_INVALID_OPTION );
            return( NULL );
        }
        NextToken();                /* grab the '(' */
        NextToken();
        parm_cnt = 0;               /* 0 ==> () following */
        parm_end = 0;
        for( ;; ) {
            if( CurToken == T_RIGHT_PAREN ) break;
            if( parm_end ) {
                Expecting( ")" );
                return( NULL );
            }
            if( CurToken != T_ID &&
                CurToken != T_DOT_DOT_DOT) {
                Expecting( "identifier" );
                return( NULL );
            }
            if( addParmName( &parm_names, TRUE ) != 0 ) {
                CErr2p( ERR_DUPLICATE_MACRO_PARM, Buffer );
            } else {
                ++parm_cnt;
                if( CurToken == T_DOT_DOT_DOT )
                    parm_end = 1; // can have no further tokens
                MacroOffsetAddMem( &mlen, Buffer, TokenLen + 1 );
            }
            NextToken();
            if( CurToken == T_RIGHT_PAREN ) break;
            if( CurToken == T_NULL ) {
                CErr1( ERR_INVALID_MACRO_DEFN );
                break;
            }
            MustRecog( T_COMMA );
        }
    } else {
        parm_cnt = -1;          /* -1 ==> no () following */
    }
    /* grab replacement tokens */
    ppscan_mode = InitPPScan();         // enable T_PPNUMBER tokens
    mptr = grabTokens( &parm_names
                     , parm_end?-(parm_cnt + 1):(parm_cnt + 1)
                     , defn
                     , name_len
                     , mlen
                     , &locn );
    FiniPPScan( ppscan_mode );          // disable T_PPNUMBER tokens

    RingFree( &parm_names );
    return( mptr );
}

static void ChkEOL( void )
{
    if( CurToken != T_NULL && CurToken != T_EOF ) {
        Expecting( "end of line" );
    }
}

static void ppIf( int value )    // PREPROCESSOR IF
{
    if( SrcFileGuardedIf( value ) ) {
        return;
    }
    IncLevel( value );
    ChkEOL();
}

static void ppIfId( int value )  // PREPROCESSOR IFDEF IFNDEF
{
    NextToken();
    ppIf( value );
}

static void CIfDef( void )
{
    SrcFileGuardPpIf();
    NextToken();
    if( CurToken != T_ID ) {
        Expecting( "identifier" );
        IncLevel( 0 );
        return;
    }
    ppIfId( MacroDependsDefined() );
}


static void CIfNDef( void )
{
    SrcFileGuardPpIf();
    NextToken();
    if( CurToken != T_ID ) {
        Expecting( "identifier" );
        IncLevel( 0 );
        return;
    }
    SrcFileGuardPpIfndef( Buffer, TokenLen );
    ppIfId( ! MacroDependsDefined() );
}


static void CIf( void )
{
    SrcFileGuardPpIf();
    // don't set PPS_NO_LEX_ERRORS since we want tokenizing errors diagnosed
    PPState = PPS_EOL;
    NextToken();
    ppIf( PpConstExpr() );
}


static void CElif( void )
{
    int         value;

    SrcFileGuardPpElse();
    PPState = PPS_EOL | PPS_NO_LEX_ERRORS;
    NextToken();
    if( NestLevel == 0 || pp_stack->cpp_type == PRE_ELSE ) {
        CErr1( ERR_MISPLACED_ELIF );
    } else {
        if( NestLevel == SkipLevel ) {
            --SkipLevel;            /* start skipping else part */
            pp_stack->processing = 0;
            pp_stack->cpp_type = PRE_ELIF;
        } else if( NestLevel == SkipLevel + 1 ) {
            /* only evaluate the expression when required */
            if( pp_stack->cpp_type == PRE_IF ) {
                value = PpConstExpr();
                ChkEOL();
                if( value ) {
                    SkipLevel = NestLevel; /* start including else part */
                    pp_stack->processing = 1;
                    pp_stack->cpp_type = PRE_ELIF;
                }
            }
        }
    }
}

static void wantEOL( void )
{
    if( CurToken != T_NULL && CurToken != T_EOF ) {
        if( NestLevel == SkipLevel ) {
            CErr1( ANSI_JUNK_FOLLOWS_DIRECTIVE );
        }
        flush2EOL();
    }
}

static void CElse( void )
{
    SrcFileGuardPpElse();
    if( NestLevel == 0  ||  pp_stack->cpp_type == PRE_ELSE ) {
        CErr1( ERR_MISPLACED_ELSE );
    } else {
        if( NestLevel == SkipLevel ) {
            --SkipLevel;            /* start skipping else part */
            pp_stack->processing = 0;
        } else if( NestLevel == SkipLevel + 1 ) {
            /* cpp_type will be PRE_ELIF if an elif was true */
            if( pp_stack->cpp_type == PRE_IF ) {    /* 19-sep-88 */
                SkipLevel = NestLevel;  /* start including else part */
                pp_stack->processing = 1;
            }
        }
        pp_stack->cpp_type = PRE_ELSE;
    }
    NextToken();
    wantEOL();
}

static void CEndif( void )
{

    if( NestLevel == 0 ) {
        CErr1( ERR_MISPLACED_ENDIF );
    } else {
        struct cpp_info *pp = pp_stack;
        if( pp != NULL && ! SrcFileSame( pp->locn.src_file, SrcFileCurrent() ) ) {
            if( CErr1( WARN_WEIRD_ENDIF_ENCOUNTER ) & MS_PRINTED ) {
                CErr2p( INF_PP_DIRECTIVE_LOCN, &(pp->locn) );
            }
        }
        --NestLevel;
        VstkPop( &vstkPp );
        pp_stack = VstkTop( &vstkPp );
        SrcFileGuardPpEndif();
    }
    if( NestLevel < SkipLevel ) {
        SkipLevel = NestLevel;
    }
    NextToken();
    wantEOL();
}

static void CUnDef( void )
{
    NextToken();
    if( CurToken != T_ID ) {
        Expecting( "identifier" );
        return;
    }
    MacroUndefine( TokenLen );
    NextToken();
    ChkEOL();
}

static void CLine( void )
{
    int         adjust;
    LINE_NO     line;

    PPState = PPS_EOL | PPS_NO_LEX_ERRORS;
    NextToken();
    if( CurToken == T_CONSTANT ) {
        line = U32Fetch( Constant64 ); // side effects of NextToken
        NextToken();
        if( CurToken == T_NULL ) {
            if( CompFlags.cpp_ignore_line == 0 ) {
                SrcFileAlias( SrcFileNameCurrent(), line, 0 );
            }
        } else if( CurToken != T_STRING ) {
            Expecting( "string" );
        } else {
            if( CompFlags.cpp_ignore_line == 0 ) {
                if( CurrChar == '\n' ) {
                    // line # has already been incremented
                    adjust = 0;
                } else {
                    // line # will be incremented
                    adjust = -1;
                }
                SrcFileAlias( Buffer, line, adjust );
            }
            NextToken();        // may clobber Buffer's contents
            ChkEOL();           // will increment line # if CurToken != T_NULL
        }
    } else {
        Expecting( "constant" );
    }
}

static void CError( void )
{
    int i;
    int save;

    i = 0;
    while( CurrChar != '\n' && CurrChar != '\r' && CurrChar != LCHR_EOF ) {
        if( i != 0 || CurrChar != ' ' ) {
            Buffer[ i ] = CurrChar;
            ++i;
        }
        NextChar();
    }
    Buffer[ i ] = '\0';
    /* Force #error output to be reported, even with preprocessor */
    save = CompFlags.cpp_output;
    CompFlags.cpp_output = 0;
    CErr2p( ERR_USER_ERROR_MSG, Buffer );
    CompFlags.cpp_output = save;
}

static void CIdent( void )
{
    if( ! CompFlags.extensions_enabled ) {
        CUnknown();
    }
    flush2EOL();
}

static void preProcStmt( void )
{
    PPCTRL      *pp;
    int         hash;

    NextChar();
    NextToken();
    if( CurToken == T_ID ) {
        hash = (TokenLen + preprocWeights[ Buffer[0] - 'a' ]
                 + preprocWeights[ Buffer[TokenLen-1] - 'a' ]) & 15;
        pp = &controlTable[hash];
        if( strcmp( pp->directive, Buffer ) == 0 ) {
            if( NestLevel == SkipLevel ) {
                pp->samelevel();
            } else {
                pp->skiplevel();
            }
        } else {
            CUnknown();
        }
    } else if( CurToken != T_NULL ) {
        CUnknown();
    }
    flush2EOL();
}

// When a new file is opened, it's guarded state will indicate top of file.
// ChkControl() is always called at the start of a file because CurrChar
// will be set to '\n'. ChkControl is always called at the start of every
// line.
// Thus we have complete control over setting the guarded state here.
// We can determine is the first directive is #if, #ifdef or #ifndef.
//
int ChkControl(                 // CHECK AND PROCESS DIRECTIVES
    int expanding )
{
    int         lines_skipped;
    ppstate_t   save_ppstate;

    while( CurrChar == '\n' ) {
        SrcFileCurrentLocation();
        if( TBreak() ) {
            CErr1( ERR_BREAK_KEY_HIT );
            CSuicide();
        }
        lines_skipped = 0;
        save_ppstate = PPState;
        for(;;) {
            if( CompFlags.cpp_output )  PrtChar( '\n' );
            NextChar();
            // look for a #-char or the corresponding digraph (%:)
            if( CurrChar != PreProcChar && CurrChar != '%' ) {
                SkipAhead();
            }
            if( CurrChar == LCHR_EOF ) break;

            if( CurrChar == '%' ) {
                NextChar();
                if( CurrChar == ':' ) {
                    // replace the digraph (%:) with the preproc-char
                    CurrChar = PreProcChar;
                } else {
                    GetNextCharUndo( CurrChar );
                    CurrChar = '%';
                }
            }
            PPState = PPS_EOL | PPS_NO_EXPAND | PPS_NO_LEX_ERRORS;
            if( CurrChar == PreProcChar ) {
                preProcStmt();
            } else if( NestLevel != SkipLevel ) {
                NextToken();
                flush2EOL();
            }
            PPState = save_ppstate;
            if( NestLevel == SkipLevel ) break;
            if( CurrChar == LCHR_EOF ) break;
            if( CurrChar == '\n' ) {
                lines_skipped = 1;
            }
        }
        if( CompFlags.cpp_output ) {
            if( lines_skipped ) {
                EmitLine( SrcFileLine(), SrcFileNameCurrent() );
            }
        }
    }
    // we have already skipped past all white space at the start of the line
    CurToken = ScanToken( expanding );
    // this will be the first significant token on the source line
    SrcFileGuardStateSig();
    return( CurToken );
}


void DirectiveInit(             // INITIALIZE FOR DIRECTIVE PROCESSING
    void )
{
    NestLevel = 0;
    SkipLevel = 0;
    pp_stack = NULL;
    VstkOpen( &vstkPp, sizeof( struct cpp_info ), 8 );
}


void DirectiveFini(             // COMPLETE DIRECTIVE PROCESSING
    void )
{
    struct cpp_info *pp;        // - unclosed entry

    for(;;) {
        pp = VstkPop( &vstkPp );
        if( pp == NULL ) break;
        SetErrLoc( &pp->locn );
        CErr1( ERR_MISSING_CENDIF );
    }
    VstkClose( &vstkPp );
}


int CppPrinting(                // TEST IF AT LEVEL FOR PREPROC PRINTING
    void )
{
    return ( NestLevel == SkipLevel ) && ( CppFile != NULL );
}


unsigned IfDepthInSrcFile(      // COMPUTE #IF DEPTH IN CURRENT SOURCE FILE
    void )
{
    unsigned depth;             // - depth of #if's
    struct cpp_info *pp;        // - current pre-processor stack entry
    SRCFILE curr_src;           // - current SRCFILE

    for( curr_src = SrcFileCurrent(), depth = 0, pp = VstkTop( &vstkPp )
       ; ( pp != NULL ) && ( pp->locn.src_file == curr_src )
       ; ++depth, pp = VstkNext( &vstkPp, pp ) );
    return depth;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?