srcfile.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,229 行 · 第 1/5 页
C
2,229 行
/****************************************************************************
*
* 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 <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "memmgr.h"
#include "fname.h"
#include "ring.h"
#include "preproc.h"
#include "scan.h"
#include "stats.h"
#include "carve.h"
#include "sysdep.h"
#include "errdefns.h"
#include "name.h"
#include "cmdline.h"
#include "toggle.h"
#include "pcheader.h"
#include "initdefs.h"
#include "iosupp.h"
#ifndef NDEBUG
#include "pragdefn.h"
#endif
#include "brinfo.h"
//
// A guarded file is one which contains:
//
// (1) White space and comments
// (2) Some form of #if (#if, #ifdef, etc )
// (3) A body with no form of #else for the #if in (2)
// (4) A #endif for the #if in (2)
// (5) White space and comments
//
// On the second and subsequent reads of a guarded file, the file can be
// skipped when not preprocessing and the condition for the #if in (2)
// indicates that the body need not be processed.
//
#define GUARD_DEFS \
GDEF( GUARD_INCLUDE ) /* - always include */ \
GDEF( GUARD_IF ) /* - file is guarded (#if expr, #ifdef) */ \
GDEF( GUARD_IFNDEF ) /* - file is guarded (#ifndef) */ \
/* following valid while file being processed */ \
GDEF( GUARD_TOP ) /* - processing white-space at top */ \
GDEF( GUARD_MID ) /* - processing body (#if to #endif) */ \
GDEF( GUARD_BOT ) /* - processing white-space at bottom */ \
/* used only when !defined(NDEBUG) */ \
GDEF( GUARD_NULL ) /* - to force printing */ \
enum { // GUARD STATE
#define GDEF( id ) id,
GUARD_DEFS
#undef GDEF
};
#ifndef NDEBUG
static char *guardStateNames[] = { // - names of guard states
#define GDEF( id ) #id ,
GUARD_DEFS
#undef GDEF
};
#endif
typedef struct open_file OPEN_FILE; // ACTIVE FILE (BEING READ)
typedef struct _src_file {
SRCFILE sister; // - ring of files for #line directives
SRCFILE parent; // - NULL or including source file
SRCFILE unique; // - next in unique list
SRCFILE pch_child; // - #include to create pchdr for (NULL otherwise)
LINE_NO parent_locn; // - line no. for inclusion
unsigned index; // - index of this source file
OPEN_FILE *active; // - information for open file
char *name; // - file name
char *full_name; // - absolute pathname for file
char *ifndef_name; // - name used when #ifndef
unsigned ifndef_len; // - length of name used when #ifndef
unsigned guard_state; // - guard state
MACRO_STATE macro_state; // - state of macro table when opened
time_t time_stamp; // - time stamp for file
// - SRCFILE attributes
unsigned lib_inc : 1; // -- library include: #include <file>
unsigned primary : 1; // -- primary source file
unsigned alias : 1; // -- alias'ed source file
unsigned cmdline : 1; // -- command-line file
unsigned cmdlneol : 1; // -- EOL for command-line file
unsigned cmdlneof : 1; // -- EOF for command-line file
unsigned uncached : 1; // -- have to re-open file on read
unsigned free : 1; // -- free SRCFILE
unsigned pch_create : 1; // -- create pchdr when child closes
unsigned pch_kludge : 1; // -- EOF needs 3 ';''s to align parser
unsigned assume_file : 1;// -- handle represents a file not a device
unsigned found_eof : 1; // -- next read will return 0
unsigned read_only : 1; // -- read-only header file
unsigned once_only : 1; // -- read once header file
unsigned ignore_swend:1; // -- ignore cmdline switch end chars
};
struct dir_list { // DIR_LIST -- directory entry
DIR_LIST *next; // - next in ring
char const *name; // - directory name
};
struct open_file {
LINE_NO line; // - current line
COLUMN_NO column; // - current column
int currc; // - current character
char *nextc; // - addr[ next character ]
char *lastc; // - addr[ last character ]
char *buff; // - buffer
FILE *fp; // - file control block
unsigned long pos; // - file offset to seek when reopened
};
union freed_open_file {
OPEN_FILE fb; // - freed open file
OPEN_FILE **next; // - next in free chain
};
// 'srcFile' and 'openFile' must always be kept in synch!
// use set_SrcFile to set 'srcFile' just to be sure
static SRCFILE srcFile; // current source file
static OPEN_FILE *openFile; // actual open file
#define BLOCK_SRCFILE 16
#define BLOCK_OPEN_FILE 8
#define BLOCK_RO_DIRS 4
static carve_t carveSrcFile; // source files
static carve_t carveOpenFile; // open files
static carve_t alternateCarveSrcFile; // loaded pchdr source files
static carve_t carveRoDir; // read-only directories
static union freed_open_file *freeFiles; // freed open files
static SRCFILE srcFilesUnique; // list of unique files
static SRCFILE traced_back; // last file traced back for msg.s
static SRCFILE primarySrcFile; // primary source file
static DIR_LIST* roDirs; // read-only directories
static unsigned totalSrcFiles; // running total of SRCFILE's
static char notFilled[2] = { '\n', '\0' }; // default buffer to force readBuffer
static int lastChar; // unknown char to return in GetNextChar
static unsigned numBlanks1;
static unsigned numTABs;
static unsigned numBlanks2;
static unsigned tabWidth;
int (*NextChar)() = GetNextChar;
// the following table is used to map three character sequences
// beginning with ?? followed by 'tri' into the single character 'new'
struct tri_graph {
char tri;
char new;
};
static struct tri_graph triGraphs[] = {
{ '=', '#' },
{ '(', '[' },
{ '/', '\\'},
{ ')', ']' },
{ '\'','^' },
{ '<', '{' },
{ '!', '|' },
{ '>', '}' },
{ '-', '~' },
{ '\0','\0'}
};
#define _FIND_ACTUAL( curr ) for( ; curr->alias; curr = curr->sister );
#ifndef NDEBUG
static OPEN_FILE *activeSrc( void )
{
SRCFILE src;
src = srcFile;
if( src != NULL ) {
if( src->active != openFile ) {
CFatal( "openFile is out of synch with srcFile" );
}
} else {
if( openFile != NULL ) {
CFatal( "openFile is out of synch with srcFile" );
}
}
return( openFile );
}
#else
#define activeSrc() (openFile)
#endif
static void set_srcFile( SRCFILE src )
{
srcFile = src;
if( src != NULL ) {
openFile = src->active;
} else {
openFile = NULL;
}
}
static void cleanupOpenFiles( // CLEAN UP ON MEMORY FAILURE
void )
{
union freed_open_file *fr;
RingIterBegSafe( freeFiles, fr ) {
CMemFree( fr->fb.buff );
fr->fb.buff = NULL;
} RingIterEndSafe( fr )
}
static void srcFileInit( // INITIALIZE SOURCE FILING
INITFINI* defn ) // - definition
{
defn = defn;
traced_back = NULL;
freeFiles = NULL;
srcFilesUnique = NULL;
primarySrcFile = NULL;
roDirs = NULL;
alternateCarveSrcFile = NULL;
totalSrcFiles = 0;
carveSrcFile = CarveCreate( sizeof( *srcFile ), BLOCK_SRCFILE );
carveOpenFile = CarveCreate( sizeof( *freeFiles ), BLOCK_OPEN_FILE );
carveRoDir = CarveCreate( sizeof( DIR_LIST ), BLOCK_RO_DIRS );
CMemRegisterCleanup( cleanupOpenFiles );
}
static void srcFileFini( // COMPLETE SOURCE FILING
INITFINI* defn ) // - definition
{
defn = defn;
if( srcFile != NULL ) {
if( activeSrc() != NULL ) {
while( NULL != srcFile ) {
SrcFileClose( TRUE );
}
} else {
set_srcFile( NULL );
}
}
cleanupOpenFiles();
CarveDestroy( carveSrcFile );
CarveDestroy( carveOpenFile );
CarveDestroy( alternateCarveSrcFile );
CarveDestroy( carveRoDir );
// cleanupOpenFiles is registered as a memory callback so once
// we destroy all OPEN_FILEs, we can't reference them anymore
freeFiles = NULL;
}
INITDEFN( srcfile, srcFileInit, srcFileFini )
static unsigned getGuardState( // GET GUARD STATE FOR CURRENT FILE
void )
{
SRCFILE src_file = srcFile;
_FIND_ACTUAL( src_file );
return( src_file->guard_state );
}
static void setGuardState( // SET GUARD STATE FOR CURRENT FILE
unsigned new_state ) // - new state
{
SRCFILE actual; // - non-aliased SRCFILE
actual = srcFile;
_FIND_ACTUAL( actual );
#ifndef NDEBUG
if( PragDbgToggle.dump_tokens ) {
if( actual->guard_state != new_state ) {
printf( "New Guard State[%s]: %s\n"
, actual->name
, guardStateNames[ new_state ] );
}
}
#endif
actual->guard_state = new_state;
}
static SRCFILE srcFileGetUnique(// FIND SOURCE FILE IN UNIQUE LIST
char const *name ) // - name of source file
{
SRCFILE srch; // - searched source file
/* Do a string sensitive compare -- it's safer. */
for( srch = srcFilesUnique
; ( srch != NULL ) && ( 0 != strcmp( srch->name, name ) )
; srch = srch->unique );
return srch;
}
static SRCFILE srcFileAddUnique(// ADD NEW SOURCE FILE TO UNIQUE LIST
SRCFILE curr ) // - current source file
{
SRCFILE srch; // - searched source file
srch = srcFileGetUnique( curr->name );
if( srch == NULL ) {
curr->unique = srcFilesUnique;
srcFilesUnique = curr;
}
return srch;
}
static SRCFILE srcFileAlloc( // ALLOCATE A SRCFILE
void *fp, // - system file control
char *name ) // - file name
{
SRCFILE new_src; // - new source file
OPEN_FILE *old_act; // - open-file information (old)
OPEN_FILE *new_act; // - open-file information (new)
new_src = CarveAlloc( carveSrcFile );
new_src->name = name;
new_src->full_name = NULL;
new_src->parent = srcFile;
new_src->unique = NULL;
new_src->pch_child = NULL;
new_src->primary = FALSE;
new_src->lib_inc = FALSE;
new_src->alias = FALSE;
new_src->cmdline = FALSE;
new_src->cmdlneol = FALSE;
new_src->cmdlneof = FALSE;
new_src->uncached = FALSE;
new_src->free = FALSE;
new_src->pch_create = FALSE;
new_src->pch_kludge = FALSE;
new_src->assume_file = TRUE;
new_src->found_eof = FALSE;
new_src->read_only = FALSE;
new_src->once_only = FALSE;
new_src->ignore_swend = FALSE;
new_src->index = totalSrcFiles;
new_src->active = NULL;
new_src->ifndef_name = NULL;
new_src->ifndef_len = 0;
new_src->sister = new_src;
MacroStateGet( &(new_src->macro_state) );
if( srcFile == NULL ) {
new_src->parent_locn = 0;
} else {
if( srcFile->pch_create ) {
srcFile->pch_child = new_src;
new_src->pch_kludge = TRUE;
}
old_act = activeSrc();
if( CurrChar == '\n' ) {
// if we have scanned a \n already then getCharCheck
// will have incremented the current line too soon
new_src->parent_locn = old_act->line - 1;
} else {
new_src->parent_locn = old_act->line;
}
old_act->currc = CurrChar;
}
new_act = RingPop( &freeFiles );
if( new_act == NULL ) {
new_act = CarveAlloc( carveOpenFile );
new_act->buff = NULL;
}
new_src->active = new_act;
new_act->line = 0;
new_act->column = 0;
new_act->nextc = ¬Filled[0];
new_act->lastc = ¬Filled[1];
new_act->fp = fp;
new_src->guard_state = GUARD_NULL;
new_src->time_stamp = 0;
new_src->free = FALSE;
set_srcFile( new_src );
if( CompFlags.cpp_output ) {
EmitLineNL( 1, new_src->name );
}
++ totalSrcFiles;
return( new_src );
}
static void setJustOpenedGuardState( void )
{
if( CompFlags.cpp_output_requested ) {
setGuardState( GUARD_INCLUDE );
} else {
setGuardState( GUARD_TOP );
}
}
static void setReOpenedGuardState( unsigned guard_state )
{
if( CompFlags.cpp_output_requested ) {
guard_state = GUARD_INCLUDE;
} else if( guard_state == GUARD_IFNDEF ) {
// seen this #include before with #ifndef MACRO but MACRO is not defined
guard_state = GUARD_TOP;
}
setGuardState( guard_state );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?