#ifndef lint
static char sccsid[] = "@(#)rpc←main.c 1.1 90/10/29 (C) 1987 SMI";
#endif
/*
* rpc←main.c, Top level of the RPC protocol compiler.
* Copyright (C) 1987, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "rpc←util.h"
#include "rpc←parse.h"
#include "rpc←scan.h"
#define EXTEND 1 /* alias for TRUE */
struct commandline {
int cflag; /* xdr C routines */
int hflag; /* header file */
int lflag; /* client side stubs */
int sflag; /* server stubs for the given transport */
char *infile; /* input module name */
char *outfile; /* output module name */
};
static char *cmdname;
static char CPP[] = "/lib/cpp";
static char CPPFLAGS[] = "-C";
int PFlag = FALSE; /* Strip prefix module names */
int ExpandProcArgs = FALSE; /* TRUE => expand proc struct parameters */
int RecoveryFlag = FALSE; /* TRUE => add RPC.Failed recovery loop to
client stubs and RecoveryProc parm. to
client import routines. */
char *svcName; /* Name of service being compiled. */
char *ServiceName();
void MakeSymbolTables();
int BadProgNameFlag[32]; /* Array of flags indicating if a program
defn. has a name that can't be translated
to Cedar by the standard means when prefix
stripping being done. The nth flag
corresponds to the nth program defn.
TRUE => Need to use an altered form of
progName with prefix stripping. */
int CurrentProgNameFlag = -1; /* Index in BadProgNameFlag for the program
defn. currently being processed. */
int PCedar = 0; /* Flag to signal that PCedar2.0 is the
target environment. */
int PCedarUDP = 0; /* Flag to signal that SunRPC should be used. */
int PCedarTCP = 0; /* Flag to signal that SunRPCStream should
be used. */
char *SunRPC = "SunRPC"; /* Name of SunRPC module to use. For PCedarTCP,
the name to use will be SunRPCStream. */
int SeqTypeId = 0; /* Global constant used to create unique
names for sequence types we need to define. */
Context *CurrentContext = NULL;
int TypeDefsExist = FALSE; /* Used to signal if an XDR file should
exist for the .x file. */
int ProgramsExist = FALSE; /* Used to signal if a program is defined
in the .x file. */
enum {noFile, svcInterface, clientImpl, serverImpl, xdrInterface, xdrImpl}
OutFileType;
list *Imports; /* List of IMPORT module names. */
list *GetPutImports; /* List of IMPORT GetPut module names. */
StringHashTableHandle ImportNames; /* Hash table of imported names.
Hash table elem values are module
names. */
/* IMPORTed .x files are searched for on a path defined by an environment var */
#define PATH←ENV←VAR "DOTXPATH"
#define PATH←DEFAULT ".:/project/ubi/src/x"
StringHashTableHandle SymbolNames; /* Hash table of struct definitions.
Used to decide whether or not to expand
procedure input parameters. */
StringHashTableHandle SeqTypes; /* Hash table of Cedar sequence types for
variable-length arrays. */
StringHashTableHandle EnumTypes; /* Hash table of enum types. Contains lists
of their element names. */
main(argc, argv)
int argc;
char *argv[];
{
struct commandline cmd;
char *interfaceName;
char *getPutName;
char *getPutImplName;
char *clientImplName;
char *serverImplName;
char *extendfile();
bzero((char *)&cmd, sizeof (struct commandline));
if (!parseargs(argc, argv, &cmd)) {
f←print(stderr,
"usage: %s [-p] [-e] infile\t\t-- generates Cedar10.0 stubs\n",
cmdname);
f←print(stderr,
"\t%s [-p] [-e] [-PCedar] infile\t\t-- generates PCedar UDP stubs\n",
cmdname);
f←print(stderr,
"\t%s [-p] [-e] [-PCedarStream] infile\t\t-- generates PCedar TCP stubs\n",
cmdname);
exit(1);
}
CurrentContext = (Context *) malloc(sizeof(Context));
reinitialize();
svcName = ServiceName(cmd.infile);
MakeSymbolTables(cmd.infile);
if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.sflag) {
fprintf(stderr, "options not available for Cedar\n");
exit(-1);
} else {
/* the rescans are required, since cpp may effect input */
interfaceName = extendfile(cmd.infile, "");
getPutName = extendfile(cmd.infile, "GetPut");
getPutImplName = extendfile(cmd.infile, "GetPutImpl");
clientImplName = extendfile(cmd.infile, "ClientImpl");
serverImplName = extendfile(cmd.infile, "ServerImpl");
if (PCedar && PCedarTCP) {
SunRPC = "SunRPCStream";
}
/* *** Note *** h←output must be called before the others. */
h←output(cmd.infile, interfaceName, "-DRPC←HDR");
reinitialize();
c←output(cmd.infile, getPutName, getPutImplName,
"-DRPC←XDR");
reinitialize();
l←output(cmd.infile, clientImplName, "-DRPC←CLNT");
reinitialize();
s←output(cmd.infile, serverImplName, "-DRPC←SVC");
reinitialize();
}
exit(0);
/* NOTREACHED */
}
/*
* add extension to filename
*/
static char *
extendfile(file, ext)
char *file;
char *ext;
{
char *res;
char *p;
res = alloc(strlen(file) + strlen(ext) + 1);
if (res == NULL) {
abort();
}
p = rindex(file, '.');
if (p == NULL) {
p = file + strlen(file);
}
(void) strcpy(res, file);
(void) strcpy(res + (p - file), ext);
return (res);
}
/*
* Return the basename of a file.
*/
static
char *ServiceName(filename)
char *filename;
{
char *s;
char *p;
char *svcName = alloc(strlen(filename)+1);
p = rindex(filename, '/');
if (p != NULL)
s = p + 1;
else
s = filename;
strcpy(svcName, s);
p = rindex(svcName, '.');
if (p != NULL) {
*p = '\0';
}
return (svcName);
}
/*
* Open output file with given extension
*/
static
open←output(infile, outfile)
char *infile;
char *outfile;
{
if (outfile == NULL) {
fout = stdout;
EmitNotice();
return;
}
if (infile != NULL && streq(outfile, infile)) {
f←print(stderr, "%s: output would overwrite %s\n", cmdname,
infile);
crash();
}
if (access(outfile, F←OK) == 0) {
(void )unlink(outfile); /* Get rid of the old version; which - if
it's a symbolic link - would cause us
problems during subsequent writing. */
}
fout = fopen(outfile, "w");
if (fout == NULL) {
f←print(stderr, "%s: unable to open ", cmdname);
perror(outfile);
crash();
}
record←open(outfile);
f←print(fout, "-- %s\n", outfile);
EmitNotice();
}
static
EmitNotice()
{
f←print(fout, "-- Please do not edit this file.\n");
f←print(fout, "-- It was generated using CedarRPCGen.\n\n");
}
/*
* FIndFileOnPath
*/
static
char *
FindFileOnPath (name, varname, defaultpath)
char *name; /* Filename to find */
char *varname; /* Name of env var that contains path */
char *defaultpath; /* Default path if no environment variable */
{
char *prefix;
char *getenv();
char *copy;
char buf[1000];
char *base, *p;
if (*name == '.' || *name == '/') {
return (strdup(name));
}
if ((prefix = getenv (varname)) == NULL) {
prefix = defaultpath;
}
copy = strdup(prefix);
base = copy;
do {
p = strchr (base, ':');
if (p != NULL)
*p = (char) 0;
sprintf (buf, "%s/%s", base, name);
if (access (buf, R←OK) == 0) {
p = strdup (buf);
free (copy);
return (p);
}
if (p != NULL && *(p+1) != (char) 0) {
base = p + 1;
} else {
base = NULL;
}
} while (base != NULL);
free (copy);
return (NULL);
}
/*
* Open input file with given define for C-preprocessor
*/
static
open←input(infile, define)
char *infile;
char *define;
{
int pd[2];
if (infile == NULL) {
CurrentContext->infilename = "<stdin>";
} else {
CurrentContext->infilename = FindFileOnPath(infile,
PATH←ENV←VAR, PATH←DEFAULT);
if (CurrentContext->infilename != NULL) {
infile = CurrentContext->infilename;
}
}
(void) pipe(pd);
switch (fork()) {
case 0:
(void) close(1);
(void) dup2(pd[1], 1);
(void) close(pd[0]);
if (define != NULL && define[0] != '\0')
execl(CPP, CPP, CPPFLAGS, define, infile, NULL);
else
execl(CPP, CPP, CPPFLAGS, infile, NULL);
perror("execv");
exit(1);
case -1:
perror("fork");
exit(1);
}
(void) close(pd[1]);
CurrentContext->fin = fdopen(pd[0], "r");
if (CurrentContext->fin == NULL) {
f←print(stderr, "%s: ", cmdname);
perror(CurrentContext->infilename);
crash();
}
}
/*
* Compile into a marshalling routines output file
*/
static
c←output(infile, getputFile, getputImplFile, define)
char *infile;
char *getputFile, *getputImplFile;
char *define;
{
char outputFileName[128];
definition *def;
char *include;
long tell;
list *l;
/*
* Emit the interface file.
*/
sleep(1); /* Do this to avoid having the same creation
time on two different files - something that
Cedar can't handle. */
OutFileType = xdrInterface;
open←input(infile, define);
sprintf(outputFileName, "%s.mesa", getputFile);
open←output(infile, outputFileName);
f←print(fout, "DIRECTORY\n");
f←print(fout, " %s,\n", SunRPC);
f←print(fout, " %s;\n\n", svcName);
f←print(fout, "%s: CEDAR DEFINITIONS =\n", getputFile);
f←print(fout, "BEGIN\n\n");
f←print(fout, "Handle: TYPE = %s.Handle;\n\n", SunRPC);
tell = ftell(fout);
while (def = get←definition()) {
emitDefn(def);
}
if (tell == ftell(fout)) {
(void) unlink(outputFileName);
return;
}
f←print(fout, "END.\n");
fclose(fout);
/*
* Emit the module file.
*/
sleep(1); /* Do this to avoid having the same creation
time on two different files - something that
Cedar can't handle. */
OutFileType = xdrImpl;
open←input(infile, define);
sprintf(outputFileName, "%s.mesa", getputImplFile);
open←output(infile, outputFileName);
f←print(fout, "DIRECTORY\n");
if (PCedar) f←print(fout, " Basics,\n");
f←print(fout, " Rope,\n");
f←print(fout, " %s,\n", SunRPC);
if (PCedarUDP) f←print(fout, " SunRPCNumbers,\n");
if (Imports != NULL) {
for (l = Imports; l != NULL; l = l->next) {
f←print(fout, " %s,\n", l->val);
}
}
if (GetPutImports != NULL) {
for (l = GetPutImports; l != NULL; l = l->next) {
f←print(fout, " %s,\n", l->val);
}
}
f←print(fout, " %s,\n", svcName);
f←print(fout, " %sGetPut;\n\n", svcName);
f←print(fout, "%s: CEDAR PROGRAM\n", getputImplFile);
f←print(fout, " IMPORTS %s", SunRPC);
if (PCedarUDP) f←print(fout, ", SunRPCNumbers");
if (GetPutImports != NULL) {
for (l = GetPutImports; l != NULL; l = l->next) {
f←print(fout, ", %s", l->val);
}
}
f←print(fout, " EXPORTS %s, %sGetPut =\n", svcName, svcName);
f←print(fout, "BEGIN\n");
f←print(fout, "Handle: TYPE = %s.Handle;\n\n", SunRPC);
f←print(fout, "ROPE: TYPE = Rope.ROPE;\n\n");
tell = ftell(fout);
while (def = get←definition()) {
emitImpl(def);
}
if (tell == ftell(fout)) {
(void) unlink(outputFileName);
return;
}
f←print(fout, "END.\n");
fclose(fout);
}
/*
* Compile into an M3 interface file for the service.
*/
static
h←output(infile, outfile, define)
char *infile;
char *outfile;
char *define;
{
definition *def;
char outfilename[128];
list *l;
sleep(1); /* Do this to avoid having the same creation
time on two different files - something that
Cedar can't handle. */
OutFileType = svcInterface;
SeqTypeId = 0;
/* Get open connection to (C-preprocessed) input file
and an open output file. */
open←input(infile, define);
sprintf(outfilename, "%s.mesa", outfile);
open←output(infile, outfilename);
/* Emit preamble. */
f←print(fout, "DIRECTORY\n");
f←print(fout, " Rope,\n");
f←print(fout, " Arpa,\n");
if (Imports != NULL) {
for (l = Imports; l != NULL; l = l->next)
f←print(fout, " %s,\n", l->val);
}
f←print(fout, " SunRPCAuth,\n");
if (PCedar) {
if (PCedarUDP)
f←print(fout, " SunRPC;\n\n");
else /* PCedarTCP */
f←print(fout, " SunRPCStream;\n\n");
}
else {
f←print(fout, " %s;\n\n", SunRPC);
}
f←print(fout, "%s: CEDAR DEFINITIONS =\n", svcName);
f←print(fout, "BEGIN\n\n");
f←print(fout, "ROPE: TYPE = Rope.ROPE;\n\n");
/* Emit definitions. */
while (def = get←definition()) {
print←datadef(def);
}
/* Print postamble. */
f←print(fout, "\nEND.");
fclose(fout);
}
/*
* Compile into an RPC service
*/
static
s←output(infile, outfile, define)
char *infile;
char *outfile;
char *define;
{
definition *def;
char outfilename[128];
version←list *vers;
proc←list *proc;
list *l;
long tell;
sleep(1); /* Do this to avoid having the same creation
time on two different files - something that
Cedar can't handle. */
OutFileType = serverImpl;
open←input(infile, define);
sprintf(outfilename, "%s.mesa", outfile);
open←output(infile, outfilename);
f←print(fout, "DIRECTORY\n");
if (PCedarUDP) f←print(fout, " Basics,\n");
if (PCedarTCP) f←print(fout, " Convert,\n");
f←print(fout, " %s,\n", SunRPC);
if (PCedarUDP) f←print(fout, " SunRPCNumbers,\n");
if (PCedar) {
f←print(fout, " SunPMap,\n");
f←print(fout, " SunPMapLocal,\n");
}
f←print(fout, " SunRPCAuth,\n");
f←print(fout, " Rope,\n");
if (Imports != NULL) {
for (l = Imports; l != NULL; l = l->next)
f←print(fout, " %s,\n", l->val);
}
if (GetPutImports != NULL) {
for (l = GetPutImports; l != NULL; l = l->next)
f←print(fout, " %s,\n", l->val);
}
if (TypeDefsExist) f←print(fout, " %sGetPut,\n", svcName);
f←print(fout, " %s;\n\n", svcName);
f←print(fout, "%s: CEDAR PROGRAM\n", outfile);
if (PCedarUDP)
f←print(fout, " IMPORTS Basics, Rope, SunPMapLocal, %s, SunRPCNumbers", SunRPC);
else if (PCedarTCP)
f←print(fout, " IMPORTS Convert, Rope, SunPMapLocal, %s", SunRPC);
else
f←print(fout, " IMPORTS Rope, %s", SunRPC);
if (GetPutImports != NULL) {
for (l = GetPutImports; l != NULL; l = l->next)
f←print(fout, ", %s", l->val);
}
if (TypeDefsExist) f←print(fout, ", %sGetPut\n", svcName);
else f←print(fout, "\n");
f←print(fout, " EXPORTS %s =\n", svcName);
f←print(fout, "BEGIN\n");
f←print(fout, "ROPE: TYPE = Rope.ROPE;\n\n");
f←print(fout, "Handle: TYPE = %s.Handle;\n", SunRPC);
f←print(fout, "Conversation: TYPE = SunRPCAuth.Conversation;\n\n");
f←print(fout, "defaultReplyTTL: CARDINAL ← 10;\n\n");
tell = ftell(fout);
while (def = get←definition()) {
if (def->def←kind == DEF←PROGRAM) {
for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
write←server←prog(svcName, def->def←name, vers);
}
}
}
if (tell == ftell(fout)) {
(void) unlink(outfilename);
return;
}
f←print(fout, "END.\n");
fclose(fout);
}
/*
* generate client side stubs
*/
static
l←output(infile, outfile, define)
char *infile;
char *outfile;
char *define;
{
char *include;
definition *def;
char outfilename[128];
int foundprogram = 0;
list *l;
sleep(1); /* Do this to avoid having the same creation
time on two different files - something that
Cedar can't handle. */
OutFileType = clientImpl;
open←input(infile, define);
sprintf(outfilename, "%s.mesa", outfile);
open←output(infile, outfilename);
f←print(fout, "DIRECTORY\n");
if (PCedar) f←print(fout, " Basics,\n");
if (PCedarTCP) f←print(fout, " Convert,\n");
f←print(fout, " Rope,\n");
f←print(fout, " SunRPC,\n"); /* We always use this because we need to
talk to the PortMapper. */
if (PCedarUDP) f←print(fout, " SunRPCNumbers,\n");
if (PCedarTCP) f←print(fout, " SunRPCStream,\n");
if (PCedar) {
f←print(fout, " SunPMap,\n");
f←print(fout, " SunPMapClient,\n");
}
f←print(fout, " SunRPCAuth,\n");
if (Imports != NULL) {
for (l = Imports; l != NULL; l = l->next)
f←print(fout, " %s,\n", l->val);
}
if (GetPutImports != NULL) {
for (l = GetPutImports; l != NULL; l = l->next)
f←print(fout, " %s,\n", l->val);
}
if (TypeDefsExist) f←print(fout, " %sGetPut,\n",
svcName);
f←print(fout, " %s;\n\n", svcName);
f←print(fout, "%s: CEDAR PROGRAM\n", outfile);
if (PCedarUDP)
f←print(fout, " IMPORTS Basics, SunPMapClient, %s, SunRPCNumbers, SunRPCAuth",
SunRPC);
else if (PCedarTCP)
f←print(fout,
" IMPORTS Basics, Convert, Rope, SunPMapClient, SunRPC, %s, SunRPCAuth",
SunRPC);
else
f←print(fout, " IMPORTS %s", SunRPC);
if (GetPutImports != NULL) {
for (l = GetPutImports; l != NULL; l = l->next)
f←print(fout, ", %s", l->val);
}
if (TypeDefsExist) f←print(fout, ", %sGetPut\n", svcName);
else f←print(fout, "\n");
f←print(fout, " EXPORTS %s =\n", svcName);
f←print(fout, "BEGIN\n");
f←print(fout, "ROPE: TYPE = Rope.ROPE;\n\n");
f←print(fout, "defaultTimeout: CARDINAL ← 2000;\n");
f←print(fout, "defaultRetries: CARDINAL ← 5;\n\n");
while (def = get←definition()) {
foundprogram |= (def->def←kind == DEF←PROGRAM);
}
if (!foundprogram) {
(void) unlink(outfilename);
return;
}
write←stubs(svcName);
f←print(fout, "END.\n");
fclose(fout);
}
/*
* Construct a list of IMPORT statements that must go into each output file.
* Also construct a hash table of symbol definitions encountered.
*/
void MakeSymbolTables(name)
char *name;
{
definition *def;
StringHashElement elem;
case←list *c;
decl←list *d;
Imports = NULL;
GetPutImports = NULL;
ImportNames = StringHashCreate(128, NULL, NULL);
if (ImportNames == NULL) {
fprintf(stderr,
"ERROR: couldn't create hash table for import names.\n");
exit(-1);
}
SymbolNames = StringHashCreate(128, NULL, NULL);
if (SymbolNames == NULL) {
fprintf(stderr,
"ERROR: couldn't create hash table for struct names.\n");
exit(-1);
}
SeqTypes = StringHashCreate(128, NULL, NULL);
if (SeqTypes == NULL) {
fprintf(stderr,
"ERROR: couldn't create hash table for sequence type names.\n");
exit(-1);
}
EnumTypes = StringHashCreate(128, NULL, NULL);
if (EnumTypes == NULL) {
fprintf(stderr,
"ERROR: couldn't create hash table for enum type names.\n");
exit(-1);
}
OutFileType = noFile;
CurrentContext->printDirectives = FALSE;
open←input(name, "-DRPC←HDR");
/* Just run through the file so that all IMPORT directives get seen
by the scanner. */
TypeDefsExist = FALSE;
ProgramsExist = FALSE;
while (def = get←definition()) {
elem = StringHashFind(SymbolNames, def->def←name, insert, NULL);
elem->userData = (char *) def;
switch (def->def←kind) {
case DEF←STRUCT:
case DEF←UNION:
case DEF←TYPEDEF:
case DEF←ENUM:
TypeDefsExist = TRUE;
break;
case DEF←PROGRAM:
ProgramsExist = TRUE;
break;
default:
break;
}
}
reinitialize();
}
/*
* Process IMPORT statements for imported .x files.
*/
void ProcessImport(name)
char *name;
{
Context *save = CurrentContext;
Context import;
char infile[256];
definition *def;
char buf[512];
list *l;
StringHashElement elem;
int inserted;
ImportModuleRec *m;
int foundDefnsFlag = FALSE;
int foundTypeDefsFlag = FALSE;
if (OutFileType != noFile) return;
sprintf(infile, "%s.x", name);
SeqTypeId = 0;
CurrentContext = &import;
reinitialize();
CurrentContext->printDirectives = FALSE;
open←input(infile, "");
name = strdup(name);
while (def = get←definition()) {
elem = StringHashFind(ImportNames, def->def←name, insert, &inserted);
elem->userData = (char *) malloc(sizeof(ImportModuleRec));
m = (ImportModuleRec *) (elem->userData);
m->moduleName = name;
sprintf(buf, "%s.%s", name, StripPrefix(name, def->def←name));
m->defnName = strdup(buf);
elem = StringHashFind(SymbolNames, def->def←name, insert, NULL);
elem->userData = (char *) def;
switch (def->def←kind) {
case DEF←STRUCT:
case DEF←UNION:
case DEF←TYPEDEF:
case DEF←ENUM:
foundDefnsFlag = TRUE;
foundTypeDefsFlag = TRUE;
break;
case DEF←CONST:
foundDefnsFlag = TRUE;
break;
default:
break;
}
CheckForSeqTypes(def, name);
}
if (foundDefnsFlag) {
l = (list *) malloc(sizeof(list));
l->val = name;
l->next = Imports;
Imports = l;
}
if (foundTypeDefsFlag) {
l = (list *) malloc(sizeof(list));
sprintf(buf, "%sGetPut", name);
l->val = strdup(buf);
l->next = GetPutImports;
GetPutImports = l;
}
CurrentContext = save;
}
/*
* Add any SeqType data definitions to the SeqTypes table.
*/
CheckForSeqTypes(def, importName)
definition *def;
char *importName;
{
switch (def->def←kind) {
case DEF←STRUCT:
CheckStructDef(def, importName);
break;
case DEF←UNION:
CheckUnionDef(def, importName);
break;
case DEF←TYPEDEF:
CheckTypeDef(def, importName);
break;
default:
break;
}
}
CheckStructDef(def, importName)
definition *def;
char *importName;
{
decl←list *l;
char *name = def->def←name;
for (l = def->def.st.decls; l != NULL; l = l->next) {
CheckDeclaration(name, &l->decl, importName);
}
}
CheckUnionDef(def, importName)
definition *def;
char *importName;
{
case←list *l;
char *name = def->def←name;
for (l = def->def.un.cases; l != NULL; l = l->next) {
if (!streq(l->case←decl.type, "void")) {
CheckDeclaration(name, &l->case←decl, importName);
}
}
}
CheckTypeDef(def, importName)
definition *def;
char *importName;
{
char *name = def->def←name;
char *old = def->def.ty.old←type;
relation rel = def->def.ty.rel;
char buf[256];
int opaqueFlag = FALSE;
StringHashElement elem;
int inserted;
if (!streq(name, old)) {
if (streq(old, "string")) {
rel = REL←ALIAS;
}
else if (streq(old, "opaque")) {
opaqueFlag = TRUE;
}
if (rel == REL←ARRAY) {
if (!opaqueFlag) {
elem = StringHashFind(SeqTypes,
def->def.ty.old←type,
insert, &inserted);
if (inserted) {
sprintf(buf, "%s.SeqType%d", importName, SeqTypeId);
SeqTypeId++;
elem->userData = strdup(buf);
}
}
}
}
}
CheckDeclaration(name, dec, importName)
char *name;
declaration *dec;
char *importName;
{
StringHashElement elem;
int inserted;
char buf[256];
if (streq(dec->type, "void")) {
return;
}
if (!streq(dec->type, "string")) {
if (dec->rel == REL←ARRAY) {
if (!streq(dec->type, "opaque")) {
sprintf(buf, "%s.%s", name, dec->name);
elem = StringHashFind(SeqTypes, buf,
insert, &inserted);
if (inserted) {
sprintf(buf, "%s.SeqType%d", importName, SeqTypeId);
SeqTypeId++;
elem->userData = strdup(buf);
}
}
}
}
}
/*
* Parse command line arguments
*/
static
parseargs(argc, argv, cmd)
int argc;
char *argv[];
struct commandline *cmd;
{
int i;
int j;
char c;
char flag[(1 << 8 * sizeof(char))];
int nflags;
cmdname = argv[0];
cmd->infile = cmd->outfile = NULL;
if (argc < 2) {
return (0);
}
flag['c'] = 0;
flag['h'] = 0;
flag['l'] = 0;
flag['s'] = 0;
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
if (cmd->infile) {
return (0);
}
cmd->infile = argv[i];
} else {
for (j = 1; argv[i][j] != 0; j++) {
c = argv[i][j];
switch (c) {
case 'c':
case 'h':
case 'l':
if (flag[c]) {
return (0);
}
flag[c] = 1;
break;
case 'P':
if (strcmp(argv[i], "-PCedar") == 0) {
PCedar = 1;
PCedarUDP = 1;
}
else if (strcmp(argv[i], "-PCedarStream") == 0) {
PCedar = 1;
PCedarTCP = 1;
}
else {
return (0);
}
if (PCedarUDP && PCedarTCP) {
fprintf(stderr, "can't specify both PCedar and PCedarStream at the same time\n");
exit(-1);
}
goto nextarg;
case 'o':
if (argv[i][j - 1] != '-' ||
argv[i][j + 1] != 0) {
return (0);
}
if (++i == argc) {
return (0);
}
if (cmd->outfile) {
return (0);
}
cmd->outfile = argv[i];
goto nextarg;
case 'p':
PFlag = TRUE;
break;
case 'e':
ExpandProcArgs = TRUE;
break;
case 'r':
RecoveryFlag = TRUE;
break;
default:
return (0);
}
}
nextarg:
;
}
}
cmd->cflag = flag['c'];
cmd->hflag = flag['h'];
cmd->sflag = flag['s'];
cmd->lflag = flag['l'];
nflags = cmd->cflag + cmd->hflag + cmd->sflag + cmd->lflag;
if (nflags == 0) {
if (cmd->outfile != NULL || cmd->infile == NULL) {
return (0);
}
} else if (nflags > 1) {
return (0);
}
return (1);
}