pchdr.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,751 行 · 第 1/4 页

C
1,751
字号
/****************************************************************************
*
*                            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:  Code to handle pre-compiled header files.
*
****************************************************************************/


#include "cvars.h"
#include "pragdefn.h"
#include "autodept.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifdef __WATCOMC__
#ifndef  __UNIX__
    #include <direct.h>
#endif
    #include <share.h>
#endif
#ifdef __UNIX__
    #define PMODE       S_IRUSR+S_IWUSR+S_IRGRP+S_IWGRP+S_IROTH+S_IWOTH
#else
    #define PMODE       S_IRWXU
#endif
#ifndef O_BINARY
    #define O_BINARY  0
#endif
#if defined( SH_DENYWR ) && !defined( SOPEN_DEFINED )
    #define sopen4 sopen
#else
    #define sopen4(a,b,c,d) open((a),(b),(d))
//    #define sopen(a,b,c) open((a),(b))
#endif

extern  TAGPTR  TagHash[TAG_HASH_SIZE + 1];

#define PH_BUF_SIZE     32768
#define PCH_SIGNATURE   (unsigned long) 'WPCH'
#define PCH_VERSION     0x019B
#if defined(__I86__)
#define PCH_VERSION_HOST ( ( 1L << 16 ) | PCH_VERSION )
#elif defined(__386__)
#define PCH_VERSION_HOST ( ( 2L << 16 ) | PCH_VERSION )
#elif defined(__AXP__)
#define PCH_VERSION_HOST ( ( 3L << 16 ) | PCH_VERSION )
#elif defined(__PPC__)
#define PCH_VERSION_HOST ( ( 4L << 16 ) | PCH_VERSION )
#elif defined(__SPARC__)
#define PCH_VERSION_HOST ( ( 5L << 16 ) | PCH_VERSION )
#elif defined(__MIPS__)
#define PCH_VERSION_HOST ( ( 6L << 16 ) | PCH_VERSION )
#else
#define PCH_VERSION_HOST ( ( 128L << 16 ) | PCH_VERSION )
#endif

enum pch_aux_info_index {
    PCH_NULL_INDEX,
    PCH_FIRST_INDEX
};

static  jmp_buf         PH_jmpbuf;
static  int             PH_handle;
static  char            *PH_Buffer;
static  char            *PH_BufPtr;
static  unsigned        PH_BufSize;
static  MEPTR           *PCHMacroHash;
static  MEPTR           PCHUndefMacroList;
static  TYPEPTR         TypeArray;
static  TAGPTR          *TagArray;
static  FNAMEPTR        FNameList;
static  struct textsegment **TextSegArray;
static  unsigned        PH_SymHashCount;
static  unsigned        PH_FileCount;
static  unsigned        PH_RDirCount;
static  unsigned        PH_IncFileCount;
static  unsigned        PH_LibraryCount;
static  unsigned        PH_SegCount;
static  unsigned        PH_MacroCount;
static  unsigned        PH_UndefMacroCount;
static  unsigned        PH_TypeCount;
static  unsigned        PH_TagCount;
static  unsigned        PH_PragmaCount;
static  unsigned        PH_size;
static  unsigned        PH_MacroSize;
static  unsigned        PH_cwd_len;
static  char            PH_computing_size;

static  struct  rdir_list *PCHRDirNames;  /* list of read-only directories */

struct  pheader {
    unsigned long   signature;      //  'WPCH'
    unsigned long   version;
    unsigned        size_of_header;
    unsigned        size_of_int;
    unsigned        pack_amount;    // PackAmount
    unsigned long   gen_switches;   // GenSwitches
    unsigned long   target_switches;// TargetSwitches
    int             toggles;        // Toggles
    unsigned        size;
    unsigned        macro_size;
    unsigned        file_count;
    unsigned        rdir_count;
    unsigned        incfile_count;
    unsigned        incline_count;  // IncLineCount
    unsigned        library_count;  // # of pragma library(s)
    unsigned        seg_count;
    unsigned        macro_count;
    unsigned        undef_macro_count;
    unsigned        type_count;
    unsigned        tag_count;
    unsigned        pragma_count;
    unsigned        symhash_count;
    unsigned        symbol_count;
    unsigned        specialsyms_count;
    unsigned        cwd_len;        // length of current working directory
    unsigned        msgflags_len;   // length of MsgFlags array
};

