entered into RCS
authorroland <roland>
Mon, 7 Feb 1994 03:15:41 +0000 (03:15 +0000)
committerroland <roland>
Mon, 7 Feb 1994 03:15:41 +0000 (03:15 +0000)
sunrpc/rpc_clntout.c [new file with mode: 0644]
sunrpc/rpc_cout.c [new file with mode: 0644]
sunrpc/rpc_hout.c [new file with mode: 0644]
sunrpc/rpc_main.c [new file with mode: 0644]
sunrpc/rpc_parse.c [new file with mode: 0644]
sunrpc/rpc_parse.h [new file with mode: 0644]
sunrpc/rpc_scan.c [new file with mode: 0644]
sunrpc/rpc_scan.h [new file with mode: 0644]
sunrpc/rpc_svcout.c [new file with mode: 0644]
sunrpc/rpc_util.c [new file with mode: 0644]

diff --git a/sunrpc/rpc_clntout.c b/sunrpc/rpc_clntout.c
new file mode 100644 (file)
index 0000000..555681b
--- /dev/null
@@ -0,0 +1,126 @@
+/* @(#)rpc_clntout.c   2.1 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#ifndef lint
+static char sccsid[] = "@(#)rpc_clntout.c 1.2 87/06/24 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsytsems, Inc.
+ */
+#include <stdio.h>
+#include <strings.h>
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+#define DEFAULT_TIMEOUT 25     /* in seconds */
+
+void
+write_stubs()
+{
+       list *l;
+       definition *def;
+
+       f_print(fout,
+               "\n/* Default timeout can be changed using clnt_control() */\n");
+       f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
+               DEFAULT_TIMEOUT);
+       for (l = defined; l != NULL; l = l->next) {
+               def = (definition *) l->val;
+               if (def->def_kind == DEF_PROGRAM) {
+                       write_program(def);
+               }
+       }
+}
+
+
+static
+write_program(def)
+       definition *def;
+{
+       version_list *vp;
+       proc_list *proc;
+
+       for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+               for (proc = vp->procs; proc != NULL; proc = proc->next) {
+                       f_print(fout, "\n");
+                       ptype(proc->res_prefix, proc->res_type, 1);
+                       f_print(fout, "*\n");
+                       pvname(proc->proc_name, vp->vers_num);
+                       f_print(fout, "(argp, clnt)\n");
+                       f_print(fout, "\t");
+                       ptype(proc->arg_prefix, proc->arg_type, 1);
+                       f_print(fout, "*argp;\n");
+                       f_print(fout, "\tCLIENT *clnt;\n");
+                       f_print(fout, "{\n");
+                       printbody(proc);
+                       f_print(fout, "}\n\n");
+               }
+       }
+}
+
+static char *
+ampr(type)
+       char *type;
+{
+       if (isvectordef(type, REL_ALIAS)) {
+               return ("");
+       } else {
+               return ("&");
+       }
+}
+
+static
+printbody(proc)
+       proc_list *proc;
+{
+       f_print(fout, "\tstatic ");
+       if (streq(proc->res_type, "void")) {
+               f_print(fout, "char ");
+       } else {
+               ptype(proc->res_prefix, proc->res_type, 0);
+       }
+       f_print(fout, "res;\n");
+       f_print(fout, "\n");
+       f_print(fout, "\tbzero((char *)%sres, sizeof(res));\n",
+               ampr(proc->res_type));
+       f_print(fout,
+               "\tif (clnt_call(clnt, %s, xdr_%s, argp, xdr_%s, %sres, TIMEOUT) != RPC_SUCCESS) {\n",
+               proc->proc_name, stringfix(proc->arg_type),
+               stringfix(proc->res_type), ampr(proc->res_type));
+       f_print(fout, "\t\treturn (NULL);\n");
+       f_print(fout, "\t}\n");
+       if (streq(proc->res_type, "void")) {
+               f_print(fout, "\treturn ((void *)%sres);\n",
+                       ampr(proc->res_type));
+       } else {
+               f_print(fout, "\treturn (%sres);\n", ampr(proc->res_type));
+       }
+}
diff --git a/sunrpc/rpc_cout.c b/sunrpc/rpc_cout.c
new file mode 100644 (file)
index 0000000..86d3865
--- /dev/null
@@ -0,0 +1,350 @@
+/* @(#)rpc_cout.c      2.1 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#ifndef lint
+static char sccsid[] = "@(#)rpc_cout.c 1.8 87/06/24 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_cout.c, XDR routine outputter for the RPC protocol compiler 
+ * Copyright (C) 1987, Sun Microsystems, Inc. 
+ */
+#include <stdio.h>
+#include <strings.h>
+#include "rpc_util.h"
+#include "rpc_parse.h"
+
+/*
+ * Emit the C-routine for the given definition 
+ */
+void
+emit(def)
+       definition *def;
+{
+       if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) {
+               return;
+       }
+       print_header(def);
+       switch (def->def_kind) {
+       case DEF_UNION:
+               emit_union(def);
+               break;
+       case DEF_ENUM:
+               emit_enum(def);
+               break;
+       case DEF_STRUCT:
+               emit_struct(def);
+               break;
+       case DEF_TYPEDEF:
+               emit_typedef(def);
+               break;
+       }
+       print_trailer();
+}
+
+static
+findtype(def, type)
+       definition *def;
+       char *type;
+{
+       if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) {
+               return (0);
+       } else {
+               return (streq(def->def_name, type));
+       }
+}
+
+static
+undefined(type)
+       char *type;
+{
+       definition *def;
+
+       def = (definition *) FINDVAL(defined, type, findtype);
+       return (def == NULL);
+}
+
+
+static
+print_header(def)
+       definition *def;
+{
+       space();
+       f_print(fout, "bool_t\n");
+       f_print(fout, "xdr_%s(xdrs, objp)\n", def->def_name);
+       f_print(fout, "\tXDR *xdrs;\n");
+       f_print(fout, "\t%s ", def->def_name);
+       if (def->def_kind != DEF_TYPEDEF ||
+           !isvectordef(def->def.ty.old_type, def->def.ty.rel)) {
+               f_print(fout, "*");
+       }
+       f_print(fout, "objp;\n");
+       f_print(fout, "{\n");
+}
+
+static
+print_trailer()
+{
+       f_print(fout, "\treturn (TRUE);\n");
+       f_print(fout, "}\n");
+       space();
+}
+
+
+static
+print_ifopen(indent, name)
+       int indent;
+       char *name;
+{
+       tabify(fout, indent);
+       f_print(fout, "if (!xdr_%s(xdrs", name);
+}
+
+
+static
+print_ifarg(arg)
+       char *arg;
+{
+       f_print(fout, ", %s", arg);
+}
+
+
+static
+print_ifsizeof(prefix, type)
+       char *prefix;
+       char *type;
+{
+       if (streq(type, "bool")) {
+               f_print(fout, ", sizeof(bool_t), xdr_bool");
+       } else {
+               f_print(fout, ", sizeof(");
+               if (undefined(type) && prefix) {
+                       f_print(fout, "%s ", prefix);
+               }
+               f_print(fout, "%s), xdr_%s", type, type);
+       }
+}
+
+static
+print_ifclose(indent)
+       int indent;
+{
+       f_print(fout, ")) {\n");
+       tabify(fout, indent);
+       f_print(fout, "\treturn (FALSE);\n");
+       tabify(fout, indent);
+       f_print(fout, "}\n");
+}
+
+static
+space()
+{
+       f_print(fout, "\n\n");
+}
+
+static
+print_ifstat(indent, prefix, type, rel, amax, objname, name)
+       int indent;
+       char *prefix;
+       char *type;
+       relation rel;
+       char *amax;
+       char *objname;
+       char *name;
+{
+       char *alt = NULL;
+
+       switch (rel) {
+       case REL_POINTER:
+               print_ifopen(indent, "pointer");
+               print_ifarg("(char **)");
+               f_print(fout, "%s", objname);
+               print_ifsizeof(prefix, type);
+               break;
+       case REL_VECTOR:
+               if (streq(type, "string")) {
+                       alt = "string";
+               } else if (streq(type, "opaque")) {
+                       alt = "opaque";
+               }
+               if (alt) {
+                       print_ifopen(indent, alt);
+                       print_ifarg(objname);
+               } else {
+                       print_ifopen(indent, "vector");
+                       print_ifarg("(char *)");
+                       f_print(fout, "%s", objname);
+               }
+               print_ifarg(amax);
+               if (!alt) {
+                       print_ifsizeof(prefix, type);
+               }
+               break;
+       case REL_ARRAY:
+               if (streq(type, "string")) {
+                       alt = "string";
+               } else if (streq(type, "opaque")) {
+                       alt = "bytes";
+               }
+               if (streq(type, "string")) {
+                       print_ifopen(indent, alt);
+                       print_ifarg(objname);
+               } else {
+                       if (alt) {
+                               print_ifopen(indent, alt);
+                       } else {
+                               print_ifopen(indent, "array");
+                       }
+                       print_ifarg("(char **)");
+                       if (*objname == '&') {
+                               f_print(fout, "%s.%s_val, (u_int *)%s.%s_len",
+                                       objname, name, objname, name);
+                       } else {
+                               f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len",
+                                       objname, name, objname, name);
+                       }
+               }
+               print_ifarg(amax);
+               if (!alt) {
+                       print_ifsizeof(prefix, type);
+               }
+               break;
+       case REL_ALIAS:
+               print_ifopen(indent, type);
+               print_ifarg(objname);
+               break;
+       }
+       print_ifclose(indent);
+}
+
+
+/* ARGSUSED */
+static
+emit_enum(def)
+       definition *def;
+{
+       print_ifopen(1, "enum");
+       print_ifarg("(enum_t *)objp");
+       print_ifclose(1);
+}
+
+
+static
+emit_union(def)
+       definition *def;
+{
+       declaration *dflt;
+       case_list *cl;
+       declaration *cs;
+       char *object;
+       char *format = "&objp->%s_u.%s";
+
+       print_stat(&def->def.un.enum_decl);
+       f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
+       for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
+               cs = &cl->case_decl;
+               f_print(fout, "\tcase %s:\n", cl->case_name);
+               if (!streq(cs->type, "void")) {
+                       object = alloc(strlen(def->def_name) + strlen(format) +
+                                      strlen(cs->name) + 1);
+                       s_print(object, format, def->def_name, cs->name);
+                       print_ifstat(2, cs->prefix, cs->type, cs->rel, cs->array_max,
+                                    object, cs->name);
+                       free(object);
+               }
+               f_print(fout, "\t\tbreak;\n");
+       }
+       dflt = def->def.un.default_decl;
+       if (dflt != NULL) {
+               if (!streq(dflt->type, "void")) {
+                       f_print(fout, "\tdefault:\n");
+                       object = alloc(strlen(def->def_name) + strlen(format) +
+                                      strlen(dflt->name) + 1);
+                       s_print(object, format, def->def_name, dflt->name);
+                       print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
+                                    dflt->array_max, object, dflt->name);
+                       free(object);
+                       f_print(fout, "\t\tbreak;\n");
+               }
+       } else {
+               f_print(fout, "\tdefault:\n");
+               f_print(fout, "\t\treturn (FALSE);\n");
+       }
+       f_print(fout, "\t}\n");
+}
+
+
+
+static
+emit_struct(def)
+       definition *def;
+{
+       decl_list *dl;
+
+       for (dl = def->def.st.decls; dl != NULL; dl = dl->next) {
+               print_stat(&dl->decl);
+       }
+}
+
+
+
+
+static
+emit_typedef(def)
+       definition *def;
+{
+       char *prefix = def->def.ty.old_prefix;
+       char *type = def->def.ty.old_type;
+       char *amax = def->def.ty.array_max;
+       relation rel = def->def.ty.rel;
+
+       print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
+}
+
+
+
+
+
+static
+print_stat(dec)
+       declaration *dec;
+{
+       char *prefix = dec->prefix;
+       char *type = dec->type;
+       char *amax = dec->array_max;
+       relation rel = dec->rel;
+       char name[256];
+
+       if (isvectordef(type, rel)) {
+               s_print(name, "objp->%s", dec->name);
+       } else {
+               s_print(name, "&objp->%s", dec->name);
+       }
+       print_ifstat(1, prefix, type, rel, amax, name, dec->name);
+}
diff --git a/sunrpc/rpc_hout.c b/sunrpc/rpc_hout.c
new file mode 100644 (file)
index 0000000..1bf0097
--- /dev/null
@@ -0,0 +1,370 @@
+/* @(#)rpc_hout.c      2.1 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#ifndef lint
+static char sccsid[] = "@(#)rpc_hout.c 1.6 87/07/28 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_hout.c, Header file outputter for the RPC protocol compiler 
+ * Copyright (C) 1987, Sun Microsystems, Inc. 
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include "rpc_util.h"
+#include "rpc_parse.h"
+
+
+/*
+ * Print the C-version of an xdr definition 
+ */
+void
+print_datadef(def)
+       definition *def;
+{
+       if (def->def_kind != DEF_CONST) {
+               f_print(fout, "\n");
+       }
+       switch (def->def_kind) {
+       case DEF_STRUCT:
+               pstructdef(def);
+               break;
+       case DEF_UNION:
+               puniondef(def);
+               break;
+       case DEF_ENUM:
+               penumdef(def);
+               break;
+       case DEF_TYPEDEF:
+               ptypedef(def);
+               break;
+       case DEF_PROGRAM:
+               pprogramdef(def);
+               break;
+       case DEF_CONST:
+               pconstdef(def);
+               break;
+       }
+       if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) {
+               f_print(fout, "bool_t xdr_%s();\n", def->def_name);
+       }
+       if (def->def_kind != DEF_CONST) {
+               f_print(fout, "\n");
+       }
+}
+
+static
+pconstdef(def)
+       definition *def;
+{
+       pdefine(def->def_name, def->def.co);
+}
+
+static
+pstructdef(def)
+       definition *def;
+{
+       decl_list *l;
+       char *name = def->def_name;
+
+       f_print(fout, "struct %s {\n", name);
+       for (l = def->def.st.decls; l != NULL; l = l->next) {
+               pdeclaration(name, &l->decl, 1);
+       }
+       f_print(fout, "};\n");
+       f_print(fout, "typedef struct %s %s;\n", name, name);
+}
+
+static
+puniondef(def)
+       definition *def;
+{
+       case_list *l;
+       char *name = def->def_name;
+       declaration *decl;
+
+       f_print(fout, "struct %s {\n", name);
+       decl = &def->def.un.enum_decl;
+       if (streq(decl->type, "bool")) {
+               f_print(fout, "\tbool_t %s;\n", decl->name);
+       } else {
+               f_print(fout, "\t%s %s;\n", decl->type, decl->name);
+       }
+       f_print(fout, "\tunion {\n");
+       for (l = def->def.un.cases; l != NULL; l = l->next) {
+               pdeclaration(name, &l->case_decl, 2);
+       }
+       decl = def->def.un.default_decl;
+       if (decl && !streq(decl->type, "void")) {
+               pdeclaration(name, decl, 2);
+       }
+       f_print(fout, "\t} %s_u;\n", name);
+       f_print(fout, "};\n");
+       f_print(fout, "typedef struct %s %s;\n", name, name);
+}
+
+
+
+static
+pdefine(name, num)
+       char *name;
+       char *num;
+{
+       f_print(fout, "#define %s %s\n", name, num);
+}
+
+static
+puldefine(name, num)
+       char *name;
+       char *num;
+{
+       f_print(fout, "#define %s ((u_long)%s)\n", name, num);
+}
+
+static
+define_printed(stop, start)
+       proc_list *stop;
+       version_list *start;
+{
+       version_list *vers;
+       proc_list *proc;
+
+       for (vers = start; vers != NULL; vers = vers->next) {
+               for (proc = vers->procs; proc != NULL; proc = proc->next) {
+                       if (proc == stop) {
+                               return (0);
+                       } else if (streq(proc->proc_name, stop->proc_name)) {
+                               return (1);
+                       }
+               }
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+
+static
+pprogramdef(def)
+       definition *def;
+{
+       version_list *vers;
+       proc_list *proc;
+
+       puldefine(def->def_name, def->def.pr.prog_num);
+       for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
+               puldefine(vers->vers_name, vers->vers_num);
+               for (proc = vers->procs; proc != NULL; proc = proc->next) {
+                       if (!define_printed(proc, def->def.pr.versions)) {
+                               puldefine(proc->proc_name, proc->proc_num);
+                       }
+                       pprocdef(proc, vers);
+               }
+       }
+}
+
+
+pprocdef(proc, vp)
+       proc_list *proc;
+       version_list *vp;
+{
+       f_print(fout, "extern ");
+       if (proc->res_prefix) {
+               if (streq(proc->res_prefix, "enum")) {
+                       f_print(fout, "enum ");
+               } else {
+                       f_print(fout, "struct ");
+               }
+       }
+       if (streq(proc->res_type, "bool")) {
+               f_print(fout, "bool_t *");
+       } else if (streq(proc->res_type, "string")) {
+               f_print(fout, "char **");
+       } else {
+               f_print(fout, "%s *", fixtype(proc->res_type));
+       }
+       pvname(proc->proc_name, vp->vers_num);
+       f_print(fout, "();\n");
+}
+
+static
+penumdef(def)
+       definition *def;
+{
+       char *name = def->def_name;
+       enumval_list *l;
+       char *last = NULL;
+       int count = 0;
+
+       f_print(fout, "enum %s {\n", name);
+       for (l = def->def.en.vals; l != NULL; l = l->next) {
+               f_print(fout, "\t%s", l->name);
+               if (l->assignment) {
+                       f_print(fout, " = %s", l->assignment);
+                       last = l->assignment;
+                       count = 1;
+               } else {
+                       if (last == NULL) {
+                               f_print(fout, " = %d", count++);
+                       } else {
+                               f_print(fout, " = %s + %d", last, count++);
+                       }
+               }
+               f_print(fout, ",\n");
+       }
+       f_print(fout, "};\n");
+       f_print(fout, "typedef enum %s %s;\n", name, name);
+}
+
+static
+ptypedef(def)
+       definition *def;
+{
+       char *name = def->def_name;
+       char *old = def->def.ty.old_type;
+       char prefix[8]; /* enough to contain "struct ", including NUL */
+       relation rel = def->def.ty.rel;
+
+
+       if (!streq(name, old)) {
+               if (streq(old, "string")) {
+                       old = "char";
+                       rel = REL_POINTER;
+               } else if (streq(old, "opaque")) {
+                       old = "char";
+               } else if (streq(old, "bool")) {
+                       old = "bool_t";
+               }
+               if (undefined2(old, name) && def->def.ty.old_prefix) {
+                       s_print(prefix, "%s ", def->def.ty.old_prefix);
+               } else {
+                       prefix[0] = 0;
+               }
+               f_print(fout, "typedef ");
+               switch (rel) {
+               case REL_ARRAY:
+                       f_print(fout, "struct {\n");
+                       f_print(fout, "\tu_int %s_len;\n", name);
+                       f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name);
+                       f_print(fout, "} %s", name);
+                       break;
+               case REL_POINTER:
+                       f_print(fout, "%s%s *%s", prefix, old, name);
+                       break;
+               case REL_VECTOR:
+                       f_print(fout, "%s%s %s[%s]", prefix, old, name,
+                               def->def.ty.array_max);
+                       break;
+               case REL_ALIAS:
+                       f_print(fout, "%s%s %s", prefix, old, name);
+                       break;
+               }
+               f_print(fout, ";\n");
+       }
+}
+
+
+static
+pdeclaration(name, dec, tab)
+       char *name;
+       declaration *dec;
+       int tab;
+{
+       char buf[8];    /* enough to hold "struct ", include NUL */
+       char *prefix;
+       char *type;
+
+       if (streq(dec->type, "void")) {
+               return;
+       }
+       tabify(fout, tab);
+       if (streq(dec->type, name) && !dec->prefix) {
+               f_print(fout, "struct ");
+       }
+       if (streq(dec->type, "string")) {
+               f_print(fout, "char *%s", dec->name);
+       } else {
+               prefix = "";
+               if (streq(dec->type, "bool")) {
+                       type = "bool_t";
+               } else if (streq(dec->type, "opaque")) {
+                       type = "char";
+               } else {
+                       if (dec->prefix) {
+                               s_print(buf, "%s ", dec->prefix);
+                               prefix = buf;
+                       }
+                       type = dec->type;
+               }
+               switch (dec->rel) {
+               case REL_ALIAS:
+                       f_print(fout, "%s%s %s", prefix, type, dec->name);
+                       break;
+               case REL_VECTOR:
+                       f_print(fout, "%s%s %s[%s]", prefix, type, dec->name,
+                               dec->array_max);
+                       break;
+               case REL_POINTER:
+                       f_print(fout, "%s%s *%s", prefix, type, dec->name);
+                       break;
+               case REL_ARRAY:
+                       f_print(fout, "struct {\n");
+                       tabify(fout, tab);
+                       f_print(fout, "\tu_int %s_len;\n", dec->name);
+                       tabify(fout, tab);
+                       f_print(fout, "\t%s%s *%s_val;\n", prefix, type, dec->name);
+                       tabify(fout, tab);
+                       f_print(fout, "} %s", dec->name);
+                       break;
+               }
+       }
+       f_print(fout, ";\n");
+}
+
+
+
+static
+undefined2(type, stop)
+       char *type;
+       char *stop;
+{
+       list *l;
+       definition *def;
+
+       for (l = defined; l != NULL; l = l->next) {
+               def = (definition *) l->val;
+               if (def->def_kind != DEF_PROGRAM) {
+                       if (streq(def->def_name, stop)) {
+                               return (1);
+                       } else if (streq(def->def_name, type)) {
+                               return (0);
+                       }
+               }
+       }
+       return (1);
+}
diff --git a/sunrpc/rpc_main.c b/sunrpc/rpc_main.c
new file mode 100644 (file)
index 0000000..795bf2a
--- /dev/null
@@ -0,0 +1,433 @@
+/* @(#)rpc_main.c      2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#ifndef lint
+static char sccsid[] = "@(#)rpc_main.c 1.7 87/06/24 (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 <sys/file.h>
+#include "rpc_util.h"
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+
+#define EXTEND 1               /* alias for TRUE */
+
+struct commandline {
+       int cflag;
+       int hflag;
+       int lflag;
+       int sflag;
+       int mflag;
+       char *infile;
+       char *outfile;
+};
+
+static char *cmdname;
+static char CPP[] = "/lib/cpp";
+static char CPPFLAGS[] = "-C";
+static char *allv[] = {
+       "rpcgen", "-s", "udp", "-s", "tcp",
+};
+static int allc = sizeof(allv)/sizeof(allv[0]);
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+
+{
+       struct commandline cmd;
+
+       if (!parseargs(argc, argv, &cmd)) {
+               f_print(stderr,
+                       "usage: %s infile\n", cmdname);
+               f_print(stderr,
+                       "       %s [-c | -h | -l | -m] [-o outfile] [infile]\n",
+                       cmdname);
+               f_print(stderr,
+                       "       %s [-s udp|tcp]* [-o outfile] [infile]\n",
+                       cmdname);
+               exit(1);
+       }
+       if (cmd.cflag) {
+               c_output(cmd.infile, "-DRPC_XDR", !EXTEND, cmd.outfile);
+       } else if (cmd.hflag) {
+               h_output(cmd.infile, "-DRPC_HDR", !EXTEND, cmd.outfile);
+       } else if (cmd.lflag) {
+               l_output(cmd.infile, "-DRPC_CLNT", !EXTEND, cmd.outfile);
+       } else if (cmd.sflag || cmd.mflag) {
+               s_output(argc, argv, cmd.infile, "-DRPC_SVC", !EXTEND,
+                        cmd.outfile, cmd.mflag);
+       } else {
+               c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
+               reinitialize();
+               h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h");
+               reinitialize();
+               l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
+               reinitialize();
+               s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND,
+                        "_svc.c", cmd.mflag);
+       }
+       exit(0);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * Open output file with given extension 
+ */
+static
+open_output(infile, outfile)
+       char *infile;
+       char *outfile;
+{
+       if (outfile == NULL) {
+               fout = stdout;
+               return;
+       }
+       if (infile != NULL && streq(outfile, infile)) {
+               f_print(stderr, "%s: output would overwrite %s\n", cmdname,
+                       infile);
+               crash();
+       }
+       fout = fopen(outfile, "w");
+       if (fout == NULL) {
+               f_print(stderr, "%s: unable to open ", cmdname);
+               perror(outfile);
+               crash();
+       }
+       record_open(outfile);
+}
+
+/*
+ * Open input file with given define for C-preprocessor 
+ */
+static
+open_input(infile, define)
+       char *infile;
+       char *define;
+{
+       int pd[2];
+
+       infilename = (infile == NULL) ? "<stdin>" : infile;
+       (void) pipe(pd);
+       switch (fork()) {
+       case 0:
+               (void) close(1);
+               (void) dup2(pd[1], 1);
+               (void) close(pd[0]);
+               execl(CPP, CPP, CPPFLAGS, define, infile, NULL);
+               perror("execl");
+               exit(1);
+       case -1:
+               perror("fork");
+               exit(1);
+       }
+       (void) close(pd[1]);
+       fin = fdopen(pd[0], "r");
+       if (fin == NULL) {
+               f_print(stderr, "%s: ", cmdname);
+               perror(infilename);
+               crash();
+       }
+}
+
+/*
+ * Compile into an XDR routine output file
+ */
+static
+c_output(infile, define, extend, outfile)
+       char *infile;
+       char *define;
+       int extend;
+       char *outfile;
+{
+       definition *def;
+       char *include;
+       char *outfilename;
+       long tell;
+
+       open_input(infile, define);     
+       outfilename = extend ? extendfile(infile, outfile) : outfile;
+       open_output(infile, outfilename);
+       f_print(fout, "#include <rpc/rpc.h>\n");
+       if (infile && (include = extendfile(infile, ".h"))) {
+               f_print(fout, "#include \"%s\"\n", include);
+               free(include);
+       }
+       tell = ftell(fout);
+       while (def = get_definition()) {
+               emit(def);
+       }
+       if (extend && tell == ftell(fout)) {
+               (void) unlink(outfilename);
+       }
+}
+
+/*
+ * Compile into an XDR header file
+ */
+static
+h_output(infile, define, extend, outfile)
+       char *infile;
+       char *define;
+       int extend;
+       char *outfile;
+{
+       definition *def;
+       char *outfilename;
+       long tell;
+
+       open_input(infile, define);
+       outfilename =  extend ? extendfile(infile, outfile) : outfile;
+       open_output(infile, outfilename);
+       tell = ftell(fout);
+       while (def = get_definition()) {
+               print_datadef(def);
+       }
+       if (extend && tell == ftell(fout)) {
+               (void) unlink(outfilename);
+       }
+}
+
+/*
+ * Compile into an RPC service
+ */
+static
+s_output(argc, argv, infile, define, extend, outfile, nomain)
+       int argc;
+       char *argv[];
+       char *infile;
+       char *define;
+       int extend;
+       char *outfile;
+       int nomain;
+{
+       char *include;
+       definition *def;
+       int foundprogram;
+       char *outfilename;
+
+       open_input(infile, define);
+       outfilename = extend ? extendfile(infile, outfile) : outfile;
+       open_output(infile, outfilename);
+       f_print(fout, "#include <stdio.h>\n");
+       f_print(fout, "#include <rpc/rpc.h>\n");
+       if (infile && (include = extendfile(infile, ".h"))) {
+               f_print(fout, "#include \"%s\"\n", include);
+               free(include);
+       }
+       foundprogram = 0;
+       while (def = get_definition()) {
+               foundprogram |= (def->def_kind == DEF_PROGRAM);
+       }
+       if (extend && !foundprogram) {
+               (void) unlink(outfilename);
+               return;
+       }
+       if (nomain) {
+               write_programs((char *)NULL);
+       } else {
+               write_most();
+               do_registers(argc, argv);
+               write_rest();
+               write_programs("static");
+       }
+}
+
+static
+l_output(infile, define, extend, outfile)
+       char *infile;
+       char *define;
+       int extend;
+       char *outfile;
+{
+       char *include;
+       definition *def;
+       int foundprogram;
+       char *outfilename;
+
+       open_input(infile, define);
+       outfilename = extend ? extendfile(infile, outfile) : outfile;
+       open_output(infile, outfilename);
+       f_print(fout, "#include <rpc/rpc.h>\n");
+       if (infile && (include = extendfile(infile, ".h"))) {
+               f_print(fout, "#include \"%s\"\n", include);
+               free(include);
+       }
+       foundprogram = 0;
+       while (def = get_definition()) {
+               foundprogram |= (def->def_kind == DEF_PROGRAM);
+       }
+       if (extend && !foundprogram) {
+               (void) unlink(outfilename);
+               return;
+       }
+       write_stubs();
+}
+
+/*
+ * Perform registrations for service output 
+ */
+static
+do_registers(argc, argv)
+       int argc;
+       char *argv[];
+
+{
+       int i;
+
+       for (i = 1; i < argc; i++) {
+               if (streq(argv[i], "-s")) {
+                       write_register(argv[i + 1]);
+                       i++;
+               }
+       }
+}
+
+/*
+ * 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['s'] = 0;
+       flag['o'] = 0;
+       flag['l'] = 0;
+       flag['m'] = 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':
+                               case 'm':
+                                       if (flag[c]) {
+                                               return (0);
+                                       }
+                                       flag[c] = 1;
+                                       break;
+                               case 'o':
+                               case 's':
+                                       if (argv[i][j - 1] != '-' || 
+                                           argv[i][j + 1] != 0) {
+                                               return (0);
+                                       }
+                                       flag[c] = 1;
+                                       if (++i == argc) {
+                                               return (0);
+                                       }
+                                       if (c == 's') {
+                                               if (!streq(argv[i], "udp") &&
+                                                   !streq(argv[i], "tcp")) {
+                                                       return (0);
+                                               }
+                                       } else if (c == 'o') {
+                                               if (cmd->outfile) {
+                                                       return (0);
+                                               }
+                                               cmd->outfile = argv[i];
+                                       }
+                                       goto nextarg;
+
+                               default:
+                                       return (0);
+                               }
+                       }
+       nextarg:
+                       ;
+               }
+       }
+       cmd->cflag = flag['c'];
+       cmd->hflag = flag['h'];
+       cmd->sflag = flag['s'];
+       cmd->lflag = flag['l'];
+       cmd->mflag = flag['m'];
+       nflags = cmd->cflag + cmd->hflag + cmd->sflag + cmd->lflag + cmd->mflag;
+       if (nflags == 0) {
+               if (cmd->outfile != NULL || cmd->infile == NULL) {
+                       return (0);
+               }
+       } else if (nflags > 1) {
+               return (0);
+       }
+       return (1);
+}
diff --git a/sunrpc/rpc_parse.c b/sunrpc/rpc_parse.c
new file mode 100644 (file)
index 0000000..9e4663f
--- /dev/null
@@ -0,0 +1,419 @@
+/* @(#)rpc_parse.c     2.1 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#ifndef lint
+static char sccsid[] = "@(#)rpc_parse.c 1.4 87/04/28 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_parse.c, Parser for the RPC protocol compiler 
+ * Copyright (C) 1987 Sun Microsystems, Inc.
+ */
+#include <stdio.h>
+#include "rpc_util.h"
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+
+/*
+ * return the next definition you see
+ */
+definition *
+get_definition()
+{
+       definition *defp;
+       token tok;
+
+       defp = ALLOC(definition);
+       get_token(&tok);
+       switch (tok.kind) {
+       case TOK_STRUCT:
+               def_struct(defp);
+               break;
+       case TOK_UNION:
+               def_union(defp);
+               break;
+       case TOK_TYPEDEF:
+               def_typedef(defp);
+               break;
+       case TOK_ENUM:
+               def_enum(defp);
+               break;
+       case TOK_PROGRAM:
+               def_program(defp);
+               break;
+       case TOK_CONST:
+               def_const(defp);
+               break;
+       case TOK_EOF:
+               return (NULL);
+               break;
+       default:
+               error("definition keyword expected");
+       }
+       scan(TOK_SEMICOLON, &tok);
+       isdefined(defp);
+       return (defp);
+}
+
+static
+isdefined(defp)
+       definition *defp;
+{
+       STOREVAL(&defined, defp);
+}
+
+
+static
+def_struct(defp)
+       definition *defp;
+{
+       token tok;
+       declaration dec;
+       decl_list *decls;
+       decl_list **tailp;
+
+       defp->def_kind = DEF_STRUCT;
+
+       scan(TOK_IDENT, &tok);
+       defp->def_name = tok.str;
+       scan(TOK_LBRACE, &tok);
+       tailp = &defp->def.st.decls;
+       do {
+               get_declaration(&dec, DEF_STRUCT);
+               decls = ALLOC(decl_list);
+               decls->decl = dec;
+               *tailp = decls;
+               tailp = &decls->next;
+               scan(TOK_SEMICOLON, &tok);
+               peek(&tok);
+       } while (tok.kind != TOK_RBRACE);
+       get_token(&tok);
+       *tailp = NULL;
+}
+
+static
+def_program(defp)
+       definition *defp;
+{
+       token tok;
+       version_list *vlist;
+       version_list **vtailp;
+       proc_list *plist;
+       proc_list **ptailp;
+
+       defp->def_kind = DEF_PROGRAM;
+       scan(TOK_IDENT, &tok);
+       defp->def_name = tok.str;
+       scan(TOK_LBRACE, &tok);
+       vtailp = &defp->def.pr.versions;
+       scan(TOK_VERSION, &tok);
+       do {
+               scan(TOK_IDENT, &tok);
+               vlist = ALLOC(version_list);
+               vlist->vers_name = tok.str;
+               scan(TOK_LBRACE, &tok);
+               ptailp = &vlist->procs;
+               do {
+                       plist = ALLOC(proc_list);
+                       get_type(&plist->res_prefix, &plist->res_type, DEF_PROGRAM);
+                       if (streq(plist->res_type, "opaque")) {
+                               error("illegal result type");
+                       }
+                       scan(TOK_IDENT, &tok);
+                       plist->proc_name = tok.str;
+                       scan(TOK_LPAREN, &tok);
+                       get_type(&plist->arg_prefix, &plist->arg_type, DEF_PROGRAM);
+                       if (streq(plist->arg_type, "opaque")) {
+                               error("illegal argument type");
+                       }
+                       scan(TOK_RPAREN, &tok);
+                       scan(TOK_EQUAL, &tok);
+                       scan_num(&tok);
+                       scan(TOK_SEMICOLON, &tok);
+                       plist->proc_num = tok.str;
+                       *ptailp = plist;
+                       ptailp = &plist->next;
+                       peek(&tok);
+               } while (tok.kind != TOK_RBRACE);
+               *vtailp = vlist;
+               vtailp = &vlist->next;
+               scan(TOK_RBRACE, &tok);
+               scan(TOK_EQUAL, &tok);
+               scan_num(&tok);
+               vlist->vers_num = tok.str;
+               scan(TOK_SEMICOLON, &tok);
+               scan2(TOK_VERSION, TOK_RBRACE, &tok);
+       } while (tok.kind == TOK_VERSION);
+       scan(TOK_EQUAL, &tok);
+       scan_num(&tok);
+       defp->def.pr.prog_num = tok.str;
+       *vtailp = NULL;
+}
+
+static
+def_enum(defp)
+       definition *defp;
+{
+       token tok;
+       enumval_list *elist;
+       enumval_list **tailp;
+
+       defp->def_kind = DEF_ENUM;
+       scan(TOK_IDENT, &tok);
+       defp->def_name = tok.str;
+       scan(TOK_LBRACE, &tok);
+       tailp = &defp->def.en.vals;
+       do {
+               scan(TOK_IDENT, &tok);
+               elist = ALLOC(enumval_list);
+               elist->name = tok.str;
+               elist->assignment = NULL;
+               scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
+               if (tok.kind == TOK_EQUAL) {
+                       scan_num(&tok);
+                       elist->assignment = tok.str;
+                       scan2(TOK_COMMA, TOK_RBRACE, &tok);
+               }
+               *tailp = elist;
+               tailp = &elist->next;
+       } while (tok.kind != TOK_RBRACE);
+       *tailp = NULL;
+}
+
+static
+def_const(defp)
+       definition *defp;
+{
+       token tok;
+
+       defp->def_kind = DEF_CONST;
+       scan(TOK_IDENT, &tok);
+       defp->def_name = tok.str;
+       scan(TOK_EQUAL, &tok);
+       scan2(TOK_IDENT, TOK_STRCONST, &tok);
+       defp->def.co = tok.str;
+}
+
+static
+def_union(defp)
+       definition *defp;
+{
+       token tok;
+       declaration dec;
+       case_list *cases;
+       case_list **tailp;
+
+       defp->def_kind = DEF_UNION;
+       scan(TOK_IDENT, &tok);
+       defp->def_name = tok.str;
+       scan(TOK_SWITCH, &tok);
+       scan(TOK_LPAREN, &tok);
+       get_declaration(&dec, DEF_UNION);
+       defp->def.un.enum_decl = dec;
+       tailp = &defp->def.un.cases;
+       scan(TOK_RPAREN, &tok);
+       scan(TOK_LBRACE, &tok);
+       scan(TOK_CASE, &tok);
+       while (tok.kind == TOK_CASE) {
+               scan(TOK_IDENT, &tok);
+               cases = ALLOC(case_list);
+               cases->case_name = tok.str;
+               scan(TOK_COLON, &tok);
+               get_declaration(&dec, DEF_UNION);
+               cases->case_decl = dec;
+               *tailp = cases;
+               tailp = &cases->next;
+               scan(TOK_SEMICOLON, &tok);
+               scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
+       }
+       *tailp = NULL;
+       if (tok.kind == TOK_DEFAULT) {
+               scan(TOK_COLON, &tok);
+               get_declaration(&dec, DEF_UNION);
+               defp->def.un.default_decl = ALLOC(declaration);
+               *defp->def.un.default_decl = dec;
+               scan(TOK_SEMICOLON, &tok);
+               scan(TOK_RBRACE, &tok);
+       } else {
+               defp->def.un.default_decl = NULL;
+       }
+}
+
+
+static
+def_typedef(defp)
+       definition *defp;
+{
+       declaration dec;
+
+       defp->def_kind = DEF_TYPEDEF;
+       get_declaration(&dec, DEF_TYPEDEF);
+       defp->def_name = dec.name;
+       defp->def.ty.old_prefix = dec.prefix;
+       defp->def.ty.old_type = dec.type;
+       defp->def.ty.rel = dec.rel;
+       defp->def.ty.array_max = dec.array_max;
+}
+
+
+static
+get_declaration(dec, dkind)
+       declaration *dec;
+       defkind dkind;
+{
+       token tok;
+
+       get_type(&dec->prefix, &dec->type, dkind);
+       dec->rel = REL_ALIAS;
+       if (streq(dec->type, "void")) {
+               return;
+       }
+       scan2(TOK_STAR, TOK_IDENT, &tok);
+       if (tok.kind == TOK_STAR) {
+               dec->rel = REL_POINTER;
+               scan(TOK_IDENT, &tok);
+       }
+       dec->name = tok.str;
+       if (peekscan(TOK_LBRACKET, &tok)) {
+               if (dec->rel == REL_POINTER) {
+                       error("no array-of-pointer declarations -- use typedef");
+               }
+               dec->rel = REL_VECTOR;
+               scan_num(&tok);
+               dec->array_max = tok.str;
+               scan(TOK_RBRACKET, &tok);
+       } else if (peekscan(TOK_LANGLE, &tok)) {
+               if (dec->rel == REL_POINTER) {
+                       error("no array-of-pointer declarations -- use typedef");
+               }
+               dec->rel = REL_ARRAY;
+               if (peekscan(TOK_RANGLE, &tok)) {
+                       dec->array_max = "~0";  /* unspecified size, use max */
+               } else {
+                       scan_num(&tok);
+                       dec->array_max = tok.str;
+                       scan(TOK_RANGLE, &tok);
+               }
+       }
+       if (streq(dec->type, "opaque")) {
+               if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
+                       error("array declaration expected");
+               }
+       } else if (streq(dec->type, "string")) {
+               if (dec->rel != REL_ARRAY) {
+                       error("variable-length array declaration expected");
+               }
+       }
+}
+
+
+static
+get_type(prefixp, typep, dkind)
+       char **prefixp;
+       char **typep;
+       defkind dkind;
+{
+       token tok;
+
+       *prefixp = NULL;
+       get_token(&tok);
+       switch (tok.kind) {
+       case TOK_IDENT:
+               *typep = tok.str;
+               break;
+       case TOK_STRUCT:
+       case TOK_ENUM:
+       case TOK_UNION:
+               *prefixp = tok.str;
+               scan(TOK_IDENT, &tok);
+               *typep = tok.str;
+               break;
+       case TOK_UNSIGNED:
+               unsigned_dec(typep);
+               break;
+       case TOK_SHORT:
+               *typep = "short";
+               (void) peekscan(TOK_INT, &tok);
+               break;
+       case TOK_LONG:
+               *typep = "long";
+               (void) peekscan(TOK_INT, &tok);
+               break;
+       case TOK_VOID:
+               if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
+                       error("voids allowed only inside union and program definitions");
+               }
+               *typep = tok.str;
+               break;
+       case TOK_STRING:
+       case TOK_OPAQUE:
+       case TOK_CHAR:
+       case TOK_INT:
+       case TOK_FLOAT:
+       case TOK_DOUBLE:
+       case TOK_BOOL:
+               *typep = tok.str;
+               break;
+       default:
+               error("expected type specifier");
+       }
+}
+
+
+static
+unsigned_dec(typep)
+       char **typep;
+{
+       token tok;
+
+       peek(&tok);
+       switch (tok.kind) {
+       case TOK_CHAR:
+               get_token(&tok);
+               *typep = "u_char";
+               break;
+       case TOK_SHORT:
+               get_token(&tok);
+               *typep = "u_short";
+               (void) peekscan(TOK_INT, &tok);
+               break;
+       case TOK_LONG:
+               get_token(&tok);
+               *typep = "u_long";
+               (void) peekscan(TOK_INT, &tok);
+               break;
+       case TOK_INT:
+               get_token(&tok);
+               *typep = "u_int";
+               break;
+       default:
+               *typep = "u_int";
+               break;
+       }
+}
diff --git a/sunrpc/rpc_parse.h b/sunrpc/rpc_parse.h
new file mode 100644 (file)
index 0000000..b53cc56
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/* @(#)rpc_parse.h 1.3 87/03/09 (C) 1987 SMI */
+
+/*
+ * rpc_parse.h, Definitions for the RPCL parser 
+ * Copyright (C) 1987, Sun Microsystems, Inc. 
+ */
+
+enum defkind {
+       DEF_CONST,
+       DEF_STRUCT,
+       DEF_UNION,
+       DEF_ENUM,
+       DEF_TYPEDEF,
+       DEF_PROGRAM
+};
+typedef enum defkind defkind;
+
+typedef char *const_def;
+
+enum relation {
+       REL_VECTOR,     /* fixed length array */
+       REL_ARRAY,      /* variable length array */
+       REL_POINTER,    /* pointer */
+       REL_ALIAS,      /* simple */
+};
+typedef enum relation relation;
+
+struct typedef_def {
+       char *old_prefix;
+       char *old_type;
+       relation rel;
+       char *array_max;
+};
+typedef struct typedef_def typedef_def;
+
+
+struct enumval_list {
+       char *name;
+       char *assignment;
+       struct enumval_list *next;
+};
+typedef struct enumval_list enumval_list;
+
+struct enum_def {
+       enumval_list *vals;
+};
+typedef struct enum_def enum_def;
+
+
+struct declaration {
+       char *prefix;
+       char *type;
+       char *name;
+       relation rel;
+       char *array_max;
+};
+typedef struct declaration declaration;
+
+
+struct decl_list {
+       declaration decl;
+       struct decl_list *next;
+};
+typedef struct decl_list decl_list;
+
+struct struct_def {
+       decl_list *decls;
+};
+typedef struct struct_def struct_def;
+
+
+struct case_list {
+       char *case_name;
+       declaration case_decl;
+       struct case_list *next;
+};
+typedef struct case_list case_list;
+
+struct union_def {
+       declaration enum_decl;
+       case_list *cases;
+       declaration *default_decl;
+};
+typedef struct union_def union_def;
+
+
+
+struct proc_list {
+       char *proc_name;
+       char *proc_num;
+       char *arg_type;
+       char *arg_prefix;
+       char *res_type;
+       char *res_prefix;
+       struct proc_list *next;
+};
+typedef struct proc_list proc_list;
+
+
+struct version_list {
+       char *vers_name;
+       char *vers_num;
+       proc_list *procs;
+       struct version_list *next;
+};
+typedef struct version_list version_list;
+
+struct program_def {
+       char *prog_num;
+       version_list *versions;
+};
+typedef struct program_def program_def;
+
+struct definition {
+       char *def_name;
+       defkind def_kind;
+       union {
+               const_def co;
+               struct_def st;
+               union_def un;
+               enum_def en;
+               typedef_def ty;
+               program_def pr;
+       } def;
+};
+typedef struct definition definition;
+
+/* @(#)rpc_parse.h     2.1 88/08/01 4.0 RPCSRC */
+definition *get_definition();
diff --git a/sunrpc/rpc_scan.c b/sunrpc/rpc_scan.c
new file mode 100644 (file)
index 0000000..e46a1b5
--- /dev/null
@@ -0,0 +1,473 @@
+/* @(#)rpc_scan.c      2.1 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#ifndef lint
+static char sccsid[] = "@(#)rpc_scan.c 1.6 87/06/24 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_scan.c, Scanner for the RPC protocol compiler 
+ * Copyright (C) 1987, Sun Microsystems, Inc. 
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <strings.h>
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+#define startcomment(where) (where[0] == '/' && where[1] == '*')
+#define endcomment(where) (where[-1] == '*' && where[0] == '/')
+
+static int pushed = 0; /* is a token pushed */
+static token lasttok;  /* last token, if pushed */
+
+/*
+ * scan expecting 1 given token 
+ */
+void
+scan(expect, tokp)
+       tok_kind expect;
+       token *tokp;
+{
+       get_token(tokp);
+       if (tokp->kind != expect) {
+               expected1(expect);
+       }
+}
+
+/*
+ * scan expecting 2 given tokens 
+ */
+void
+scan2(expect1, expect2, tokp)
+       tok_kind expect1;
+       tok_kind expect2;
+       token *tokp;
+{
+       get_token(tokp);
+       if (tokp->kind != expect1 && tokp->kind != expect2) {
+               expected2(expect1, expect2);
+       }
+}
+
+/*
+ * scan expecting 3 given token 
+ */
+void
+scan3(expect1, expect2, expect3, tokp)
+       tok_kind expect1;
+       tok_kind expect2;
+       tok_kind expect3;
+       token *tokp;
+{
+       get_token(tokp);
+       if (tokp->kind != expect1 && tokp->kind != expect2
+           && tokp->kind != expect3) {
+               expected3(expect1, expect2, expect3);
+       }
+}
+
+
+/*
+ * scan expecting a constant, possibly symbolic 
+ */
+void
+scan_num(tokp)
+       token *tokp;
+{
+       get_token(tokp);
+       switch (tokp->kind) {
+       case TOK_IDENT:
+               break;
+       default:
+               error("constant or identifier expected");
+       }
+}
+
+
+/*
+ * Peek at the next token 
+ */
+void
+peek(tokp)
+       token *tokp;
+{
+       get_token(tokp);
+       unget_token(tokp);
+}
+
+
+/*
+ * Peek at the next token and scan it if it matches what you expect 
+ */
+int
+peekscan(expect, tokp)
+       tok_kind expect;
+       token *tokp;
+{
+       peek(tokp);
+       if (tokp->kind == expect) {
+               get_token(tokp);
+               return (1);
+       }
+       return (0);
+}
+
+
+
+/*
+ * Get the next token, printing out any directive that are encountered. 
+ */
+void
+get_token(tokp)
+       token *tokp;
+{
+       int commenting;
+
+       if (pushed) {
+               pushed = 0;
+               *tokp = lasttok;
+               return;
+       }
+       commenting = 0;
+       for (;;) {
+               if (*where == 0) {
+                       for (;;) {
+                               if (!fgets(curline, MAXLINESIZE, fin)) {
+                                       tokp->kind = TOK_EOF;
+                                       *where = 0;
+                                       return;
+                               }
+                               linenum++;
+                               if (commenting) {
+                                       break;
+                               } else if (cppline(curline)) {
+                                       docppline(curline, &linenum, 
+                                                 &infilename);
+                               } else if (directive(curline)) {
+                                       printdirective(curline);
+                               } else {
+                                       break;
+                               }
+                       }
+                       where = curline;
+               } else if (isspace(*where)) {
+                       while (isspace(*where)) {
+                               where++;        /* eat */
+                       }
+               } else if (commenting) {
+                       where++;
+                       if (endcomment(where)) {
+                               where++;
+                               commenting--;
+                       }
+               } else if (startcomment(where)) {
+                       where += 2;
+                       commenting++;
+               } else {
+                       break;
+               }
+       }
+
+       /*
+        * 'where' is not whitespace, comment or directive Must be a token! 
+        */
+       switch (*where) {
+       case ':':
+               tokp->kind = TOK_COLON;
+               where++;
+               break;
+       case ';':
+               tokp->kind = TOK_SEMICOLON;
+               where++;
+               break;
+       case ',':
+               tokp->kind = TOK_COMMA;
+               where++;
+               break;
+       case '=':
+               tokp->kind = TOK_EQUAL;
+               where++;
+               break;
+       case '*':
+               tokp->kind = TOK_STAR;
+               where++;
+               break;
+       case '[':
+               tokp->kind = TOK_LBRACKET;
+               where++;
+               break;
+       case ']':
+               tokp->kind = TOK_RBRACKET;
+               where++;
+               break;
+       case '{':
+               tokp->kind = TOK_LBRACE;
+               where++;
+               break;
+       case '}':
+               tokp->kind = TOK_RBRACE;
+               where++;
+               break;
+       case '(':
+               tokp->kind = TOK_LPAREN;
+               where++;
+               break;
+       case ')':
+               tokp->kind = TOK_RPAREN;
+               where++;
+               break;
+       case '<':
+               tokp->kind = TOK_LANGLE;
+               where++;
+               break;
+       case '>':
+               tokp->kind = TOK_RANGLE;
+               where++;
+               break;
+
+       case '"':
+               tokp->kind = TOK_STRCONST;
+               findstrconst(&where, &tokp->str);
+               break;
+
+       case '-':
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+               tokp->kind = TOK_IDENT;
+               findconst(&where, &tokp->str);
+               break;
+
+
+       default:
+               if (!(isalpha(*where) || *where == '_')) {
+                       char buf[100];
+                       char *p;
+
+                       s_print(buf, "illegal character in file: ");
+                       p = buf + strlen(buf);
+                       if (isprint(*where)) {
+                               s_print(p, "%c", *where);
+                       } else {
+                               s_print(p, "%d", *where);
+                       }
+                       error(buf);
+               }
+               findkind(&where, tokp);
+               break;
+       }
+}
+
+
+
+static
+unget_token(tokp)
+       token *tokp;
+{
+       lasttok = *tokp;
+       pushed = 1;
+}
+
+
+static
+findstrconst(str, val)
+       char **str;
+       char **val;
+{
+       char *p;
+       int size;
+
+       p = *str;
+       do {
+               *p++;
+       } while (*p && *p != '"');
+       if (*p == 0) {
+               error("unterminated string constant");
+       }
+       p++;
+       size = p - *str;
+       *val = alloc(size + 1);
+       (void) strncpy(*val, *str, size);
+       (*val)[size] = 0;
+       *str = p;
+}
+
+static
+findconst(str, val)
+       char **str;
+       char **val;
+{
+       char *p;
+       int size;
+
+       p = *str;
+       if (*p == '0' && *(p + 1) == 'x') {
+               p++;
+               do {
+                       p++;
+               } while (isxdigit(*p));
+       } else {
+               do {
+                       p++;
+               } while (isdigit(*p));
+       }
+       size = p - *str;
+       *val = alloc(size + 1);
+       (void) strncpy(*val, *str, size);
+       (*val)[size] = 0;
+       *str = p;
+}
+
+
+
+static token symbols[] = {
+                         {TOK_CONST, "const"},
+                         {TOK_UNION, "union"},
+                         {TOK_SWITCH, "switch"},
+                         {TOK_CASE, "case"},
+                         {TOK_DEFAULT, "default"},
+                         {TOK_STRUCT, "struct"},
+                         {TOK_TYPEDEF, "typedef"},
+                         {TOK_ENUM, "enum"},
+                         {TOK_OPAQUE, "opaque"},
+                         {TOK_BOOL, "bool"},
+                         {TOK_VOID, "void"},
+                         {TOK_CHAR, "char"},
+                         {TOK_INT, "int"},
+                         {TOK_UNSIGNED, "unsigned"},
+                         {TOK_SHORT, "short"},
+                         {TOK_LONG, "long"},
+                         {TOK_FLOAT, "float"},
+                         {TOK_DOUBLE, "double"},
+                         {TOK_STRING, "string"},
+                         {TOK_PROGRAM, "program"},
+                         {TOK_VERSION, "version"},
+                         {TOK_EOF, "??????"},
+};
+
+
+static
+findkind(mark, tokp)
+       char **mark;
+       token *tokp;
+{
+
+       int len;
+       token *s;
+       char *str;
+
+       str = *mark;
+       for (s = symbols; s->kind != TOK_EOF; s++) {
+               len = strlen(s->str);
+               if (strncmp(str, s->str, len) == 0) {
+                       if (!isalnum(str[len]) && str[len] != '_') {
+                               tokp->kind = s->kind;
+                               tokp->str = s->str;
+                               *mark = str + len;
+                               return;
+                       }
+               }
+       }
+       tokp->kind = TOK_IDENT;
+       for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
+       tokp->str = alloc(len + 1);
+       (void) strncpy(tokp->str, str, len);
+       tokp->str[len] = 0;
+       *mark = str + len;
+}
+
+static
+cppline(line)
+       char *line;
+{
+       return (line == curline && *line == '#');
+}
+
+static
+directive(line)
+       char *line;
+{
+       return (line == curline && *line == '%');
+}
+
+static
+printdirective(line)
+       char *line;
+{
+       f_print(fout, "%s", line + 1);
+}
+
+static
+docppline(line, lineno, fname)
+       char *line;
+       int *lineno;
+       char **fname;
+{
+       char *file;
+       int num;
+       char *p;
+
+       line++;
+       while (isspace(*line)) {
+               line++;
+       }
+       num = atoi(line);
+       while (isdigit(*line)) {
+               line++;
+       }
+       while (isspace(*line)) {
+               line++;
+       }
+       if (*line != '"') {
+               error("preprocessor error");
+       }
+       line++;
+       p = file = alloc(strlen(line) + 1);
+       while (*line && *line != '"') {
+               *p++ = *line++;
+       }
+       if (*line == 0) {
+               error("preprocessor error");
+       }
+       *p = 0;
+       if (*file == 0) {
+               *fname = NULL;
+       } else {
+               *fname = file;
+       }
+       *lineno = num - 1;
+}
diff --git a/sunrpc/rpc_scan.h b/sunrpc/rpc_scan.h
new file mode 100644 (file)
index 0000000..ad243d5
--- /dev/null
@@ -0,0 +1,101 @@
+/* @(#)rpc_scan.h      2.1 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/* @(#)rpc_scan.h 1.3 87/03/09 (C) 1987 SMI */
+
+/*
+ * rpc_scan.h, Definitions for the RPCL scanner 
+ * Copyright (C) 1987, Sun Microsystems, Inc. 
+ */
+
+/*
+ * kinds of tokens 
+ */
+enum tok_kind {
+       TOK_IDENT,
+       TOK_STRCONST,
+       TOK_LPAREN,
+       TOK_RPAREN,
+       TOK_LBRACE,
+       TOK_RBRACE,
+       TOK_LBRACKET,
+       TOK_RBRACKET,
+       TOK_LANGLE,
+       TOK_RANGLE,
+       TOK_STAR,
+       TOK_COMMA,
+       TOK_EQUAL,
+       TOK_COLON,
+       TOK_SEMICOLON,
+       TOK_CONST,
+       TOK_STRUCT,
+       TOK_UNION,
+       TOK_SWITCH,
+       TOK_CASE,
+       TOK_DEFAULT,
+       TOK_ENUM,
+       TOK_TYPEDEF,
+       TOK_INT,
+       TOK_SHORT,
+       TOK_LONG,
+       TOK_UNSIGNED,
+       TOK_FLOAT,
+       TOK_DOUBLE,
+       TOK_OPAQUE,
+       TOK_CHAR,
+       TOK_STRING,
+       TOK_BOOL,
+       TOK_VOID,
+       TOK_PROGRAM,
+       TOK_VERSION,
+       TOK_EOF
+};
+typedef enum tok_kind tok_kind;
+
+/*
+ * a token 
+ */
+struct token {
+       tok_kind kind;
+       char *str;
+};
+typedef struct token token;
+
+
+/*
+ * routine interface 
+ */
+void scanprint();
+void scan();
+void scan2();
+void scan3();
+void scan_num();
+void peek();
+int peekscan();
+void get_token();
diff --git a/sunrpc/rpc_svcout.c b/sunrpc/rpc_svcout.c
new file mode 100644 (file)
index 0000000..7289b0d
--- /dev/null
@@ -0,0 +1,275 @@
+/* @(#)rpc_svcout.c    2.1 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#ifndef lint
+static char sccsid[] = "@(#)rpc_svcout.c 1.6 87/06/24 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsytsems, Inc. 
+ */
+#include <stdio.h>
+#include <strings.h>
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+static char RQSTP[] = "rqstp";
+static char TRANSP[] = "transp";
+static char ARG[] = "argument";
+static char RESULT[] = "result";
+static char ROUTINE[] = "local";
+
+
+/*
+ * write most of the service, that is, everything but the registrations. 
+ */
+void
+write_most()
+{
+       list *l;
+       definition *def;
+       version_list *vp;
+
+       for (l = defined; l != NULL; l = l->next) {
+               def = (definition *) l->val;
+               if (def->def_kind == DEF_PROGRAM) {
+                       for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+                               f_print(fout, "\nstatic void ");
+                               pvname(def->def_name, vp->vers_num);
+                               f_print(fout, "();");
+                       }
+               }
+       }
+       f_print(fout, "\n\n");
+       f_print(fout, "main()\n");
+       f_print(fout, "{\n");
+       f_print(fout, "\tSVCXPRT *%s;\n", TRANSP);
+       f_print(fout, "\n");
+       for (l = defined; l != NULL; l = l->next) {
+               def = (definition *) l->val;
+               if (def->def_kind != DEF_PROGRAM) {
+                       continue;
+               }
+               for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+                       f_print(fout, "\t(void)pmap_unset(%s, %s);\n", def->def_name, vp->vers_name);
+               }
+       }
+}
+
+
+/*
+ * write a registration for the given transport 
+ */
+void
+write_register(transp)
+       char *transp;
+{
+       list *l;
+       definition *def;
+       version_list *vp;
+
+       f_print(fout, "\n");
+       f_print(fout, "\t%s = svc%s_create(RPC_ANYSOCK", TRANSP, transp);
+       if (streq(transp, "tcp")) {
+               f_print(fout, ", 0, 0");
+       }
+       f_print(fout, ");\n");
+       f_print(fout, "\tif (%s == NULL) {\n", TRANSP);
+       f_print(fout, "\t\t(void)fprintf(stderr, \"cannot create %s service.\\n\");\n", transp);
+       f_print(fout, "\t\texit(1);\n");
+       f_print(fout, "\t}\n");
+
+       for (l = defined; l != NULL; l = l->next) {
+               def = (definition *) l->val;
+               if (def->def_kind != DEF_PROGRAM) {
+                       continue;
+               }
+               for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+                       f_print(fout,
+                               "\tif (!svc_register(%s, %s, %s, ",
+                               TRANSP, def->def_name, vp->vers_name);
+                       pvname(def->def_name, vp->vers_num);
+                       f_print(fout, ", IPPROTO_%s)) {\n",
+                               streq(transp, "udp") ? "UDP" : "TCP");
+                       f_print(fout,
+                               "\t\t(void)fprintf(stderr, \"unable to register (%s, %s, %s).\\n\");\n",
+                               def->def_name, vp->vers_name, transp);
+                       f_print(fout, "\t\texit(1);\n");
+                       f_print(fout, "\t}\n");
+               }
+       }
+}
+
+
+/*
+ * write the rest of the service 
+ */
+void
+write_rest()
+{
+       f_print(fout, "\tsvc_run();\n");
+       f_print(fout, "\t(void)fprintf(stderr, \"svc_run returned\\n\");\n");
+       f_print(fout, "\texit(1);\n");
+       f_print(fout, "}\n");
+}
+
+void
+write_programs(storage)
+       char *storage;
+{
+       list *l;
+       definition *def;
+
+       for (l = defined; l != NULL; l = l->next) {
+               def = (definition *) l->val;
+               if (def->def_kind == DEF_PROGRAM) {
+                       write_program(def, storage);
+               }
+       }
+}
+
+
+static
+write_program(def, storage)
+       definition *def;
+       char *storage;
+{
+       version_list *vp;
+       proc_list *proc;
+       int filled;
+
+       for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+               f_print(fout, "\n");
+               if (storage != NULL) {
+                       f_print(fout, "%s ", storage);
+               }
+               f_print(fout, "void\n");
+               pvname(def->def_name, vp->vers_num);
+               f_print(fout, "(%s, %s)\n", RQSTP, TRANSP);
+               f_print(fout, " struct svc_req *%s;\n", RQSTP);
+               f_print(fout, " SVCXPRT *%s;\n", TRANSP);
+               f_print(fout, "{\n");
+
+               filled = 0;
+               f_print(fout, "\tunion {\n");
+               for (proc = vp->procs; proc != NULL; proc = proc->next) {
+                       if (streq(proc->arg_type, "void")) {
+                               continue;
+                       }
+                       filled = 1;
+                       f_print(fout, "\t\t");
+                       ptype(proc->arg_prefix, proc->arg_type, 0);
+                       pvname(proc->proc_name, vp->vers_num);
+                       f_print(fout, "_arg;\n");
+               }
+               if (!filled) {
+                       f_print(fout, "\t\tint fill;\n");
+               }
+               f_print(fout, "\t} %s;\n", ARG);
+               f_print(fout, "\tchar *%s;\n", RESULT);
+               f_print(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", ARG, RESULT);
+               f_print(fout, "\tchar *(*%s)();\n", ROUTINE);
+               f_print(fout, "\n");
+               f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
+
+               if (!nullproc(vp->procs)) {
+                       f_print(fout, "\tcase NULLPROC:\n");
+                       f_print(fout, "\t\t(void)svc_sendreply(%s, xdr_void, (char *)NULL);\n", TRANSP);
+                       f_print(fout, "\t\treturn;\n\n");
+               }
+               for (proc = vp->procs; proc != NULL; proc = proc->next) {
+                       f_print(fout, "\tcase %s:\n", proc->proc_name);
+                       f_print(fout, "\t\txdr_%s = xdr_%s;\n", ARG, 
+                               stringfix(proc->arg_type));
+                       f_print(fout, "\t\txdr_%s = xdr_%s;\n", RESULT, 
+                               stringfix(proc->res_type));
+                       f_print(fout, "\t\t%s = (char *(*)()) ", ROUTINE);
+                       pvname(proc->proc_name, vp->vers_num);
+                       f_print(fout, ";\n");
+                       f_print(fout, "\t\tbreak;\n\n");
+               }
+               f_print(fout, "\tdefault:\n");
+               printerr("noproc", TRANSP);
+               f_print(fout, "\t\treturn;\n");
+               f_print(fout, "\t}\n");
+
+               f_print(fout, "\tbzero((char *)&%s, sizeof(%s));\n", ARG, ARG);
+               printif("getargs", TRANSP, "&", ARG);
+               printerr("decode", TRANSP);
+               f_print(fout, "\t\treturn;\n");
+               f_print(fout, "\t}\n");
+
+               f_print(fout, "\t%s = (*%s)(&%s, %s);\n", RESULT, ROUTINE, ARG,
+                       RQSTP);
+               f_print(fout, 
+                       "\tif (%s != NULL && !svc_sendreply(%s, xdr_%s, %s)) {\n",
+                       RESULT, TRANSP, RESULT, RESULT);
+               printerr("systemerr", TRANSP);
+               f_print(fout, "\t}\n");
+
+               printif("freeargs", TRANSP, "&", ARG);
+               f_print(fout, "\t\t(void)fprintf(stderr, \"unable to free arguments\\n\");\n");
+               f_print(fout, "\t\texit(1);\n");
+               f_print(fout, "\t}\n");
+
+               f_print(fout, "}\n\n");
+       }
+}
+
+static
+printerr(err, transp)
+       char *err;
+       char *transp;
+{
+       f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
+}
+
+static
+printif(proc, transp, prefix, arg)
+       char *proc;
+       char *transp;
+       char *prefix;
+       char *arg;
+{
+       f_print(fout, "\tif (!svc_%s(%s, xdr_%s, %s%s)) {\n",
+               proc, transp, arg, prefix, arg);
+}
+
+
+nullproc(proc)
+       proc_list *proc;
+{
+       for (; proc != NULL; proc = proc->next) {
+               if (streq(proc->proc_num, "0")) {
+                       return (1);
+               }
+       }
+       return (0);
+}
diff --git a/sunrpc/rpc_util.c b/sunrpc/rpc_util.c
new file mode 100644 (file)
index 0000000..8136535
--- /dev/null
@@ -0,0 +1,436 @@
+/* @(#)rpc_util.c      2.1 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#ifndef lint
+static char sccsid[] = "@(#)rpc_util.c 1.5 87/06/24 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_util.c, Utility routines for the RPC protocol compiler 
+ * Copyright (C) 1987, Sun Microsystems, Inc. 
+ */
+#include <stdio.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+char curline[MAXLINESIZE];     /* current read line */
+char *where = curline; /* current point in line */
+int linenum = 0;       /* current line number */
+
+char *infilename;      /* input filename */
+
+#define NFILES 4
+char *outfiles[NFILES];        /* output file names */
+int nfiles;
+
+FILE *fout;    /* file pointer of current output */
+FILE *fin;     /* file pointer of current input */
+
+list *defined; /* list of defined things */
+
+/*
+ * Reinitialize the world 
+ */
+reinitialize()
+{
+       bzero(curline, MAXLINESIZE);
+       where = curline;
+       linenum = 0;
+       defined = NULL;
+}
+
+/*
+ * 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(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(defined, type, typedefed);
+                       if (def == NULL) {
+                               return (0);
+                       }
+                       type = def->def.ty.old_type;
+                       rel = def->def.ty.rel;
+               }
+       }
+}
+
+
+static 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: ", infilename, 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 = 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 < where - curline; i++) {
+               c = curline[i];
+               if (c == '\t') {
+                       cnt = 8 - (i % TABSIZE);
+               } else {
+                       cnt = 1;
+               }
+               while (cnt--) {
+                       (void) fputc('^', stderr);
+               }
+       }
+       (void) fputc('\n', stderr);
+}