fmacros.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 350 行
C
350 行
/****************************************************************************
*
* 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 processor
*
****************************************************************************/
#include "ftnstd.h"
#include "global.h"
#include "progsw.h"
#include "errcod.h"
#include "cpopt.h"
#include "fmemmgr.h"
#include "ferror.h"
#include <string.h>
typedef struct macro_entry {
struct macro_entry *link;
byte name_len;
byte status;
char name[1];
} macro_entry;
static macro_entry *MacroList;
static unsigned char NestingLevel;
static unsigned_16 NestingFlags;
static unsigned_16 NestingStack;
static unsigned_8 MacroFlags;
#define MAX_NESTING 16
#define MACRO_PERMANENT 0x01
#define DEBUG_MACRO_LEN 9
static char DebugMacro[] = { "__debug__" };
void InitMacroProcessor( void ) {
//============================
// Initialize macro processor in case macros defined on command line.
MacroFlags = MACRO_PERMANENT;
}
void FiniMacroProcessor( void ) {
//============================
// Finalize macro processor.
FreeMacros( TRUE );
}
void InitPredefinedMacros( void ) {
//==============================
#if _CPU == 386
MacroDEFINE( "__386__", 7 );
#elif _CPU == 8086
MacroDEFINE( "__i86__", 7 );
#elif _CPU == _AXP
MacroDEFINE( "__AXP__", 7 );
#elif _CPU == _PPC
MacroDEFINE( "__PPC__", 7 );
#else
#error Unknown platform/OS
#endif
#if _CPU == 386
if( CGOpts & CGOPT_STK_ARGS ) {
MacroDEFINE( "__stack_conventions__", 21 );
}
#endif
#if _CPU == 8086 || _CPU == 386
if( CPUOpts & (CPUOPT_FPR | CPUOPT_FPI | CPUOPT_FPI87 |
CPUOPT_FP287 | CPUOPT_FP387 | CPUOPT_FP5) ) {
MacroDEFINE( "__FPI__", 7 );
}
#endif
MacroFlags = 0;
}
void InitMacros( void ) {
//====================
// Initialize macro processor for a compilation.
NestingLevel = 0;
NestingFlags = 0;
NestingStack = 0;
}
void FiniMacros( void ) {
//====================
// Finalize macro processor for a compilation.
if( NestingLevel != 0 ) {
InfoError( CO_MACRO_STRUCTURE_MISMATCH );
}
FreeMacros( FALSE );
}
static void FreeMacros( bool free_perm ) {
//============================================
// Free macros.
macro_entry *link;
while( MacroList != NULL ) {
link = MacroList->link;
if( !free_perm && ( MacroList->status == MACRO_PERMANENT ) ) break;
FMemFree( MacroList );
MacroList = link;
}
}
static macro_entry *FindMacroEntry( char *macro, uint macro_len ) {
//======================================================================
// Find a macro.
macro_entry *me;
for( me = MacroList; me != NULL; me = me->link ) {
if( me->name_len != macro_len ) continue;
if( memicmp( me->name, macro, macro_len ) == 0 ) return( me );
}
return( NULL );
}
bool CompileDebugStmts( void ) {
//===========================
// Determine if debug statements should be compiled.
return( FindMacroEntry( DebugMacro, DEBUG_MACRO_LEN ) != NULL );
}
void MacroDEFINE( char *macro, uint macro_len ) {
//==================================================
// Define a macro.
macro_entry *me;
me = FindMacroEntry( macro, macro_len );
if( me == NULL ) {
me = FMemAlloc( sizeof( macro_entry ) + macro_len - sizeof( char ) );
me->link = MacroList;
me->name_len = macro_len;
me->status = MacroFlags;
memcpy( &me->name, macro, macro_len );
MacroList = me;
}
}
void MacroUNDEFINE( char *macro, uint macro_len ) {
//====================================================
// Define a macro.
macro_entry **me;
macro_entry *free_me;
for( me = &MacroList; *me != NULL; me = &(*me)->link ) {
if( (*me)->name_len != macro_len ) continue;
if( memicmp( (*me)->name, macro, macro_len ) == 0 ) {
free_me = *me;
*me = free_me->link;
FMemFree( free_me );
return;
}
}
}
static void SetSkipStatus( void ) {
//===============================
// Determine whether source is to be skipped.
int i;
for( i = 0; i <= NestingLevel; ++i ) {
if( NestingFlags & ( 1 << i ) ) {
ProgSw |= PS_SKIP_SOURCE;
return;
}
}
ProgSw &= ~PS_SKIP_SOURCE;
}
void MacroIFDEF( char *macro, uint macro_len ) {
//=================================================
// Process IFDEF directive.
IFCondition( FindMacroEntry( macro, macro_len ) != NULL );
}
void MacroIFNDEF( char *macro, uint macro_len ) {
//==================================================
// Process IFNDEF directive.
IFCondition( FindMacroEntry( macro, macro_len ) == NULL );
}
static void IFCondition( bool cond ) {
//========================================
// Process a IF condition.
if( NestingLevel == MAX_NESTING ) {
InfoError( CO_MACRO_NESTING_EXCEEDED );
} else {
MacroCondition( cond );
++NestingLevel;
}
}
static void MacroCondition( bool cond ) {
//===========================================
// Process a macro condition.
NestingStack |= 1 << NestingLevel;
if( cond ) {
NestingFlags &= ~( 1 << NestingLevel );
} else {
NestingFlags |= 1 << NestingLevel;
}
SetSkipStatus();
}
void MacroELIFDEF( char *macro, uint macro_len ) {
//===================================================
// Process ELIFDEF directive.
--NestingLevel;
if( !( NestingStack & ( 1 << NestingLevel ) ) ) {
InfoError( CO_MACRO_STRUCTURE_MISMATCH );
} else {
if( NestingFlags & ( 1 << NestingLevel ) ) {
MacroCondition( FindMacroEntry( macro, macro_len ) != NULL );
} else {
NestingFlags |= 1 << NestingLevel;
SetSkipStatus();
NestingFlags &= ~( 1 << NestingLevel );
}
}
++NestingLevel;
}
void MacroELIFNDEF( char *macro, uint macro_len ) {
//====================================================
// Process ELIFNDEF directive.
--NestingLevel;
if( !( NestingStack & ( 1 << NestingLevel ) ) ) {
InfoError( CO_MACRO_STRUCTURE_MISMATCH );
} else {
if( NestingFlags & ( 1 << NestingLevel ) ) {
MacroCondition( FindMacroEntry( macro, macro_len ) == NULL );
} else {
NestingFlags |= 1 << NestingLevel;
SetSkipStatus();
}
}
++NestingLevel;
}
void MacroELSE( void ) {
//===================
// Process ELSE directive.
--NestingLevel;
if( !( NestingStack & ( 1 << NestingLevel ) ) ) {
InfoError( CO_MACRO_STRUCTURE_MISMATCH );
} else {
NestingStack &= ~( 1 << NestingLevel );
if( NestingFlags & ( 1 << NestingLevel ) ) {
NestingFlags &= ~( 1 << NestingLevel );
} else {
NestingFlags |= 1 << NestingLevel;
}
SetSkipStatus();
}
++NestingLevel;
}
void MacroENDIF( void ) {
//====================
// Process ENDIF directive.
if( NestingLevel == 0 ) {
InfoError( CO_MACRO_STRUCTURE_MISMATCH );
} else {
--NestingLevel;
NestingFlags &= ~( 1 << NestingLevel );
SetSkipStatus();
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?