wcl.c

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

C
1,055
字号
/****************************************************************************
*
*                            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/C++ Compile and Link utility.
*
****************************************************************************/


#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#ifndef __UNIX__
#include <direct.h>
#else
#include <dirent.h>
#endif
#include <process.h>
#include <malloc.h>
#include <conio.h>

#include "cmdlhelp.h"
#include "clcommon.h"
#include "banner.h"
#undef  _BANEXTRA
#define _BANEXTRA _BANEXSHORT

#ifdef WCLAXP
  #define WCLNAME     "wclaxp"          /* Name of Compile and Link Utility*/
  #define CC          "wccaxp"          /* Open Watcom C compiler          */
  #define CCXX        "wppaxp"          /* Open Watcom C++ compiler        */
  #define WCLENV      "WCLAXP"          /* name of environment variable    */
  #define STACKSIZE   "8192"            /* default stack size              */
  #define _NAME_      "C/C++ Alpha AXP "
#elif defined( WCLPPC )
  #define WCLNAME     "wclppc"          /* Name of Compile and Link Utility*/
  #define CC          "wccppc"          /* Open Watcom C compiler          */
  #define CCXX        "wppppc"          /* Open Watcom C++ compiler        */
  #define WCLENV      "WCLPPC"          /* name of environment variable    */
  #define STACKSIZE   "8192"            /* default stack size              */
  #define _NAME_      "C/C++ PowerPC "
#elif defined( WCLMPS )
  #define WCLNAME     "wclmps"          /* Name of Compile and Link Utility*/
  #define CC          "wccmps"          /* Open Watcom C compiler          */
  #define CCXX        "wppmps"          /* Open Watcom C++ compiler        */
  #define WCLENV      "WCLMPS"          /* name of environment variable    */
  #define STACKSIZE   "8192"            /* default stack size              */
  #define _NAME_      "C/C++ MIPS "
#elif defined( WCL386 )
  #define WCLNAME     "wcl386"          /* Name of Compile and Link Utility*/
  #define CC          "wcc386"          /* Open Watcom C compiler          */
  #define CCXX        "wpp386"          /* Open Watcom C++ compiler        */
  #define WCLENV      "WCL386"          /* name of environment variable    */
  #define STACKSIZE   "8192"            /* default stack size              */
  #define _NAME_      "C/C++32 "
#else
  #define WCLNAME     "wcl"             /* Name of Compile and Link Utility*/
  #define CC          "wcc"             /* Open Watcom C compiler          */
  #define CCXX        "wpp"             /* Open Watcom C++ compiler        */
  #define WCLENV      "WCL"             /* name of environment variable    */
  #define STACKSIZE   "4096"            /* default stack size              */
  #define _NAME_      "C/C++16 "
#endif
#ifdef __UNIX__
#define PATH_SEP_STR "/"
#else
#define PATH_SEP_STR "\\"
#endif
#define LINK        "wlink"         /* Open Watcom linker                 */
#define TEMPFILE    "@__wcl__.lnk"  /* temporary linker directive file    */

static  char    *Word;              /* one parameter                      */
static  char    *SystemName;        /* system to link for                 */
static  char    Files[MAX_CMD];     /* list of filenames from Cmd         */
static  char    Resources[MAX_CMD]; /* list of resources from Cmd         */
static  char    CC_Opts[MAX_CMD];   /* list of compiler options from Cmd  */
static  char    CC_Path[_MAX_PATH]; /* path name for wcc.exe              */
static  char    PathBuffer[_MAX_PATH];/* buffer for path name of tool     */
static  char    *Link_Name;         /* Temp_Link copy if /fd specified    */
static  char    *Temp_Link;         /* temporary linker directive file    */
                                    /* Temp_Link concurrent usages clash  */
static  struct directives *Directive_List; /* linked list of directives   */
static  char    *StackSize = NULL;  /* size of stack                      */
static  char    DebugFlag = 0;      /* debug info wanted                  */
static  char    Conventions;        /* 'r' for -3r or 's' for -3s         */
static  char    Switch_Chars[4];    /* valid switch characters            */
static  int     via_environment = FALSE;

/*
 *  Static function prototypes
 */
static int     Parse( char *Cmd );


#if defined( __UNIX__ )
    #define _dos_switch_char() '-'
#elif defined( __OS2__ ) || defined( __NT__ )
    #define _dos_switch_char() '/'
#else
    extern  int     _dos_switch_char( void );
#endif


#undef pick
#define pick( code, english )   english

extern const char *WclMsgs[] = {
#include "wclmsg.h"
};

static const char *EnglishHelp[] = {
#include "wclhelp.h"
NULL
};


static void initialize_Flags( void )
/**********************************/
{
    struct flags const zero_flags = { 0 };

    Flags = zero_flags;
    Flags.math_8087 = 1;
}


