cmac2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 856 行 · 第 1/2 页
C
856 行
int ppscan_mode; // - previous ppnumber scan mode
unsigned mlen; // - current length of macro def'n
TOKEN_LOCN locn; // - location for definition
SrcFileGuardStateSig();
NextToken();
if( CurToken != T_ID ) {
Expecting( "identifier" );
return( NULL );
} else {
SrcFileGetTokenLocn( &locn );
}
name_len = TokenLen;
mlen = offsetof( MEDEFN, macro_name );
parm_names = NULL;
MacroOffsetAddMem( &mlen, Buffer, TokenLen + 1 );
if( CurrChar == '(' ) { /* parms present */
if( ! ( defn & MSCAN_MANY ) ) {
BadCmdLine( ERR_INVALID_OPTION );
return( NULL );
}
NextToken(); /* grab the '(' */
NextToken();
parm_cnt = 0; /* 0 ==> () following */
parm_end = 0;
for( ;; ) {
if( CurToken == T_RIGHT_PAREN ) break;
if( parm_end ) {
Expecting( ")" );
return( NULL );
}
if( CurToken != T_ID &&
CurToken != T_DOT_DOT_DOT) {
Expecting( "identifier" );
return( NULL );
}
if( addParmName( &parm_names, TRUE ) != 0 ) {
CErr2p( ERR_DUPLICATE_MACRO_PARM, Buffer );
} else {
++parm_cnt;
if( CurToken == T_DOT_DOT_DOT )
parm_end = 1; // can have no further tokens
MacroOffsetAddMem( &mlen, Buffer, TokenLen + 1 );
}
NextToken();
if( CurToken == T_RIGHT_PAREN ) break;
if( CurToken == T_NULL ) {
CErr1( ERR_INVALID_MACRO_DEFN );
break;
}
MustRecog( T_COMMA );
}
} else {
parm_cnt = -1; /* -1 ==> no () following */
}
/* grab replacement tokens */
ppscan_mode = InitPPScan(); // enable T_PPNUMBER tokens
mptr = grabTokens( &parm_names
, parm_end?-(parm_cnt + 1):(parm_cnt + 1)
, defn
, name_len
, mlen
, &locn );
FiniPPScan( ppscan_mode ); // disable T_PPNUMBER tokens
RingFree( &parm_names );
return( mptr );
}
static void ChkEOL( void )
{
if( CurToken != T_NULL && CurToken != T_EOF ) {
Expecting( "end of line" );
}
}
static void ppIf( int value ) // PREPROCESSOR IF
{
if( SrcFileGuardedIf( value ) ) {
return;
}
IncLevel( value );
ChkEOL();
}
static void ppIfId( int value ) // PREPROCESSOR IFDEF IFNDEF
{
NextToken();
ppIf( value );
}
static void CIfDef( void )
{
SrcFileGuardPpIf();
NextToken();
if( CurToken != T_ID ) {
Expecting( "identifier" );
IncLevel( 0 );
return;
}
ppIfId( MacroDependsDefined() );
}
static void CIfNDef( void )
{
SrcFileGuardPpIf();
NextToken();
if( CurToken != T_ID ) {
Expecting( "identifier" );
IncLevel( 0 );
return;
}
SrcFileGuardPpIfndef( Buffer, TokenLen );
ppIfId( ! MacroDependsDefined() );
}
static void CIf( void )
{
SrcFileGuardPpIf();
// don't set PPS_NO_LEX_ERRORS since we want tokenizing errors diagnosed
PPState = PPS_EOL;
NextToken();
ppIf( PpConstExpr() );
}
static void CElif( void )
{
int value;
SrcFileGuardPpElse();
PPState = PPS_EOL | PPS_NO_LEX_ERRORS;
NextToken();
if( NestLevel == 0 || pp_stack->cpp_type == PRE_ELSE ) {
CErr1( ERR_MISPLACED_ELIF );
} else {
if( NestLevel == SkipLevel ) {
--SkipLevel; /* start skipping else part */
pp_stack->processing = 0;
pp_stack->cpp_type = PRE_ELIF;
} else if( NestLevel == SkipLevel + 1 ) {
/* only evaluate the expression when required */
if( pp_stack->cpp_type == PRE_IF ) {
value = PpConstExpr();
ChkEOL();
if( value ) {
SkipLevel = NestLevel; /* start including else part */
pp_stack->processing = 1;
pp_stack->cpp_type = PRE_ELIF;
}
}
}
}
}
static void wantEOL( void )
{
if( CurToken != T_NULL && CurToken != T_EOF ) {
if( NestLevel == SkipLevel ) {
CErr1( ANSI_JUNK_FOLLOWS_DIRECTIVE );
}
flush2EOL();
}
}
static void CElse( void )
{
SrcFileGuardPpElse();
if( NestLevel == 0 || pp_stack->cpp_type == PRE_ELSE ) {
CErr1( ERR_MISPLACED_ELSE );
} else {
if( NestLevel == SkipLevel ) {
--SkipLevel; /* start skipping else part */
pp_stack->processing = 0;
} else if( NestLevel == SkipLevel + 1 ) {
/* cpp_type will be PRE_ELIF if an elif was true */
if( pp_stack->cpp_type == PRE_IF ) { /* 19-sep-88 */
SkipLevel = NestLevel; /* start including else part */
pp_stack->processing = 1;
}
}
pp_stack->cpp_type = PRE_ELSE;
}
NextToken();
wantEOL();
}
static void CEndif( void )
{
if( NestLevel == 0 ) {
CErr1( ERR_MISPLACED_ENDIF );
} else {
struct cpp_info *pp = pp_stack;
if( pp != NULL && ! SrcFileSame( pp->locn.src_file, SrcFileCurrent() ) ) {
if( CErr1( WARN_WEIRD_ENDIF_ENCOUNTER ) & MS_PRINTED ) {
CErr2p( INF_PP_DIRECTIVE_LOCN, &(pp->locn) );
}
}
--NestLevel;
VstkPop( &vstkPp );
pp_stack = VstkTop( &vstkPp );
SrcFileGuardPpEndif();
}
if( NestLevel < SkipLevel ) {
SkipLevel = NestLevel;
}
NextToken();
wantEOL();
}
static void CUnDef( void )
{
NextToken();
if( CurToken != T_ID ) {
Expecting( "identifier" );
return;
}
MacroUndefine( TokenLen );
NextToken();
ChkEOL();
}
static void CLine( void )
{
int adjust;
LINE_NO line;
PPState = PPS_EOL | PPS_NO_LEX_ERRORS;
NextToken();
if( CurToken == T_CONSTANT ) {
line = U32Fetch( Constant64 ); // side effects of NextToken
NextToken();
if( CurToken == T_NULL ) {
if( CompFlags.cpp_ignore_line == 0 ) {
SrcFileAlias( SrcFileNameCurrent(), line, 0 );
}
} else if( CurToken != T_STRING ) {
Expecting( "string" );
} else {
if( CompFlags.cpp_ignore_line == 0 ) {
if( CurrChar == '\n' ) {
// line # has already been incremented
adjust = 0;
} else {
// line # will be incremented
adjust = -1;
}
SrcFileAlias( Buffer, line, adjust );
}
NextToken(); // may clobber Buffer's contents
ChkEOL(); // will increment line # if CurToken != T_NULL
}
} else {
Expecting( "constant" );
}
}
static void CError( void )
{
int i;
int save;
i = 0;
while( CurrChar != '\n' && CurrChar != '\r' && CurrChar != LCHR_EOF ) {
if( i != 0 || CurrChar != ' ' ) {
Buffer[ i ] = CurrChar;
++i;
}
NextChar();
}
Buffer[ i ] = '\0';
/* Force #error output to be reported, even with preprocessor */
save = CompFlags.cpp_output;
CompFlags.cpp_output = 0;
CErr2p( ERR_USER_ERROR_MSG, Buffer );
CompFlags.cpp_output = save;
}
static void CIdent( void )
{
if( ! CompFlags.extensions_enabled ) {
CUnknown();
}
flush2EOL();
}
static void preProcStmt( void )
{
PPCTRL *pp;
int hash;
NextChar();
NextToken();
if( CurToken == T_ID ) {
hash = (TokenLen + preprocWeights[ Buffer[0] - 'a' ]
+ preprocWeights[ Buffer[TokenLen-1] - 'a' ]) & 15;
pp = &controlTable[hash];
if( strcmp( pp->directive, Buffer ) == 0 ) {
if( NestLevel == SkipLevel ) {
pp->samelevel();
} else {
pp->skiplevel();
}
} else {
CUnknown();
}
} else if( CurToken != T_NULL ) {
CUnknown();
}
flush2EOL();
}
// When a new file is opened, it's guarded state will indicate top of file.
// ChkControl() is always called at the start of a file because CurrChar
// will be set to '\n'. ChkControl is always called at the start of every
// line.
// Thus we have complete control over setting the guarded state here.
// We can determine is the first directive is #if, #ifdef or #ifndef.
//
int ChkControl( // CHECK AND PROCESS DIRECTIVES
int expanding )
{
int lines_skipped;
ppstate_t save_ppstate;
while( CurrChar == '\n' ) {
SrcFileCurrentLocation();
if( TBreak() ) {
CErr1( ERR_BREAK_KEY_HIT );
CSuicide();
}
lines_skipped = 0;
save_ppstate = PPState;
for(;;) {
if( CompFlags.cpp_output ) PrtChar( '\n' );
NextChar();
// look for a #-char or the corresponding digraph (%:)
if( CurrChar != PreProcChar && CurrChar != '%' ) {
SkipAhead();
}
if( CurrChar == LCHR_EOF ) break;
if( CurrChar == '%' ) {
NextChar();
if( CurrChar == ':' ) {
// replace the digraph (%:) with the preproc-char
CurrChar = PreProcChar;
} else {
GetNextCharUndo( CurrChar );
CurrChar = '%';
}
}
PPState = PPS_EOL | PPS_NO_EXPAND | PPS_NO_LEX_ERRORS;
if( CurrChar == PreProcChar ) {
preProcStmt();
} else if( NestLevel != SkipLevel ) {
NextToken();
flush2EOL();
}
PPState = save_ppstate;
if( NestLevel == SkipLevel ) break;
if( CurrChar == LCHR_EOF ) break;
if( CurrChar == '\n' ) {
lines_skipped = 1;
}
}
if( CompFlags.cpp_output ) {
if( lines_skipped ) {
EmitLine( SrcFileLine(), SrcFileNameCurrent() );
}
}
}
// we have already skipped past all white space at the start of the line
CurToken = ScanToken( expanding );
// this will be the first significant token on the source line
SrcFileGuardStateSig();
return( CurToken );
}
void DirectiveInit( // INITIALIZE FOR DIRECTIVE PROCESSING
void )
{
NestLevel = 0;
SkipLevel = 0;
pp_stack = NULL;
VstkOpen( &vstkPp, sizeof( struct cpp_info ), 8 );
}
void DirectiveFini( // COMPLETE DIRECTIVE PROCESSING
void )
{
struct cpp_info *pp; // - unclosed entry
for(;;) {
pp = VstkPop( &vstkPp );
if( pp == NULL ) break;
SetErrLoc( &pp->locn );
CErr1( ERR_MISSING_CENDIF );
}
VstkClose( &vstkPp );
}
int CppPrinting( // TEST IF AT LEVEL FOR PREPROC PRINTING
void )
{
return ( NestLevel == SkipLevel ) && ( CppFile != NULL );
}
unsigned IfDepthInSrcFile( // COMPUTE #IF DEPTH IN CURRENT SOURCE FILE
void )
{
unsigned depth; // - depth of #if's
struct cpp_info *pp; // - current pre-processor stack entry
SRCFILE curr_src; // - current SRCFILE
for( curr_src = SrcFileCurrent(), depth = 0, pp = VstkTop( &vstkPp )
; ( pp != NULL ) && ( pp->locn.src_file == curr_src )
; ++depth, pp = VstkNext( &vstkPp, pp ) );
return depth;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?