#if ( _CPU == 8086 ) || ( _CPU == 386 )
static struct aux_info *BuiltinInfos[] = {
    &DefaultInfo,
    &WatcallInfo,
    &CdeclInfo,
    &PascalInfo,
    &FortranInfo,
    &SyscallInfo,
    &StdcallInfo,
    &FastcallInfo,
    &OptlinkInfo,
    NULL
};
#endif

static int FixupDataStructures( char *p, struct pheader *pch );

void InitDebugTypes( void );

//========================================================================
//      This portion of the code creates the pre-compiled header.
//========================================================================

static void InitPHVars( void )
//*****************************
// Set vars to 0
//*****************************
{
    PH_SymHashCount    = 0;
    PH_FileCount       = 0;
    PH_RDirCount       = 0;
    PH_IncFileCount    = 0;
    PH_LibraryCount    = 0;
    PH_SegCount        = 0;
    PH_MacroCount      = 0;
    PH_UndefMacroCount = 0;
    PH_TypeCount       = 0;
    PH_TagCount        = 0;
    PH_PragmaCount     = 0;
    PH_size            = 0;
    PH_MacroSize       = 0;
    PH_cwd_len         = 0;
    PH_computing_size  = 0;
}

static void CreatePHeader( char *filename )
{
    PH_handle = sopen4( filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, SH_DENYRW, PMODE );
    if( PH_handle == -1 ) {
        longjmp( PH_jmpbuf, 1 );
    }
}

static int WritePHeader( void *bufptr, unsigned len )
{
    unsigned    amt_written;
    char        *buf;

    buf = bufptr;
    if( PH_computing_size ) {
        PH_size += len;
    } else if( len != 0 ) {
        if( PH_Buffer != NULL ) {
            for( ;; ) {
                amt_written = len;
                if( amt_written > PH_BufSize )
                    amt_written = PH_BufSize;
                memcpy( PH_BufPtr, buf, amt_written );
                PH_BufSize -= amt_written;
                PH_BufPtr  += amt_written;
                buf += amt_written;
                len -= amt_written;
                if( PH_BufSize == 0 ) {         // if buffer is full
                    PH_BufSize = PH_BUF_SIZE;
                    PH_BufPtr  = PH_Buffer;
                    amt_written = write( PH_handle, PH_Buffer, PH_BUF_SIZE );
                    if( amt_written != PH_BUF_SIZE ) {
                        return( 1 );
                    }

                }
                if( len == 0 ) {
                    break;
                }
            }
        } else {
            amt_written = write( PH_handle, buf, len );
            if( amt_written != len ) {
                return( 1 );
            }
        }
    }
    return( 0 );
}

static void FlushPHeader( void )
{
    unsigned    len;

    if( PH_BufSize != PH_BUF_SIZE ) {   // if buffer has some stuff in it
        len = PH_BUF_SIZE - PH_BufSize;
        if( write( PH_handle, PH_Buffer, len ) != len ) {
            longjmp( PH_jmpbuf, 1 );
        }
    }
}

static void ClosePHeader( void )
{
    close( PH_handle );
    PH_handle = -1;
}


static void OutPutHeader( void )
{
    int                 rc;
    struct pheader      pch;

    pch.signature         = PCH_SIGNATURE;
    pch.version           = PCH_VERSION_HOST;
    pch.size_of_header    = sizeof( struct pheader );
    pch.size_of_int       = TARGET_INT;
    pch.pack_amount       = PackAmount;
    pch.gen_switches      = GenSwitches;
    pch.target_switches   = TargetSwitches;
    pch.toggles           = Toggles;
    pch.size              = PH_size - PH_MacroSize;
    pch.macro_size        = PH_MacroSize;
    pch.file_count        = PH_FileCount;
    pch.rdir_count        = PH_RDirCount;
    pch.incfile_count     = PH_IncFileCount;
    pch.incline_count     = IncLineCount;
    pch.library_count     = PH_LibraryCount;
    pch.seg_count         = PH_SegCount;
    pch.macro_count       = PH_MacroCount;
    pch.undef_macro_count = PH_UndefMacroCount;
    pch.type_count        = PH_TypeCount;
    pch.tag_count         = PH_TagCount;
    pch.pragma_count      = PH_PragmaCount;
    pch.symhash_count     = PH_SymHashCount;
    pch.symbol_count      = SymGetNumSyms();
    pch.specialsyms_count = SymGetNumSpecialSyms();
    pch.cwd_len           = PH_cwd_len;
    if( MsgFlags != NULL ) {                            /* 06-jul-94 */
        pch.msgflags_len  = _RoundUp( ((HIGHEST_MESSAGE_NUMBER + 7) / 8), sizeof( int ) );
    } else {
        pch.msgflags_len = 0;
    }
    rc  = WritePHeader( &pch, sizeof( struct pheader ) );
    rc |= WritePHeader( PH_Buffer + sizeof( struct pheader ), pch.cwd_len );
    if( rc != 0 ) {
        longjmp( PH_jmpbuf, rc );
    }
}

