📄 cmac2.c
字号:
/****************************************************************************
*
* 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 + -