📄 cmac1.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 one.
*
****************************************************************************/
#include "cvars.h"
#include "scan.h"
#define T_UNEXPANDABLE_ID T_LAST_TOKEN
struct tokens {
struct tokens *next;
int length;
char buf[1];
};
typedef struct macro_token {
struct macro_token *next;
byte token;
char data[1];
} MACRO_TOKEN;
typedef struct macro_arg {
char *arg;
} MACRO_ARG;
typedef struct nested_macros {
struct nested_macros *next;
MEPTR mentry;
MACRO_ARG *macro_parms;
char rescanning;
char substituting_parms;
} NESTED_MACRO;
static NESTED_MACRO *NestedMacros;
static MACRO_TOKEN *TokenList;
static MACRO_TOKEN *MacroExpansion();
static MACRO_TOKEN *NestedMacroExpansion( int );
static int MacroBeingExpanded ( MEPTR mentry );
local void SaveParm( MEPTR mentry,
int i,
int parm_cnt,
MACRO_ARG *macro_parms,
struct tokens *token_list,
int total );
struct special_macro_names {
char *name;
int value;
};
static struct special_macro_names SpcMacros[] = {
{"__LINE__", MACRO_LINE},
{"__FILE__", MACRO_FILE},
{"__DATE__", MACRO_DATE},
{"__TIME__", MACRO_TIME},
{"__STDC__", MACRO_STDC},
{NULL, 0}
};
static MEPTR MKSpcMacEntry( struct special_macro_names *mac )
{
int macro_len;
MEPTR mentry;
macro_len = sizeof( MEDEFN ) + strlen( mac->name );
mentry = (MEPTR) CMemAlloc( macro_len );
mentry->macro_defn = 0; /* indicate special macro */
mentry->macro_len = macro_len;
mentry->parm_count = mac->value;
strcpy( mentry->macro_name, mac->name );
return( mentry );
}
void MacroInit(void)
{
int i;
struct special_macro_names *mac;
MEPTR mentry;
MTokenLen = 0;
MacroCount = 0;
MacroPtr = NULL;
CppStackInit();
NestedMacros = NULL;
TokenList = NULL;
UndefMacroList = NULL; /* 26-may-94 */
InitialMacroFlag = MACRO_DEFINED_BEFORE_FIRST_INCLUDE;
AllocMacroSegment( 0x1000 );
MacHash = (MEPTR *)MacroSegment;
MacroOffset = MacroSegment + MACRO_HASH_SIZE * sizeof(MEPTR);
for( i=0; i < MACRO_HASH_SIZE; ++i ) {
MacHash[i] = NULL;
}
for( mac = SpcMacros; mac->name; ++mac ) {
mentry = MKSpcMacEntry( mac );
MacroAdd( mentry, NULL, 0, 0 );
}
TimeInit(); /* grab time and date for __TIME__ and __DATE__ */
}
static struct special_macro_names SpcMacroCompOnly[] = {
{"__FUNCTION__", MACRO_FUNC},
{"__func__", MACRO_FUNC},
{NULL, 0}
};
void MacroAddComp(void)
{
struct special_macro_names *mac;
MEPTR mentry;
for( mac = SpcMacroCompOnly; mac->name; ++mac ) {
mentry = MKSpcMacEntry( mac );
MacroAdd( mentry, NULL, 0, 0 );
}
}
void MacroFini(void)
{
CppStackFini();
MacroPurge();
}
void MacroPurge(void)
{
#if 0
int i;
MEPTR mentry;
for( i = 0; i < MACRO_HASH_SIZE; ++i ) {
for( ; mentry = MacHash[i]; ) {
MacHash[i] = mentry->next_macro;
CMemFree( mentry );
}
}
#endif
}
static void DeleteNestedMacro(void)
{
MEPTR mentry;
NESTED_MACRO *nested;
MACRO_ARG *macro_parms;
int i;
nested = NestedMacros;
if( nested != NULL ) {
NestedMacros = nested->next;
macro_parms = nested->macro_parms;
mentry = nested->mentry;
CMemFree( nested );
i = mentry->parm_count - 1;
if( i > 0 && macro_parms != NULL ) {
do {
--i;
CMemFree( macro_parms[i].arg );
} while( i != 0 );
CMemFree( macro_parms );
}
}
}
void GetMacroToken(void)
{
MACRO_TOKEN *mtok;
unsigned i;
char *buf;
struct {
unsigned keep_token : 1;
unsigned next_token : 1;
} flag;
buf = Buffer;
CurToken = T_NULL;
for(;;) {
flag.keep_token = FALSE;
flag.next_token = FALSE;
mtok = TokenList;
if( mtok == NULL ) {
MacroPtr = NULL;
break;
}
CurToken = mtok->token;
i = 0;
while( (buf[i] = mtok->data[i]) )i++;
switch( CurToken ) {
case T_UNEXPANDABLE_ID:
if( ! CompFlags.doing_macro_expansion ) {
CalcHash( buf, i );
CurToken = KwLookup( buf );
}
break;
case T_ID:
case T_SAVED_ID:
CalcHash( buf, i );
if( CompFlags.doing_macro_expansion ) { /* 04-nov-94 */
CurToken = T_ID;
} else {
CurToken = KwLookup( buf );
}
break;
case T_CONSTANT:
ReScanInit( mtok->data );
ReScanToken();
break;
case T_PPNUMBER:
ReScanInit( mtok->data );
if( ReScanToken() ){ // didn't finish string bad boy
char *tcur;
char *tbeg;
tbeg = mtok->data;
tcur = ReScanPos();
// ppnumber is quite general so it may absorb multiple tokens
// overlapping src & dst so do our own copy;
for(;;){
*tbeg = *tcur;
if( *tcur == '\0' )break;
++tcur;
++tbeg;
}
flag.keep_token = TRUE;
}
break;
case T_LSTRING:
CurToken = T_STRING;
CompFlags.wide_char_string = 1;
CLitLength = i + 1;
break;
case T_STRING:
CompFlags.wide_char_string = 0;
CLitLength = i + 1;
break;
case T_BAD_CHAR:
break;
case T_NULL:
if( mtok->data[0] == 'Z' ) { // if end of macro
DeleteNestedMacro();
}
flag.next_token = TRUE;
break;
default:
break;
}
if( ! flag.keep_token ) {
TokenList = mtok->next;
CMemFree( mtok );
}
if( ! flag.next_token ) {
break;
}
}
}
/* returns Dynamically allocated buffer with expanded macro */
local char *ExpandMacroToken( void )
{
size_t i, len;
char *p;
char *buf;
len = 0;
switch( *MacroPtr ) {
case T_CONSTANT:
case T_PPNUMBER:
case T_ID:
case T_UNEXPANDABLE_ID:
case T_SAVED_ID:
case T_BAD_TOKEN: /* 07-apr-91 */
p = ++MacroPtr;
len = strlen( p );
MacroPtr += len;
break;
case T_LSTRING: /* 15-may-92 */
len = 1;
case T_STRING: /* 15-dec-91 */
++MacroPtr;
len += strlen( MacroPtr ) + 3;
buf = CMemAlloc( len );
i = 0;
if ( MacroPtr[-1] == T_LSTRING )
buf[i++] = 'L';
buf[i++] = '"';
while( (buf[i] = *MacroPtr++) ) ++i;
buf[i++] = '"';
buf[i] = '\0';
return( buf );
default: /* 28-mar-90 */
p = Tokens[ *MacroPtr++ ];
len = strlen( p );
break;
}
buf = NULL;
if( len > 0 ) {
len++;
buf = CMemAlloc( len );
memcpy( buf, p, len );
}
return( buf );
}
int SpecialMacro( MEPTR mentry )
{
char *p;
char *bufp;
CompFlags.wide_char_string = 0; /* 16-dec-91 */
switch( mentry->parm_count ) {
case MACRO_LINE:
utoa( TokenLine, Buffer, 10 );
Constant = TokenLine;
ConstType = TYPE_INT;
return( T_CONSTANT );
case MACRO_FILE:
if( SrcFile == NULL ) { /* 26-sep-94 */
// SrcFile can be NULL if user is missing a closing ')' on
// a macro to contains a reference to __FILE__.
// We end up scanning all the way to the end of the file
// causing SrcFile to become NULL.
p = "";
} else {
p = SrcFile->src_name;
}
bufp = Buffer;
for(;;) {
*bufp++ = *p;
if( *p == '\0' ) break;
if( *p == '\\' ) *bufp++ = '\\';
++p;
}
CLitLength = bufp - Buffer;
return( T_STRING );
case MACRO_DATE:
CLitLength = 12;
strcpy( Buffer, __Date );
return( T_STRING );
case MACRO_TIME:
CLitLength = 9;
strcpy( Buffer, __Time );
return( T_STRING );
case MACRO_STDC:
Buffer[0] = '1';
Buffer[1] = '\0';
Constant = 1;
ConstType = TYPE_INT;
return( T_CONSTANT );
case MACRO_FUNC:
p = "";
if( CurFunc != NULL ){
if( CurFunc->name != NULL ){
p = CurFunc->name;
}
}
CLitLength = strlen( p ) +1;
strcpy( Buffer, p );
return( T_STRING );
default:
return( 0 ); // shut up the compiler
}
}
local int NextMToken()
{
CompFlags.doing_macro_expansion = 1;
GetMacroToken();
if( CurToken == T_NULL ) {
CurToken = ScanToken();
}
CompFlags.doing_macro_expansion = 0;
return( CurToken );
}
void EnlargeBuffer( size_t size )
{
char *newBuffer;
newBuffer = CMemAlloc( size );
memcpy( newBuffer, Buffer, BufSize );
CMemFree( Buffer );
Buffer = newBuffer;
newBuffer = CMemAlloc( size );
memcpy( newBuffer, TokenBuf, BufSize );
CMemFree( TokenBuf );
TokenBuf = newBuffer;
BufSize = size;
}
static MACRO_ARG *CollectParms(void)
{
MEPTR mentry;
int j;
int bracket;
TOKEN tok;
TOKEN prev_tok;
int parm_cnt;
int total; /* total # of bytes in token sequence */
int ppscan_mode;
MACRO_ARG *macro_parms;
struct tokens **token_tail;
auto struct tokens *token_head;
macro_parms = NULL;
mentry = NextMacro;
if( mentry->parm_count != 0 ) { /* if () expected */
ppscan_mode = InitPPScan(); // enable T_PPNUMBER tokens
if( mentry->parm_count > 1 ) {
macro_parms = (MACRO_ARG *)CMemAlloc( (mentry->parm_count - 1) *
sizeof( MACRO_ARG ) );
}
parm_cnt = 0;
do {
tok = NextMToken();
} while( tok == T_WHITE_SPACE );
/* tok will now be a '(' */
bracket = 0;
token_tail = &token_head;
token_head = NULL;
total = 0;
MTokenLen = 0;
for( ;; ) {
prev_tok = tok;
do {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -