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 + -
显示快捷键?