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 = &notFilled[0];
    new_act->lastc = &notFilled[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 + -
显示快捷键?