wfl.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 863 行 · 第 1/2 页
C
863 行
/****************************************************************************
*
* 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: Compile and link utility for Open Watcom FORTRAN.
*
****************************************************************************/
#include "ftnstd.h"
#include "errcod.h"
#include "optflags.h"
#include "cioconst.h"
#include "banner.h"
#include "errrtns.h"
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifndef __UNIX__
#include <direct.h>
#endif
#include <process.h>
#include <malloc.h>
extern void MsgBuffer(uint,char *,...);
extern void ShowOptions(char *);
extern void __InitResource(void);
#if _CPU == 386
#define _CmpName "wfc386" // compiler name
#define _CmpExeName "wfc386.exe" // compiler executable file name
#define _LnkTmpFile "@_WFL386_.LNK" // temporary linker directive file
#define _WCLEnv "WFL386" // "wcl" environment variable
#elif _CPU == 8086
#define _CmpName "wfc" // copmiler name
#define _CmpExeName "wfc.exe" // compiler exe file name
#define _LnkTmpFile "@__WFL__.LNK" // temporary linker directive file
#define _WCLEnv "WFL" // "wcl" environment variable
#elif _CPU == _AXP
#define _CmpName "wfcaxp" // copmiler name
#define _CmpExeName "wfcaxp.exe" // compiler exe file name
#define _LnkTmpFile "@_WFLAXP_.LNK"// temporary linker directive file
#define _WCLEnv "WFLAXP" // "wcl" environment variable
#elif _CPU == _PPC
#define _CmpName "wfcppc" // copmiler name
#define _CmpExeName "wfcppc.exe" // compiler exe file name
#define _LnkTmpFile "@_WFLPPC_.LNK"// temporary linker directive file
#define _WCLEnv "WFLPPC" // "wcl" environment variable
#else
#error Unknown OS/CPU
#endif
#if defined( __QNX__ )
#define _ObjExtn ".o" // object file extension
#else
#define _ObjExtn ".obj" // object file extension
#endif
#define _LnkName "wlink" // linker name
#define _LnkExeName "wlink.exe" // linker executable file name
#define _CVPName "cvpack" // Codeview pack name
#define _CVPExeName "cvpack.exe" // Codeview pack executable file name
#define NULL_STR ""
#define NULLCHAR '\0'
#define ATTR_MASK _A_HIDDEN + _A_SYSTEM + _A_VOLID + _A_SUBDIR
// mask for illegal file types
#define TRUE 1
#define FALSE 0
typedef struct list {
char *filename;
struct list *next;
} list;
#if defined( __OS2__ ) || defined( __NT__ )
#define MAX_CMD 10240
#else
#define MAX_CMD 130
#endif
static char *Cmd; // command line parameters
static char *Word; // one parameter
static char Files[MAX_CMD]; // list of filenames from Cmd
static char Libs[MAX_CMD]; // list of libraries from Cmd
static char CmpOpts[MAX_CMD]; // list of compiler options from Cmd
static char CmpPath[_MAX_PATH]; // path for compiler executable file
static char LinkPath[_MAX_PATH]; // path for linker executable file
static FILE *Fp; // file pointer for TempFile
static char *LinkName; // name for TempFile if /fd specified
static char *TempFile; // temporary linker directive file
static list *ObjList; // linked list of object filenames
static char SwitchChars[3]; // valid switch characters
static char ExeName[_MAX_PATH]; // name of executable
static char *ObjName; // object file name pattern
static char *SystemName; // system name
static char DebugFlag; // debugging flag
static char *DebugOptions[] = {
"",
"debug dwarf\n",
"debug dwarf\n",
"debug watcom all\n",
"debug codeview\n",
"debug dwarf\n"
};
static struct flags {
unsigned quiet : 1; // compile quietly
unsigned no_link : 1; // compile only, no link step
unsigned link_for_sys : 1; // system specified
#if _CPU == 386 || _CPU == _AXP || _CPU == _PPC
unsigned default_win : 1; // OS/2 default windowed application
#else
unsigned windows : 1; // Windows application
unsigned link_for_dos : 1; // produce DOS executable
unsigned link_for_os2 : 1; // produce OS/2 executable
#endif
unsigned do_cvpack : 1; // do codeview cvpack
} Flags;
#if _CPU == 386
#define _NAME_ "F77/32 "
#elif _CPU == 8086
#define _NAME_ "F77/16 "
#elif _CPU == _AXP
#define _NAME_ "F77 Alpha AXP "
#elif _CPU == _PPC
#define _NAME_ "F77 PowerPC "
#else
#error Unknown System
#endif
static void wfl_exit( int rc ) {
//==================================
__ErrorFini();
exit( rc );
}
static void PrintMsg( uint msg, ... ) {
//=========================================
va_list args;
char buff[LIST_BUFF_SIZE+1];
va_start( args, msg );
__BldErrMsg( msg, buff, args );
va_end( args );
puts( &buff[1] ); // skip leading blank
}
static void PrtBanner( void ) {
//===========================
puts( banner1w( _NAME_ "Compile and Link Utility", _WFL_VERSION_ ) );
puts( banner2( "1990" ) );
puts( banner3 );
puts( banner3a );
}
static char *SkipSpaces( char *ptr ) {
//========================================
while( *ptr == ' ' ) ptr++;
return( ptr );
}
static void *MemAlloc( int size ) {
//=====================================
void *ptr;
ptr = malloc( size );
if( ptr == NULL ) {
PrintMsg( CL_OUT_OF_MEMORY );
wfl_exit( 1 );
}
return( ptr );
}
void main( int argc, char *argv[] ) {
//======================================
int rc;
char *wcl_env;
char *p;
char *q;
argc = argc;
__InitResource();
__ErrorInit( argv[0] );
CmpOpts[0] = '\0';
SwitchChars[0] = '/';
SwitchChars[1] = '-';
SwitchChars[2] = '\0';
Word = MemAlloc( MAX_CMD );
Cmd = MemAlloc( 2*MAX_CMD ); // for "wfl" environment variable and command line
// add "wcl" environment variable to "Cmd" unless "/y" is specified
// in "Cmd" or the "wcl" environment string
wcl_env = getenv( _WCLEnv );
if( wcl_env != NULL ) {
strcpy( Cmd, wcl_env );
strcat( Cmd, " " );
p = Cmd + strlen( Cmd );
getcmd( p );
q = Cmd;
for(;;) {
q = strpbrk( q, SwitchChars );
if( q == NULL ) break;
++q;
if( tolower( *q ) == 'y' ) {
getcmd( Cmd );
p = Cmd;
break;
}
}
} else {
getcmd( Cmd );
p = Cmd;
}
p = SkipSpaces( p );
if( ( *p == NULLCHAR ) || ( strncmp( p, "? ", 2 ) == NULL ) ) {
Usage();
wfl_exit( 1 );
}
TempFile = _LnkTmpFile;
Fp = fopen( &TempFile[1], "w" );
if( Fp == NULL ) {
PrintMsg( CL_ERROR_OPENING_TMP_FILE );
wfl_exit( 1 );
}
ObjName = NULL;
rc = Parse();
FindPath( _CmpExeName, CmpPath );
if( rc == 0 ) {
if( !Flags.quiet ) {
PrtBanner();
}
rc = CompLink();
}
if( rc == 1 ) fclose( Fp );
if( LinkName != NULL ) {
if( stricmp( LinkName, &TempFile[1] ) != 0 ) {
remove( LinkName );
rename( &TempFile[1], LinkName );
}
} else {
remove( &TempFile[1] );
}
wfl_exit( rc == 0 ? 0 : 1 );
}
static char *ScanFName( char *end, int len ) {
//================================================
for(;;) {
if( *end == '\0' ) break;
if( *end == ' ' ) break;
if( *end == SwitchChars[0] ) break;
if( *end == SwitchChars[1] ) break;
Word[len] = *end;
++len;
++end;
}
Word[len] = NULLCHAR;
return( end );
}
static int Parse( void ) {
//=============================
char opt;
char *end;
int len;
int cmp_option;
char in_quotes;
Flags.no_link = 0;
Flags.link_for_sys = 0;
Flags.quiet = 0;
#if _CPU == 386 || _CPU == _AXP || _CPU == _PPC
Flags.default_win = 0;
#else
Flags.windows = 0;
Flags.link_for_dos = 0;
Flags.link_for_os2 = 0;
#endif
Flags.do_cvpack = 0;
DebugFlag = 0;
// "Cmd" will always begin with at least one
// non-space character if we get this far
do {
opt = *Cmd;
if( ( opt == SwitchChars[0] ) || ( opt == SwitchChars[1] ) ) {
Cmd++;
} else {
opt = ' ';
}
in_quotes = FALSE;
end = Cmd;
for(;;) {
if( *end == '\0' ) break;
if( *end == '"' ) {
if( in_quotes ) break;
in_quotes = TRUE;
}
if( !in_quotes ) {
if( *end == ' ' ) break;
if( *end == SwitchChars[0] ) break;
if( *end == SwitchChars[1] ) break;
}
++end;
}
len = end - Cmd;
if( len != 0 ) {
if( opt == ' ' ) { // if filename, add to list
strncpy( Word, Cmd, len );
Word[len] = NULLCHAR;
strlwr( Word );
if( strstr( Word, ".lib" ) != NULL ) {
strcat( Libs, Libs[0] != '\0' ? "," : " " );
strcat( Libs, Word );
} else {
strcat( Files, Word );
strcat( Files, " " );
}
} else { // otherwise, do option
--len;
strncpy( Word, Cmd + 1, len );
Word[len] = NULLCHAR;
cmp_option = 1; // assume its a compiler option
switch( tolower( *Cmd ) ) {
case 'f': // files option
end = ScanFName( end, len );
switch( tolower( Word[0] ) ) {
case 'd': // name of linker directive file
if( Word[1] == '\0' ) {
LinkName = _LnkTmpFile;
++LinkName; // skip over '@'
cmp_option = 0;
} else if( (Word[1] == '=') || (Word[1] == '#') ) {
MakeName( Word, ".lnk" ); // add extension
LinkName = strdup( Word + 2 );
cmp_option = 0;
}
break;
case 'e': // name of exe file
if( ( Word[1] == '=' ) || ( Word[1] == '#' ) ) {
fputs( "name ", Fp );
Fputnl( Word + 2, Fp );
strcpy( ExeName, Word + 2 );
cmp_option = 0;
}
break;
case 'm': // name of map file
if( Word[1] == '\0' ) {
fputs( "option map\n", Fp );
cmp_option = 0;
} else if( (Word[1] == '=') || (Word[1] == '#') ) {
fputs( "option map=", Fp );
Fputnl( Word + 2, Fp );
cmp_option = 0;
}
break;
case 'i':
if( ( Word[1] == '=' ) || ( Word[1] == '#' ) ) {
fputs( "@", Fp );
Fputnl( Word + 2, Fp );
cmp_option = 0;
}
break;
case 'o': // name of object file
// parse off argument, so we get right filename
// in linker command file
if( ( Word[1] == '=' ) || ( Word[1] == '#' ) ) {
ObjName = strdup( &Word[2] );
}
break;
default:
break;
}
break;
case 'k': // stack size option
if( ( Word[0] == '=' ) || ( Word[0] == '#' ) ) {
fputs( "option stack=", Fp );
Fputnl( Word + 1, Fp );
cmp_option = 0;
}
break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?