ccmain.c

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

C
1,314
字号
/****************************************************************************
*
*                            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:  C compiler top level driver module and file I/O.
*
****************************************************************************/


#include "cvars.h"
#include "iopath.h"
#include "scan.h"
#include "autodept.h"
#include <stdarg.h>
#include <stdio.h>
#ifdef __OSI__
    #include "ostype.h"
#endif
#define BY_CLI
#include "feprotos.h"
#include "swchar.h"

#ifndef _MAX_PATH
    #define _MAX_PATH   (PATH_MAX + 1)
#endif
#ifndef _MAX_PATH2
    #define _MAX_PATH2  (PATH_MAX + 4)
#endif

#if defined( __UNIX__ )
    #define IS_PATH_SEP( ch ) ((ch) == '/')
#else
    #define IS_PATH_SEP( ch ) ((ch) == '/' || (ch) == '\\')
#endif

#define MAX_INC_DEPTH   255

extern  char    CharSet[];

static  char    IsStdIn;
static  int     IncFileDepth;

int PrintWhiteSpace;     // also refered from cmac2.c

// local function prototypes
static  void    DoCCompile( char **cmdline );
static  void    DelErrFile( void );
static  void    MakePgmName( void );
static  int     OpenFCB( FILE *fp, char *filename );
static  bool    IsFNameOnce( char const *filename );
static  int     TryOpen( char *prefix, char *separator, char *filename, char *suffix );
static  void    ParseInit( void );
static  void    CPP_Parse( void );
static  int     FCB_Alloc( FILE *fp, char *filename );
local   void    Parse( void );
static  int     OpenPgmFile( void );
static  void    DelDepFile( void );


void FrontEndInit( bool reuse )
//***************************//
// Do the once only things   //
//***************************//
{
    GlobalCompFlags.cc_reuse = reuse;
    GlobalCompFlags.cc_first_use = TRUE;
}

void FrontEndFini( void )
//********************//
// Fini the once only //
//********************//
{
    GlobalCompFlags.cc_reuse = FALSE;
    GlobalCompFlags.cc_first_use = TRUE;
}

void ClearGlobals( void )
{
    InitStats();
    IsStdIn = 0;
    FNames = NULL;
    RDirNames = NULL;
    SrcFile = NULL;
    ErrFile = NULL;
    DefFile = NULL;
    CppFile = NULL;
    DepFile = NULL;
    SymLoc  = NULL;
    HFileList = NULL;
    IncFileDepth = MAX_INC_DEPTH;
    SegmentNum = FIRST_PRIVATE_SEGMENT;
    BufSize = BUF_SIZE;
    Buffer = CMemAlloc( BufSize );
    TokenBuf = CMemAlloc( BufSize );
}


unsigned char _8087;                                    /* 27-may-91 */
unsigned char _real87;

int FrontEnd( char **cmdline )
{
    _real87 = _8087 = 0;/* set to 0 in case 8087 is present; 27-may-91 */

    InitGlobalVars();
    CMemInit();
    InitMsg();
    InitPurge();

    SwitchChar = _dos_switch_char();
    ClearGlobals();
    DoCCompile( cmdline );
    PurgeMemory();
    FiniMsg();
    CMemFini();
    GlobalCompFlags.cc_first_use = FALSE;
    return( ErrCount );
}


void CloseFiles( void )
{
    if( CppFile != NULL ) {
        fflush( CppFile );
        if( ferror( CppFile ) ) {
            char    msgtxt[80];
            char    msgbuf[MAX_MSG_LEN];

            /* issue message */
            CGetMsg( msgtxt, ERR_FATAL_ERROR );
            sprintf( msgbuf, msgtxt, strerror( errno ) );
            NoteMsg( msgbuf );
        }
        fclose( CppFile );
        CppFile = NULL;
    }
    if( ErrFile != NULL ) {
        fclose( ErrFile );
        ErrFile = NULL;
        if( ! CompFlags.errfile_written ) {
            DelErrFile();
        }
    }
    if( DefFile != NULL ) {
        fclose( DefFile );
        DefFile = NULL;
    }
    if( ErrFile != NULL ) {
        fclose( ErrFile );
        ErrFile = NULL;
    }
}

