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 + -
显示快捷键?