cmac2.c

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

C
840
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Macro processing, part 2.
*
****************************************************************************/


#include "cvars.h"
#include "scan.h"
#include <stddef.h>
#include "cgmisc.h"

static void    CSkip( void );
static void    CSkipIf( void );
static void    CDefine( void );
static void    CInclude( void );
static void    CIfDef( void );
static void    CIfNDef( void );
static void    CIf( void );
static void    CElif( void );
static void    CElse( void );
static void    CEndif( void );
static void    CUndef( void );
static void    CLine( void );
static void    CError( void );
static void    CIdent( void );
static void    CUnknown( void );

local void Flush2EOL( void );
local void GrabTokens( int parm_cnt, struct macro_parm *formal_parms, const char *mac_name );
local void IncLevel( int value );
local int  FormalParm( struct macro_parm *formal_parms );
local void ChkEOL( void );

struct preproc {
    char  *directive;
    void  (*samelevel)( void ); /* func to call when NestLevel == SkipLevel */
    void  (*skipfunc)( void );  /* func to call when NestLevel != SkipLevel */
};

static unsigned char PreProcWeights[] = {
//a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y,z
  2, 0, 0,11, 1, 4, 0, 0, 5, 0, 0,12, 0, 0, 0,13, 0,14, 0, 9,15, 0, 0, 0, 0,0
};

static struct preproc PreProcTable[] = {
    { "",       NULL,           NULL },  // 0
    { "line",   CLine,          CSkip }, // 4 +12 + 1 = 17 mod 16 = 1
    { "define", CDefine,        CSkip }, // 6 +11 + 1 = 18 mod 16 = 2
    { "ident",  CIdent,         CSkip }, // 5 + 5 + 9 = 19 mod 16 = 3
    { "error",  CError,         CSkip }, // 5 + 1 +14 = 20 mod 16 = 4
    { "pragma", CPragma,        CSkip }, // 6 +13 + 2 = 21 mod 16 = 5
    { "else",   CElse,          CElse }, // 4 + 1 + 1 = 6
    { "",       NULL,           NULL },  // 7
    { "undef",  CUndef,         CSkip }, // 5 +15 + 4 = 24 mod 16 = 8
    { "elif",   CElif,          CElif }, // 4 + 1 + 4 = 9
    { "endif",  CEndif,         CEndif },// 5 + 1 + 4 = 10
    { "if",     CIf,            CSkipIf },//2 + 5 + 4 = 11
    { "",       NULL,           NULL },  // 12
    { "include",CInclude,       CSkip }, // 7 + 5 + 1 = 13
    { "ifdef",  CIfDef,         CSkipIf },//5 + 5 + 4 = 14
    { "ifndef", CIfNDef,        CSkipIf },//6 + 5 + 4 = 15
};

enum    pp_types {
        PRE_IF,
        PRE_ELIF,
        PRE_ELSE
};

struct  cpp_info {              /* C Pre-processor information */
        struct cpp_info *prev_cpp;
        char            *file_name;
        unsigned        line_num;
        enum pp_types   cpp_type;
        int             processing;
};


static void PreProcStmt( void )
{
    struct preproc      *pp;
    int                 hash;

    NextChar();                 /* skip over '#' */
    PPNextToken();
    if( CurToken == T_ID ) {
        hash = (TokenLen + PreProcWeights[ Buffer[0] - 'a' ]
                 + PreProcWeights[ Buffer[TokenLen-1] - 'a' ]) & 15;
        pp = &PreProcTable[hash];
        if( strcmp( pp->directive, Buffer ) == 0 ) {
            if( NestLevel == SkipLevel ) {
                pp->samelevel();
            } else {
                pp->skipfunc();
            }
        } else {
            CUnknown();
        }
    } else if( CurToken != T_NULL ) {
        CUnknown();
    }
    Flush2EOL();
}

extern bool PrintWhiteSpace;  //ppc printing   (from ccmain.c)

int ChkControl( void )
{
    int lines_skipped;


    if( !CompFlags.doing_macro_expansion ) {
        if( CompFlags.cpp_output ) {
            PrintWhiteSpace = FALSE;
        }
    }
    while( CurrChar == '\n' ) {
        if( TBreak() ) {
            CErr1( ERR_BREAK_KEY_HIT );
            CSuicide();
        }
        lines_skipped = 0;
        for( ;; ) {
            if( CompFlags.cpp_output ) {
                PrtChar( '\n' );
            }
            NextChar();
            if( CurrChar != PreProcChar ) {
                SkipAhead();
            }
            if( CurrChar == EOF_CHAR ) break;
            CompFlags.pre_processing = 2;
            if( CurrChar == PreProcChar ) { /* start of comp control line */
                PreProcStmt();
            } else if( NestLevel != SkipLevel ) {
                PPNextToken();              /* get into token mode */
                Flush2EOL();
            }
            if( NestLevel == SkipLevel ) break;
            if( CurrChar == '\n' ) {
                lines_skipped = 1;
            }
            if( CurrChar == EOF_CHAR ) break;   /* 16-may-89 */
        }
        CompFlags.pre_processing = 0;
        if( CompFlags.cpp_output ) {
            if( lines_skipped ) {
                if( SrcFile != NULL ) {                 /* 14-may-92 */
                    EmitLine( SrcFile->src_line, SrcFile->src_name );
                }
            }
        }
    }
    // we have already skipped past all white space at the start of the line
    CurToken = T_WHITE_SPACE;
//  CurToken = ScanToken();
    return( T_WHITE_SPACE );
}


static void Flush2EOL( void )
{
    while( CurToken != T_NULL ) {
        if( CurToken == T_EOF ) break;          /* 07-may-89 */
        PPNextToken();
    }
}


local void CSkip( void )
{
}


local void CSkipIf( void )
{
    IncLevel( 0 );
}


local void CUnknown( void )
{
    if( NestLevel == SkipLevel ) {
        CErr2p( ERR_UNKNOWN_DIRECTIVE, Buffer );
    }
}


local void CIdent( void )
{
    if( !CompFlags.extensions_enabled )
        CUnknown();
    Flush2EOL();
}


void CInclude( void )
{
    char        in_macro;
    auto char   buf[82];

    if( PCH_FileName != NULL && CompFlags.make_precompiled_header == 0 ) {
        if( CompFlags.ok_to_use_precompiled_hdr ) {     /* 27-jun-94 */
            CompFlags.use_precompiled_header = 1;
        }
    }
    if( CompFlags.make_precompiled_header ) {
        InitBuildPreCompiledHeader();
    }
    InitialMacroFlag = 0;
    in_macro = 0;
    if( MacroPtr != NULL )
        in_macro = 1;
    CompFlags.pre_processing = 1;
    PPNextToken();
    if( CurToken == T_STRING ) {
        OpenSrcFile( Buffer, 0 );
#if _CPU == 370
        if( !CompFlags.use_precompiled_header ) {
            SrcFile->colum = Column;    /* do trunc and col on  */
            SrcFile->trunc = Trunc;     /* on user source files */
        }
#endif
    } else if( CurToken == T_LT ) {
        if( !in_macro )                 /* 28-may-89 */
            CompFlags.pre_processing = 2;
        buf[0] = '\0';
        for( ;; ) {
            PPNextToken();
            if( CurToken == T_GT ) {
                OpenSrcFile( buf, '<' );
                break;
            }
            strncat( buf, Buffer, 80 );
            if( (in_macro != 0  &&  MacroPtr == NULL)
                ||      CurToken == T_NULL
                ||      CurToken == T_EOF ) {
                CErr1( ERR_INVALID_INCLUDE );
                break;
            }
        }
    } else {
        CErr1( ERR_INVALID_INCLUDE );
    }
    if( CurToken != T_EOF ) {
        PPNextToken();
    }
    CompFlags.use_precompiled_header = 0;
}


