cmdline.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 859 行 · 第 1/2 页
C
859 行
/****************************************************************************
*
* 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: Command line processing for WOMP.
*
****************************************************************************/
#include <ctype.h>
#include <direct.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h> /* for SEEK_SET */
#include <malloc.h> /* for _fheapshrink/_nheapshrink */
#include <conio.h>
#include "banner.h"
#include "womp.h"
#include "cmdline.h"
#include "memutil.h"
#include "genutil.h"
#include "myassert.h"
#include "watdbg.h"
#include "msdbg.h"
#include "genmsomf.h"
#include "can2txt.h"
#include "genphar.h"
#include "turbodbg.h"
#include "deflib.h"
/*
THIS MODULE NEEDS A REWRITE!
The interface to this module sucks bad. (addFile's hack for
wildcarding is especially gross.) The processing model
should have been more along the lines of:
// in main.c
while( there_are_more_files_to_do() ) {
ActionInput( ... );
...
ActionOutput( ... );
...
...
ActionRename( ... );
}
Main.c should not know about act_grp_t and cmdline_t in cmdline.h.
There's no need for it.
Then instead of wasting loads of memory by building all the stupid
structures that we parse. We could have simply written a state-machine
in here. i.e.,
there_are_more_files_to_do() {
if( we_are_wildcarding_a_filename ) {
advance_to_next_wildcard_match;
return( TRUE );
}
parse_any_switches_and_@includes;
if( end_of_input ) {
return( FALSE );
}
parse_a_filename;
if( filename_has_wildcards ) {
set we_are_wildcarding_a_filename to TRUE;
}
return( TRUE );
}
22-jul-91 DJG
*/
#define ENVVAR "WOMP"
#define SWCHAR '/'
#define INCCHAR '@'
#define CMTCHAR '#'
#define WMP_EXTENSION ".WMP"
#define OBJ_EXTENSION ".OBJ"
#define WILD_CARDS "*?" /* wild cards that may appear in filenames */
/*
Be careful that none of these enumerated types outgrow their bitfield
width in struct action_group.
*/
enum dbg_parsers {
PARSE_NULL,
PARSE_WATCOM,
PARSE_WATCOM_70
};
enum dbg_generators {
DGEN_NULL,
DGEN_TXT,
DGEN_MICROSOFT,
DGEN_METAWARE,
DGEN_TURBO
};
enum omf_generators {
OGEN_NULL,
OGEN_MICROSOFT,
OGEN_MICROSOFT_OS2,
OGEN_PHARLAP
};
STATIC cmdline_t cmdLine;
STATIC act_grp_t *curAct; /* stack of actions */
STATIC int headerDone;
STATIC uint_16 tempFileNum;
int BeQuiet( void ) {
return( cmdLine.quiet );
}
STATIC void header( void ) {
if( headerDone ) return;
headerDone = 1;
if( cmdLine.quiet ) return;
PrtFmt(
banner1w( "Object Module Processor", _WOMP_VERSION_ ) "\n"
banner2( "1990" ) "\n"
banner3 "\n"
banner3a "\n"
);
}
static void waitForKey( void ) {
char c;
PrtMsg( MSG_PRESS_KEY );
c = getch();
}
#pragma aux usage aborts;
STATIC void usage( void ) {
char msgbuff[MAX_RESOURCE_SIZE];
int previous_null = 0;
int i;
header();
for( i = MSG_USE_BASE;; i++ ) {
MsgGet( i, msgbuff );
if( ( msgbuff[ 0 ] == '.' ) && ( msgbuff[ 1 ] == 0 ) ) break;
if( previous_null ) {
if( msgbuff[0] != '\0' ) {
waitForKey();
PrtFmt( msgbuff );
PrtFmt( "\n" );
previous_null = 0;
} else break;
} else if( msgbuff[0] == '\0' ) {
previous_null = 1;
} else {
PrtFmt( msgbuff );
PrtFmt( "\n" );
}
}
exit( EXIT_FAILURE );
}
STATIC int isBreakChar( char x ) {
if( isspace( x ) ) return( 1 );
switch( x ) {
case '-':
case SWCHAR:
case INCCHAR:
case CMTCHAR:
case 0:
return( 1 );
}
return( 0 );
}
STATIC void getAct( int mk_new ) {
act_grp_t *act;
act = curAct;
if( act == NULL ) {
/*
Build the default action group
*/
act = curAct = MemAlloc( sizeof( act_grp_t ) );
act->next = NULL;
act->dbg_parser = PARSE_WATCOM;
act->dbg_generator = DGEN_METAWARE;
act->omf_generator = OGEN_MICROSOFT;
act->deflib = 1;
act->quiet = 0;
act->batch = 0;
act->output = NULL;
act->num_files = 0;
} else if( act->num_files > 0 && mk_new ) {
/* gotta create a new act_grp_t */
act = MemAlloc( sizeof( act_grp_t ) );
*act = *curAct; /* copy the old info */
act->next = curAct; /* stack it up */
curAct = act;
act->num_files = 0; /* no files in this group yet */
}
}
STATIC char *getFile( const char ** pstr ) {
const char *start;
const char *str;
size_t len;
char *copy;
/**/myassert( pstr != NULL && *pstr != NULL );
str = *pstr;
/**/myassert( !isBreakChar( *str ) );
start = str;
for(;;) {
++str;
if( *str == '\0' ) break;
if( isspace( *str ) ) break;
}
*pstr = str;
len = str - start;
copy = MemAlloc( len + 1 );
memcpy( copy, start, len );
copy[ len ] = 0;
return( copy );
}
#pragma aux unrecognized aborts;
STATIC void unrecognized( char opt ) {
char msgbuff[MAX_RESOURCE_SIZE];
header();
MsgGet( MSG_SYNTAX_ERR_IN_OPT, msgbuff );
PrtFmt( msgbuff, opt );
PrtFmt( "\n" );
usage();
}
STATIC const char *doParse( const char *str ) {
/**/myassert( str != NULL );
getAct( 1 );
switch( tolower( *str ) ) {
case 'w': curAct->dbg_parser = PARSE_WATCOM; break;
case '7': curAct->dbg_parser = PARSE_WATCOM_70; break;
case '-': curAct->dbg_parser = PARSE_NULL; break;
default: unrecognized( 'p' );
}
return( str + 1 );
}
STATIC const char *doDebug( const char *str ) {
/**/myassert( str != NULL );
getAct( 1 );
switch( tolower( *str ) ) {
case 'm': curAct->dbg_generator = DGEN_MICROSOFT; break;
case 'p': curAct->dbg_generator = DGEN_METAWARE; break;
case 't': curAct->dbg_generator = DGEN_TURBO; break;
case 'x': curAct->dbg_generator = DGEN_TXT; break;
case '-': curAct->dbg_generator = DGEN_NULL; break;
default: unrecognized( 'd' );
}
return( str + 1 );
}
STATIC const char *doFile( const char *str ) {
/**/myassert( str != NULL );
getAct( 1 );
switch( tolower( *str ) ) {
case 'm':
curAct->omf_generator = OGEN_MICROSOFT;
if( str[1] == '2' ) {
curAct->omf_generator = OGEN_MICROSOFT_OS2;
++str;
}
break;
case 'p':
curAct->omf_generator = OGEN_PHARLAP;
break;
case '-':
curAct->omf_generator = OGEN_NULL;
break;
default:
unrecognized( 'f' );
}
return( str + 1 );
}
STATIC const char *doOutput( const char * str ) {
/**/myassert( str != NULL );
if( *str != '=' && *str != '#' ) unrecognized( 'o' );
++str;
getAct( 1 );
if( curAct->output != NULL ) {
MemFree( curAct->output );
}
if( isBreakChar( *str ) ) unrecognized( 'o' );
curAct->output = getFile( &str );
return( str );
}
STATIC const char *doToggle( const char *str ) {
/**/myassert( str != NULL );
getAct( 1 );
switch( tolower( str[-1] ) ) {
case 'q': curAct->quiet = ! curAct->quiet; break;
#if 0
case 'l': curAct->deflib = ! curAct->deflib; break;
#endif
case 'b': curAct->batch = ! curAct->batch; break;
default: unrecognized( str[-1] ); break;
}
return( str );
}
STATIC const char *addFile( const char *str ) {
DIR *parent;
struct dirent *direntp;
char sp_buf[ _MAX_PATH2 ];
char *drive;
char *dir;
char path[ _MAX_PATH ];
char *p;
size_t len;
size_t files_in_dir;
/**/myassert( str != NULL );
getAct( 0 );
p = getFile( &str );
if( strpbrk( p, WILD_CARDS ) == NULL ) {
curAct = MemRealloc( curAct, sizeof( act_grp_t ) +
sizeof( const char * ) * curAct->num_files );
curAct->files[ curAct->num_files ] = p;
++curAct->num_files;
return( str );
}
/* process a wildcarded name */
parent = opendir( p );
if( parent == NULL ) {
Fatal( MSG_UNABLE_TO_OPEN_FILE, p );
}
/*
Since we must allocate memory for the filenames we shouldn't
MemRealloc the curAct to a larger size at the same time. So
we count the number of files in the directory.
*/
files_in_dir = 0;
for(;;) { /* count number of directory entries */
direntp = readdir( parent );
if( direntp == NULL ) break;
++files_in_dir;
}
closedir( parent );
if( files_in_dir == 0 ) {
Fatal( MSG_UNABLE_TO_OPEN_FILE, p );
}
curAct = MemRealloc( curAct, sizeof( act_grp_t ) +
sizeof( const char * ) * ( curAct->num_files + files_in_dir - 1 ) );
parent = opendir( p );
if( parent == NULL ) {
Fatal( MSG_UNABLE_TO_OPEN_FILE, p );
}
_splitpath2( p, sp_buf, &drive, &dir, NULL, NULL );
MemFree( p ); /* no longer need this */
for(;;) {
/* we ignore any difference between the number of times we can
loop here, and file_in_dir calc'd above */
direntp = readdir( parent );
if( direntp == NULL ) break;
_makepath( path, drive, dir, direntp->d_name, NULL );
len = strlen( path ) + 1;
curAct->files[ curAct->num_files ] =
memcpy( MemAlloc( len ), path, len );
++curAct->num_files;
--files_in_dir;
if( files_in_dir == 0 ) break;
}
closedir( parent );
return( str );
}
STATIC const char *doComment( const char *str ) {
/**/myassert( str != NULL );
while( *str != '\n' && *str != 0 ) ++str;
return( str );
}
/*
The next three functions (openIncludeFile, readIncludeFile, doInclude)
require stack checking.
*/
#pragma on( check_stack );
STATIC int openIncludeFile( const char * file_name ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?