cmac2.c

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

C
856
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "plusplus.h"
#include "preproc.h"
#include "errdefns.h"
#include "scan.h"
#include "memmgr.h"
#include "fname.h"
#include "ring.h"
#include "vstk.h"
#include "cmdline.h"
#include "cgmisc.h"
#include "name.h"
#include "cmacsupp.h"
#include "brinfo.h"


typedef struct mac_parm MAC_PARM;
struct mac_parm {
    MAC_PARM    *next;
    char        name[1];
};

struct cpp_info {                   // Pre-processor information
    TOKEN_LOCN  locn;
    char        cpp_type;
    char        processing;
};

static struct cpp_info *pp_stack;   // top of pre-processor stack
static VSTK_CTL vstkPp;             // pre-processor stack

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 );
extern void CPragma( void );
static void CIdent( void );
static void CUnknown( void );

typedef struct {
    char        *directive;
    void        (*samelevel)( void );
    void        (*skiplevel)( void );
} PPCTRL;

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 PPCTRL controlTable[] = {
    { "",       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_stack_states {
    PRE_NULL,
    PRE_ELSE,
    PRE_ELIF,
    PRE_IF,
};



static void flush2EOL( void )
{
    while( CurToken != T_NULL ) {
        if( CurToken == T_EOF ) break;
        NextToken();
    }
}

static void CSkip( void )
{
}

static void IncLevel( int value )
{
    struct cpp_info *cpp;

    cpp = VstkPush( &vstkPp );
    pp_stack = cpp;
    SrcFileGetTokenLocn( &cpp->locn );
    cpp->cpp_type = PRE_IF;
    cpp->processing = 0;
    if( NestLevel == SkipLevel ) {
        if( value ) {
            ++SkipLevel;
            cpp->processing = 1;
        }
    }
    ++NestLevel;
}

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

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

static void CInclude( void )
{
    struct {
        unsigned in_macro : 1;
    } flags;

    auto char   buf[_MAX_PATH];

    SrcFileGuardStateSig();
    InitialMacroFlag = 0;
    flags.in_macro = 0;
    if( CompFlags.use_macro_tokens ) {
        flags.in_macro = 1;
    }
    PPState = PPS_EOL | PPS_NO_LEX_ERRORS;
    NextToken();
    if( CurToken == T_STRING ) {
        OpenSrcFile( Buffer, FALSE );
    } else if( CurToken == T_LT ) {
        if( ! flags.in_macro ) {
            PPState = PPS_EOL | PPS_NO_LEX_ERRORS | PPS_NO_EXPAND;
        }
        buf[0] = '\0';
        for(;;) {
            NextToken();
            if( CurToken == T_GT ) {
                OpenSrcFile( buf, TRUE );
                break;
            }
            strncat( buf, Buffer, sizeof( buf ) - 2 );
            if( ( flags.in_macro != 0  && ! CompFlags.use_macro_tokens )
                ||  CurToken == T_NULL
                ||  CurToken == T_EOF ) {
                CErr1( ERR_INVALID_INCLUDE );
                break;
            }
        }
    } else {
        CErr1( ERR_INVALID_INCLUDE );
    }
    if( CurToken != T_EOF ) {
        NextToken();
    }
}

static void CDefine( void )
{
    MEPTR define_macro;

    define_macro = MacroScan( MSCAN_DEFINE );
    if( define_macro != NULL ) {
        define_macro->macro_flags |= MACRO_USER_DEFINED;
    }
}

static unsigned addParmName( MAC_PARM **h, boolean add_name )
{
    unsigned index;
    size_t len;
    size_t len_1;
    MAC_PARM *parm_name;
    if( CurToken == T_DOT_DOT_DOT )
        strcpy( Buffer, "__VA_ARGS__" );
    len = strlen( Buffer );
    len_1 = len + 1;
    index = 0;
    RingIterBeg( *h, parm_name ) {
        ++index;
        if( NameMemCmp( parm_name->name, Buffer, len_1 ) == 0 ) {
            /* already present */
            return( index );
        }
    } RingIterEnd( parm_name );
    if( add_name ) {
        parm_name = CMemAlloc( offsetof( MAC_PARM, name ) + len + 1 );
        memcpy( parm_name->name, Buffer, len_1 );
        RingAppend( h, parm_name );
    }
    return( 0 );
}

static unsigned findParmName( MAC_PARM **h )
{
    if( *h != NULL ) {
        return( addParmName( h, FALSE ) );
    }
    return( 0 );
}

static boolean skipEqualOK( void )
{
    switch( CurToken ) {
    case T_EQ :
        CurToken = T_EQUAL;     // strip = from ==
        break;
    case T_EQUAL :
        NextToken();
        break;
    case T_SHARP :
    case T_ALT_SHARP :
        NextToken();
        break;
    case T_SHARP_SHARP :
    case T_ALT_SHARP_SHARP :
        CurToken = T_SHARP;     // strip # from ##
        break;
    case T_NULL :
        break;
    default :
        BadCmdLine( ERR_INVALID_OPTION );
        return( FALSE );
    }
    return( TRUE );
}


static MEPTR grabTokens(    // SAVE TOKENS IN A MACRO DEFINITION
    MAC_PARM **parm_names,  // - macro parm names
    int parm_cnt,           // - parameter count
    macro_scanning defn,    // - scanning definition
    unsigned name_len,      // - length of macro name
    unsigned mlen,          // - length of macro def'n (so far)
    TOKEN_LOCN* locn )      // - definition point
{
    MEPTR mptr;
    MEPTR mentry;
    unsigned parm_index;
    unsigned prev_token;
    unsigned prev_non_ws_token;
    unsigned has_var_args = 0;

    // MacroOverflow was called for the name of the macro + mentry already
    mentry = (MEPTR) MacroOffset;
    DbgAssert( ( MacroOverflow( mlen, 0 ), MacroOffset == (void*) mentry ) );
    if( parm_cnt < 0 )
    {
        has_var_args = 1;
        parm_cnt = -parm_cnt;
    }
    mentry->parm_count = parm_cnt;
    mentry->macro_defn = mlen;
    prev_token = T_NULL;
    prev_non_ws_token = T_NULL;
    if( CurToken != T_NULL ) {
        do {
            CurToken = ScanToken( 0 );
        } while( CurToken == T_WHITE_SPACE );
        if( defn & MSCAN_EQUALS ) {
            if( CurToken == T_NULL ) {
                // -dFOO from a command line
                MacroOffsetAddChar( &mlen, 1, T_PPNUMBER );
                MacroOffsetAddMem( &mlen, "1", 2 );
                prev_non_ws_token = T_PPNUMBER;
                prev_token = T_PPNUMBER;
            } else {
                if( ! skipEqualOK() ) {
                    return( NULL );
                }
            }
        }
        if( ( CurToken == T_SHARP_SHARP )
          || ( CurToken == T_ALT_SHARP_SHARP ) ) {
            CErr1( ERR_MISPLACED_SHARP_SHARP );
            NextToken();
        }
    }
    for(;;) {
        if( CurToken == T_NULL ) break;
        switch( CurToken ) {
          case T_SHARP:
          case T_ALT_SHARP:
            /* if it is a function-like macro definition */
            if( parm_cnt != 0 ) {
                CurToken = T_MACRO_SHARP;
            }
            MacroOffsetAddChar( &mlen, 1, CurToken );
            break;
          case T_SHARP_SHARP:
          case T_ALT_SHARP_SHARP:
            CurToken = T_MACRO_SHARP_SHARP;
            MacroOffsetAddChar( &mlen, 1, CurToken );
            break;
          case T_WHITE_SPACE:
            if( prev_token != T_WHITE_SPACE ) {
                MacroOffsetAddChar( &mlen, 1, CurToken );
            }
            break;
          case T_ID:
            parm_index = findParmName( parm_names );
            if( parm_index != 0 ) {
                if( has_var_args && parm_index == ( parm_cnt - 1 ) )
                    CurToken = T_MACRO_VAR_PARM;
                else
                    CurToken = T_MACRO_PARM;
                MacroOffsetAddChar( &mlen, 2, CurToken, parm_index - 1 );
            } else {
                MacroOffsetAddChar( &mlen, 1, CurToken );
                MacroOffsetAddMem( &mlen, Buffer, TokenLen + 1 );
            }
            break;
          case T_BAD_CHAR:
            if( Buffer[1] != '\0' ) {
                MacroOffsetAddChar( &mlen, 3, CurToken, Buffer[0], T_WHITE_SPACE );
            } else {
                MacroOffsetAddChar( &mlen, 2, CurToken, Buffer[0] );
            }
            break;
          case T_BAD_TOKEN :
          case T_CONSTANT:
          case T_PPNUMBER:
            MacroOffsetAddChar( &mlen, 1, CurToken );
            MacroOffsetAddMem( &mlen, Buffer, TokenLen + 1 );
            break;
          case T_STRING:
          case T_LSTRING:
            // TokenLen includes '\0' for strings
            MacroOffsetAddChar( &mlen, 1, CurToken );
            MacroOffsetAddMem( &mlen, Buffer, TokenLen );
            break;
          default :
            MacroOffsetAddChar( &mlen, 1, CurToken );
            break;
        }
        if( CurToken != T_WHITE_SPACE ) {
            if( prev_non_ws_token == T_MACRO_SHARP && 
                CurToken != T_MACRO_VAR_PARM &&
                CurToken != T_MACRO_PARM ) {
                CErr1( ERR_MUST_BE_MACRO_PARM );
            }
            prev_non_ws_token = CurToken;
        }
        prev_token = CurToken;
        CurToken = ScanToken( 0 );
        if( ! ( defn & MSCAN_MANY ) ) break;
    }
    if( prev_token == T_WHITE_SPACE ) {
        --mlen;
    }
    MacroOffsetAddChar( &mlen, 1, T_NULL );
    if( prev_non_ws_token == T_MACRO_SHARP_SHARP ) {
        CErr1( ERR_MISPLACED_SHARP_SHARP );
    }
    mentry = (MEPTR) MacroOffset;       // MacroOffset could have changed
    TokenLocnAssign( mentry->defn, *locn );
    mentry->macro_len = mlen;
    if( has_var_args )
        InitialMacroFlag |= MACRO_HAS_VAR_ARGS;
    mptr = MacroDefine( mentry, mlen, name_len );
    InitialMacroFlag &= ~MACRO_HAS_VAR_ARGS;
    BrinfDeclMacro( mptr );
    if( ! ( defn & MSCAN_MANY ) ) {
        while( CurToken == T_WHITE_SPACE ) {
            CurToken = ScanToken( 0 );
        }
        if( CurToken != T_NULL ) {
            BadCmdLine( ERR_INVALID_OPTION );
        }
    }
    return( mptr );
}


MEPTR MacroScan(                // SCAN AND DEFINE A MACRO (#define, -d)
    macro_scanning defn )       // - scanning definition
{
    int parm_cnt, parm_end;     // - parameter count, end found
    unsigned name_len;          // - length of macro name
    MEPTR mptr;                 // - final macro defn
    MAC_PARM *parm_names;       // - macro parm names

⌨️ 快捷键说明

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