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