static void OutPutHFileList( void )     // output include paths
{
    int         rc;
    unsigned    len;

    if( HFileList == NULL ) {
        rc = 0;
        rc = WritePHeader( &rc, sizeof( int ) );
    } else {
        len = strlen( HFileList ) + 1;
        len = _RoundUp( len, sizeof( int ) );
        rc = WritePHeader( HFileList, len );
    }
    if( rc != 0 ) {
        longjmp( PH_jmpbuf, rc );
    }
}

static void OutPutIncFileList( void )   // output primary include files
{
    int         rc;
    unsigned    len;
    INCFILE     *ifile;

    for( ifile = IncFileList; ifile; ifile = ifile->nextfile ) {
        len = sizeof( INCFILE ) + ifile->len;
        len = _RoundUp( len, sizeof( int ) );
        rc = WritePHeader( ifile, len );
        if( rc != 0 ) {
            longjmp( PH_jmpbuf, rc );
        }
        PH_IncFileCount++;
    }
}

static void OutPutLibraries( void )
{
    int                 rc;
    unsigned            len;
    struct library_list *lib;

    for( lib = HeadLibs; lib; lib = lib->next ) {
        len = sizeof( struct library_list ) + strlen( lib->name );
        len = _RoundUp( len, sizeof( int ) );
        rc = WritePHeader( lib, len );
        if( rc != 0 ) {
            longjmp( PH_jmpbuf, rc );
        }
        PH_LibraryCount++;
    }
}

static void OutPutMsgFlags( void )
{
    int         rc;

    if( MsgFlags != NULL ) {                            /* 06-jul-94 */
        rc = WritePHeader( MsgFlags, (HIGHEST_MESSAGE_NUMBER + 7) / 8 );
        if( rc != 0 ) {
            longjmp( PH_jmpbuf, rc );
        }
    }
}

static void OutPutIncludes( void )
{
    FNAMEPTR    flist;
    FNAMEPTR    next_flist;
    unsigned    len;
    int         rc;

    flist = FNames;
    // don't want to include the primary source file
    while( flist != NULL ) {
        if( strcmp( flist->name, SrcFile->src_name ) == 0 ) {
            flist = flist->next;
            break;
        }
        flist = flist->next;
    }
    while( flist != NULL ) {
        next_flist = flist->next;
        len = strlen( flist->name ) + sizeof( struct fname_list );
        len = _RoundUp( len, sizeof( int ) );
        flist->fname_len = len;
        rc = WritePHeader( flist, len );
        flist->next = next_flist;
        if( rc != 0 ) {
            longjmp( PH_jmpbuf, rc );
        }
        flist = next_flist;
        PH_FileCount++;
    }
}

static void OutPutRoDirList( void )
{
    RDIRPTR     dirlist;
    RDIRPTR     next_dirlist;
    unsigned    len;
    int         rc;

    dirlist = PCHRDirNames;
    while( dirlist != NULL ) {
        next_dirlist = dirlist->next;
        len = strlen( dirlist->name ) + sizeof( struct rdir_list );
        len = _RoundUp( len, sizeof( int ) );
        dirlist->name_len = len;
        rc = WritePHeader( dirlist, len );
        dirlist->next = next_dirlist;
        if( rc != 0 ) {
            longjmp( PH_jmpbuf, rc );
        }
        dirlist = next_dirlist;
        PH_RDirCount++;
    }
}

static void OutPutSegInfo( void )
{
    struct textsegment  *seg;
    struct textsegment  *next;
    int                 rc;
    unsigned            len;

    for( seg = TextSegList; seg; seg = seg->next ) {
        ++PH_SegCount;
        seg->index = PH_SegCount;
        len = strlen( seg->segname );           // segment name
        len += strlen( &seg->segname[len+1] );  // class name
        len += sizeof( struct textsegment ) + 1;
        len = _RoundUp( len, sizeof( int ) );
        next = seg->next;                       // save next pointer
        seg->textsegment_len = len;             // replace with len
        rc = WritePHeader( seg, len );
        seg->next = next;                       // restore next pointer
        if( rc != 0 ) {
            longjmp( PH_jmpbuf, rc );
        }
    }

⌨️ 快捷键说明

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