static int handle_environment_variable( const char *env )
/*******************************************************/
// This is an adaptation of code in sdk/rc/rc/c/param.c
{
    typedef struct EnvVarInfo {
        struct EnvVarInfo       *next;
        char                    *varname;
        // An anonymous copy of Word and *env is appended here
    } EnvVarInfo;
    EnvVarInfo          *info;
    static EnvVarInfo   *stack = 0; // Needed to detect recursion.
    unsigned            argbufsize;
    size_t              varlen;     // size to hold varname copy.
    int                 result;     // Parse Result.

    for( info = stack; info != NULL; info = info->next ) {
#if !defined( __UNIX__ )
        if( stricmp( Word, info->varname ) == 0 ) // Case-insensitive
#else
        if( strcmp( Word, info->varname ) == 0 )  // Case-sensitive
#endif
        {
            PrintMsg( WclMsgs[RECURSIVE_ENVIRONMENT_VARIABLE], Word );
            return( 1 );
        }
    }
    argbufsize = strlen( env ) + 1;         // inter-parameter spaces map to 0
    varlen = strlen( Word ) + 1;            // Copy taken to detect recursion.
    info = MemAlloc( sizeof( *info ) + argbufsize + varlen );
    info->next = stack;
    stack = info;                           // push info on stack
    info->varname = (char *)info + sizeof( *info );
    strcpy( info->varname, Word );
    result = Parse( strcpy( info->varname + varlen, env ) );
    stack = info->next;                     // pop stack
    free( info );
    return( result );
}


/*
 * makeTmpEnv() and killTmpEnv() ar adapted from synonyms in wmake/c/mexec.c.
 * They are simpler because support for recursion is not needed.
 */
static void *makeTmpEnv( char *arg )
/**********************************/
/*
 *  Copy arg into an environment var if possible.  If succeeds, then changes
 *  arg to just "@WCLxxxxx", and returns non-zero.  Otherwise leaves
 *  arg alone and returns zero.
 */
{
    int         wcl_index;
    char        buf[20];    /* "WCLxxxxx=" + '\0' = 11 + room for FmtStr */
    size_t      len;
    size_t      buflen;
    char        *env;

    wcl_index = 1;
    while( sprintf( buf, "WCL%d", wcl_index ), getenv( buf ) != NULL ) {
        ++wcl_index;
    }
    len = strlen( arg );
    buflen = strlen( buf );
    if( len < 4 + buflen )  /* need room for " @WCLxxxxx" */
        return( 0 );
                            /* "WCLxxxxx=" + arg + '\0' */
    env = MemAlloc( len + buflen + 2 );
    sprintf( env, "%s=%s", buf, arg );
    if( putenv( env ) != 0 )
        return( 0 );
    if( !Flags.be_quiet )
        PrintMsg( "       set %s\n", env );
    sprintf( arg, " @%s", buf );
    return( env );
}


static void killTmpEnv( char *env )
/*********************************/
{
    char const * const  equals = strchr( env, '=' );

    if( equals ) {
        size_t const    chars = 1 + (size_t)(equals - env);
        char * const    never_free = MemAlloc( 1 + chars );

        strncpy( never_free, env, chars );
        never_free[chars] = 0;
        if( !Flags.be_quiet )
            PrintMsg( "       set %s\n", never_free );
        if( putenv( never_free ) == 0 )
            free( env );
        free( never_free ); /* Actually OK */
    }

}


void print_banner( void )
/***********************/
{
    static int done;

    if( done ) return;
    puts( banner1w( _NAME_ "Compile and Link Utility", _WCL_VERSION_ ) );
    puts( banner2( "1988" ) );
    puts( banner3 );
    puts( banner3a );
    done = 1;
}


static  char  *SkipSpaces( char *ptr )
/************************************/
{
    while( *ptr == ' ' || *ptr == '\t' ) {  /* 16-mar-91 */
        ptr++;
    }
    return( ptr );
}


static  void  MakeName( char *name, char *ext )
/*********************************************/
{
    /* If the last '.' is before the last path seperator character */
    if( strrchr( name, '.' ) <= strpbrk( name, PATH_SEP_STR ) ) {
        strcat( name, ext );
    }
}


static void  Usage( void )
/************************/
{
    char const  **list;
    char const  *p;
    int         lines_printed;
    unsigned int i, n;
    auto        char buf[82];
#ifndef __UNIX__
    int const   paging = isatty( fileno( stdout ) );
    int const   height = 24; /* Number of lines assumed on screen */
#endif

    print_banner();
    lines_printed = 4;
    list = EnglishHelp;
    while( *list ) {
        memset( buf, ' ', 80 );
        if( **list == '[' ) {                   /* title to be centered */
            i = strlen( *list );
            strcpy( &buf[38 - i / 2], *list );
            ++list;
            for( n = 0; list[n]; ++n ) {        /* count number in list */
                if( *list[n] == '[' ) break;
            }
            n = (n + 1) / 2;                    /* half way through list */
#ifndef __UNIX__
            if( paging && lines_printed != 0 && lines_printed >= height ) {
                fputs( WclMsgs[ PRESS_ANY_KEY_TO_CONTINUE ], stdout );
                fflush( stdout );
                getch();
                puts( "" );
                lines_printed = 0;
            }
#endif
            puts( buf );
            lines_printed++;
            for( ;; ) {
                memset( buf, ' ', 80 );
                p = *list;
                if( p == NULL ) break;
                for( i = 0; *p; )  buf[i++] = *p++;
                p = list[n];
                if( p != NULL  &&  *p != '[' ) {
                    for( i = 38; *p; )  buf[i++] = *p++;
                }
                buf[i] = '\0';
                puts( buf );
                lines_printed++;
#ifndef __UNIX__
                if( paging && lines_printed != 0 && lines_printed >= height ) {
                    fputs( WclMsgs[ PRESS_ANY_KEY_TO_CONTINUE ], stdout );
                    fflush( stdout );
                    getch();
                    puts( "" );
                    lines_printed = 0;
                }
#endif
                p = list[n];
                if( p == NULL ) break;
                if( *p == '[' ) break;
                list[n] = NULL; /* indicate already printed */
                ++list;
            }
            list = &list[n];
        } else {
            puts( *list );
            lines_printed++;

⌨️ 快捷键说明

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