iosupp.c

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

C
977
字号
/****************************************************************************
*
*                            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:  I/O support routines.
*
****************************************************************************/


#include "plusplus.h"

#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <unistd.h>

#include "preproc.h"
#include "errdefns.h"
#include "memmgr.h"
#include "iosupp.h"
#include "cgdata.h"
#include "fname.h"
#include "hfile.h"
#include "initdefs.h"
#include "stats.h"
#include "pcheader.h"
#include "ring.h"
#include "brinfo.h"
#include "autodept.h"

#if defined(__UNIX__)
 #include <dirent.h>
#else
 #include <direct.h>
#endif

typedef struct buf_alloc BUF_ALLOC;
struct buf_alloc {              // BUF_ALLOC -- allocated buffer
    BUF_ALLOC* next;            // - next buffer allocation
    FILE* file;                 // - file in question
    void* buffer;               // - allocated buffer
};


static carve_t carve_buf;       // carver: BUF_ALLOC
static BUF_ALLOC* buffers;      // allocated buffers
static int  temphandle;         // handle for temp file
static char *tempname;          // name of temp file
static DISK_ADDR tempBlock;     // next available block in temp file
static unsigned outFileChecked; // mask for checking output files

static char  workFile[] =       // template for work file
    "__wrk0__";

#if defined(__OS2__) || defined(__DOS__) || defined(__NT__)

static char* pathSrc[] =        // paths for source file
    {   "..\\cpp"
    ,   "..\\c"
    ,   NULL
    };

static char* pathHdr[] =        // paths for header files
    {   "..\\h"
    ,   "..\\include"
    ,   NULL
    };

static char* pathCmd[] =        // paths for command files
    {   "..\\occ"
    ,   NULL
    };

static char* extsHdr[] =        // extensions for header files
    {   ".hpp"
    ,   ".h"
    ,   NULL
    };

static char* extsSrc[] =        // extensions for source files
    {   ".cpp"
    ,   ".cc"
    ,    ".c"
    ,   NULL
    };

static char* extsCmd[] =        // extensions for command files
    {   ".occ"
    ,   NULL
    };

static char* extsOut[] =        // extensions for output files
    {   ".obj"
    ,   ".i"
    ,   ".err"
    ,   ".mbr"
    ,   ".def"
#ifdef OPT_BR
    ,   ".brm"
#endif
    ,   ".d"
    ,   ".obj"
    };

#define IS_DIR_SEP( c )         ((c)=='/'||(c)=='\\')
#define IS_PATH_SEP( c )        ((c)==':'||IS_DIR_SEP(c))
#define PATH_SEP                '\\'
#define INC_PATH_SEP            ';'

#elif defined(__UNIX__)

static char* pathSrc[] =        // paths for source file
    {   "../C"
    ,   "../cpp"
    ,   "../c"
    ,   NULL
    };

static char* pathHdr[] =        // paths for header files
    {   "../H"
    ,   "../h"
    ,   NULL
    };

static char* pathCmd[] =        // paths for command files
    {   "../occ"
    ,   NULL
    };

static char* extsHdr[] =        // extensions for header files
    {   ".H"
    ,   ".hpp"
    ,   ".h"
    ,   NULL
    };

static char* extsSrc[] =        // extensions for source files
    {   ".C"
    ,   ".cpp"
    ,   ".cc"
    ,   ".c"
    ,   NULL
    };

static char* extsCmd[] =        // extensions for command files
    {   ".occ"
    ,   NULL
    };

static char* extsOut[] =        // extensions for output files
    {   ".o"
    ,   ".i"
    ,   ".err"
    ,   ".mbr"
    ,   ".def"
#ifdef OPT_BR
    ,   ".brm"
#endif
    ,   ".d"
    ,   ".o"
    };

#define IS_DIR_SEP( c )         ((c)=='/')
#define IS_PATH_SEP( c )        IS_DIR_SEP( c )
#define PATH_SEP                '/'
#define INC_PATH_SEP            ':'

#else

#error IOSUPP not configured for OS

#endif



char *IoSuppOutFileName(        // BUILD AN OUTPUT NAME FROM SOURCE NAME
    enum out_file_type typ )    // - extension
{
    char *drive;
    char *dir;
    char *fname;
    char *ext;
    char *extsrc;
    char *path;
    int use_defaults;
    unsigned mask;
    FILE *try_create;
    auto char buff[ _MAX_PATH2 ];

