#ifndef lint
static char sccsid[] = "@(#)rpc←util.c 1.1 90/10/29 (C) 1987 SMI";
#endif
/*
* rpc←util.c, Utility routines for the RPC protocol compiler
* Copyright (C) 1987, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <string.h>
#include "rpc←scan.h"
#include "rpc←parse.h"
#include "rpc←util.h"
#define NFILES 5
char *outfiles[NFILES]; /* output file names */
int nfiles;
FILE *fout; /* file pointer of current output */
/*
* Reinitialize the world
*/
reinitialize()
{
bzero(CurrentContext->curline, MAXLINESIZE);
CurrentContext->where = CurrentContext->curline;
CurrentContext->linenum = 0;
CurrentContext->defined = NULL;
CurrentContext->printDirectives = TRUE;
CurrentProgNameFlag = -1;
}
/*
* string equality
*/
streq(a, b)
char *a;
char *b;
{
return (strcmp(a, b) == 0);
}
/*
* find a value in a list
*/
char *
findval(lst, val, cmp)
list *lst;
char *val;
int (*cmp) ();
{
for (; lst != NULL; lst = lst->next) {
if ((*cmp) (lst->val, val)) {
return (lst->val);
}
}
return (NULL);
}
/*
* store a value in a list
*/
void
storeval(lstp, val)
list **lstp;
char *val;
{
list **l;
list *lst;
for (l = lstp; *l != NULL; l = (list **) & (*l)->next);
lst = ALLOC(list);
lst->val = val;
lst->next = NULL;
*l = lst;
}
static
findit(def, type)
definition *def;
char *type;
{
return (streq(def->def←name, type));
}
static char *
fixit(type, orig)
char *type;
char *orig;
{
definition *def;
def = (definition *) FINDVAL(CurrentContext->defined, type, findit);
if (def == NULL || def->def←kind != DEF←TYPEDEF) {
return (orig);
}
switch (def->def.ty.rel) {
case REL←VECTOR:
return (def->def.ty.old←type);
case REL←ALIAS:
return (fixit(def->def.ty.old←type, orig));
default:
return (orig);
}
}
char *
fixtype(type)
char *type;
{
return (fixit(type, type));
}
char *
stringfix(type)
char *type;
{
if (streq(type, "string")) {
return ("wrapstring");
} else {
return (type);
}
}
void
ptype(prefix, type, follow)
char *prefix;
char *type;
int follow;
{
if (prefix != NULL) {
if (streq(prefix, "enum")) {
f←print(fout, "enum ");
} else {
f←print(fout, "struct ");
}
}
if (streq(type, "bool")) {
f←print(fout, "bool←t ");
} else if (streq(type, "string")) {
f←print(fout, "char *");
} else {
f←print(fout, "%s ", follow ? fixtype(type) : type);
}
}
static
typedefed(def, type)
definition *def;
char *type;
{
if (def->def←kind != DEF←TYPEDEF || def->def.ty.old←prefix != NULL) {
return (0);
} else {
return (streq(def->def←name, type));
}
}
isvectordef(type, rel)
char *type;
relation rel;
{
definition *def;
for (;;) {
switch (rel) {
case REL←VECTOR:
return (!streq(type, "string"));
case REL←ARRAY:
return (0);
case REL←POINTER:
return (0);
case REL←ALIAS:
def = (definition *) FINDVAL(CurrentContext->defined,
type, typedefed);
if (def == NULL) {
return (0);
}
type = def->def.ty.old←type;
rel = def->def.ty.rel;
}
}
}
char *
locase(str)
char *str;
{
char c;
static char buf[100];
char *p = buf;
while (c = *str++) {
*p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
}
*p = 0;
return (buf);
}
void
pvname(pname, vnum)
char *pname;
char *vnum;
{
f←print(fout, "%s←%s", locase(pname), vnum);
}
/*
* print a useful (?) error message, and then die
*/
void
error(msg)
char *msg;
{
printwhere();
f←print(stderr, "%s, line %d: ",
CurrentContext->infilename, CurrentContext->linenum);
f←print(stderr, "%s\n", msg);
crash();
}
/*
* Something went wrong, unlink any files that we may have created and then
* die.
*/
crash()
{
int i;
for (i = 0; i < nfiles; i++) {
(void) unlink(outfiles[i]);
}
exit(1);
}
void
record←open(file)
char *file;
{
if (nfiles < NFILES) {
outfiles[nfiles++] = file;
} else {
f←print(stderr, "too many files!\n");
crash();
}
}
static char expectbuf[100];
static char *toktostr();
/*
* error, token encountered was not the expected one
*/
void
expected1(exp1)
tok←kind exp1;
{
s←print(expectbuf, "expected '%s'",
toktostr(exp1));
error(expectbuf);
}
/*
* error, token encountered was not one of two expected ones
*/
void
expected2(exp1, exp2)
tok←kind exp1, exp2;
{
s←print(expectbuf, "expected '%s' or '%s'",
toktostr(exp1),
toktostr(exp2));
error(expectbuf);
}
/*
* error, token encountered was not one of 3 expected ones
*/
void
expected3(exp1, exp2, exp3)
tok←kind exp1, exp2, exp3;
{
s←print(expectbuf, "expected '%s', '%s' or '%s'",
toktostr(exp1),
toktostr(exp2),
toktostr(exp3));
error(expectbuf);
}
void
tabify(f, tab)
FILE *f;
int tab;
{
while (tab--) {
(void) fputc('\t', f);
}
}
static token tokstrings[] = {
{TOK←IDENT, "identifier"},
{TOK←CONST, "const"},
{TOK←RPAREN, ")"},
{TOK←LPAREN, "("},
{TOK←RBRACE, "}"},
{TOK←LBRACE, "{"},
{TOK←LBRACKET, "["},
{TOK←RBRACKET, "]"},
{TOK←STAR, "*"},
{TOK←COMMA, ","},
{TOK←EQUAL, "="},
{TOK←COLON, ":"},
{TOK←SEMICOLON, ";"},
{TOK←UNION, "union"},
{TOK←STRUCT, "struct"},
{TOK←SWITCH, "switch"},
{TOK←CASE, "case"},
{TOK←DEFAULT, "default"},
{TOK←ENUM, "enum"},
{TOK←TYPEDEF, "typedef"},
{TOK←INT, "int"},
{TOK←SHORT, "short"},
{TOK←LONG, "long"},
{TOK←UNSIGNED, "unsigned"},
{TOK←DOUBLE, "double"},
{TOK←FLOAT, "float"},
{TOK←CHAR, "char"},
{TOK←STRING, "string"},
{TOK←OPAQUE, "opaque"},
{TOK←BOOL, "bool"},
{TOK←VOID, "void"},
{TOK←PROGRAM, "program"},
{TOK←VERSION, "version"},
{TOK←EOF, "??????"}
};
static char *
toktostr(kind)
tok←kind kind;
{
token *sp;
for (sp = tokstrings; sp->kind != TOK←EOF && sp->kind != kind; sp++);
return (sp->str);
}
static
printbuf()
{
char c;
int i;
int cnt;
# define TABSIZE 4
for (i = 0; c = CurrentContext->curline[i]; i++) {
if (c == '\t') {
cnt = 8 - (i % TABSIZE);
c = ' ';
} else {
cnt = 1;
}
while (cnt--) {
(void) fputc(c, stderr);
}
}
}
static
printwhere()
{
int i;
char c;
int cnt;
printbuf();
for (i = 0; i < CurrentContext->where - CurrentContext->curline; i++) {
c = CurrentContext->curline[i];
if (c == '\t') {
cnt = 8 - (i % TABSIZE);
} else {
cnt = 1;
}
while (cnt--) {
(void) fputc('↑', stderr);
}
}
(void) fputc('\n', stderr);
}
/*
* Return the module name for a given defn.
*/
char *ModuleName(defn)
char *defn;
{
StringHashElement importElem;
ImportModuleRec *m;
importElem = StringHashFind(ImportNames, defn, find, NULL);
if (importElem != NULL) {
m = (ImportModuleRec *) importElem->userData;
return (m->moduleName);
}
else
return (svcName);
}
/*
* Return the getput module name for a given defn, followed by a period.
* If it is the name of the getput module for the service we are currently
* compiling then return the "" string if defaultFlag is TRUE.
*/
char *GetPutModuleName(defn, defaultFlag)
char *defn;
int defaultFlag;
{
StringHashElement importElem;
ImportModuleRec *m;
char buf[256];
importElem = StringHashFind(ImportNames, defn, find, NULL);
if (importElem != NULL) {
m = (ImportModuleRec *) importElem->userData;
sprintf(buf, "%sGetPut.", m->moduleName);
return (strdup(buf));
}
else if (defaultFlag)
return ("");
else {
sprintf(buf, "%sGetPut.", svcName);
return (strdup(buf));
}
}
/*
* Map from an rpcgen name to a Cedar name.
*/
char *MapToCedarName(name, defaultFlag)
char *name;
int defaultFlag;
{
StringHashElement importElem;
ImportModuleRec *m;
char buf[256];
char *newName;
importElem = StringHashFind(ImportNames, name, find, NULL);
if (importElem != NULL) {
m = (ImportModuleRec *) importElem->userData;
newName = m->defnName;
}
else if (defaultFlag) {
newName = name;
}
else {
sprintf(buf, "%s.%s", svcName, name);
newName = strdup(buf);
}
return (newName);
}
/*
* Map from an rpcgen type name to an Cedar type name.
*/
char *MapToCedarType(type, defaultFlag)
char *type;
int defaultFlag;
{
if (streq(type, "int") || streq(type, "long"))
return ("INT32");
else if (streq(type, "string"))
return ("ROPE");
else if (streq(type, "bool"))
return ("BOOLEAN");
else if (streq(type, "char"))
return ("BYTE");
else if (streq(type, "u←int") ||
streq(type, "uint") ||
streq(type, "u←long") ||
streq(type, "ulong"))
return ("CARD32");
else if (streq(type, "u←short") ||
streq(type, "ushort"))
return ("CARD16");
else if (streq(type, "u←char") ||
streq(type, "uchar"))
return ("BYTE");
else if (streq(type, "short"))
return ("INT16");
else if (streq(type, "float"))
return ("REAL");
else if (streq(type, "double"))
return ("DREAL");
else if (streq(type, "opaque"))
return ("REF ARRAY OF CHAR");
else if (streq(type, "~0"))
return ("LAST(INTEGER)");
else {
if (isdigit(type[0]))
return type;
else
return (MapToCedarName(type, defaultFlag));
}
}
/*
* Return the Cedar source/sink method type for an rpcgen type.
* Returns NULL if there is none.
*/
char *rpcgenBaseType(type)
char *type;
{
if (streq(type, "int") || streq(type, "long"))
return ("Int32");
else if (streq(type, "string"))
return ("Rope");
else if (streq(type, "bool"))
return ("Int32");
else if (streq(type, "char"))
return ("Byte");
else if (streq(type, "u←int") ||
streq(type, "uint") ||
streq(type, "u←long") ||
streq(type, "ulong"))
return ("Card32");
else if (streq(type, "u←short") ||
streq(type, "ushort"))
return ("Card32");
else if (streq(type, "u←char") ||
streq(type, "uchar"))
return ("Byte");
else if (streq(type, "short"))
return ("Int32");
else if (streq(type, "float"))
return ("Real");
else if (streq(type, "double"))
return ("DReal");
else
return (NULL);
}
/*
* Return the appropriate array index number string.
* If array←max is a number then return that.
* If array←max is an identifier then return the appropriate Cedar
* identifier name (which may include a module name).
*/
char *ArrayMax(numStr, defaultFlag)
char *numStr;
int defaultFlag;
{
char *str;
char buf[256];
int n = atoi(numStr);
if (n == 0) {
str = MapToCedarType(numStr, defaultFlag);
return (strdup(str));
}
else {
sprintf(buf, "%d", n);
return (strdup(buf));
}
}
/*
* Return the base type of a definition.
*/
definition *BaseType(def)
definition *def;
{
StringHashElement elem;
while (def->def←kind == DEF←TYPEDEF) {
elem = StringHashFind(SymbolNames, def->def.ty.old←type, find, NULL);
if (elem == NULL) break;
def = (definition *) (elem->userData);
}
return def;
}
/*
* Return the base type of a struct definition.
* If typeName is not the name of a struct defn then return NULL.
*/
definition *FindStructDefn(typeName)
{
StringHashElement elem;
definition *defStruct;
elem = StringHashFind(SymbolNames, typeName, find, NULL);
if (elem != NULL) {
defStruct = (definition *) (elem->userData);
defStruct = BaseType(defStruct);
if (defStruct->def←kind == DEF←STRUCT)
return (defStruct);
}
return NULL;
}
/*
* Return a unique name that is different from any of the names in dl.
*/
char *FindUniqueName(name, dl)
char *name;
decl←list *dl;
{
char *newname = name;
int indx = 0;
char buf[128];
L:
for (; dl != NULL; dl = dl->next) {
if (streq(newname, dl->decl.name)) {
sprintf(buf, "%s%d", name, indx++);
newname = buf;
goto L;
}
}
return (strdup(newname));
}
/*
* Strip module name prefix off name if there is one.
*/
char *
StripPrefix(module, str)
char *module;
char *str;
{
char *p;
char namePrefix[128];
int namePrefixLen;
if (PFlag) {
sprintf(namePrefix, "%s", module);
namePrefixLen = strlen(namePrefix);
if (strncmp(str, namePrefix, namePrefixLen) == 0)
return (str + namePrefixLen);
else
return str;
}
else {
return str;
}
}
/*
* Make sure all the assignment fields of "l" have meaningful values.
* Return an indication of whether the enumerated type is a compact, 0-based
* enumeration or not.
*/
int
FillEnumAssignments(l)
enumval←list *l;
{
char buf[64];
int val, prevVal;
int i, minVal, maxVal, nVals;
if (l->assignment == NULL) {
l->assignment = "0";
}
prevVal = 0;
minVal = maxVal = atoi(l->assignment);
nVals = 0;
for (; l != NULL; l = l->next) {
if (l->assignment == NULL) {
sprintf(buf, "%d", prevVal + 1);
l->assignment = strdup(buf);
}
prevVal = atoi(l->assignment);
if (prevVal < minVal) minVal = prevVal;
if (prevVal > maxVal) maxVal = prevVal;
nVals++;
}
if ((minVal == 0) && (maxVal == (nVals - 1))) {
return 1;
}
else {
return 0;
}
}
/*
* Return TRUE if the type of decl is "int" or "unsigned int".
*/
int NumericEnumType(type)
char *type;
{
if (streq(type, "int") ||
streq(type, "u←int") ||
streq(type, "uint"))
return (TRUE);
else
return (FALSE);
}
/*
* Returns a comma-separated list of enum element names that correspond
* to the default case of a union and a null-terminated array of such
* element names.
*/
char *DefaultEnumTypes(def, namesArray)
definition *def;
char *namesArray[];
{
StringHashElement elem;
list *l;
case←list *cl;
char *names[256];
int n = 0;
int i, j;
static char str[256];
elem = StringHashFind(EnumTypes, def->def.un.enum←decl.type, find, NULL);
if (elem == NULL) return "";
for (l = (list *) elem->userData; l != NULL; l = l->next) {
names[n++] = l->val;
}
names[n] = NULL;
for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
for (i = 0; i < n; i++) {
if (streq(names[i], cl->case←name)) {
names[i] = "";
break;
}
}
}
str[0] = '\0';
for (i = 0, j = 0; i < n; i++) {
if (!streq(names[i], "")) {
strcat(str, names[i]);
strcat(str, ", ");
namesArray[j++] = names[i];
}
}
str[strlen(str)-2] = '\0';
namesArray[j] = NULL;
return str;
}