cmacadd.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 728 行 · 第 1/2 页
C
728 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "plusplus.h"
#include "errdefns.h"
#include "memmgr.h"
#include "preproc.h"
#include "ring.h"
#include "pcheader.h"
#include "stats.h"
#include "name.h"
#include "brinfo.h"
#define MACRO_HASH_SIZE NAME_HASH
#define MAC_SEGMENT_SIZE (0x8000 - sizeof( char *) )
#define HASH_TABLE_SIZE ( MACRO_HASH_SIZE * sizeof( macroHashTable ) )
typedef struct macro_seg_list MACRO_SEG_LIST;
struct macro_seg_list {
MACRO_SEG_LIST *next;
char segment[ MAC_SEGMENT_SIZE ];
};
typedef struct pch_delmac PCH_DELMAC;
struct pch_delmac {
PCH_DELMAC *next;
unsigned hash;
char name[1];
};
static char *macroLimit; // last free byte in MacroSegment
static MEPTR *macroHashTable; // hash table [ MACRO_HASH_SIZE ]
static MEPTR beforeIncludeChecks;// #undef macros defined before first #include
static MACRO_SEG_LIST *macroSegmentList; // pointer to list of macro segments
static MACRO_SEG_LIST *macroSegment; // current macro segment
static PCH_DELMAC *macroPCHDeletes; // macros to delete after PCH load
static unsigned long undefCount; // # macros #undef'd
ExtraRptCtr( macro_segments );
ExtraRptCtr( macros_defined );
ExtraRptCtr( macros_defined_with_parms );
ExtraRptCtr( macros_redefined );
ExtraRptSpace( macro_space );
#define macroSizeAlign( s ) (((s)+(sizeof(int)-1))&~(sizeof(int)-1))
static void *macroAllocateInSeg( // ALLOCATE WITHIN A SEGMENT
unsigned size ) // - size
{
void *retn; // - return location
retn = MacroOffset;
MacroOffset += macroSizeAlign( size );
ExtraRptSpaceAdd( macro_space, size );
return( retn );
}
static void macroAllocSegment( // ALLOCATE MACRO SEGMENT
unsigned minimum ) // - minimum size req'd
{
if( minimum > MAC_SEGMENT_SIZE - 2 ) {
CErr1( ERR_OUT_OF_MACRO_MEMORY );
CSuicide();
}
macroSegment = RingAlloc( ¯oSegmentList, sizeof( MACRO_SEG_LIST ) );
MacroOffset = macroSegment->segment;
macroLimit = MacroOffset + MAC_SEGMENT_SIZE - 2;
ExtraRptIncrementCtr( macro_segments );
}
static void storageInitialize( // INITIALIZE STORAGE DATA
void )
{
macroAllocSegment( HASH_TABLE_SIZE );
macroHashTable = (MEPTR *) macroAllocateInSeg( HASH_TABLE_SIZE );
memset( macroHashTable, 0, HASH_TABLE_SIZE );
beforeIncludeChecks = NULL;
//macroPCHDeletes = NULL;
undefCount = 0;
}
void MacroStorageInit( // INITIALIZE FOR MACRO STORAGE
void )
{
storageInitialize();
// macroStorageRestart doesn't want this
macroPCHDeletes = NULL;
ExtraRptRegisterCtr( ¯o_segments, "macro segments" );
ExtraRptRegisterCtr( ¯os_defined, "macros defined" );
ExtraRptRegisterCtr( ¯os_defined_with_parms, "macros defined with parms" );
ExtraRptRegisterCtr( ¯os_redefined, "macros redefined" );
ExtraRptRegisterSpace( ¯o_space, "macros space" );
}
static int macroCompare( // COMPARE TWO MACROS TO SEE IF IDENTICAL
MEPTR m1, // - macro #1
MEPTR m2 ) // - macro #2
{
char *p1;
char *p2;
if( m1->macro_len != m2->macro_len ) return( -1 );
if( m1->macro_defn != m2->macro_defn ) return( -1 );
if( m1->parm_count != m2->parm_count ) return( -1 );
p1 = (char *)m1 + offsetof(MEDEFN,macro_name);
p2 = (char *)m2 + offsetof(MEDEFN,macro_name);
return( memcmp( p1, p2, m1->macro_len - offsetof(MEDEFN,macro_name) ) );
}
void MacroStorageFini( void )
/***************************/
{
RingFree( ¯oSegmentList );
}
#ifdef OPT_BR
void MacroWriteBrinf // WRITE MACROS TO BRINF
( void )
{
unsigned i;
MEPTR curr;
for( i = 0; i < MACRO_HASH_SIZE; ++i ) {
RingIterBeg( macroHashTable[ i ], curr ) {
BrinfDeclMacro( curr );
} RingIterEnd( curr )
}
}
#endif
pch_status PCHWriteMacros( void )
{
unsigned i;
unsigned wlen;
MEPTR curr;
MEPTR next;
SRCFILE save_defn_src_file;
for( i = 0; i < MACRO_HASH_SIZE; ++i ) {
RingIterBeg( macroHashTable[ i ], curr ) {
next = curr->next_macro;
curr->macro_flags &= ~MACRO_PCH_TEMPORARY_FLAGS;
wlen = curr->macro_len;
curr->next_macro = (MEPTR) i;
save_defn_src_file = curr->defn.src_file;
curr->defn.src_file = SrcFileGetIndex( save_defn_src_file );
PCHWriteUInt( wlen );
PCHWrite( curr, wlen );
curr->defn.src_file = save_defn_src_file;
curr->next_macro = next;
} RingIterEnd( curr )
}
wlen = 0;
PCHWriteUInt( wlen );
return( PCHCB_OK );
}
pch_status PCHInitMacros( boolean writing )
{
writing = writing;
return( PCHCB_OK );
}
pch_status PCHFiniMacros( boolean writing )
{
writing = writing;
return( PCHCB_OK );
}
static void findMaxLength( MEPTR curr, void *data )
{
unsigned *pmax = data;
unsigned wlen;
wlen = curr->macro_len;
if( wlen > *pmax ) {
*pmax = wlen;
}
}
static void writeMacroCheck( MEPTR curr, void *data )
{
unsigned *phash = data;
unsigned wlen;
MEPTR next;
next = curr->next_macro;
wlen = curr->macro_len;
curr->next_macro = (MEPTR) *phash;
PCHWriteUInt( wlen );
PCHWrite( curr, wlen );
curr->next_macro = next;
}
static void forAllMacrosDefinedBeforeFirstInclude( void (*rtn)( MEPTR, void * ),
void *data )
{
size_t len;
unsigned i;
unsigned hash;
MEPTR curr;
for( i = 0; i < MACRO_HASH_SIZE; ++i ) {
hash = i;
RingIterBeg( macroHashTable[ i ], curr ) {
if( curr->macro_flags & MACRO_DEFINED_BEFORE_FIRST_INCLUDE ) {
if( data == NULL ) {
(*rtn)( curr, &hash );
} else {
(*rtn)( curr, data );
}
}
} RingIterEnd( curr )
}
RingIterBeg( beforeIncludeChecks, curr ) {
if( data == NULL ) {
len = strlen( curr->macro_name );
hash = NameCalcHashLen( curr->macro_name, len );
(*rtn)( curr, &hash );
} else {
(*rtn)( curr, data );
}
} RingIterEnd( curr )
}
void PCHDumpMacroCheck( // DUMP MACRO CHECK INFO INTO PCHDR
void )
{
unsigned wlen;
unsigned max_wlen;
// find largest macro definition size
max_wlen = 1;
forAllMacrosDefinedBeforeFirstInclude( findMaxLength, &max_wlen );
PCHWriteUInt( max_wlen );
// write macros out
forAllMacrosDefinedBeforeFirstInclude( writeMacroCheck, NULL );
wlen = 0;
PCHWriteUInt( wlen );
}
boolean PCHVerifyMacroCheck( // READ AND VERIFY MACRO CHECK INFO FROM PCHDR
void )
{
boolean ret;
int macros_different;
unsigned max_rlen;
unsigned rlen;
unsigned pch_hash;
unsigned i;
size_t del_len;
MEPTR cmdln_macro;
MEPTR pch_macro;
MEPTR new_macro;
MEPTR matched_macro;
PCH_DELMAC *macro_delete;
/*
This check is performed before we load the PCH so we have all macros
that are defined before the first #include in our current macro table.
Checks we perform are:
if a macro was defined before the PCH was created
if it was referenced during #include processing
(1) a definition must be present
(2) the definition must match exactly
else
(3) keep the current definition
(may mean deleting macro after PCH load)
endif
else
if the current compilation has a new user-defined macro
(4) macro could have potentially triggered a #ifdef/#ifndef/#if
so we can't trust the PCH
endif
endif
*/
ret = TRUE;
max_rlen = PCHReadUInt();
pch_macro = CMemAlloc( max_rlen );
for(;;) {
rlen = PCHReadUInt();
if( rlen == 0 ) break;
PCHRead( pch_macro, rlen );
pch_hash = (unsigned) pch_macro->next_macro;
//printf( "pch mac: %s\n", pch_macro->macro_name );
matched_macro = NULL;
RingIterBeg( macroHashTable[pch_hash], new_macro ) {
if( strcmp( new_macro->macro_name, pch_macro->macro_name ) == 0 ) {
matched_macro = new_macro;
new_macro->macro_flags |= MACRO_PCH_CHECKED;
macros_different = macroCompare( new_macro, pch_macro );
if( pch_macro->macro_flags & MACRO_REFERENCED ) {
// (2) original macro was referenced during first #include
if( ! macros_different ) {
// OK; defns are identical in both compilation units
break;
}
PCHWarn2p( WARN_PCH_CONTENTS_MACRO_DIFFERENT, pch_macro->macro_name );
ret = FALSE;
break;
}
if( macros_different ) {
// (3) macro is different but never referenced in PCH build
// action: keep this macro definition
new_macro->macro_flags |= MACRO_PCH_OVERRIDE;
}
break;
}
} RingIterEnd( new_macro )
if( matched_macro != NULL ) {
/* macro is in current compilation */
if( ret == FALSE ) {
/* problem was detected */
break;
}
} else {
/* macro not found in current compile */
if( pch_macro->macro_flags & MACRO_REFERENCED ) {
// (1) original macro was referenced during first #include
// but no definition in current compilation
PCHWarn2p( WARN_PCH_CONTENTS_MACRO_NOT_PRESENT, pch_macro->macro_name );
ret = FALSE;
break;
}
// (3) queue macro to be deleted when PCH is loaded
del_len = offsetof( PCH_DELMAC, name ) + 1 + strlen( pch_macro->macro_name );
macro_delete = CMemAlloc( del_len );
macro_delete->hash = pch_hash;
strcpy( macro_delete->name, pch_macro->macro_name );
RingAppend( ¯oPCHDeletes, macro_delete );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?