    use_defaults = FALSE;
    switch( typ ) {
      case OFT_DEF:
#ifdef OPT_BR
      case OFT_BRI:
#endif
        path = WholeFName;
        use_defaults = TRUE;
        break;
      case OFT_DEP:
        path = DependFileName;
        if( path == NULL ) {
            use_defaults = TRUE;
            path = WholeFName;
        }
        break;
      case OFT_ERR:
        if( ErrorFileName == NULL ) return( NULL );
        path = ErrorFileName;
        break;
      case OFT_SRCDEP:
        outFileChecked |= 1 << typ;
        if( !(path = SrcDepFileName ) ) {
            path = WholeFName;
        }
        else 
        {
            auto char buff[ _MAX_PATH2 ];
            char *drive;
            char *dir;
            char *fname;
            _splitpath2( WholeFName, buff, &drive, &dir, &fname, &extsrc );
        }
        break;
      case OFT_TRG:
        outFileChecked |= 1 << typ; // don't create a file. it's just a name.
        if( path = TargetFileName ) break;
      case OFT_PPO:
      case OFT_OBJ:
      case OFT_MBR:
        path = ObjectFileName;
        if( path == NULL ) {
            use_defaults = TRUE;
            path = WholeFName;
        }
        break;
    }
    _splitpath2( path, buff, &drive, &dir, &fname, &ext );
    switch( typ ) {
      case OFT_MBR:
        ext = "";       // don't override extension
        break;
      case OFT_SRCDEP:
        if( !ext || !ext[0] )
            ext = extsrc;
        break;
    }
    if( use_defaults || ext[0] == '\0' ) {
        ext = extsOut[ typ ];
    }
    if( fname[0] == '\0' || fname[0] == '*' ) {
        fname = ModuleName;
    }
    if( use_defaults ) {
        drive = "";
        dir = "";
    }
    _makepath( Buffer, drive, dir, fname, ext );
    mask = 1 << typ;
    if(( outFileChecked & mask ) == 0 ) {
        outFileChecked |= mask;
        try_create = fopen( Buffer, "w" );
        if( try_create != NULL ) {
            fclose( try_create );
        } else {
            CErr2p( ERR_CANNOT_CREATE_OUTPUT_FILE, Buffer );
        }
    }
    return( Buffer );
}


static void set_buffering(       // SET BUFFERING FOR AN OPEN FILE
    FILE *fp,                   // - opened file
    size_t buf_size,            // - buffer size
    int mode )                  // - buffering mode
{
    BUF_ALLOC* ba = RingCarveAlloc( carve_buf, &buffers );
    ba->file = fp;
    ba->buffer = CMemAlloc( buf_size );
    setvbuf( fp, ba->buffer, mode, buf_size );
}


void IoSuppSetBuffering(        // SET FULL BUFFERING FOR AN OPEN FILE
    FILE *fp,                   // - opened file
    size_t buf_size )           // - buffer size
{
    set_buffering( fp, buf_size, _IOFBF );
}


void IoSuppSetLineBuffering(    // SET LINE BUFFERING FOR AN OPEN FILE
    FILE *fp,                   // - opened file
    size_t buf_size )           // - buffer size
{
    set_buffering( fp, buf_size, _IOLBF );
}


static void freeBuffer(         // FREE A BUFFER
    BUF_ALLOC* ba )             // - allocated buffer
{
    CMemFree( ba->buffer );
    RingPrune( &buffers, ba );
    CarveFree( carve_buf, ba );
}


boolean IoSuppCloseFile(        // CLOSE FILE IF OPENED
    FILE **file_ptr )           // - addr( file pointer )
{
    boolean retn;               // - return: TRUE ==> was open
    BUF_ALLOC* ba;              // - current allocated buffer

    if( *file_ptr == NULL ) {
        retn = FALSE;
    } else {
        RingIterBegSafe( buffers, ba ) {
            if( *file_ptr == ba->buffer ) {
                freeBuffer( ba );
                break;
            }
        } RingIterEndSafe( ba );
        SrcFileFClose( *file_ptr );
        *file_ptr = NULL;
        retn = TRUE;
    }
    return( retn );
}


