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

📄 cmac2.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*
*                            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 "pragmas.h"
#include "scan.h"
#include <stddef.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, int defn_offset );
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 );
}

#if 0
int ScanCharacters()
{
    int         c;
    char        *scanptr;

    scanptr = ScanCharPtr;
    for(;;) {
        c = *scanptr++;
        if( CharSet[c] & C_EX ) break;
        c = *scanptr++;
        if( CharSet[c] & C_EX ) break;
        c = *scanptr++;
        if( CharSet[c] & C_EX ) break;
        c = *scanptr++;
        if( CharSet[c] & C_EX ) break;
        c = *scanptr++;
        if( CharSet[c] & C_EX ) break;
        c = *scanptr++;
        if( CharSet[c] & C_EX ) break;
        c = *scanptr++;
        if( CharSet[c] & C_EX ) break;
        c = *scanptr++;
        if( CharSet[c] & C_EX ) break;
    }
    ScanCharPtr = scanptr;
    return( c );
}
#endif

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

    // mark some special characters so that we only have to do one test
    // for each character inside the main loop
    c = CurrChar;
    for(;;) {
        CharSet['/']  |= C_EX;          // make '/' special character
        if( (CharSet[c] & C_EX) == 0 ) {
            c = ScanCharacters();
        }
        if( c == '\n' ) {               // we are at end of line
            SrcFile->src_line++;
            SrcFileLineNum = SrcFile->src_line;
            break;
        }
        if( c == '/' ) {                // check for comment
            ScanSlash();
            c = CurrChar;
        } else {                // one of the other special characters
            c = GetCharCheck( c );
            if( c == EOF_CHAR ) break;
        }
    }
    CharSet['/']  &= ~C_EX;             // undo '/' special character
#endif
}

local void CSkip(void)
{
}

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

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


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


void CInclude()
{
    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 )  CompFlags.pre_processing = 2; /* 28-may-89 */
        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()
{
    struct macro_parm *mp, *prev_mp, *formal_parms;
    int         parm_cnt, parm_end = 0;
    int         i, j;
    int         ppscan_mode;

    PPNextToken();
    if( CurToken != T_ID ) {
        ExpectIdentifier();
        return;
    }
    if( strcmp( Buffer, "defined" ) == 0 ) {
        CErr1( ERR_CANT_DEFINE_DEFINED );
        return;
    }
    i = 0;
    while( (TokenBuf[i] = Buffer[i]) ) ++i;
    ++i;
    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;
            j = 0;
            while( (TokenBuf[i++] = Buffer[j++]) )
                /* empty */;
            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, i );
    FiniPPScan( ppscan_mode );          // disable T_PPNUMBER tokens
    for(; (mp = formal_parms); ) {
        formal_parms = mp->next_macro_parm;
        CMemFree( mp->parm );
        CMemFree( mp );
    }
}


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

        i = defn_offset;
        j = strlen( TokenBuf );
        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, TokenBuf );
        mlen = offsetof(MEDEFN,macro_name) + i;
        mentry->macro_defn = mlen;
        MacroOverflow( mlen, 0 );
        MacroCopy( (char *)mentry, MacroOffset, offsetof(MEDEFN,macro_name) );
        MacroCopy( TokenBuf, MacroOffset + offsetof(MEDEFN,macro_name), i );
        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 );

⌨️ 快捷键说明

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