static bool ParseCmdLine( char **cmdline )
{
    char        *cmd;

    cmd = (cmdline == NULL) ?  "" : cmdline[0];  // from cpp.c
    if( cmd == NULL ) { // argv == 1
        cmd = "";
    }
    while( *cmd == ' ' ) ++cmd;                     /* 13-mar-90 */
    if( *cmd == '?' || *cmd == '\0' ) {
        CBanner();
        CCusage();
        return( FALSE );
    }
    GenCOptions( cmdline );
    FESetCurInc();
    if( WholeFName != NULL ) {
        MakePgmName( );
        OpenPgmFile();
        MainSrcFile = SrcFile;                  /* 05-jan-94 */
    }
    return( TRUE );
}

void OpenDepFile( void )
{
    char        *name;

    if( CompFlags.generate_auto_depend ) {                        /* 15-dec-88 */
        name = DepFileName();
        if( name != NULL ) {
            DepFile = fopen( name, "w" );
            if( DepFile != NULL ) {
                setvbuf( DepFile, CPermAlloc( 1024 ), _IOFBF, 1024 );
            }
        }
     }
}

char *ForceSlash( char *name, char slash )
{
    char    *save = name;

    if( !slash || !save )
        return( name );
    while( name[0] )
    {
        if( name[0] == '\\' || name[0] == '/' )
            name[0] = slash;
        name++;
    }
    return( save );
}

void DumpDepFile( void )
{
    FNAMEPTR    curr;

    if( CompFlags.generate_auto_depend && FNames ) {
        curr = FNames;
        if( !DepFile ) {
            return;
        }
        fprintf( DepFile, "%s :"
               , ForceSlash( CreateFileName( DependTarget, OBJ_EXT, FALSE )
                          , DependForceSlash ) );
        if( curr )
            if( curr->rwflag && !SrcFileInRDir( curr ) )
                fprintf( DepFile, " %s"
                        , ForceSlash( GetSourceDepName()
                                    , DependForceSlash ) );
        curr = curr->next;
        for( ; curr; curr = curr->next ) {
            if( curr->rwflag && !SrcFileInRDir( curr ) )
                fprintf( DepFile, " %s", ForceSlash( curr->name, DependForceSlash ) );
        }
        fprintf( DepFile, "\n" );
        /*
        for( curr = FNames; curr; curr = curr->next )
        {
            if( curr->rwflag && !SrcFileInRDir( curr ) )
                continue;
            //fprintf( DepFile, "#Skipped file...%s\n", curr->name );
        }
        */
    }
}

static void DoCCompile( char **cmdline )
/**************************************/
{
    jmp_buf     env;

    Environment = &env;
    if( setjmp( env ) ) {       /* if fatal error has occurred */
        EmitAbort();                /* abort code generator */
        PragmaFini();
        CloseFiles();
        FreeFNames();
        FreeRDir();
        ErrCount = 1;
        MyExit( 1 );
    }
    ParseInit();
    ForceInclude = FEGetEnv( "FORCE" );
    if( ParseCmdLine( cmdline ) ) {
        if( WholeFName == NULL ) {
            CErr1( ERR_FILENAME_REQUIRED );
            return;
        }
        DelErrFile();               /* delete old error file */
        OpenErrFile();              /* open error file just in case */
        OpenDepFile();
        MergeInclude();             /* merge INCLUDE= with HFileList */
        CPragmaInit();              /* memory model is known now */
#if _CPU == 370
        ParseAuxFile();
#endif
        if( CompFlags.cpp_output ) {
            CPP_Parse();
            if( !CompFlags.quiet_mode ) {
                PrintStats();
            }
        } else {
            MacroAddComp(); // Add any compile time only macros
            Parse();
            if( !CompFlags.quiet_mode ) {
                PrintStats();
            }
            if( ( ErrCount == 0 ) && ( !CompFlags.check_syntax ) ) {
                if( CompFlags.emit_browser_info ) {
                    DwarfBrowseEmit();
                }
                FreeMacroSegments();
                DoCompile();
            } else {
                FreeMacroSegments();
            }
        }
        if( ErrCount == 0 && DepFile ) {
            DumpDepFile();
            fclose( DepFile );
        }
        else {
            if( DepFile ) {
                fclose( DepFile );
            }
            DelDepFile();
        }
        DepFile = NULL;

        SymFini();
        PragmaFini();
    } else {
        ErrCount = 1;
    }
    CloseFiles();
    FreeFNames();
    FreeRDir();
}


