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( &macroSegmentList, 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( &macro_segments, "macro segments" );
    ExtraRptRegisterCtr( &macros_defined, "macros defined" );
    ExtraRptRegisterCtr( &macros_defined_with_parms, "macros defined with parms" );
    ExtraRptRegisterCtr( &macros_redefined, "macros redefined" );
    ExtraRptRegisterSpace( &macro_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( &macroSegmentList );
}

#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( &macroPCHDeletes, macro_delete );
        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?