optencod.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,981 行 · 第 1/4 页
C
1,981 行
/****************************************************************************
*
* 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: Generate scaffolding for autogenerated option parsing.
*
****************************************************************************/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "lsspec.h"
#include "encodlng.h"
// functions that are supplied by the host environment
#define FN_UNGET "OPT_UNGET" // void ( void )
#define FN_GET_LOWER "OPT_GET_LOWER" // int ( void )
#define FN_RECOG "OPT_RECOG" // int ( int )
#define FN_RECOG_LOWER "OPT_RECOG_LOWER" // int ( int )
#define FN_END "OPT_END" // int ( void )
#define FN_NUMBER "OPT_GET_NUMBER" // int ( unsigned * )
#define FN_NUMBER_DEFAULT "OPT_GET_NUMBER_DEFAULT" // int ( unsigned *, unsigned )
#define FN_NUMBER_MULTIPLE "OPT_GET_NUMBER_MULTIPLE" // int ( OPT_NUMBER ** )
#define FN_CHAR "OPT_GET_CHAR" // int ( int * )
#define FN_CHAR_OPT "OPT_GET_CHAR_OPT" // int ( int * )
#define FN_ID "OPT_GET_ID" // int ( OPT_STRING ** )
#define FN_ID_OPT "OPT_GET_ID_OPT" // int ( OPT_STRING ** )
#define FN_FILE "OPT_GET_FILE" // int ( OPT_STRING ** )
#define FN_FILE_OPT "OPT_GET_FILE_OPT" // int ( OPT_STRING ** )
#define FN_DIR "OPT_GET_DIR" // int ( OPT_STRING ** )
#define FN_DIR_OPT "OPT_GET_DIR_OPT" // int ( OPT_STRING ** )
#define FN_PATH "OPT_GET_PATH" // int ( OPT_STRING ** )
#define FN_PATH_OPT "OPT_GET_PATH_OPT" // int ( OPT_STRING ** )
#define FN_CLEAN_STRING "OPT_CLEAN_STRING" // void ( OPT_STRING ** )
#define FN_CLEAN_NUMBER "OPT_CLEAN_NUMBER" // void ( OPT_NUMBER ** )
#define FN_PROCESS "OPT_PROCESS" // int ( OPT_STORAGE * )
#define FN_INIT "OPT_INIT" // void ( OPT_STORAGE * )
#define FN_FINI "OPT_FINI" // void ( OPT_STORAGE * )
#define USE_SWITCH_THRESHOLD (4)
#define CONSOLE_WIDTH (79)
unsigned line;
FILE *gfp;
FILE *ofp;
FILE *pfp;
FILE *ufp;
FILE *mfp;
FILE *bfp;
#define BUFF_SIZE 1024
static char ibuff[BUFF_SIZE];
static char tagbuff[BUFF_SIZE];
static char tokbuff[BUFF_SIZE];
static char enumbuff[BUFF_SIZE];
static char hdrbuff[BUFF_SIZE];
static char maxusgbuff[BUFF_SIZE];
typedef struct option OPTION;
typedef struct codeseq CODESEQ;
#define CHAIN_YES 0x01
#define CHAIN_USAGE 0x02
static char alternateEqual;
static char chainOption[256];
static char *chainUsage[256][LANG_MAX];
static char lastChain;
static unsigned maxUsageLen;
static char *pageUsage[LANG_MAX];
static unsigned targetMask;
static unsigned targetAnyMask;
static unsigned targetDbgMask;
static unsigned nextTargetMask = 1;
typedef enum tag_id {
#define TAG( s ) TAG_##s ,
#include "opttags.h"
TAG_UNKNOWN,
TAG_NULL
} tag_id;
static tag_id getsUsage = TAG_NULL;
#define TAG( s ) #s ,
char *tagNames[] = {
#include "opttags.h"
NULL };
#define TAG( s ) static void do##s( char * );
#include "opttags.h"
#define TAG( s ) do##s ,
void (*processTag[])( char * ) = {
#include "opttags.h"
NULL };
static char *validTargets[] = {
"any",
"i86",
"386",
"axp",
"ppc",
"dbg",
"linux",
"qnx",
"sparc",
NULL
};
static const char * const langName[] = {
#define LANG_DEF( id, dbcs ) #id ,
LANG_DEFS
#undef LANG_DEF
};
static uint_8 const langMaxChar[] = {
#define LANG_DEF( id, dbcs ) dbcs ,
LANG_DEFS
#undef LANG_DEF
};
static char *usageMsg[] = {
"optencod [-i] [-q] [-u <usage-u>] <gml-file> <option-h> <parse-c> <usage-h> <target>*",
"where:",
" <gml-file> is the tagged input GML file",
" <parse-h> is the output file for the command line parser",
" <usage-h> is the output file for the usage message",
" <usage-u> is the output file for the QNX usage file",
" <target> can be chosen from:",
NULL
};
static struct {
unsigned international : 1;
unsigned quiet : 1;
unsigned no_equal : 1;
unsigned alternate_equal : 1;
} optFlag;
typedef struct target TARGET;
struct target {
TARGET *next;
unsigned mask;
char name[1];
};
static TARGET *targetList;
typedef struct name NAME;
struct name {
NAME *next;
unsigned is_timestamp : 1;
char name[1];
};
static NAME *enumList;
static NAME *enumeratorList;
struct option {
OPTION *next;
OPTION *synonym;
char *lang_usage[LANG_MAX];
char *check;
char *special;
char *special_arg_usage;
char *field_name;
char *value_field_name;
NAME *enumerate;
char *immediate;
char *code;
unsigned number_default;
unsigned target;
unsigned ntarget;
unsigned default_specified : 1;
unsigned is_simple : 1;
unsigned is_immediate : 1;
unsigned is_code : 1;
unsigned is_internal : 1;
unsigned is_multiple : 1;
unsigned is_number : 1;
unsigned is_id : 1;
unsigned is_char : 1;
unsigned is_file : 1;
unsigned is_dir : 1;
unsigned is_optional : 1;
unsigned is_path : 1;
unsigned is_special : 1;
unsigned is_prefix : 1;
unsigned is_timestamp : 1;
unsigned is_negate : 1;
unsigned nochain : 1;
char name[1];
};
static OPTION *optionList;
static OPTION *uselessOptionList;
#define HAS_OPT_STRING( o ) ( (o)->is_id || (o)->is_file || (o)->is_dir || (o)->is_path || (o)->is_special )
#define HAS_OPT_NUMBER( o ) ( (o)->is_number && (o)->is_multiple )
struct codeseq {
CODESEQ *sibling;
CODESEQ *children;
OPTION *option;
int c;
unsigned sensitive : 1;
unsigned accept : 1;
unsigned chain : 1;
};
typedef struct title TITLE;
struct title {
TITLE *next;
unsigned target;
unsigned ntarget;
char *lang_title[LANG_MAX];
};
static TITLE *titleList;
static TITLE *targetTitle;
enum {
EC_CONTINUE = 0x01,
EC_NULL = 0
};
static void fail( char *msg, ... )
{
va_list args;
if( line ) {
fprintf( stderr, "error on line %u\n", line );
}
va_start( args, msg );
vfprintf( stderr, msg, args );
va_end( args );
exit( EXIT_FAILURE );
}
static void dumpUsage( void )
{
char **p;
for( p = usageMsg; *p; ++p ) {
fprintf( stderr, "%s\n", *p );
}
fprintf( stderr, " " );
for( p = validTargets; *p; ++p ) {
fprintf( stderr, "%s ", *p );
}
fprintf( stderr, "\n", *p );
}
static void emitPrintf( unsigned depth, char *msg, ... )
{
va_list args;
unsigned i;
for( i = ( depth >> 1 ); i != 0; --i ) {
fprintf( pfp, "\t" );
}
if( depth & 1 ) {
fprintf( pfp, " " );
}
va_start( args, msg );
vfprintf( pfp, msg, args );
va_end( args );
}
static void addTarget( char *t )
{
size_t len;
TARGET *p;
len = strlen( t );
p = malloc( sizeof( *p ) + len );
p->mask = nextTargetMask;
p->next = targetList;
targetList = p;
strcpy( p->name, t );
nextTargetMask <<= 1;
if( nextTargetMask == 0 ) {
fail( "too many targets defined\n" );
}
}
static unsigned findTarget( char *t )
{
TARGET *p;
for( p = targetList; p != NULL; p = p->next ) {
if( strcmp( t, p->name ) == 0 ) {
return( p->mask );
}
}
fail( "invalid target name '%s'\n", t );
return( 0 );
}
static NAME *findName( NAME **h, char *n )
{
NAME *p;
for( p = *h; p != NULL; p = p->next ) {
if( strcmp( n, p->name ) == 0 ) {
return( p );
}
}
return( NULL );
}
static NAME *addName( NAME **h, char *n )
{
size_t len;
NAME *p;
len = strlen( n );
p = malloc( sizeof(*p) + len );
strcpy( p->name, n );
p->next = *h;
*h = p;
return( p );
}
static NAME *addEnumerator( char *enumerate, char *field_name )
{
NAME *n;
strcpy( enumbuff, "OPT_" );
strcat( enumbuff, enumerate );
strcat( enumbuff, "_" );
strcat( enumbuff, field_name );
n = findName( &enumeratorList, enumbuff );
if( n == NULL ) {
n = addName( &enumeratorList, enumbuff );
}
return( n );
}
static void procCmdLine( int argc, char **argv )
{
char **t;
unsigned mask;
if( argc < 5 ) {
dumpUsage();
exit( EXIT_FAILURE );
}
if( strcmp( argv[1], "-i" ) == 0 ) {
optFlag.international = 1;
--argc;
++argv;
}
if( strcmp( argv[1], "-q" ) == 0 ) {
optFlag.quiet = 1;
--argc;
++argv;
}
if( strcmp( argv[1], "-u" ) == 0 ) {
mfp = fopen( argv[2], "wb" );
if( !mfp ) fail( "cannot open '%s' for output", argv[2] );
argc -= 2;
argv += 2;
}
if( argc < 5 ) {
dumpUsage();
exit( EXIT_FAILURE );
}
++argv;
gfp = fopen( argv[0], "r" );
if( !gfp ) fail( "cannot open '%s' for input", argv[0] );
++argv;
ofp = fopen( argv[0], "w" );
if( !ofp ) fail( "cannot open '%s' for output", argv[0] );
++argv;
pfp = fopen( argv[0], "w" );
if( !pfp ) fail( "cannot open '%s' for output", argv[0] );
++argv;
ufp = fopen( argv[0], "w" );
if( !ufp ) fail( "cannot open '%s' for output", argv[0] );
++argv;
for( t = validTargets; *t; ++t ) {
addTarget( *t );
}
targetAnyMask = findTarget( "any" );
targetDbgMask = findTarget( "dbg" );
targetMask |= targetAnyMask;
while( *argv ) {
mask = findTarget( *argv );
targetMask |= mask;
++argv;
}
}
static char *skipSpace( char *p )
{
while( *p && isspace( *p ) ) {
++p;
}
return( p );
}
static char *copyNonSpaceUntil( char *i, char *o, char t )
{
for( ; *i; ++i ) {
if( isspace( *i ) ) break;
if( *i == t ) {
++i;
break;
}
*o = *i;
++o;
}
*o = '\0';
return( i );
}
static tag_id findTag( char *t )
{
char **c;
for( c = tagNames; *c; ++c ) {
if( stricmp( t, *c ) == 0 ) {
return( c - tagNames );
}
}
fail( "unknown tag: %s\n", t );
return( TAG_UNKNOWN );
}
static tag_id isTag( char **eot )
{
tag_id tag;
char *p;
p = ibuff;
p = skipSpace( p );
if( *p == ':' ) {
++p;
p = copyNonSpaceUntil( p, tagbuff, '.' );
tag = findTag( tagbuff );
if( tag != TAG_UNKNOWN ) {
*eot = p;
return( tag );
}
}
return( TAG_NULL );
}
static OPTION *pushNewOption( char *name, OPTION *same )
{
size_t len;
OPTION *p;
len = strlen( name );
p = calloc( 1, sizeof( *p ) + len );
p->synonym = same;
strcpy( p->name, name );
p->is_simple = 1;
p->next = optionList;
optionList = p;
return( p );
}
static char *pickUpRest( char *p )
{
size_t len;
len = strlen( p );
if( len != 0 ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?