#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; }