/* open the primary source file, and return pointer to root file name */

#define STDIN_NAME      "stdin"

static void MakePgmName( void )
{
// Get fname, if file name has no extension whack ".c" on
// if stdin a "." then replace with "stdin" don't whack ".c"
// If no module name make the same as fname
    int         len;
    char        *ptr;
    char        buff[ _MAX_PATH2 ];
    char        *fname;
    char        *ext;

    ptr = WholeFName;
    if( ptr[0] == '.' && ptr[1] == '\0' ) {
        IsStdIn = 1;
        CMemFree( WholeFName );
        len = strlen( STDIN_NAME );
        WholeFName = CMemAlloc( len + sizeof( char ) );
        strcpy( WholeFName, STDIN_NAME );
        fname = WholeFName;
    } else {
        _splitpath2( ptr, buff, NULL, NULL, &fname, &ext );
        if(  *ext == '\0' ) { // no extension
            char *new;

            len = strlen( WholeFName );
            len += sizeof( C_EXT );      /* for the ".c\0" */
            new = CMemAlloc( len );
            strcpy( new, WholeFName );
            strcat( new, C_EXT );
            CMemFree( WholeFName );
            WholeFName = new;
        }
    }
    len = strlen( fname );
    SrcFName = CMemAlloc( len + sizeof( char ) );
    strcpy( SrcFName, fname );
    if( ModuleName == NULL ) ModuleName = SrcFName;
}

local void CantOpenFile( char *name )
{
    char msgtxt[80];
    char  msgbuf[MAX_MSG_LEN];

    CGetMsg( msgtxt, ERR_CANT_OPEN_FILE );
    sprintf( msgbuf, msgtxt, name );
    BannerMsg( msgbuf );
}

static int OpenPgmFile( void )
{
    if( IsStdIn ) {
        return( OpenFCB( stdin, "stdin" ) );
    }
    if( TryOpen( "", "", WholeFName, "" ) == 0 ) {
        if( TryOpen( C_PATH, PATH_SEP, WholeFName, "" ) == 0 ) {
            CantOpenFile( WholeFName );
            CSuicide();
            return( 0 );
        }
    }
#if _CPU == 370
    SrcFile->colum = Column;
    SrcFile->trunc = Trunc;
#endif
    return( 1 );
}


char *CreateFileName( char *template, char *extension, bool forceext )
{
#if !defined( __CMS__ )
    char    buff[ _MAX_PATH2 ];
    char    *drive;
    char    *dir;
    char    *fname;
    char    *ext;
    char    *path;

    path = (template == NULL) ? WholeFName : template;

    _splitpath2( path, buff, &drive, &dir, &fname, &ext );
    if( forceext || template == NULL || ext[0] == '\0' ) {
        ext = extension;
    }
    if( fname[0] == '\0' || fname[0] == '*' ) {
        fname = ModuleName;
    }
    if( template == NULL ) {
        /* default object file goes in current directory */
        drive = "";
        dir = "";
    }
    _makepath( Buffer, drive, dir, fname, ext );
#else
    char    *p;

⌨️ 快捷键说明

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