langdat.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 708 行 · 第 1/2 页
C
708 行
/****************************************************************************
*
* 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: Langdat tool mainline.
*
****************************************************************************/
#include <string.h>
#include <ctype.h>
#ifdef __UNIX__
#include <stdlib.h>
#include <unistd.h>
#else
#include <direct.h>
#endif
#if defined( __WATCOMC__ ) || !defined( __UNIX__ )
#include <env.h>
#endif
#include "watcom.h"
#include "builder.h"
#define DEFCTLNAME "files.dat"
#define DEFCTLENV "FILES_DAT"
bool Quiet;
FILE *LogFile;
static ctl_file *CtlList;
include *IncludeStk;
static char Line[MAX_LINE];
static char ProcLine[MAX_LINE];
static unsigned VerbLevel;
static bool UndefWarn;
static unsigned ParmCount;
static char *Product = NULL;
/* Defaults for all output values */
static char *DefType = NULL;
static char *DefRedist = NULL;
static char *DefDir = NULL;
static char *DefUsr = NULL;
static char *DefRel = NULL;
static char *DefCond = NULL;
static char *DefPack = NULL;
static char *DefWhere = NULL;
static char *DefDesc = NULL;
static char *DefOld = NULL;
static char *DefPatch = NULL;
static char *DefDstvar = NULL;
static void AddCtlFile( const char *name )
{
ctl_file **owner;
ctl_file *curr;
owner = &CtlList;
for( ;; ) {
curr = *owner;
if( curr == NULL )
break;
owner = &curr->next;
}
curr = Alloc( sizeof( *curr ) );
curr->next = NULL;
strcpy( curr->name, name );
*owner = curr;
}
static char **getvalue( char **argv, char *buff )
{
if( argv[0][2] != '\0' ) {
strcpy( buff, &argv[0][2] );
return( argv );
}
++argv;
strcpy( buff, argv[0] );
return( argv );
}
static void Usage( void )
{
printf( "Usage: langdat [-c <ctl_file>]* [-l <log_file>] [-v] [-u] [-q] <product>\n" );
exit( 0 );
}
static void ProcessOptions( char *argv[] )
{
char parm_buff[_MAX_PATH];
bool opt_end;
opt_end = FALSE;
while( argv[0] != NULL ) {
if( !opt_end && argv[0][0] == '-' ) {
switch( tolower( argv[0][1] ) ) {
case 'c':
argv = getvalue( argv, parm_buff );
AddCtlFile( parm_buff );
break;
case 'l':
argv = getvalue( argv, parm_buff );
if( LogFile != NULL ) {
Fatal( "-l option specified twice\n" );
}
OpenLog( parm_buff );
break;
case 'v':
++VerbLevel;
break;
case 'u':
UndefWarn = TRUE;
break;
case 'q':
Quiet = TRUE;
break;
case '-':
opt_end = TRUE;
break;
default:
fprintf( stderr, "Unknown option '%c'\n\n", argv[0][1] );
/* fall through */
case '?':
Usage();
break;
}
} else if( strchr( argv[0], '=' ) != NULL ) {
putenv( argv[0] );
} else {
if( Product != NULL ) {
Fatal( "Product already set (was %s, now %s)\n", Product, argv[0] );
}
Product = argv[0];
}
++argv;
}
}
static void PushInclude( const char *name )
{
include *new;
char buff[_MAX_PATH2];
char *drive;
char *dir;
char *fn;
char *ext;
char dir_name[_MAX_PATH];
new = Alloc( sizeof( *new ) );
new->prev = IncludeStk;
new->skipping = 0;
new->ifdefskipping = 0;
new->reset_abit = NULL;
IncludeStk = new;
new->fp = fopen( name, "r" );
if( new->fp == NULL ) {
Fatal( "Could not open '%s': %s\n", name, strerror( errno ) );
}
strcpy( new->name, name );
_splitpath2( name, buff, &drive, &dir, &fn, &ext );
_makepath( dir_name, drive, dir, NULL, NULL );
if( SysChdir( dir_name ) != 0 ) {
Fatal( "Could not chdir to '%s': %s\n", dir_name, strerror( errno ) );
}
getcwd( IncludeStk->cwd, sizeof( IncludeStk->cwd ) );
}
static bool PopInclude( void )
{
include *curr;
curr = IncludeStk;
fclose( curr->fp );
IncludeStk = curr->prev;
free( curr );
if( IncludeStk == NULL ) {
return( FALSE );
}
SysChdir( IncludeStk->cwd );
return( TRUE );
}
static bool GetALine( char *line )
{
for( ;; ) {
fgets( line, MAX_LINE, IncludeStk->fp );
if( ferror( IncludeStk->fp ) ) {
Fatal( "Error reading '%s': %s\n", IncludeStk->name, strerror( errno ) );
}
if( !feof( IncludeStk->fp ) ) {
break;
}
if( !PopInclude() ) {
return( FALSE );
}
}
return( TRUE );
}
static char *SubstOne( const char **inp, char *out )
{
const char *in;
char *p;
char *starpos;
char *rep;
unsigned parm;
in = *inp;
p = out;
for( ;; ) {
switch( *in ) {
case '>':
*p = '\0';
// If the parameter is a number (n) followed by an asterisk,
// copy from parameter n to the end to out. E.g. <2*>
parm = 1;
for( starpos = out; isdigit( *starpos ); starpos++ )
;
if( stricmp( starpos, "*" ) == 0 ) {
rep = NULL;
p = out;
sscanf( out, "%u", &parm );
for( ; parm <= ParmCount; ++parm ) {
sprintf( out, "%d", parm );
rep = getenv( out );
if( rep != NULL ) {
if( out != p )
*out++ = ' ';
strcpy( out, rep );
out += strlen( out );
}
}
*inp = in + 1;
*out = '\0';
return( out );
} else if( stricmp( out, "CWD" ) == 0 ) {
rep = IncludeStk->cwd;
} else {
rep = getenv( out );
}
if( rep == NULL ) {
if( UndefWarn ) {
Log( FALSE, "<%s> is undefined\n", out );
}
rep = "";
}
strcpy( out, rep );
*inp = in + 1;
return( out + strlen( out ) );
case '<':
++in;
p = SubstOne( &in, p );
break;
default:
*p++ = *in++;
break;
}
}
}
static void SubstLine( const char *in, char *out )
{
bool first;
first = TRUE;
in = SkipBlanks( in );
for( ;; ) {
switch( *in ) {
case '^':
++in;
switch( *in ) {
case '\n':
case '\0':
break;
default:
*out++ = *in++;
break;
}
break;
case '[': // Surround special chars with a space
case ']':
case '(':
case ')':
if( !first )
*out++ = ' ';
*out++ = *in++;
*out++ = ' ';
break;
case '<':
++in;
out = SubstOne( &in, out );
break;
case '\n':
case '\0':
*out = '\0';
return;
default:
*out++ = *in++;
}
first = FALSE;
}
}
static char *FirstWord( char *p )
{
char *start;
p = SkipBlanks( p );
if( *p == '\0' )
return( NULL );
start = p;
for( ;; ) {
switch( *p ) {
case '\0':
p[1] = '\0';
/* fall through */
case ' ':
case '\t':
*p = '\0';
return( start );
}
++p;
}
}
static char *NextWord( char *p )
{
return( FirstWord( p + strlen( p ) + 1 ) );
}
static bool ContainsWord( const char *str, const char *word )
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?