local void CDefine( void )
{
    struct macro_parm *mp, *prev_mp, *formal_parms;
    int         parm_cnt, parm_end = 0;
    int         ppscan_mode;
    char        *token_buf;

    PPNextToken();
    if( CurToken != T_ID ) {
        ExpectIdentifier();
        return;
    }
    if( strcmp( Buffer, "defined" ) == 0 ) {
        CErr1( ERR_CANT_DEFINE_DEFINED );
        return;
    }
    token_buf = CStrSave( Buffer );
    formal_parms = NULL;
    parm_cnt = -1;              /* -1 ==> no () following */
    if( CurrChar == '(' ) {     /* parms present */
        PPNextToken();          /* grab the '(' */
        PPNextToken();
        parm_cnt = 0;           /* 0 ==> () following */
        parm_end = 0;
        prev_mp = NULL;
        for( ;; ) {
            if( CurToken == T_RIGHT_PAREN ) break;
            if( parm_end ) {
                ExpectingAfter( ")", "..." );
                return;
            }
            if( CurToken != T_ID &&
                CurToken != T_DOT_DOT_DOT ) {
                ExpectIdentifier();
                return;
            }
            ++parm_cnt;
            if( CurToken == T_DOT_DOT_DOT ) {
                parm_end = 1; /* can have no more parms after this. */
            }
            mp = (struct macro_parm *)CMemAlloc( sizeof( struct macro_parm ) );
            if( formal_parms == NULL ) {
                formal_parms = mp;
            } else {
                if( FormalParm( formal_parms ) ) {
                    CErr2p( ERR_DUPLICATE_MACRO_PARM, Buffer );
                }
                prev_mp->next_macro_parm = mp;
            }
            if( CurToken == T_DOT_DOT_DOT )
                mp->parm = CStrSave( "__VA_ARGS__" );
            else
                mp->parm = CStrSave( Buffer );
            prev_mp = mp;
            PPNextToken();
            if( CurToken == T_RIGHT_PAREN ) break;
            if( CurToken == T_NULL ) {
                CErr1( ERR_INVALID_MACRO_DEFN );
                break;
            }
            if( parm_end ) {
                ExpectingAfter( ")", "..." );
                return;
            }
            MustRecog( T_COMMA );
            if( CurToken != T_ID && CurToken != T_DOT_DOT_DOT ) {   /* 16-nov-94 */
                ExpectIdentifier();
                return;
            }
        }
    }
    /* grab replacement tokens */
    ppscan_mode = InitPPScan();         // enable T_PPNUMBER tokens
    GrabTokens( parm_end ? -(parm_cnt + 1) : (parm_cnt + 1), formal_parms, token_buf );
    FiniPPScan( ppscan_mode );          // disable T_PPNUMBER tokens
    for( ; mp = formal_parms; ) {
        formal_parms = mp->next_macro_parm;
        CMemFree( mp->parm );
        CMemFree( mp );
    }
    CMemFree( token_buf );
}


local void GrabTokens( int parm_cnt, struct macro_parm *formal_parms, const char *mac_name )
{
    MEPTR       mentry;
    int         i;
    int         j;
    int         prev_token;
    int         prev_non_ws_token;
    unsigned    mlen;
    int         has_var_args = 0;

    j = strlen( mac_name ) + 1;
    mentry = (MEPTR)CMemAlloc( sizeof( MEDEFN ) + j );
    if( parm_cnt < 0 ) {
        has_var_args = 1;
        parm_cnt = -parm_cnt;
    }
    mentry->parm_count = parm_cnt;
    strcpy( mentry->macro_name, mac_name );
    mlen = offsetof( MEDEFN, macro_name ) + j;
    mentry->macro_defn = mlen;
    MacroOverflow( mlen, 0 );
    MacroCopy( (const char *)mentry, MacroOffset, mlen );
    prev_token = T_NULL;
    prev_non_ws_token = T_NULL;
    if( CurToken != T_NULL ) {
        do {
            CurToken = ScanToken();
        } while( CurToken == T_WHITE_SPACE );
        if( CurToken == T_SHARP_SHARP ) {
            CErr1( ERR_MISPLACED_SHARP_SHARP );
            PPNextToken();
        }
    }
    for( ;; ) {
        i = 0;
        if( (CurToken == T_STRING) && CompFlags.wide_char_string ) {
            CurToken = T_LSTRING;                   /* 15-may-92 */
        }
        TokenBuf[i++] = CurToken;
        if( CurToken == T_NULL ) break;
        if( CurToken == T_EOF )  break;
        switch( CurToken ) {
        case T_SHARP:
            /* if it is a function-like macro definition */
            if( parm_cnt != 0 ) {
                TokenBuf[i-1] = T_MACRO_SHARP;
                CurToken = T_MACRO_SHARP;           /* 26-mar-91 */
            }
            break;
        case T_SHARP_SHARP:
            TokenBuf[i-1] = T_MACRO_SHARP_SHARP;
            break;
        case T_WHITE_SPACE:
            if( prev_token == T_WHITE_SPACE )
                --i;
            break;
        case T_ID:
            j = FormalParm( formal_parms );
            if( j != 0 ) {
                if( has_var_args && (j == parm_cnt - 1) )

⌨️ 快捷键说明

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