struct path_descr               // path description
{   char buffer[ _MAX_PATH2 ];  // - buffer
    char *drv;                  // - drive
    char *dir;                  // - directory
    char *fnm;                  // - file name
    char *ext;                  // - extension
};


static void splitFileName(      // SPLIT APART PATH/FILENAME
    char *name,                 // - name to be split
    struct path_descr *descr )  // - descriptor
{
    _splitpath2( name
               , descr->buffer
               , &descr->drv
               , &descr->dir
               , &descr->fnm
               , &descr->ext );
}


static void makeDirName(        // MAKE FILE NAME (WITHOUT DRIVE)
    char *pp,                   // - target location
    struct path_descr *nd )     // - name descriptor
{
    _makepath( pp, NULL, nd->dir, nd->fnm, nd->ext );
}


static boolean openSrc(         // ATTEMPT TO OPEN FILE
    char *name,                 // - file name
    enum file_type typ )        // - type of file being opened
{
    pch_status pch_OK;          // - pre-compiled header load status
    FILE *fp;                   // - file pointer
    boolean might_browse;       // - true ==> might browse, if right file type

    if( SrcFileProcessOnce( name ) ) {
        SrcFileOpen( NULL, name );
        return( TRUE );
    }
    fp = SrcFileFOpen( name, SFO_SOURCE_FILE );
    if( fp == NULL ) {
        return( FALSE );
    }
    might_browse = FALSE;
    if( CompFlags.watch_for_pcheader ) {
        CompFlags.watch_for_pcheader = FALSE;
        pch_OK = PCHeaderAbsorb( name );
        if( pch_OK != PCHA_OK ) {
            SrcFileSetCreatePCHeader();
            SrcFileOpen( fp, name );
            might_browse = TRUE;
        } else {
            SrcFileOpen( NULL, name );
            fclose( fp );
        }
    } else {
        SrcFileOpen( fp, name );
        if( typ == FT_SRC ) {
            SetSrcFilePrimary();
        }
        might_browse = TRUE;
    }
#ifdef OPT_BR
    if( might_browse ) switch( typ ) {
      case FT_SRC :
      case FT_LIBRARY :
      case FT_HEADER :
        BrinfOpenSource( SrcFileCurrent() );
        break;
    }
#endif
    return( TRUE );
}


static char *openExt(           // ATTEMPT TO OPEN FILE (EXT. TO BE APPENDED)
    char *ext,                  // - extension
    struct path_descr *nd,      // - name descriptor
    enum file_type typ )        // - type of file being opened
{
    char        *ret;           // - ret
    char name[ _MAX_PATH ];     // - buffer for file name

    _makepath( name, nd->drv, nd->dir, nd->fnm, ext );
    /* so we can tell if the open worked */
    ret = (ext != NULL) ? ext : "";
    if( ! openSrc( name, typ ) ) {
        ret = NULL;
    }
    return ret;
}


static char *openSrcExts(       // ATTEMPT TO OPEN FILE (EXT.S TO BE APPENDED)
    char **exts,                // - extensions
    struct path_descr *nd,      // - name descriptor
    enum file_type typ )        // - type of file being opened
{
    char *ext;                  // - current extension

    if( nd->ext[0] == '\0' ) {
        int doSrc = (!(CompFlags.dont_autogen_ext_src) && (FT_SRC == typ));
        int doInc = (!(CompFlags.dont_autogen_ext_inc) && ((FT_HEADER == typ)||(FT_LIBRARY == typ)));
        int doExt = (doSrc || doInc);

        ext = openExt( NULL, nd, typ );

        if(( ext == NULL ) && (doExt)) {
            for( ; ; ) {
                ext = *exts++;
                if( ext == NULL ) break;
                ext = openExt( ext, nd, typ );
                if( ext != NULL ) break;
            }
        }
    } else {
        ext = openExt( nd->ext, nd, typ );
    }
    return ext;
}


static char *concSep(           // CONCATENATE PATH SEPARATOR AS REQUIRED
    char *pp,                   // - pointer into buffer
    char *buffer )              // - buffer
{
    char *pred;                 // - preceding char in buffer

    if( pp > buffer ) {
        pred = pp - 1;
        if( !IS_PATH_SEP( *pred ) ) {
            *pp++ = PATH_SEP;
        }

⌨️ 快捷键说明

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