cmac1.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,383 行 · 第 1/3 页
C
1,383 行
/****************************************************************************
*
* 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 one.
*
****************************************************************************/
#include "plusplus.h"
#include "preproc.h"
#include "tokenbuf.h"
#include "errdefns.h"
#include "memmgr.h"
#include "macro.h"
#include "ring.h"
#include "dbg.h"
#include "fmtsym.h"
#include "initdefs.h"
#include "yydriver.h"
#include "carve.h"
#define T_UNEXPANDABLE_ID T_LAST_TOKEN
typedef struct _tokens TOKEN_LIST;
struct _tokens {
TOKEN_LIST *next;
unsigned length;
char buf[1];
};
typedef struct macro_token MACRO_TOKEN;
struct macro_token {
MACRO_TOKEN *next;
uint_8 token;
char data[1];
};
typedef struct macro_arg {
char *arg;
} MACRO_ARG;
typedef struct nested_macros NESTED_MACRO;
struct nested_macros {
NESTED_MACRO *next;
MEPTR fmentry;
MACRO_ARG *macro_parms;
unsigned rescanning : 1;
unsigned substituting_parms : 1;
};
static carve_t carveNESTED_MACRO;
static NESTED_MACRO *nestedMacros;
static MACRO_TOKEN *scannerTokenList;
static MACRO_TOKEN *internalTokenList;
static unsigned macroDepth;
static MACRO_TOKEN *macroExpansion( MEPTR, int );
static MACRO_TOKEN *nestedMacroExpansion( MEPTR, boolean );
#ifdef pick
#undef pick
#endif
#define pick( s, i, f ) { s, i, f },
typedef struct special_macro_name SPECIAL_MACRO_NAME;
static struct special_macro_name {
char *name;
int value;
unsigned flags;
} SpcMacros[] = {
#include "specmac.h"
{ NULL, 0, 0 }
};
static void macroDiagNesting( // DIAGNOSE NESTING
void )
{
NESTED_MACRO* curr; // - current entry
for( curr = nestedMacros ; NULL != curr ; curr = curr->next ) {
MEPTR mdef = curr->fmentry;
CErr( INF_MACRO_EXPANSION, mdef->macro_name, &mdef->defn );
}
}
static void macroInit( // MACRO PROCESSING -- INITIALIZATION
INITFINI* defn ) // - definition
{
SPECIAL_MACRO_NAME *mac;
defn = defn;
DirectiveInit();
nestedMacros = NULL;
scannerTokenList = NULL;
InitialMacroFlag = MACRO_DEFINED_BEFORE_FIRST_INCLUDE;
MacroStorageInit();
for( mac = SpcMacros; mac->name != NULL; ++mac ) {
MacroSpecialAdd( mac->name, mac->value, mac->flags );
}
TimeInit(); /* grab time and date for __TIME__ and __DATE__ */
carveNESTED_MACRO = CarveCreate( sizeof( NESTED_MACRO ), 16 );
}
static void macroFini( // MACRO PROCESSING -- COMPLETION
INITFINI* defn ) // - definition
{
defn = defn;
DirectiveFini();
MacroStorageFini();
#ifndef NDEBUG
CarveVerifyAllGone( carveNESTED_MACRO, "NESTED_MACRO" );
#endif
CarveDestroy( carveNESTED_MACRO );
}
INITDEFN( macros, macroInit, macroFini )
static void deleteNestedMacro( void )
{
MEPTR fmentry;
NESTED_MACRO *nested;
MACRO_ARG *macro_parms;
int i;
nested = nestedMacros;
if( nested != NULL ) {
nestedMacros = nested->next;
macro_parms = nested->macro_parms;
fmentry = nested->fmentry;
CarveFree( carveNESTED_MACRO, nested );
i = fmentry->parm_count - 1;
if( i > 0 && macro_parms != NULL ) {
do {
--i;
CMemFree( macro_parms[i].arg );
} while( i != 0 );
CMemFree( macro_parms );
}
}
}
static unsigned copyMTokToBuffer( MACRO_TOKEN *mtok )
{
char *s;
unsigned len;
s = mtok->data;
len = strlen( s );
memcpy( Buffer, s, len + 1 );
return( len );
}
static MACRO_TOKEN *doGetMacroToken( // GET NEXT TOKEN
MACRO_TOKEN *list, // - list of tokens
boolean doing_macro_expansion ) // - TRUE ==> doing an expansion
{
char *token_end;
MACRO_TOKEN *mtok;
unsigned i;
struct {
unsigned keep_token : 1;
unsigned next_token : 1;
} flag;
CurToken = T_NULL;
for(;;) {
flag.keep_token = FALSE;
flag.next_token = FALSE;
mtok = list;
if( mtok == NULL ) {
CompFlags.use_macro_tokens = FALSE;
break;
}
CurToken = mtok->token;
i = copyMTokToBuffer( mtok );
switch( CurToken ) {
case T_UNEXPANDABLE_ID:
if( ! doing_macro_expansion ) {
CurToken = KwLookup( i );
TokenLen = i;
}
break;
case T_ID:
case T_SAVED_ID:
if( doing_macro_expansion ) {
CurToken = T_ID;
} else {
CurToken = KwLookup( i );
}
TokenLen = i;
break;
case T_BAD_TOKEN:
case T_CONSTANT:
ReScanInit( Buffer );
ReScanToken();
DbgAssert( mtok->data[ TokenLen ] == '\0' || CurToken == T_BAD_TOKEN );
break;
case T_PPNUMBER:
ReScanInit( Buffer );
ReScanToken();
DbgAssert( CurToken != T_STRING && CurToken != T_LSTRING );
token_end = &(mtok->data[ TokenLen ]);
if( *token_end != '\0' ) {
// ppnumber is quite general so it may absorb multiple tokens
strcpy( mtok->data, token_end );
flag.keep_token = TRUE;
}
break;
case T_STRING:
case T_LSTRING:
TokenLen = i + 1;
break;
case T_BAD_CHAR:
break;
case T_NULL:
if( Buffer[0] == 'Z' ) { // if end of macro
deleteNestedMacro();
}
flag.next_token = TRUE;
break;
}
if( ! flag.keep_token ) {
list = mtok->next;
CMemFree( mtok );
}
if( ! flag.next_token ) {
break;
}
}
DumpMacToken();
return( list );
}
void GetMacroToken( // GET NEXT TOKEN
boolean doing_macro_expansion ) // - TRUE ==> doing an expansion
{
scannerTokenList = doGetMacroToken( scannerTokenList, doing_macro_expansion );
}
static unsigned copySafe( unsigned i, char *m )
{
for(;;) {
if( i >= (BUF_SIZE-4) ) {
CErr1( ERR_TOKEN_TRUNCATED );
macroDiagNesting();
Buffer[i] = '\0';
break;
}
if(( Buffer[i] = *m++ ) == 0 ) break;
++i;
if(( Buffer[i] = *m++ ) == 0 ) break;
++i;
if(( Buffer[i] = *m++ ) == 0 ) break;
++i;
if(( Buffer[i] = *m++ ) == 0 ) break;
++i;
}
return( i );
}
static unsigned expandMacroToken( unsigned i, char *m )
{
char *p;
switch( *m ) {
case T_CONSTANT:
case T_PPNUMBER:
case T_ID:
case T_UNEXPANDABLE_ID:
case T_SAVED_ID:
case T_BAD_TOKEN:
++m;
i = copySafe( i, m );
break;
case T_LSTRING:
Buffer[i++] = 'L';
case T_STRING:
Buffer[i++] = '"';
++m;
i = copySafe( i, m );
Buffer[i++] = '"';
Buffer[i] = '\0';
break;
default:
p = Tokens[ *m ];
++m;
i = copySafe( i, p );
}
return( i );
}
static int file_name_copy( // COPY STRING, ESCAPING ANY BACKSLASHES
char *dst, // - destination
char const *src ) // - source
{
char *org = dst;
while( *src ) {
if( *src == '\\' ) {
*dst++ = '\\';
}
*dst++ = *src++;
}
*dst++ = *src++;
return( dst - org );
}
#define _FUNCTION_expandable (CompFlags.cpp_output == 0)
static int genFUNCTION(
int spec_macro )
{
SYMBOL sym;
size_t len;
VBUF buff;
char *name;
DbgAssert( ( spec_macro == MACRO_FUNCTION )
|| ( spec_macro == MACRO_FUNC ) );
if( ! _FUNCTION_expandable ) {
name = SpcMacros[ spec_macro ].name;
len = strlen( name );
memcpy( Buffer, name, len + 1 );
TokenLen = len;
return( T_ID );
}
sym = ParseCurrFunction();
if( sym != NULL ) {
FormatSymWithTypedefs( sym, &buff );
len = VStrLen( &buff );
if( len >= BUF_SIZE ) {
len = BUF_SIZE;
}
memcpy( Buffer, buff.buf, len );
VbufFree( &buff );
} else {
Buffer[0] = '?';
len = 1;
}
Buffer[len] = '\0';
TokenLen = len + 1;
return( T_STRING );
}
int SpecialMacro( // EXECUTE A SPECIAL MACRO
MEPTR fmentry ) // - macro entry
{
switch( fmentry->parm_count ) {
case MACRO_LINE:
ultoa( TokenLine, Buffer, 10 );
U32ToU64( TokenLine, &Constant64 );
ConstType = TYP_SINT;
return( T_CONSTANT );
case MACRO_FILE:
TokenLen = file_name_copy( Buffer, SrcFileNameCurrent() );
return( T_STRING );
case MACRO_DATE:
TokenLen = stpcpy( Buffer, __Date ) - Buffer + 1;
return( T_STRING );
case MACRO_TIME:
TokenLen = stpcpy( Buffer, __Time ) - Buffer + 1;
return( T_STRING );
case MACRO_FUNCTION:
case MACRO_FUNC:
return( genFUNCTION( fmentry->parm_count ) );
case MACRO_CPLUSPLUS:
Buffer[0] = '1';
Buffer[1] = '\0';
U32ToU64( 1, &Constant64 );
ConstType = TYP_SINT;
return( T_CONSTANT );
case MACRO_ALT_AND:
return( T_ALT_AND_AND );
case MACRO_ALT_BITAND:
return( T_ALT_AND );
case MACRO_ALT_AND_EQ:
return( T_ALT_AND_EQUAL );
case MACRO_ALT_OR:
return( T_ALT_OR_OR );
case MACRO_ALT_BITOR:
return( T_ALT_OR );
case MACRO_ALT_OR_EQ:
return( T_ALT_OR_EQUAL );
case MACRO_ALT_XOR:
return( T_ALT_XOR );
case MACRO_ALT_XOR_EQ:
return( T_ALT_XOR_EQUAL );
case MACRO_ALT_NOT:
return( T_ALT_EXCLAMATION );
case MACRO_ALT_NOT_EQ:
return( T_ALT_NE );
case MACRO_ALT_COMPL:
return( T_ALT_TILDE );
}
return( T_EOF );
}
static int nextMToken( unsigned prev_token )
{
ppstate_t save_ppstate;
internalTokenList = doGetMacroToken( internalTokenList, TRUE );
if( CurToken == T_NULL ) {
if( ScanOptionalComment() ) {
CurToken = T_WHITE_SPACE;
} else {
if( prev_token != T_WHITE_SPACE ) {
// at EOL, ChkControl skips white-space for you which
// is not appropriate at this point (this white-space
// may be significant)
// [the prev_token check is req'd because the scanner
// will not advance past T_NULL]
save_ppstate = PPState;
PPState |= PPS_EOL;
CurToken = ScanToken( 1 );
PPState = save_ppstate;
if( CurToken == T_NULL ) {
CurToken = T_WHITE_SPACE;
}
} else {
CurToken = ScanToken( 1 );
}
}
}
return( CurToken );
}
static void saveParm(
MEPTR fmentry,
int parm_cnt,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?