| From 866b651bcb9f93f47582e5e2e4f1eb3155025298 Mon Sep 17 00:00:00 2001 |
| From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
| Date: Sat, 10 Nov 2012 16:21:01 +0100 |
| Subject: [PATCH] Add rpcgen program from nfs-utils sources |
| |
| Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
| [yann.morin.1998@free.fr: update for 0.3.1] |
| Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> |
| --- |
| Makefile.am | 2 +- |
| configure.ac | 14 +- |
| rpcgen/Makefile.am | 22 ++ |
| rpcgen/rpc_clntout.c | 217 ++++++++++ |
| rpcgen/rpc_cout.c | 706 +++++++++++++++++++++++++++++++++ |
| rpcgen/rpc_hout.c | 490 +++++++++++++++++++++++ |
| rpcgen/rpc_main.c | 1067 ++++++++++++++++++++++++++++++++++++++++++++++++++ |
| rpcgen/rpc_output.h | 16 + |
| rpcgen/rpc_parse.c | 609 ++++++++++++++++++++++++++++ |
| rpcgen/rpc_parse.h | 166 ++++++++ |
| rpcgen/rpc_sample.c | 247 ++++++++++++ |
| rpcgen/rpc_scan.c | 474 ++++++++++++++++++++++ |
| rpcgen/rpc_scan.h | 103 +++++ |
| rpcgen/rpc_svcout.c | 882 +++++++++++++++++++++++++++++++++++++++++ |
| rpcgen/rpc_tblout.c | 165 ++++++++ |
| rpcgen/rpc_util.c | 479 ++++++++++++++++++++++ |
| rpcgen/rpc_util.h | 166 ++++++++ |
| rpcgen/rpcgen.1 | 521 ++++++++++++++++++++++++ |
| 18 files changed, 6344 insertions(+), 2 deletions(-) |
| create mode 100644 rpcgen/Makefile.am |
| create mode 100644 rpcgen/rpc_clntout.c |
| create mode 100644 rpcgen/rpc_cout.c |
| create mode 100644 rpcgen/rpc_hout.c |
| create mode 100644 rpcgen/rpc_main.c |
| create mode 100644 rpcgen/rpc_output.h |
| create mode 100644 rpcgen/rpc_parse.c |
| create mode 100644 rpcgen/rpc_parse.h |
| create mode 100644 rpcgen/rpc_sample.c |
| create mode 100644 rpcgen/rpc_scan.c |
| create mode 100644 rpcgen/rpc_scan.h |
| create mode 100644 rpcgen/rpc_svcout.c |
| create mode 100644 rpcgen/rpc_tblout.c |
| create mode 100644 rpcgen/rpc_util.c |
| create mode 100644 rpcgen/rpc_util.h |
| create mode 100644 rpcgen/rpcgen.1 |
| |
| diff --git a/Makefile.am b/Makefile.am |
| index 466b6dd..8558289 100644 |
| --- a/Makefile.am |
| +++ b/Makefile.am |
| @@ -1,4 +1,4 @@ |
| -SUBDIRS = src man doc |
| +SUBDIRS = src man doc rpcgen |
| ACLOCAL_AMFLAGS = -I m4 |
| |
| noinst_HEADERS = tirpc/reentrant.h \ |
| diff --git a/configure.ac b/configure.ac |
| index e3cb8af..0ea2e6e 100644 |
| --- a/configure.ac |
| +++ b/configure.ac |
| @@ -58,6 +58,18 @@ AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h locale.h netdb.h netine |
| AC_CHECK_LIB([pthread], [pthread_create]) |
| AC_CHECK_FUNCS([getrpcbyname getrpcbynumber setrpcent endrpcent getrpcent]) |
| |
| -AC_CONFIG_FILES([Makefile src/Makefile man/Makefile doc/Makefile]) |
| +AM_CONDITIONAL(CROSS_COMPILING, test $cross_compiling = yes) |
| + |
| +AC_MSG_CHECKING([for a C compiler for build tools]) |
| +if test $cross_compiling = yes; then |
| + AC_CHECK_PROGS(CC_FOR_BUILD, gcc cc) |
| +else |
| + CC_FOR_BUILD=$CC |
| +fi |
| +AC_MSG_RESULT([$CC_FOR_BUILD]) |
| +AC_SUBST(CC_FOR_BUILD) |
| + |
| +AC_CONFIG_FILES([Makefile src/Makefile man/Makefile doc/Makefile rpcgen/Makefile]) |
| + |
| AC_OUTPUT(libtirpc.pc) |
| |
| diff --git a/rpcgen/Makefile.am b/rpcgen/Makefile.am |
| new file mode 100644 |
| index 0000000..2277b6f |
| --- /dev/null |
| +++ b/rpcgen/Makefile.am |
| @@ -0,0 +1,22 @@ |
| +COMPILE = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) -I../tirpc $(AM_CPPFLAGS) \ |
| + $(CPPFLAGS_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) |
| +LINK = $(CC_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) $(AM_LDFLAGS) $(LDFLAGS_FOR_BUILD) -o $@ |
| + |
| +noinst_PROGRAMS = rpcgen |
| + |
| +rpcgen_SOURCES = \ |
| + rpc_clntout.c \ |
| + rpc_cout.c \ |
| + rpc_hout.c \ |
| + rpc_main.c \ |
| + rpc_parse.c \ |
| + rpc_sample.c \ |
| + rpc_scan.c \ |
| + rpc_svcout.c \ |
| + rpc_tblout.c \ |
| + rpc_util.c \ |
| + rpc_parse.h \ |
| + rpc_scan.h \ |
| + rpc_util.h |
| + |
| +dist_man1_MANS = rpcgen.1 |
| diff --git a/rpcgen/rpc_clntout.c b/rpcgen/rpc_clntout.c |
| new file mode 100644 |
| index 0000000..e2f4382 |
| --- /dev/null |
| +++ b/rpcgen/rpc_clntout.c |
| @@ -0,0 +1,217 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| +static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (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 <string.h> |
| +#include <rpc/types.h> |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| +#include "rpc_output.h" |
| + |
| +/* extern pdeclaration(); */ |
| +/* void printarglist(); */ |
| + |
| +#define DEFAULT_TIMEOUT 25 /* in seconds */ |
| +static char RESULT[] = "clnt_res"; |
| + |
| +static void write_program(definition *def); |
| +static void printbody(proc_list *proc); |
| + |
| + |
| +void |
| +write_stubs(void) |
| +{ |
| + 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 void |
| +write_program(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); |
| + printarglist(proc, "clnt", "CLIENT *"); |
| + f_print(fout, "{\n"); |
| + printbody(proc); |
| + f_print(fout, "}\n"); |
| + } |
| + } |
| +} |
| + |
| +/* |
| + * Writes out declarations of procedure's argument list. |
| + * In either ANSI C style, in one of old rpcgen style (pass by reference), |
| + * or new rpcgen style (multiple arguments, pass by value); |
| + */ |
| + |
| +/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */ |
| + |
| +void |
| +printarglist(proc_list *proc, char *addargname, char *addargtype) |
| +{ |
| + |
| + decl_list *l; |
| + |
| + if (!newstyle) { /* old style: always pass arg by reference */ |
| + if (Cflag) { /* C++ style heading */ |
| + f_print(fout, "("); |
| + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); |
| + f_print(fout, "*argp, %s%s)\n", addargtype, addargname); |
| + } else { |
| + f_print(fout, "(argp, %s)\n", addargname); |
| + f_print(fout, "\t"); |
| + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); |
| + f_print(fout, "*argp;\n"); |
| + } |
| + } else if (streq(proc->args.decls->decl.type, "void")) { |
| + /* newstyle, 0 argument */ |
| + if (Cflag) |
| + f_print(fout, "(%s%s)\n", addargtype, addargname); |
| + else |
| + f_print(fout, "(%s)\n", addargname); |
| + } else { |
| + /* new style, 1 or multiple arguments */ |
| + if (!Cflag) { |
| + f_print(fout, "("); |
| + for (l = proc->args.decls; l != NULL; l = l->next) |
| + f_print(fout, "%s, ", l->decl.name); |
| + f_print(fout, "%s)\n", addargname); |
| + for (l = proc->args.decls; l != NULL; l = l->next) { |
| + pdeclaration(proc->args.argname, &l->decl, 1, ";\n"); |
| + } |
| + } else { /* C++ style header */ |
| + f_print(fout, "("); |
| + for (l = proc->args.decls; l != NULL; l = l->next) { |
| + pdeclaration(proc->args.argname, &l->decl, 0, ", "); |
| + } |
| + f_print(fout, " %s%s)\n", addargtype, addargname); |
| + } |
| + } |
| + |
| + if (!Cflag) |
| + f_print(fout, "\t%s%s;\n", addargtype, addargname); |
| +} |
| + |
| + |
| + |
| +static char * |
| +ampr(char *type) |
| +{ |
| + if (isvectordef(type, REL_ALIAS)) { |
| + return (""); |
| + } else { |
| + return ("&"); |
| + } |
| +} |
| + |
| +static void |
| +printbody(proc_list *proc) |
| +{ |
| + decl_list *l; |
| + bool_t args2 = (proc->arg_num > 1); |
| + |
| + /* For new style with multiple arguments, need a structure in which |
| + * to stuff the arguments. */ |
| + if (newstyle && args2) { |
| + f_print(fout, "\t%s", proc->args.argname); |
| + f_print(fout, " arg;\n"); |
| + } |
| + 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, "%s;\n", RESULT); |
| + f_print(fout, "\n"); |
| + f_print(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n", |
| + ampr(proc->res_type), RESULT, RESULT); |
| + if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) { |
| + /* newstyle, 0 arguments */ |
| + f_print(fout, |
| + "\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_void, (caddr_t) NULL, " |
| + "(xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n", |
| + proc->proc_name, |
| + stringfix(proc->res_type), ampr(proc->res_type), RESULT); |
| + |
| + } else if (newstyle && args2) { |
| + /* newstyle, multiple arguments: stuff arguments into structure */ |
| + for (l = proc->args.decls; l != NULL; l = l->next) { |
| + f_print(fout, "\targ.%s = %s;\n", |
| + l->decl.name, l->decl.name); |
| + } |
| + f_print(fout, |
| + "\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_%s, (caddr_t) &arg, " |
| + "(xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n", |
| + proc->proc_name, proc->args.argname, |
| + stringfix(proc->res_type), ampr(proc->res_type), RESULT); |
| + } else { /* single argument, new or old style */ |
| + f_print(fout, |
| + "\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_%s, " |
| + "(caddr_t) %s%s, (xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n", |
| + proc->proc_name, |
| + stringfix(proc->args.decls->decl.type), |
| + (newstyle ? "&" : ""), |
| + (newstyle ? proc->args.decls->decl.name : "argp"), |
| + stringfix(proc->res_type), ampr(proc->res_type), RESULT); |
| + } |
| + f_print(fout, "\t\treturn (NULL);\n"); |
| + f_print(fout, "\t}\n"); |
| + if (streq(proc->res_type, "void")) { |
| + f_print(fout, "\treturn ((void *)%s%s);\n", |
| + ampr(proc->res_type), RESULT); |
| + } else { |
| + f_print(fout, "\treturn (%s%s);\n", ampr(proc->res_type), RESULT); |
| + } |
| +} |
| diff --git a/rpcgen/rpc_cout.c b/rpcgen/rpc_cout.c |
| new file mode 100644 |
| index 0000000..a61214f |
| --- /dev/null |
| +++ b/rpcgen/rpc_cout.c |
| @@ -0,0 +1,706 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| +static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI"; |
| +#endif |
| + |
| +/* |
| + * rpc_cout.c, XDR routine outputter for the RPC protocol compiler |
| + */ |
| +#include <stdio.h> |
| +#include <string.h> |
| +#include <stdlib.h> |
| +#include <malloc.h> |
| +#include <ctype.h> |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| + |
| +static int findtype(definition *def, char *type); |
| +static int undefined(char *type); |
| +static void print_generic_header(char *procname, int pointerp); |
| +static void print_header(definition *def); |
| +static void print_prog_header(proc_list *plist); |
| +static void print_trailer(void); |
| +static void print_ifopen(int indent, char *name); |
| +static void print_ifarg(char *arg); |
| +static void print_ifsizeof(char *prefix, char *type); |
| +static void print_ifclose(int indent); |
| +static void print_ifstat(int indent, char *prefix, char *type, relation rel, |
| + char *amax, char *objname, char *name); |
| +static void emit_enum(definition *def); |
| +static void emit_program(definition *def); |
| +static void emit_union(definition *def); |
| +static void emit_struct(definition *def); |
| +static void emit_typedef(definition *def); |
| +static void print_stat(int indent, declaration *dec); |
| +static void emit_inline(declaration *decl, int flag); |
| +static void emit_single_in_line(declaration *decl, int flag, relation rel); |
| +static char * upcase(char *str); |
| + |
| +/* |
| + * Emit the C-routine for the given definition |
| + */ |
| +void |
| +emit(definition *def) |
| +{ |
| + if (def->def_kind == DEF_CONST) { |
| + return; |
| + } |
| + if (def->def_kind == DEF_PROGRAM) { |
| + emit_program(def); |
| + return; |
| + } |
| + if (def->def_kind == DEF_TYPEDEF) { |
| + /* now we need to handle declarations like |
| + * struct typedef foo foo; |
| + * since we dont want this to be expanded into 2 calls |
| + * to xdr_foo */ |
| + |
| + if (strcmp(def->def.ty.old_type, def->def_name) == 0) |
| + 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; |
| + default: |
| + break; |
| + } |
| + print_trailer(); |
| +} |
| + |
| +static int |
| +findtype(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 int |
| +undefined(char *type) |
| +{ |
| + definition *def; |
| + |
| + def = (definition *) FINDVAL(defined, type, findtype); |
| + |
| + return (def == NULL); |
| +} |
| + |
| + |
| +static void |
| +print_generic_header(char *procname, int pointerp) |
| +{ |
| + f_print(fout, "\n"); |
| + f_print(fout, "bool_t\n"); |
| + if (Cflag) { |
| + f_print(fout, "xdr_%s(", procname); |
| + f_print(fout, "XDR *xdrs, "); |
| + f_print(fout, "%s ", procname); |
| + if (pointerp) |
| + f_print(fout, "*"); |
| + f_print(fout, "objp)\n{\n\n"); |
| + } else { |
| + f_print(fout, "xdr_%s(xdrs, objp)\n", procname); |
| + f_print(fout, "\tXDR *xdrs;\n"); |
| + f_print(fout, "\t%s ", procname); |
| + if (pointerp) |
| + f_print(fout, "*"); |
| + f_print(fout, "objp;\n{\n\n"); |
| + } |
| +} |
| + |
| +static void |
| +print_header(definition *def) |
| +{ |
| + print_generic_header(def->def_name, |
| + def->def_kind != DEF_TYPEDEF || |
| + !isvectordef(def->def.ty.old_type, def->def.ty.rel)); |
| + |
| + /* Now add Inline support */ |
| + |
| + |
| + if (Inline == 0) |
| + return; |
| +} |
| + |
| +static void |
| +print_prog_header(proc_list *plist) |
| +{ |
| + print_generic_header(plist->args.argname, 1); |
| +} |
| + |
| +static void |
| +print_trailer(void) |
| +{ |
| + f_print(fout, "\treturn (TRUE);\n"); |
| + f_print(fout, "}\n"); |
| +} |
| + |
| + |
| +static void |
| +print_ifopen(int indent, char *name) |
| +{ |
| + tabify(fout, indent); |
| + f_print(fout, " if (!xdr_%s(xdrs", name); |
| +} |
| + |
| +static void |
| +print_ifarg(char *arg) |
| +{ |
| + f_print(fout, ", %s", arg); |
| +} |
| + |
| +static void |
| +print_ifsizeof(char *prefix, char *type) |
| +{ |
| + if (streq(type, "bool")) { |
| + f_print(fout, ", sizeof(bool_t), (xdrproc_t)xdr_bool"); |
| + } else { |
| + f_print(fout, ", sizeof("); |
| + if (undefined(type) && prefix) { |
| + f_print(fout, "%s ", prefix); |
| + } |
| + f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type); |
| + } |
| +} |
| + |
| +static void |
| +print_ifclose(int indent) |
| +{ |
| + f_print(fout, ")) {\n"); |
| + tabify(fout, indent); |
| + f_print(fout, "\t return (FALSE);\n"); |
| + tabify(fout, indent); |
| + f_print(fout, " }\n"); |
| +} |
| + |
| +static void |
| +print_ifstat(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"); |
| + } |
| + /* The (void*) avoids a gcc-4.1 warning */ |
| + print_ifarg("(char **)(void*)"); |
| + 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); |
| +} |
| + |
| +static void |
| +emit_enum(definition *def) |
| +{ |
| + print_ifopen(1, "enum"); |
| + print_ifarg("(enum_t *)objp"); |
| + print_ifclose(1); |
| +} |
| + |
| +static void |
| +emit_program(definition *def) |
| +{ |
| + decl_list *dl; |
| + version_list *vlist; |
| + proc_list *plist; |
| + |
| + for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next) |
| + for (plist = vlist->procs; plist != NULL; plist = plist->next) { |
| + if (!newstyle || plist->arg_num < 2) |
| + continue;/* old style, or single argument */ |
| + print_prog_header(plist); |
| + for (dl = plist->args.decls; dl != NULL; dl = dl->next) |
| + print_stat(1, &dl->decl); |
| + print_trailer(); |
| + } |
| +} |
| + |
| + |
| +static void |
| +emit_union(definition *def) |
| +{ |
| + declaration *dflt; |
| + case_list *cl; |
| + declaration *cs; |
| + char *object; |
| + char *vecformat = "objp->%s_u.%s"; |
| + char *format = "&objp->%s_u.%s"; |
| + |
| + print_stat(1,&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) { |
| + |
| + f_print(fout, "\tcase %s:\n", cl->case_name); |
| + if(cl->contflag == 1) /* a continued case statement */ |
| + continue; |
| + cs = &cl->case_decl; |
| + if (!streq(cs->type, "void")) { |
| + object = alloc(strlen(def->def_name) + strlen(format) + |
| + strlen(cs->name) + 1); |
| + if (isvectordef (cs->type, cs->rel)) { |
| + s_print(object, vecformat, def->def_name, |
| + cs->name); |
| + } else { |
| + 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); |
| + if (isvectordef (dflt->type, dflt->rel)) { |
| + s_print(object, vecformat, def->def_name, |
| + dflt->name); |
| + } else { |
| + 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 { |
| + /* Avoid gcc warnings about `value not handled in switch' */ |
| + f_print(fout, "\tdefault:\n"); |
| + 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 void |
| +emit_struct(definition *def) |
| +{ |
| + decl_list *dl; |
| + int i, j, size, flag; |
| + decl_list *cur = NULL, *psav; |
| + bas_type *ptr; |
| + char *sizestr, *plus; |
| + char ptemp[256]; |
| + int can_inline; |
| + const char *buf_declaration; |
| + |
| + |
| + if (Inline == 0) { |
| + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) |
| + print_stat(1, &dl->decl); |
| + } else { |
| + size = 0; |
| + can_inline = 0; |
| + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) |
| + if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { |
| + |
| + if (dl->decl.rel == REL_ALIAS) |
| + size += ptr->length; |
| + else { |
| + can_inline = 1; |
| + break; /* can be inlined */ |
| + }; |
| + } else { |
| + if (size >= Inline) { |
| + can_inline = 1; |
| + break; /* can be inlined */ |
| + } |
| + size = 0; |
| + } |
| + if (size > Inline) |
| + can_inline = 1; |
| + |
| + if (can_inline == 0) { /* can not inline, drop back to old mode */ |
| + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) |
| + print_stat(1, &dl->decl); |
| + return; |
| + }; |
| + |
| + |
| + |
| + |
| + flag = PUT; |
| + for (j = 0; j < 2; j++) { |
| + |
| + if (flag == PUT) |
| + f_print(fout, "\n\t if (xdrs->x_op == XDR_ENCODE) {\n"); |
| + else |
| + f_print(fout, "\n \t return (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n"); |
| + |
| + |
| + i = 0; |
| + size = 0; |
| + sizestr = NULL; |
| + buf_declaration = "int32_t *"; |
| + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */ |
| + |
| + /* now walk down the list and check for basic types */ |
| + if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { |
| + if (i == 0) |
| + cur = dl; |
| + i++; |
| + |
| + if (dl->decl.rel == REL_ALIAS) |
| + size += ptr->length; |
| + else { |
| + /* this is required to handle arrays */ |
| + |
| + if (sizestr == NULL) |
| + plus = " "; |
| + else |
| + plus = "+"; |
| + |
| + if (ptr->length != 1) |
| + s_print(ptemp, " %s %s * %d", plus, dl->decl.array_max, ptr->length); |
| + else |
| + s_print(ptemp, " %s %s ", plus, dl->decl.array_max); |
| + |
| + /*now concatenate to sizestr !!!! */ |
| + if (sizestr == NULL) |
| + sizestr = strdup(ptemp); |
| + else { |
| + sizestr = realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1); |
| + if (sizestr == NULL) { |
| + |
| + f_print(stderr, "Fatal error : no memory \n"); |
| + crash(); |
| + }; |
| + sizestr = strcat(sizestr, ptemp); /*build up length of array */ |
| + |
| + } |
| + } |
| + |
| + } else { |
| + if (i > 0) |
| + { |
| + if (sizestr == NULL && size < Inline) { |
| + /* don't expand into inline code if size < inline */ |
| + while (cur != dl) { |
| + print_stat(1, &cur->decl); |
| + cur = cur->next; |
| + } |
| + } else { |
| + |
| + |
| + |
| + /* were already looking at a xdr_inlineable structure */ |
| + if (sizestr == NULL) |
| + f_print(fout, "\t %sbuf = XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);", |
| + buf_declaration, size); |
| + else if (size == 0) |
| + f_print(fout, |
| + "\t %sbuf = XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);", |
| + buf_declaration, sizestr); |
| + else |
| + f_print(fout, |
| + "\t %sbuf = XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);", |
| + buf_declaration, size, sizestr); |
| + buf_declaration = ""; |
| + |
| + f_print(fout, "\n\t if (buf == NULL) {\n"); |
| + |
| + psav = cur; |
| + while (cur != dl) { |
| + print_stat(2, &cur->decl); |
| + cur = cur->next; |
| + } |
| + |
| + f_print(fout, "\n\t }\n\t else {\n"); |
| + |
| + cur = psav; |
| + while (cur != dl) { |
| + emit_inline(&cur->decl, flag); |
| + cur = cur->next; |
| + } |
| + |
| + f_print(fout, "\t }\n"); |
| + } |
| + } |
| + size = 0; |
| + i = 0; |
| + sizestr = NULL; |
| + print_stat(1, &dl->decl); |
| + } |
| + |
| + } |
| + if (i > 0) |
| + { |
| + if (sizestr == NULL && size < Inline) { |
| + /* don't expand into inline code if size < inline */ |
| + while (cur != dl) { |
| + print_stat(1, &cur->decl); |
| + cur = cur->next; |
| + } |
| + } else { |
| + |
| + /* were already looking at a xdr_inlineable structure */ |
| + if (sizestr == NULL) |
| + f_print(fout, "\t\t%sbuf = XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);", |
| + buf_declaration, size); |
| + else if (size == 0) |
| + f_print(fout, |
| + "\t\t%sbuf = XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);", |
| + buf_declaration, sizestr); |
| + else |
| + f_print(fout, |
| + "\t\t%sbuf = XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);", |
| + buf_declaration, size, sizestr); |
| + buf_declaration = ""; |
| + |
| + f_print(fout, "\n\t\tif (buf == NULL) {\n"); |
| + |
| + psav = cur; |
| + while (cur != NULL) { |
| + print_stat(2, &cur->decl); |
| + cur = cur->next; |
| + } |
| + f_print(fout, "\n\t }\n\t else {\n"); |
| + |
| + cur = psav; |
| + while (cur != dl) { |
| + emit_inline(&cur->decl, flag); |
| + cur = cur->next; |
| + } |
| + |
| + f_print(fout, "\t }\n"); |
| + |
| + } |
| + } |
| + flag = GET; |
| + } |
| + f_print(fout, "\t return(TRUE);\n\t}\n\n"); |
| + |
| + /* now take care of XDR_FREE case */ |
| + |
| + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) |
| + print_stat(1, &dl->decl); |
| + } |
| +} |
| + |
| + |
| + |
| + |
| +static void |
| +emit_typedef(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 void |
| +print_stat(int indent, 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(indent, prefix, type, rel, amax, name, dec->name); |
| +} |
| + |
| + |
| +static void |
| +emit_inline(declaration *decl, int flag) |
| +{ |
| + |
| + /*check whether an array or not */ |
| + |
| + switch (decl->rel) { |
| + case REL_ALIAS: |
| + emit_single_in_line(decl, flag, REL_ALIAS); |
| + break; |
| + case REL_VECTOR: |
| + f_print(fout, "\t\t{ register %s *genp; \n", decl->type); |
| + f_print(fout, "\t\t int i;\n"); |
| + f_print(fout, "\t\t for ( i = 0,genp=objp->%s;\n \t\t\ti < %s; i++){\n\t\t", |
| + decl->name, decl->array_max); |
| + emit_single_in_line(decl, flag, REL_VECTOR); |
| + f_print(fout, "\t\t }\n\t\t };\n"); |
| + break; |
| + default: |
| + break; |
| + } |
| +} |
| + |
| +static void |
| +emit_single_in_line(declaration *decl, int flag, relation rel) |
| +{ |
| + char *upp_case; |
| + int freed=0; |
| + |
| + if(flag == PUT) |
| + f_print(fout,"\t\t (void) IXDR_PUT_"); |
| + else |
| + if(rel== REL_ALIAS) |
| + f_print(fout,"\t\t objp->%s = IXDR_GET_",decl->name); |
| + else |
| + f_print(fout,"\t\t *genp++ = IXDR_GET_"); |
| + |
| + upp_case=upcase(decl->type); |
| + |
| + /* hack - XX */ |
| + if(strcmp(upp_case,"INT") == 0) |
| + { |
| + free(upp_case); |
| + freed=1; |
| + upp_case="INT32"; |
| + } |
| + |
| + if(strcmp(upp_case,"U_INT") == 0) |
| + { |
| + free(upp_case); |
| + freed=1; |
| + upp_case="U_INT32"; |
| + } |
| + |
| + |
| + if(flag == PUT) |
| + if(rel== REL_ALIAS) |
| + f_print(fout,"%s(buf,objp->%s);\n",upp_case,decl->name); |
| + else |
| + f_print(fout,"%s(buf,*genp++);\n",upp_case); |
| + |
| + else |
| + f_print(fout,"%s(buf);\n",upp_case); |
| + if(!freed) |
| + free(upp_case); |
| + |
| +} |
| + |
| + |
| +static char * |
| +upcase(char *str) |
| +{ |
| + char *ptr, *hptr; |
| + |
| + |
| + ptr = (char *) malloc(strlen(str)+1); |
| + if (ptr == (char *) NULL) { |
| + f_print(stderr, "malloc failed \n"); |
| + exit(1); |
| + }; |
| + |
| + hptr = ptr; |
| + while (*str != '\0') |
| + *ptr++ = toupper(*str++); |
| + |
| + *ptr = '\0'; |
| + return (hptr); |
| + |
| +} |
| diff --git a/rpcgen/rpc_hout.c b/rpcgen/rpc_hout.c |
| new file mode 100644 |
| index 0000000..ea1cb24 |
| --- /dev/null |
| +++ b/rpcgen/rpc_hout.c |
| @@ -0,0 +1,490 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| +static char sccsid[] = "@(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI"; |
| +#endif |
| + |
| +/* |
| + * rpc_hout.c, Header file outputter for the RPC protocol compiler |
| + */ |
| +#include <stdio.h> |
| +#include <ctype.h> |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| +#include "rpc_output.h" |
| + |
| + |
| +static int undefined2(char *type, char *stop); |
| +static void pxdrfuncdecl(char *name, int pointerp); |
| +static void pconstdef(definition *def); |
| +static void pargdef(definition *def); |
| +static void pstructdef(definition *def); |
| +static void puniondef(definition *def); |
| +static void pdefine(char *name, char *num); |
| +static void puldefine(char *name, char *num); |
| +static int define_printed(proc_list *stop, version_list *start); |
| +static void pprogramdef(definition *def); |
| +static void pprocdef(proc_list *proc, version_list *vp, |
| + char *addargtype, int server_p, int mode); |
| +static void parglist(proc_list *proc, char *addargtype); |
| +static void penumdef(definition *def); |
| +static void ptypedef(definition *def); |
| + |
| +/* |
| + * Print the C-version of an xdr definition |
| + */ |
| +void |
| +print_datadef(definition *def) |
| +{ |
| + |
| + if (def->def_kind == DEF_PROGRAM ) /* handle data only */ |
| + return; |
| + |
| + 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) { |
| + pxdrfuncdecl( def->def_name, |
| + def->def_kind != DEF_TYPEDEF || |
| + !isvectordef(def->def.ty.old_type, def->def.ty.rel)); |
| + |
| + } |
| +} |
| + |
| + |
| +void |
| +print_funcdef(definition *def) |
| +{ |
| + switch (def->def_kind) { |
| + case DEF_PROGRAM: |
| + f_print(fout, "\n"); |
| + pprogramdef(def); |
| + break; |
| + default: |
| + break; |
| + } |
| +} |
| + |
| +static void |
| +pxdrfuncdecl(char *name, int pointerp) |
| +{ |
| + f_print(fout, |
| + "#ifdef __cplusplus \n" |
| + "extern \"C\" bool_t xdr_%s(XDR *, %s%s);\n" |
| + "#elif __STDC__ \n" |
| + "extern bool_t xdr_%s(XDR *, %s%s);\n" |
| + "#else /* Old Style C */ \n" |
| + "bool_t xdr_%s();\n" |
| + "#endif /* Old Style C */ \n\n", |
| + name, name, pointerp ? "*" : "", |
| + name, name, pointerp ? "*" : "", |
| + name); |
| +} |
| + |
| + |
| +static void |
| +pconstdef(definition *def) |
| +{ |
| + pdefine(def->def_name, def->def.co); |
| +} |
| + |
| +/* print out the definitions for the arguments of functions in the |
| + header file |
| +*/ |
| +static void |
| +pargdef(definition *def) |
| +{ |
| + decl_list *l; |
| + version_list *vers; |
| + char *name; |
| + proc_list *plist; |
| + |
| + |
| + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) { |
| + for(plist = vers->procs; plist != NULL; |
| + plist = plist->next) { |
| + |
| + if (!newstyle || plist->arg_num < 2) { |
| + continue; /* old style or single args */ |
| + } |
| + name = plist->args.argname; |
| + f_print(fout, "struct %s {\n", name); |
| + for (l = plist->args.decls; |
| + l != NULL; l = l->next) { |
| + pdeclaration(name, &l->decl, 1, ";\n" ); |
| + } |
| + f_print(fout, "};\n"); |
| + f_print(fout, "typedef struct %s %s;\n", name, name); |
| + pxdrfuncdecl(name, 0); |
| + f_print( fout, "\n" ); |
| + } |
| + } |
| + |
| +} |
| + |
| + |
| +static void |
| +pstructdef(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, ";\n"); |
| + } |
| + f_print(fout, "};\n"); |
| + f_print(fout, "typedef struct %s %s;\n", name, name); |
| +} |
| + |
| +static void |
| +puniondef(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) { |
| + if (l->contflag == 0) |
| + pdeclaration(name, &l->case_decl, 2, ";\n"); |
| + } |
| + decl = def->def.un.default_decl; |
| + if (decl && !streq(decl->type, "void")) { |
| + pdeclaration(name, decl, 2, ";\n"); |
| + } |
| + f_print(fout, "\t} %s_u;\n", name); |
| + f_print(fout, "};\n"); |
| + f_print(fout, "typedef struct %s %s;\n", name, name); |
| +} |
| + |
| +static void |
| +pdefine(char *name, char *num) |
| +{ |
| + f_print(fout, "#define %s %s\n", name, num); |
| +} |
| + |
| +static void |
| +puldefine(char *name, char *num) |
| +{ |
| + f_print(fout, "#define %s ((u_int32_t)%s)\n", name, num); |
| +} |
| + |
| +static int |
| +define_printed(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 void |
| +pprogramdef(definition *def) |
| +{ |
| + version_list *vers; |
| + proc_list *proc; |
| + int i; |
| + char *ext; |
| + |
| + pargdef(def); |
| + |
| + puldefine(def->def_name, def->def.pr.prog_num); |
| + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) { |
| + if (tblflag) { |
| + f_print(fout, "extern struct rpcgen_table %s_%s_table[];\n", |
| + locase(def->def_name), vers->vers_num); |
| + f_print(fout, "extern %s_%s_nproc;\n", |
| + locase(def->def_name), vers->vers_num); |
| + } |
| + puldefine(vers->vers_name, vers->vers_num); |
| + |
| + /* |
| + * Print out 3 definitions, one for ANSI-C, another for C++, |
| + * a third for old style C |
| + */ |
| + |
| + for (i = 0; i < 3; i++) { |
| + if (i == 0) { |
| + f_print(fout, "\n#ifdef __cplusplus\n"); |
| + ext = "extern \"C\" "; |
| + } else if (i == 1) { |
| + f_print(fout, "\n#elif __STDC__\n"); |
| + ext = "extern "; |
| + } else { |
| + f_print(fout, "\n#else /* Old Style C */ \n"); |
| + ext = "extern "; |
| + } |
| + |
| + |
| + for (proc = vers->procs; proc != NULL; proc = proc->next) { |
| + if (!define_printed(proc, def->def.pr.versions)) { |
| + puldefine(proc->proc_name, proc->proc_num); |
| + } |
| + f_print(fout, "%s", ext); |
| + pprocdef(proc, vers, "CLIENT *", 0, i); |
| + f_print(fout, "%s", ext); |
| + pprocdef(proc, vers, "struct svc_req *", 1, i); |
| + |
| + } |
| + |
| + } |
| + f_print(fout, "#endif /* Old Style C */ \n"); |
| + } |
| +} |
| + |
| +static void |
| +pprocdef(proc_list *proc, version_list *vp, char *addargtype, |
| + int server_p, int mode) |
| +{ |
| + ptype(proc->res_prefix, proc->res_type, 1); |
| + f_print(fout, "* "); |
| + if (server_p) |
| + pvname_svc(proc->proc_name, vp->vers_num); |
| + else |
| + pvname(proc->proc_name, vp->vers_num); |
| + |
| + /* |
| + * mode 0 == cplusplus, mode 1 = ANSI-C, mode 2 = old style C |
| + */ |
| + if (mode == 0 || mode == 1) |
| + parglist(proc, addargtype); |
| + else |
| + f_print(fout, "();\n"); |
| +} |
| + |
| + |
| + |
| +/* print out argument list of procedure */ |
| +static void |
| +parglist(proc_list *proc, char *addargtype) |
| +{ |
| + decl_list *dl; |
| + |
| + f_print(fout, "("); |
| + |
| + if (proc->arg_num < 2 && newstyle && |
| + streq(proc->args.decls->decl.type, "void")) { |
| + /* 0 argument in new style: do nothing */ |
| + } else { |
| + for (dl = proc->args.decls; dl != NULL; dl = dl->next) { |
| + ptype(dl->decl.prefix, dl->decl.type, 1); |
| + if (!newstyle) |
| + f_print(fout, "*"); /* old style passes by reference */ |
| + |
| + f_print(fout, ", "); |
| + } |
| + } |
| + |
| + f_print(fout, "%s);\n", addargtype); |
| +} |
| + |
| +static void |
| +penumdef(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 void |
| +ptypedef(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"); |
| + } |
| +} |
| + |
| +void |
| +pdeclaration(char *name, declaration *dec, int tab, char *separator) |
| +{ |
| + 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, separator ); |
| +} |
| + |
| +static int |
| +undefined2(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/rpcgen/rpc_main.c b/rpcgen/rpc_main.c |
| new file mode 100644 |
| index 0000000..28aa60c |
| --- /dev/null |
| +++ b/rpcgen/rpc_main.c |
| @@ -0,0 +1,1067 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| +static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI"; |
| +#endif |
| + |
| +/* |
| + * rpc_main.c, Top level of the RPC protocol compiler. |
| + */ |
| + |
| +#include <sys/types.h> |
| +#include <sys/param.h> |
| +#include <sys/file.h> |
| +#include <sys/stat.h> |
| +#include <stdio.h> |
| +#include <string.h> |
| +#include <stdlib.h> |
| +#include <unistd.h> |
| +#include <ctype.h> |
| +#include <errno.h> |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| +#include "rpc_scan.h" |
| + |
| +struct commandline { |
| + int cflag; /* xdr C routines */ |
| + int hflag; /* header file */ |
| + int lflag; /* client side stubs */ |
| + int mflag; /* server side stubs */ |
| + int nflag; /* netid flag */ |
| + int sflag; /* server stubs for the given transport */ |
| + int tflag; /* dispatch Table file */ |
| + int Ssflag; /* produce server sample code */ |
| + int Scflag; /* produce client sample code */ |
| + char *infile; /* input module name */ |
| + char *outfile; /* output module name */ |
| +}; |
| + |
| +static char * extendfile(char *file, char *ext); |
| +static void open_output(char *infile, char *outfile); |
| +static void add_warning(void); |
| +static void clear_args(void); |
| +static void open_input(char *infile, char *define); |
| +static int check_nettype(char *name, char **list_to_check); |
| +static void c_output(char *infile, char *define, int extend, char *outfile); |
| +static void c_initialize(void); |
| +static char * generate_guard(char *pathname); |
| +static void h_output(char *infile, char *define, int extend, char *outfile); |
| +static void s_output(int argc, char **argv, char *infile, |
| + char *define, int extend, char *outfile, |
| + int nomain, int netflag); |
| +static void l_output(char *infile, char *define, int extend, char *outfile); |
| +static void t_output(char *infile, char *define, int extend, char *outfile); |
| +static void svc_output(char *, char *, int, char *); |
| +static void clnt_output(char *, char *, int, char *); |
| +static int do_registers(int argc, char **argv); |
| +static void addarg(char *cp); |
| +static void putarg(int where, char *cp); |
| +static void checkfiles(char *infile, char *outfile); |
| +static int parseargs(int argc, char **argv, struct commandline *cmd); |
| +static void usage(void); |
| +static void options_usage(void); |
| + |
| +/* |
| +extern void write_sample_svc(); |
| +int write_sample_clnt(); |
| +void write_sample_clnt_main(); |
| + |
| +static svc_output(); |
| + */ |
| + |
| +#define EXTEND 1 /* alias for TRUE */ |
| +#define DONT_EXTEND 0 /* alias for FALSE */ |
| + |
| +#define SVR4_CPP "/usr/ccs/lib/cpp" |
| +#define SUNOS_CPP "/lib/cpp" |
| +static int cppDefined = 0; /* explicit path for C preprocessor */ |
| + |
| + |
| +static char *cmdname; |
| + |
| +static char *svcclosetime = "120"; |
| +static char *CPP = SVR4_CPP; |
| +static char CPPFLAGS[] = "-C"; |
| +static char pathbuf[MAXPATHLEN + 1]; |
| +static char *allv[] = { |
| + "rpcgen", "-s", "udp", "-s", "tcp", |
| +}; |
| +static int allc = sizeof(allv)/sizeof(allv[0]); |
| +static char *allnv[] = { |
| + "rpcgen", "-s", "netpath", |
| +}; |
| +static int allnc = sizeof(allnv)/sizeof(allnv[0]); |
| + |
| +/* |
| + * machinations for handling expanding argument list |
| + */ |
| +#if 0 |
| +static void addarg(); /* add another argument to the list */ |
| +static void putarg(); /* put argument at specified location */ |
| +static void clear_args(); /* clear argument list */ |
| +static void checkfiles(); /* check if out file already exists */ |
| +#endif |
| + |
| + |
| + |
| +#define ARGLISTLEN 20 |
| +#define FIXEDARGS 2 |
| + |
| +static char *arglist[ARGLISTLEN]; |
| +static int argcount = FIXEDARGS; |
| + |
| + |
| +int nonfatalerrors; /* errors */ |
| +int inetdflag/* = 1*/; /* Support for inetd */ /* is now the default */ |
| +int pmflag; /* Support for port monitors */ |
| +int logflag; /* Use syslog instead of fprintf for errors */ |
| +int tblflag; /* Support for dispatch table file */ |
| + |
| +/* length at which to start doing an inline */ |
| +#define INLINE 3 |
| + |
| +int Inline = INLINE; /* length at which to start doing an inline. 3 = default |
| + * if 0, no xdr_inline code */ |
| + |
| +int indefinitewait; /* If started by port monitors, hang till it wants */ |
| +int exitnow; /* If started by port monitors, exit after the call */ |
| +int timerflag; /* TRUE if !indefinite && !exitnow */ |
| +int newstyle; /* newstyle of passing arguments (by value) */ |
| +int Cflag = 0 ; /* ANSI C syntax */ |
| +static int allfiles; /* generate all files */ |
| +#ifdef linux |
| +int tirpcflag = 0; /* no tirpc by default */ |
| +#else |
| +int tirpcflag = 1; /* generating code for tirpc, by default */ |
| +#endif |
| + |
| +int |
| +main(int argc, char **argv) |
| +{ |
| + struct commandline cmd; |
| + |
| + (void) memset((char *) &cmd, 0, sizeof(struct commandline)); |
| + clear_args(); |
| + if (!parseargs(argc, argv, &cmd)) |
| + usage(); |
| + |
| + if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag || |
| + cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) { |
| + checkfiles(cmd.infile, cmd.outfile); |
| + } else |
| + checkfiles(cmd.infile, NULL); |
| + |
| + if (cmd.cflag) { |
| + c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); |
| + } else if (cmd.hflag) { |
| + h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); |
| + } else if (cmd.lflag) { |
| + l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); |
| + } else if (cmd.sflag || cmd.mflag || (cmd.nflag)) { |
| + s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, |
| + cmd.outfile, cmd.mflag, cmd.nflag); |
| + } else if (cmd.tflag) { |
| + t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile); |
| + } else if (cmd.Ssflag) { |
| + svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile); |
| + } else if (cmd.Scflag) { |
| + clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile); |
| + } else { |
| + /* the rescans are required, since cpp may effect input */ |
| + 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(); |
| + if (inetdflag || !tirpcflag) |
| + s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, |
| + "_svc.c", cmd.mflag, cmd.nflag); |
| + else |
| + s_output(allnc, allnv, cmd.infile, "-DRPC_SVC", |
| + EXTEND, "_svc.c", cmd.mflag, cmd.nflag); |
| + if (tblflag) { |
| + reinitialize(); |
| + t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); |
| + } |
| + if (allfiles) { |
| + reinitialize(); |
| + svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c"); |
| + } |
| + if (allfiles) { |
| + reinitialize(); |
| + clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c"); |
| + } |
| + } |
| + exit(nonfatalerrors); |
| + /* NOTREACHED */ |
| +} |
| + |
| +/* |
| + * add extension to filename |
| + */ |
| +static char * |
| +extendfile(char *file, char *ext) |
| +{ |
| + char *res; |
| + char *p; |
| + |
| + res = alloc(strlen(file) + strlen(ext) + 1); |
| + if (res == NULL) { |
| + abort(); |
| + } |
| + p = strrchr(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 void |
| +open_output(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); |
| + |
| +} |
| + |
| +static void |
| +add_warning(void) |
| +{ |
| + f_print(fout, "/*\n"); |
| + f_print(fout, " * Please do not edit this file.\n"); |
| + f_print(fout, " * It was generated using rpcgen.\n"); |
| + f_print(fout, " */\n\n"); |
| +} |
| + |
| +/* clear list of arguments */ |
| +static void |
| +clear_args(void) |
| +{ |
| + int i; |
| + for( i=FIXEDARGS; i<ARGLISTLEN; i++ ) |
| + arglist[i] = NULL; |
| + argcount = FIXEDARGS; |
| +} |
| + |
| +/* |
| + * Open input file with given define for C-preprocessor |
| + */ |
| +static void |
| +open_input(char *infile, char *define) |
| +{ |
| + int pd[2]; |
| + |
| + infilename = (infile == NULL) ? "<stdin>" : infile; |
| + (void) pipe(pd); |
| + switch (fork()) { |
| + case 0: |
| + putarg(0, "cpp"); |
| + putarg(1, CPPFLAGS); |
| + addarg(define); |
| + addarg(infile); |
| + addarg((char *)NULL); |
| + (void) close(1); |
| + (void) dup2(pd[1], 1); |
| + (void) close(pd[0]); |
| + if (cppDefined) |
| + execv(CPP, arglist); |
| + else { |
| + execvp("cpp", arglist); |
| + if (errno == ENOENT) |
| + execvp(SVR4_CPP, arglist); |
| + if (errno == ENOENT) |
| + execvp(SUNOS_CPP, arglist); |
| + } |
| + perror("execv"); |
| + 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(); |
| + } |
| +} |
| + |
| +/* valid tirpc nettypes */ |
| +static char* valid_ti_nettypes[] = |
| +{ |
| + "netpath", |
| + "visible", |
| + "circuit_v", |
| + "datagram_v", |
| + "circuit_n", |
| + "datagram_n", |
| + "udp", |
| + "tcp", |
| + "raw", |
| + NULL |
| +}; |
| + |
| +/* valid inetd nettypes */ |
| +static char* valid_i_nettypes[] = |
| +{ |
| + "udp", |
| + "tcp", |
| + NULL |
| +}; |
| + |
| +static int |
| +check_nettype(char *name, char **list_to_check) |
| +{ |
| + int i; |
| + for( i = 0; list_to_check[i] != NULL; i++ ) { |
| + if( strcmp( name, list_to_check[i] ) == 0 ) { |
| + return 1; |
| + } |
| + } |
| + f_print( stderr, "illegal nettype :\'%s\'\n", name ); |
| + return 0; |
| +} |
| + |
| +/* |
| + * Compile into an XDR routine output file |
| + */ |
| + |
| +static void |
| +c_output(char *infile, char *define, int extend, char *outfile) |
| +{ |
| + definition *def; |
| + char *include; |
| + char *outfilename; |
| + long tell; |
| + |
| + c_initialize(); |
| + open_input(infile, define); |
| + outfilename = extend ? extendfile(infile, outfile) : outfile; |
| + open_output(infile, outfilename); |
| + add_warning(); |
| + if (infile && (include = extendfile(infile, ".h"))) { |
| + f_print(fout, "#include \"%s\"\n", include); |
| + free(include); |
| + /* .h file already contains rpc/rpc.h */ |
| + } else |
| + f_print(fout, "#include <rpc/rpc.h>\n"); |
| + tell = ftell(fout); |
| + while ((def = get_definition()) != NULL) { |
| + emit(def); |
| + } |
| + if (extend && tell == ftell(fout)) { |
| + (void) unlink(outfilename); |
| + } |
| +} |
| + |
| + |
| +static void |
| +c_initialize(void) |
| +{ |
| + |
| + /* add all the starting basic types */ |
| + |
| + add_type(1,"int"); |
| + add_type(1,"int32_t"); |
| + add_type(1,"short"); |
| + add_type(1,"bool"); |
| + |
| + add_type(1,"u_int"); |
| + add_type(1,"u_int32_t"); |
| + add_type(1,"u_short"); |
| + |
| +} |
| + |
| +char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ |
| + char *(*proc)();\n\ |
| + xdrproc_t xdr_arg;\n\ |
| + unsigned len_arg;\n\ |
| + xdrproc_t xdr_res;\n\ |
| + unsigned len_res;\n\ |
| +};\n"; |
| + |
| + |
| +static char * |
| +generate_guard(char *pathname) |
| +{ |
| + char* filename, *guard, *tmp; |
| + |
| + filename = strrchr(pathname, '/' ); /* find last component */ |
| + filename = ((filename == 0) ? pathname : filename+1); |
| + guard = strdup(filename); |
| + /* convert to upper case */ |
| + tmp = guard; |
| + while (*tmp) { |
| + if (islower(*tmp)) |
| + *tmp = toupper(*tmp); |
| + tmp++; |
| + } |
| + |
| + guard = extendfile(guard, "_H_RPCGEN"); |
| + return( guard ); |
| +} |
| + |
| +/* |
| + * Compile into an XDR header file |
| + */ |
| +static void |
| +h_output(char *infile, char *define, int extend, char *outfile) |
| +{ |
| + definition *def; |
| + char *outfilename; |
| + long tell; |
| + char *guard; |
| + list *l; |
| + |
| + open_input(infile, define); |
| + outfilename = extend ? extendfile(infile, outfile) : outfile; |
| + open_output(infile, outfilename); |
| + add_warning(); |
| + guard = generate_guard( outfilename ? outfilename: infile ); |
| + |
| + f_print(fout,"#ifndef _%s\n#define _%s\n\n", guard, |
| + guard); |
| + |
| + f_print(fout, "#include <rpc/rpc.h>\n\n"); |
| + |
| + f_print(fout, "#ifndef IXDR_GET_INT32\n"); |
| + f_print(fout, "#define IXDR_GET_INT32(buf) IXDR_GET_LONG((buf))\n"); |
| + f_print(fout, "#endif\n"); |
| + f_print(fout, "#ifndef IXDR_PUT_INT32\n"); |
| + f_print(fout, "#define IXDR_PUT_INT32(buf, v) IXDR_PUT_LONG((buf), (v))\n"); |
| + f_print(fout, "#endif\n"); |
| + f_print(fout, "#ifndef IXDR_GET_U_INT32\n"); |
| + f_print(fout, "#define IXDR_GET_U_INT32(buf) IXDR_GET_U_LONG((buf))\n"); |
| + f_print(fout, "#endif\n"); |
| + f_print(fout, "#ifndef IXDR_PUT_U_INT32\n"); |
| + f_print(fout, "#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_U_LONG((buf), (v))\n"); |
| + f_print(fout, "#endif\n"); |
| + |
| + tell = ftell(fout); |
| + /* print data definitions */ |
| + while ((def = get_definition()) != NULL) { |
| + print_datadef(def); |
| + } |
| + |
| + /* print function declarations. |
| + Do this after data definitions because they might be used as |
| + arguments for functions */ |
| + for (l = defined; l != NULL; l = l->next) { |
| + print_funcdef(l->val); |
| + } |
| + if (extend && tell == ftell(fout)) { |
| + (void) unlink(outfilename); |
| + } else if (tblflag) { |
| + f_print(fout, rpcgen_table_dcl); |
| + } |
| + f_print(fout, "\n#endif /* !_%s */\n", guard); |
| +} |
| + |
| +/* |
| + * Compile into an RPC service |
| + */ |
| +static void |
| +s_output(int argc, char **argv, char *infile, char *define, int extend, |
| + char *outfile, int nomain, int netflag) |
| +{ |
| + char *include; |
| + definition *def; |
| + int foundprogram = 0; |
| + char *outfilename; |
| + |
| + open_input(infile, define); |
| + outfilename = extend ? extendfile(infile, outfile) : outfile; |
| + open_output(infile, outfilename); |
| + add_warning(); |
| + if (infile && (include = extendfile(infile, ".h"))) { |
| + f_print(fout, "#include \"%s\"\n", include); |
| + free(include); |
| + } else |
| + f_print(fout, "#include <rpc/rpc.h>\n"); |
| + |
| + f_print(fout, "#include <stdio.h>\n"); |
| + f_print(fout, "#include <stdlib.h>/* getenv, exit */\n"); |
| + if (Cflag) { |
| + f_print (fout, "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n"); |
| + f_print (fout, "#include <string.h> /* strcmp */ \n"); |
| + } |
| + if (strcmp(svcclosetime, "-1") == 0) |
| + indefinitewait = 1; |
| + else if (strcmp(svcclosetime, "0") == 0) |
| + exitnow = 1; |
| + else if (inetdflag || pmflag) { |
| + f_print(fout, "#include <signal.h>\n"); |
| + timerflag = 1; |
| + } |
| + |
| +#ifndef linux |
| + if( !tirpcflag && inetdflag ) |
| + f_print(fout, "#include <sys/ttycom.h>/* TIOCNOTTY */\n"); |
| +#else |
| + if( !tirpcflag ) |
| + f_print(fout, "#include <sys/ioctl.h>/* TIOCNOTTY */\n"); |
| +#endif |
| + if( Cflag && (inetdflag || pmflag ) ) { |
| + f_print(fout, "#ifdef __cplusplus\n"); |
| + f_print(fout, "#include <sysent.h> /* getdtablesize, open */\n"); |
| + f_print(fout, "#endif /* __cplusplus */\n"); |
| + |
| + if( tirpcflag ) |
| + f_print(fout, "#include <unistd.h> /* setsid */\n"); |
| + } |
| + if( tirpcflag ) |
| + f_print(fout, "#include <sys/types.h>\n"); |
| + |
| + f_print(fout, "#include <memory.h>\n"); |
| +#ifndef linux |
| + f_print(fout, "#include <stropts.h>\n"); |
| +#endif |
| + if (inetdflag || !tirpcflag ) { |
| + f_print(fout, "#include <sys/socket.h>\n"); |
| + f_print(fout, "#include <netinet/in.h>\n"); |
| + } |
| + |
| + if ( (netflag || pmflag) && tirpcflag ) { |
| + f_print(fout, "#include <netconfig.h>\n"); |
| + } |
| + if (/*timerflag &&*/ tirpcflag) |
| + f_print(fout, "#include <sys/resource.h> /* rlimit */\n"); |
| + if (logflag || inetdflag || pmflag) { |
| +#ifdef linux |
| + f_print(fout, "#include <syslog.h>\n"); |
| +#else |
| + f_print(fout, "#ifdef SYSLOG\n"); |
| + f_print(fout, "#include <syslog.h>\n"); |
| + f_print(fout, "#else\n"); |
| + f_print(fout, "#define LOG_ERR 1\n"); |
| + f_print(fout, "#define openlog(a, b, c)\n"); |
| + f_print(fout, "#endif\n"); |
| +#endif |
| + } |
| + |
| + /* for ANSI-C */ |
| + f_print(fout, "\n#ifdef __STDC__\n#define SIG_PF void(*)(int)\n#endif\n"); |
| + |
| + f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n"); |
| + if (timerflag) |
| + f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime); |
| + while ((def = get_definition()) != NULL) { |
| + foundprogram |= (def->def_kind == DEF_PROGRAM); |
| + } |
| + if (extend && !foundprogram) { |
| + (void) unlink(outfilename); |
| + return; |
| + } |
| + write_most(infile, netflag, nomain); |
| + if (!nomain) { |
| + if( !do_registers(argc, argv) ) { |
| + if (outfilename) |
| + (void) unlink(outfilename); |
| + usage(); |
| + } |
| + write_rest(); |
| + } |
| +} |
| + |
| +/* |
| + * generate client side stubs |
| + */ |
| +static void |
| +l_output(char *infile, char *define, int extend, char *outfile) |
| +{ |
| + char *include; |
| + definition *def; |
| + int foundprogram = 0; |
| + char *outfilename; |
| + |
| + open_input(infile, define); |
| + outfilename = extend ? extendfile(infile, outfile) : outfile; |
| + open_output(infile, outfilename); |
| + add_warning(); |
| + if (Cflag) |
| + f_print (fout, "#include <memory.h> /* for memset */\n"); |
| + if (infile && (include = extendfile(infile, ".h"))) { |
| + f_print(fout, "#include \"%s\"\n", include); |
| + free(include); |
| + } else |
| + f_print(fout, "#include <rpc/rpc.h>\n"); |
| + while ((def = get_definition()) != NULL) { |
| + foundprogram |= (def->def_kind == DEF_PROGRAM); |
| + } |
| + if (extend && !foundprogram) { |
| + (void) unlink(outfilename); |
| + return; |
| + } |
| + write_stubs(); |
| +} |
| + |
| +/* |
| + * generate the dispatch table |
| + */ |
| +static void |
| +t_output(char *infile, char *define, int extend, char *outfile) |
| +{ |
| + definition *def; |
| + int foundprogram = 0; |
| + char *outfilename; |
| + |
| + open_input(infile, define); |
| + outfilename = extend ? extendfile(infile, outfile) : outfile; |
| + open_output(infile, outfilename); |
| + add_warning(); |
| + while ((def = get_definition()) != NULL) { |
| + foundprogram |= (def->def_kind == DEF_PROGRAM); |
| + } |
| + if (extend && !foundprogram) { |
| + (void) unlink(outfilename); |
| + return; |
| + } |
| + write_tables(); |
| +} |
| + |
| +/* sample routine for the server template */ |
| +static void |
| +svc_output(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; |
| + checkfiles(infile,outfilename); /*check if outfile already exists. |
| + if so, print an error message and exit*/ |
| + open_output(infile, outfilename); |
| + add_sample_msg(); |
| + |
| + if (infile && (include = extendfile(infile, ".h"))) { |
| + f_print(fout, "#include \"%s\"\n", include); |
| + free(include); |
| + } else |
| + f_print(fout, "#include <rpc/rpc.h>\n"); |
| + |
| + tell = ftell(fout); |
| + while ((def = get_definition()) != NULL) { |
| + write_sample_svc(def); |
| + } |
| + if (extend && tell == ftell(fout)) { |
| + (void) unlink(outfilename); |
| + } |
| +} |
| + |
| + |
| +/* sample main routine for client */ |
| +static void |
| +clnt_output(char *infile, char *define, int extend, char *outfile) |
| +{ |
| + definition *def; |
| + char *include; |
| + char *outfilename; |
| + long tell; |
| + int has_program = 0; |
| + |
| + open_input(infile, define); |
| + outfilename = extend ? extendfile(infile, outfile) : outfile; |
| + checkfiles(infile, outfilename); /*check if outfile already exists. |
| + if so, print an error message and exit*/ |
| + |
| + open_output(infile, outfilename); |
| + add_sample_msg(); |
| + if (infile && (include = extendfile(infile, ".h"))) { |
| + f_print(fout, "#include \"%s\"\n", include); |
| + free(include); |
| + } else |
| + f_print(fout, "#include <rpc/rpc.h>\n"); |
| + tell = ftell(fout); |
| + while ((def = get_definition()) != NULL) { |
| + has_program += write_sample_clnt(def); |
| + } |
| + |
| + if (has_program) |
| + write_sample_clnt_main(); |
| + |
| + if (extend && tell == ftell(fout)) { |
| + (void) unlink(outfilename); |
| + } |
| +} |
| + |
| +/* |
| + * Perform registrations for service output |
| + * Return 0 if failed; 1 otherwise. |
| + */ |
| +static int |
| +do_registers(int argc, char **argv) |
| +{ |
| + int i; |
| + |
| + if (inetdflag || !tirpcflag) { |
| + for (i = 1; i < argc; i++) { |
| + if (streq(argv[i], "-s")) { |
| + if (!check_nettype(argv[i + 1], valid_i_nettypes)) |
| + return 0; |
| + write_inetd_register(argv[i + 1]); |
| + i++; |
| + } |
| + } |
| + } else { |
| + for (i = 1; i < argc; i++) |
| + if (streq(argv[i], "-s")) { |
| + if (!check_nettype(argv[i + 1], valid_ti_nettypes)) |
| + return 0; |
| + write_nettype_register(argv[i + 1]); |
| + i++; |
| + } else if (streq(argv[i], "-n")) { |
| + write_netid_register(argv[i + 1]); |
| + i++; |
| + } |
| + } |
| + return 1; |
| +} |
| + |
| +/* |
| + * Add another argument to the arg list |
| + */ |
| +static void |
| +addarg(char *cp) |
| +{ |
| + if (argcount >= ARGLISTLEN) { |
| + f_print(stderr, "rpcgen: too many defines\n"); |
| + crash(); |
| + /*NOTREACHED*/ |
| + } |
| + arglist[argcount++] = cp; |
| + |
| +} |
| + |
| +static void |
| +putarg(int where, char *cp) |
| +{ |
| + if (where >= ARGLISTLEN) { |
| + f_print(stderr, "rpcgen: arglist coding error\n"); |
| + crash(); |
| + /*NOTREACHED*/ |
| + } |
| + arglist[where] = cp; |
| + |
| +} |
| + |
| +/* |
| + * if input file is stdin and an output file is specified then complain |
| + * if the file already exists. Otherwise the file may get overwritten |
| + * If input file does not exist, exit with an error |
| + */ |
| + |
| +static void |
| +checkfiles(char *infile, char *outfile) |
| +{ |
| + |
| + struct stat buf; |
| + |
| + if(infile) /* infile ! = NULL */ |
| + if(stat(infile,&buf) < 0) |
| + { |
| + perror(infile); |
| + crash(); |
| + }; |
| + if (outfile) { |
| + if (stat(outfile, &buf) < 0) |
| + return; /* file does not exist */ |
| + else { |
| + f_print(stderr, |
| + "file '%s' already exists and may be overwritten\n", outfile); |
| + crash(); |
| + } |
| + } |
| +} |
| + |
| +/* |
| + * Parse command line arguments |
| + */ |
| +static int |
| +parseargs(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); |
| + } |
| + allfiles = 0; |
| + flag['c'] = 0; |
| + flag['h'] = 0; |
| + flag['l'] = 0; |
| + flag['m'] = 0; |
| + flag['o'] = 0; |
| + flag['s'] = 0; |
| + flag['n'] = 0; |
| + flag['t'] = 0; |
| + flag['S'] = 0; |
| + flag['C'] = 0; |
| + for (i = 1; i < argc; i++) { |
| + if (argv[i][0] != '-') { |
| + if (cmd->infile) { |
| + f_print( stderr, "Cannot specify more than one input file!\n"); |
| + |
| + return (0); |
| + } |
| + cmd->infile = argv[i]; |
| + } else { |
| + for (j = 1; argv[i][j] != 0; j++) { |
| + c = argv[i][j]; |
| + switch (c) { |
| + case 'a': |
| + allfiles = 1; |
| + break; |
| + case 'c': |
| + case 'h': |
| + case 'l': |
| + case 'm': |
| + case 't': |
| + if (flag[(int) c]) { |
| + return (0); |
| + } |
| + flag[(int) c] = 1; |
| + break; |
| + case 'S': |
| + /* sample flag: Ss or Sc. |
| + Ss means set flag['S']; |
| + Sc means set flag['C']; */ |
| + c = argv[i][++j]; /* get next char */ |
| + if( c == 's' ) |
| + c = 'S'; |
| + else if( c == 'c' ) |
| + c = 'C'; |
| + else |
| + return( 0 ); |
| + |
| + if (flag[(int) c]) { |
| + return (0); |
| + } |
| + flag[(int) c] = 1; |
| + break; |
| + case 'C': /* ANSI C syntax */ |
| + Cflag = 1; |
| + break; |
| + |
| + case 'b': /* turn TIRPC flag off for |
| + generating backward compatible |
| + */ |
| + tirpcflag = 0; |
| + break; |
| + |
| + case 'I': |
| + inetdflag = 1; |
| + break; |
| + case 'N': |
| + newstyle = 1; |
| + break; |
| + case 'L': |
| + logflag = 1; |
| + break; |
| + case 'K': |
| + if (++i == argc) { |
| + return (0); |
| + } |
| + svcclosetime = argv[i]; |
| + goto nextarg; |
| + case 'T': |
| + tblflag = 1; |
| + break; |
| + case 'i' : |
| + if (++i == argc) { |
| + return (0); |
| + } |
| + Inline = atoi(argv[i]); |
| + goto nextarg; |
| + case 'n': |
| + case 'o': |
| + case 's': |
| + if (argv[i][j - 1] != '-' || |
| + argv[i][j + 1] != 0) { |
| + return (0); |
| + } |
| + flag[(int) 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; |
| + case 'D': |
| + if (argv[i][j - 1] != '-') { |
| + return (0); |
| + } |
| + (void) addarg(argv[i]); |
| + goto nextarg; |
| + case 'Y': |
| + if (++i == argc) { |
| + return (0); |
| + } |
| + (void) strcpy(pathbuf, argv[i]); |
| + (void) strcat(pathbuf, "/cpp"); |
| + CPP = pathbuf; |
| + cppDefined = 1; |
| + goto nextarg; |
| + |
| + |
| + |
| + default: |
| + return (0); |
| + } |
| + } |
| + nextarg: |
| + ; |
| + } |
| + } |
| + |
| + cmd->cflag = flag['c']; |
| + cmd->hflag = flag['h']; |
| + cmd->lflag = flag['l']; |
| + cmd->mflag = flag['m']; |
| + cmd->nflag = flag['n']; |
| + cmd->sflag = flag['s']; |
| + cmd->tflag = flag['t']; |
| + cmd->Ssflag = flag['S']; |
| + cmd->Scflag = flag['C']; |
| + |
| + if( tirpcflag ) { |
| + pmflag = inetdflag ? 0 : 1; /* pmflag or inetdflag is always TRUE */ |
| + if( (inetdflag && cmd->nflag)) { /* netid not allowed with inetdflag */ |
| + f_print(stderr, "Cannot use netid flag with inetd flag!\n"); |
| + return (0); |
| + } |
| + } else { /* 4.1 mode */ |
| + pmflag = 0; /* set pmflag only in tirpcmode */ |
| + inetdflag = 1; /* inetdflag is TRUE by default */ |
| + if( cmd->nflag ) { /* netid needs TIRPC */ |
| + f_print( stderr, "Cannot use netid flag without TIRPC!\n"); |
| + return( 0 ); |
| + } |
| + } |
| + |
| + if( newstyle && ( tblflag || cmd->tflag) ) { |
| + f_print( stderr, "Cannot use table flags with newstyle!\n"); |
| + return( 0 ); |
| + } |
| + |
| + /* check no conflicts with file generation flags */ |
| + nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + |
| + cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag; |
| + |
| + if (nflags == 0) { |
| + if (cmd->outfile != NULL || cmd->infile == NULL) { |
| + return (0); |
| + } |
| + } else if (nflags > 1) { |
| + f_print( stderr, "Cannot have more than one file generation flag!\n"); |
| + return (0); |
| + } |
| + return (1); |
| +} |
| + |
| +static void |
| +usage(void) |
| +{ |
| + f_print(stderr, "usage: %s infile\n", cmdname); |
| + f_print(stderr, "\t%s [-a][-b][-C][-Dname[=value]] -i size [-I [-K seconds]] [-L][-N][-T] infile\n", |
| + cmdname); |
| + f_print(stderr, "\t%s [-c | -h | -l | -m | -t | -Sc | -Ss] [-o outfile] [infile]\n", |
| + cmdname); |
| + f_print(stderr, "\t%s [-s nettype]* [-o outfile] [infile]\n", cmdname); |
| + f_print(stderr, "\t%s [-n netid]* [-o outfile] [infile]\n", cmdname); |
| + options_usage(); |
| + exit(1); |
| +} |
| + |
| +static void |
| +options_usage(void) |
| +{ |
| + f_print(stderr, "options:\n"); |
| + f_print(stderr, "-a\t\tgenerate all files, including samples\n"); |
| + f_print(stderr, "-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n"); |
| + f_print(stderr, "-c\t\tgenerate XDR routines\n"); |
| + f_print(stderr, "-C\t\tANSI C mode\n"); |
| + f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n"); |
| + f_print(stderr, "-h\t\tgenerate header file\n"); |
| + f_print(stderr, "-i size\t\tsize at which to start generating inline code\n"); |
| + f_print(stderr, "-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n"); |
| + f_print(stderr, "-K seconds\tserver exits after K seconds of inactivity\n"); |
| + f_print(stderr, "-l\t\tgenerate client side stubs\n"); |
| + f_print(stderr, "-L\t\tserver errors will be printed to syslog\n"); |
| + f_print(stderr, "-m\t\tgenerate server side stubs\n"); |
| + f_print(stderr, "-n netid\tgenerate server code that supports named netid\n"); |
| + f_print(stderr, "-N\t\tsupports multiple arguments and call-by-value\n"); |
| + f_print(stderr, "-o outfile\tname of the output file\n"); |
| + f_print(stderr, "-s nettype\tgenerate server code that supports named nettype\n"); |
| + f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote procedures\n"); |
| + f_print(stderr, "-Ss\t\tgenerate sample server code that defines remote procedures\n"); |
| + f_print(stderr, "-t\t\tgenerate RPC dispatch table\n"); |
| + f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n"); |
| + f_print(stderr, "-Y path\t\tdirectory name to find C preprocessor (cpp)\n"); |
| + |
| + exit(1); |
| +} |
| diff --git a/rpcgen/rpc_output.h b/rpcgen/rpc_output.h |
| new file mode 100644 |
| index 0000000..eb25a60 |
| --- /dev/null |
| +++ b/rpcgen/rpc_output.h |
| @@ -0,0 +1,16 @@ |
| +/* |
| + * rpc_output.h |
| + * |
| + * Declarations for output functions |
| + * |
| + */ |
| + |
| +#ifndef RPCGEN_NEW_OUTPUT_H |
| +#define RPCGEN_NEW_OUTPUT_H |
| + |
| +void write_msg_out(void); |
| +int nullproc(proc_list *); |
| +void printarglist(proc_list *, char *, char *); |
| +void pdeclaration(char *, declaration *, int, char *); |
| + |
| +#endif /* RPCGEN_NEW_OUTPUT_H */ |
| diff --git a/rpcgen/rpc_parse.c b/rpcgen/rpc_parse.c |
| new file mode 100644 |
| index 0000000..b53a553 |
| --- /dev/null |
| +++ b/rpcgen/rpc_parse.c |
| @@ -0,0 +1,609 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| +static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI"; |
| +#endif |
| + |
| +/* |
| + * rpc_parse.c, Parser for the RPC protocol compiler |
| + * Copyright (C) 1987 Sun Microsystems, Inc. |
| + */ |
| +#include <stdio.h> |
| +#include <string.h> |
| +#include "rpc/types.h" |
| +#include "rpc_scan.h" |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| + |
| +#define ARGNAME "arg" |
| + |
| +/* |
| +extern char *make_argname(); |
| +extern char *strdup(); |
| + */ |
| + |
| +static void isdefined(definition *defp); |
| +static void def_struct(definition *defp); |
| +static void def_program(definition *defp); |
| +static void def_enum(definition *defp); |
| +static void def_const(definition *defp); |
| +static void def_union(definition *defp); |
| +static void check_type_name(char *name, int new_type); |
| +static void def_typedef(definition *defp); |
| +static void get_declaration(declaration *dec, defkind dkind); |
| +static void get_prog_declaration(declaration *dec, defkind dkind, int num); |
| +static void get_type(char **prefixp, char **typep, defkind dkind); |
| +static void unsigned_dec(char **typep); |
| + |
| +/* |
| + * return the next definition you see |
| + */ |
| +definition * |
| +get_definition(void) |
| +{ |
| + 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: |
| + free(defp); |
| + return (NULL); |
| + default: |
| + error("definition keyword expected"); |
| + } |
| + scan(TOK_SEMICOLON, &tok); |
| + isdefined(defp); |
| + return (defp); |
| +} |
| + |
| +static void |
| +isdefined(definition *defp) |
| +{ |
| + STOREVAL(&defined, defp); |
| +} |
| + |
| +static void |
| +def_struct(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 void |
| +def_program(definition *defp) |
| +{ |
| + token tok; |
| + declaration dec; |
| + decl_list *decls; |
| + decl_list **tailp; |
| + version_list *vlist; |
| + version_list **vtailp; |
| + proc_list *plist; |
| + proc_list **ptailp; |
| + int num_args; |
| + bool_t isvoid = FALSE; /* whether first argument is void */ |
| + defp->def_kind = DEF_PROGRAM; |
| + scan(TOK_IDENT, &tok); |
| + defp->def_name = tok.str; |
| + scan(TOK_LBRACE, &tok); |
| + vtailp = &defp->def.pr.versions; |
| + tailp = &defp->def.st.decls; |
| + 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 { |
| + /* get result type */ |
| + 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 args - first one*/ |
| + num_args = 1; |
| + isvoid = FALSE; |
| + /* type of DEF_PROGRAM in the first |
| + * get_prog_declaration and DEF_STURCT in the next |
| + * allows void as argument if it is the only argument |
| + */ |
| + get_prog_declaration(&dec, DEF_PROGRAM, num_args); |
| + if (streq(dec.type, "void")) |
| + isvoid = TRUE; |
| + decls = ALLOC(decl_list); |
| + plist->args.decls = decls; |
| + decls->decl = dec; |
| + tailp = &decls->next; |
| + /* get args */ |
| + while(peekscan(TOK_COMMA, &tok)) { |
| + num_args++; |
| + get_prog_declaration(&dec, DEF_STRUCT, |
| + num_args); |
| + decls = ALLOC(decl_list); |
| + decls->decl = dec; |
| + *tailp = decls; |
| + if (streq(dec.type, "void")) |
| + isvoid = TRUE; |
| + tailp = &decls->next; |
| + } |
| + /* multiple arguments are only allowed in newstyle */ |
| + if( !newstyle && num_args > 1 ) { |
| + error("only one argument is allowed" ); |
| + } |
| + if (isvoid && num_args > 1) { |
| + error("illegal use of void in program definition"); |
| + } |
| + *tailp = NULL; |
| + scan(TOK_RPAREN, &tok); |
| + scan(TOK_EQUAL, &tok); |
| + scan_num(&tok); |
| + scan(TOK_SEMICOLON, &tok); |
| + plist->proc_num = tok.str; |
| + plist->arg_num = num_args; |
| + *ptailp = plist; |
| + ptailp = &plist->next; |
| + peek(&tok); |
| + } while (tok.kind != TOK_RBRACE); |
| + *ptailp = NULL; |
| + *vtailp = vlist; |
| + vtailp = &vlist->next; |
| + scan(TOK_RBRACE, &tok); |
| + scan(TOK_EQUAL, &tok); |
| + scan_num(&tok); |
| + vlist->vers_num = tok.str; |
| + /* make the argument structure name for each arg*/ |
| + for(plist = vlist->procs; plist != NULL; |
| + plist = plist->next) { |
| + plist->args.argname = make_argname(plist->proc_name, |
| + vlist->vers_num); |
| + /* free the memory ??*/ |
| + } |
| + 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 void |
| +def_enum(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 void |
| +def_const(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 void |
| +def_union(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) { |
| + scan2(TOK_IDENT, TOK_CHARCONST, &tok); |
| + cases = ALLOC(case_list); |
| + cases->case_name = tok.str; |
| + scan(TOK_COLON, &tok); |
| + /* now peek at next token */ |
| + if(peekscan(TOK_CASE,&tok)) |
| + { |
| + |
| + do |
| + { |
| + scan2(TOK_IDENT, TOK_CHARCONST, &tok); |
| + cases->contflag=1; /* continued case statement */ |
| + *tailp = cases; |
| + tailp = &cases->next; |
| + cases = ALLOC(case_list); |
| + cases->case_name = tok.str; |
| + scan(TOK_COLON, &tok); |
| + |
| + }while(peekscan(TOK_CASE,&tok)); |
| + } |
| + |
| + get_declaration(&dec, DEF_UNION); |
| + cases->case_decl = dec; |
| + cases->contflag=0; /* no continued case statement */ |
| + *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 char* reserved_words[] = |
| +{ |
| + "array", |
| + "bytes", |
| + "destroy", |
| + "free", |
| + "getpos", |
| + "inline", |
| + "pointer", |
| + "reference", |
| + "setpos", |
| + "sizeof", |
| + "union", |
| + "vector", |
| + NULL |
| + }; |
| + |
| +static char* reserved_types[] = |
| +{ |
| + "opaque", |
| + "string", |
| + NULL |
| + }; |
| + |
| +/* check that the given name is not one that would eventually result in |
| + xdr routines that would conflict with internal XDR routines. */ |
| +static void |
| +check_type_name(char *name, int new_type) |
| +{ |
| + int i; |
| + char tmp[100]; |
| + |
| + for( i = 0; reserved_words[i] != NULL; i++ ) { |
| + if( strcmp( name, reserved_words[i] ) == 0 ) { |
| + sprintf(tmp, |
| + "illegal (reserved) name :\'%s\' in type definition", name ); |
| + error(tmp); |
| + } |
| + } |
| + if( new_type ) { |
| + for( i = 0; reserved_types[i] != NULL; i++ ) { |
| + if( strcmp( name, reserved_types[i] ) == 0 ) { |
| + sprintf(tmp, |
| + "illegal (reserved) name :\'%s\' in type definition", name ); |
| + error(tmp); |
| + } |
| + } |
| + } |
| +} |
| + |
| +static void |
| +def_typedef(definition *defp) |
| +{ |
| + declaration dec; |
| + |
| + defp->def_kind = DEF_TYPEDEF; |
| + get_declaration(&dec, DEF_TYPEDEF); |
| + defp->def_name = dec.name; |
| + check_type_name( dec.name, 1 ); |
| + 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 void |
| +get_declaration(declaration *dec, defkind dkind) |
| +{ |
| + token tok; |
| + |
| + get_type(&dec->prefix, &dec->type, dkind); |
| + dec->rel = REL_ALIAS; |
| + if (streq(dec->type, "void")) { |
| + return; |
| + } |
| + |
| + check_type_name( dec->type, 0 ); |
| + |
| + 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 void |
| +get_prog_declaration(declaration *dec, defkind dkind, int num) |
| +{ |
| + token tok; |
| + char name[10]; /* argument name */ |
| + |
| + if (dkind == DEF_PROGRAM) { |
| + peek(&tok); |
| + if (tok.kind == TOK_RPAREN) { /* no arguments */ |
| + dec->rel = REL_ALIAS; |
| + dec->type = "void"; |
| + dec->prefix = NULL; |
| + dec->name = NULL; |
| + return; |
| + } |
| + } |
| + get_type(&dec->prefix, &dec->type, dkind); |
| + dec->rel = REL_ALIAS; |
| + if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ |
| + strcpy(name, tok.str); |
| + else |
| + sprintf(name, "%s%d", ARGNAME, num); /* default name of argument */ |
| + |
| + dec->name = (char *) strdup(name); |
| + |
| + if (streq(dec->type, "void")) { |
| + return; |
| + } |
| + |
| + if (streq(dec->type, "opaque")) { |
| + error("opaque -- illegal argument type"); |
| + } |
| + if (peekscan(TOK_STAR, &tok)) { |
| + if (streq(dec->type, "string")) { |
| + error("pointer to string not allowed in program arguments\n"); |
| + } |
| + dec->rel = REL_POINTER; |
| + if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ |
| + dec->name = strdup(tok.str); |
| + } |
| + if (peekscan(TOK_LANGLE, &tok)) { |
| + if (!streq(dec->type, "string")) { |
| + error("arrays cannot be declared as arguments to procedures -- 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, "string")) { |
| + if (dec->rel != REL_ARRAY) { /* .x specifies just string as |
| + * type of argument |
| + * - make it string<> |
| + */ |
| + dec->rel = REL_ARRAY; |
| + dec->array_max = "~0";/* unspecified size, use max */ |
| + } |
| + } |
| +} |
| + |
| + |
| + |
| +static void |
| +get_type(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_INT32: |
| + *typep = "int32_t"; |
| + (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 with one argument"); |
| + } |
| + *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 void |
| +unsigned_dec(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_INT32: |
| + get_token(&tok); |
| + *typep = "u_int32_"; |
| + (void) peekscan(TOK_INT, &tok); |
| + break; |
| + case TOK_INT: |
| + get_token(&tok); |
| + *typep = "u_int"; |
| + break; |
| + default: |
| + *typep = "u_int"; |
| + break; |
| + } |
| +} |
| diff --git a/rpcgen/rpc_parse.h b/rpcgen/rpc_parse.h |
| new file mode 100644 |
| index 0000000..2afae10 |
| --- /dev/null |
| +++ b/rpcgen/rpc_parse.h |
| @@ -0,0 +1,166 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +/* @(#)rpc_parse.h 1.3 90/08/29 (C) 1987 SMI */ |
| + |
| +/* |
| + * rpc_parse.h, Definitions for the RPCL parser |
| + */ |
| + |
| +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; |
| + int contflag; |
| + 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 arg_list { |
| + char *argname; /* name of struct for arg*/ |
| + decl_list *decls; |
| +}; |
| + |
| +typedef struct arg_list arg_list; |
| + |
| +struct proc_list { |
| + char *proc_name; |
| + char *proc_num; |
| + arg_list args; |
| + int arg_num; |
| + 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; |
| + |
| +definition *get_definition(); |
| + |
| + |
| +struct bas_type |
| +{ |
| + char *name; |
| + int length; |
| + struct bas_type *next; |
| +}; |
| + |
| +typedef struct bas_type bas_type; |
| diff --git a/rpcgen/rpc_sample.c b/rpcgen/rpc_sample.c |
| new file mode 100644 |
| index 0000000..2b5c81b |
| --- /dev/null |
| +++ b/rpcgen/rpc_sample.c |
| @@ -0,0 +1,247 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| +static char sccsid[] = "@(#)rpc_sample.c 1.1 90/08/30 (C) 1987 SMI"; |
| + |
| +#endif |
| + |
| +/* |
| + * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler |
| + */ |
| + |
| +#include <stdio.h> |
| +#include <string.h> |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| + |
| + |
| +static char RQSTP[] = "rqstp"; |
| + |
| +static void write_sample_client(char *program_name, version_list *vp); |
| +static void write_sample_server(definition * def); |
| +static void return_type(proc_list *plist); |
| + |
| +void |
| +write_sample_svc(definition *def) |
| +{ |
| + if (def->def_kind != DEF_PROGRAM) |
| + return; |
| + write_sample_server(def); |
| +} |
| + |
| + |
| +int |
| +write_sample_clnt(definition *def) |
| +{ |
| + version_list *vp; |
| + int count = 0; |
| + |
| + if (def->def_kind != DEF_PROGRAM) |
| + return (0); |
| + /* generate sample code for each version */ |
| + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { |
| + write_sample_client(def->def_name, vp); |
| + ++count; |
| + } |
| + return (count); |
| +} |
| + |
| + |
| +static void |
| +write_sample_client(char *program_name, version_list *vp) |
| +{ |
| + proc_list *proc; |
| + int i; |
| + decl_list *l; |
| + |
| + f_print(fout, "\n\nvoid\n"); |
| + pvname(program_name, vp->vers_num); |
| + if (Cflag) |
| + f_print(fout, "( char* host )\n{\n"); |
| + else |
| + f_print(fout, "(host)\nchar *host;\n{\n"); |
| + f_print(fout, "\tCLIENT *clnt;\n"); |
| + |
| + i = 0; |
| + for (proc = vp->procs; proc != NULL; proc = proc->next) { |
| + f_print(fout, "\t"); |
| + ptype(proc->res_prefix, proc->res_type, 1); |
| + f_print(fout, " *result_%d;\n", ++i); |
| + /* print out declarations for arguments */ |
| + if (proc->arg_num < 2 && !newstyle) { |
| + f_print(fout, "\t"); |
| + if (!streq(proc->args.decls->decl.type, "void")) |
| + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); |
| + else |
| + f_print(fout, "char* "); /* cannot have "void" type */ |
| + f_print(fout, " "); |
| + pvname(proc->proc_name, vp->vers_num); |
| + f_print(fout, "_arg;\n"); |
| + } else if (!streq(proc->args.decls->decl.type, "void")) { |
| + for (l = proc->args.decls; l != NULL; l = l->next) { |
| + f_print(fout, "\t"); |
| + ptype(l->decl.prefix, l->decl.type, 1); |
| + f_print(fout, " "); |
| + pvname(proc->proc_name, vp->vers_num); |
| + f_print(fout, "_%s;\n", l->decl.name); |
| + /* pdeclaration(proc->args.argname, &l->decl, 1, ";\n" );*/ |
| + } |
| + } |
| + } |
| + |
| + /* generate creation of client handle */ |
| + f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n", |
| + program_name, vp->vers_name, tirpcflag ? "netpath" : "udp"); |
| + f_print(fout, "\tif (clnt == NULL) {\n"); |
| + f_print(fout, "\t\tclnt_pcreateerror(host);\n"); |
| + f_print(fout, "\t\texit(1);\n\t}\n"); |
| + |
| + /* generate calls to procedures */ |
| + i = 0; |
| + for (proc = vp->procs; proc != NULL; proc = proc->next) { |
| + f_print(fout, "\tresult_%d = ", ++i); |
| + pvname(proc->proc_name, vp->vers_num); |
| + if (proc->arg_num < 2 && !newstyle) { |
| + f_print(fout, "("); |
| + if (streq(proc->args.decls->decl.type, "void")) /* cast to void* */ |
| + f_print(fout, "(void*)"); |
| + f_print(fout, "&"); |
| + pvname(proc->proc_name, vp->vers_num); |
| + f_print(fout, "_arg, clnt);\n"); |
| + } else if (streq(proc->args.decls->decl.type, "void")) { |
| + f_print(fout, "(clnt);\n"); |
| + } else { |
| + f_print(fout, "("); |
| + for (l = proc->args.decls; l != NULL; l = l->next) { |
| + pvname(proc->proc_name, vp->vers_num); |
| + f_print(fout, "_%s, ", l->decl.name); |
| + } |
| + f_print(fout, "clnt);\n"); |
| + } |
| + f_print(fout, "\tif (result_%d == NULL) {\n", i); |
| + f_print(fout, "\t\tclnt_perror(clnt, \"call failed:\");\n"); |
| + f_print(fout, "\t}\n"); |
| + } |
| + |
| + f_print(fout, "\tclnt_destroy( clnt );\n"); |
| + f_print(fout, "}\n"); |
| +} |
| + |
| +static void |
| +write_sample_server(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"); |
| + /* if( Cflag ) |
| + f_print( fout, "extern \"C\"{\n"); |
| +*/ |
| + return_type(proc); |
| + f_print(fout, "* \n"); |
| + if (Cflag) |
| + pvname_svc(proc->proc_name, vp->vers_num); |
| + else |
| + pvname(proc->proc_name, vp->vers_num); |
| + printarglist(proc, RQSTP, "struct svc_req *"); |
| + |
| + f_print(fout, "{\n"); |
| + f_print(fout, "\n\tstatic "); |
| + if (!streq(proc->res_type, "void")) |
| + return_type(proc); |
| + else |
| + f_print(fout, "char*"); /* cannot have void type */ |
| + /* f_print(fout, " result;\n", proc->res_type); */ |
| + f_print(fout, " result;\n"); |
| + f_print(fout, |
| + "\n\t/*\n\t * insert server code here\n\t */\n\n"); |
| + if (!streq(proc->res_type, "void")) |
| + f_print(fout, "\treturn(&result);\n}\n"); |
| + else /* cast back to void * */ |
| + f_print(fout, "\treturn((void*) &result);\n}\n"); |
| + /* if( Cflag) |
| + f_print( fout, "};\n"); |
| +*/ |
| + |
| + } |
| + } |
| +} |
| + |
| + |
| + |
| +static void |
| +return_type(proc_list *plist) |
| +{ |
| + ptype( plist->res_prefix, plist->res_type, 1 ); |
| +} |
| + |
| +void |
| +add_sample_msg(void) |
| +{ |
| + f_print(fout, "/*\n"); |
| + f_print(fout, " * This is sample code generated by rpcgen.\n"); |
| + f_print(fout, " * These are only templates and you can use them\n"); |
| + f_print(fout, " * as a guideline for developing your own functions.\n"); |
| + f_print(fout, " */\n\n"); |
| +} |
| + |
| +void |
| +write_sample_clnt_main(void) |
| +{ |
| + list *l; |
| + definition *def; |
| + version_list *vp; |
| + |
| + f_print(fout, "\n\n" ); |
| + if( Cflag ) |
| + f_print(fout,"main( int argc, char* argv[] )\n{\n" ); |
| + else |
| + f_print(fout, "main(argc, argv)\nint argc;\nchar *argv[];\n{\n" ); |
| + |
| + f_print(fout, "\tchar *host;"); |
| + f_print(fout, "\n\n\tif(argc < 2) {"); |
| + f_print(fout, "\n\t\tprintf(\"usage: %%s server_host\\n\", argv[0]);\n" ); |
| + f_print(fout, "\t\texit(1);\n\t}"); |
| + f_print(fout, "\n\thost = argv[1];\n"); |
| + |
| + for (l = defined; l != NULL; l = l->next) { |
| + def = l->val; |
| + if (def->def_kind != DEF_PROGRAM) { |
| + continue; |
| + } |
| + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { |
| + f_print( fout, "\t" ); |
| + pvname(def->def_name, vp->vers_num); |
| + f_print( fout, "( host );\n" ); |
| + } |
| + } |
| + f_print(fout, "}\n"); |
| +} |
| diff --git a/rpcgen/rpc_scan.c b/rpcgen/rpc_scan.c |
| new file mode 100644 |
| index 0000000..f58fa9f |
| --- /dev/null |
| +++ b/rpcgen/rpc_scan.c |
| @@ -0,0 +1,474 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| +static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (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 <string.h> |
| +#include "rpc_scan.h" |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| + |
| +static void unget_token(token *tokp); |
| +static void findstrconst(char **str, char **val); |
| +static void findchrconst(char **str, char **val); |
| +static void findconst(char **str, char **val); |
| +static void findkind(char **mark, token *tokp); |
| +static int cppline(char *line); |
| +static int directive(char *line); |
| +static void printdirective(char *line); |
| +static void docppline(char *line, int *lineno, char **fname); |
| + |
| +#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(tok_kind expect, token *tokp) |
| +{ |
| + get_token(tokp); |
| + if (tokp->kind != expect) { |
| + expected1(expect); |
| + } |
| +} |
| + |
| +/* |
| + * scan expecting any of the 2 given tokens |
| + */ |
| +void |
| +scan2(tok_kind expect1, tok_kind expect2, token *tokp) |
| +{ |
| + get_token(tokp); |
| + if (tokp->kind != expect1 && tokp->kind != expect2) { |
| + expected2(expect1, expect2); |
| + } |
| +} |
| + |
| +/* |
| + * scan expecting any of the 3 given token |
| + */ |
| +void |
| +scan3(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(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(token *tokp) |
| +{ |
| + get_token(tokp); |
| + unget_token(tokp); |
| +} |
| + |
| +/* |
| + * Peek at the next token and scan it if it matches what you expect |
| + */ |
| +int |
| +peekscan(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(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) { |
| + for (where++; *where; where++) { |
| + if (endcomment(where)) { |
| + where++; |
| + commenting--; |
| + break; |
| + } |
| + } |
| + } 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 '\'': |
| + tokp->kind = TOK_CHARCONST; |
| + findchrconst(&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 void |
| +unget_token(token *tokp) |
| +{ |
| + lasttok = *tokp; |
| + pushed = 1; |
| +} |
| + |
| +static void |
| +findstrconst(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 void |
| +findchrconst(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; |
| + if (size != 3) { |
| + error("empty char string"); |
| + } |
| + *val = alloc(size + 1); |
| + (void) strncpy(*val, *str, size); |
| + (*val)[size] = 0; |
| + *str = p; |
| +} |
| + |
| +static void |
| +findconst(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_INT32, "int32"}, |
| + {TOK_FLOAT, "float"}, |
| + {TOK_DOUBLE, "double"}, |
| + {TOK_STRING, "string"}, |
| + {TOK_PROGRAM, "program"}, |
| + {TOK_VERSION, "version"}, |
| + {TOK_EOF, "??????"}, |
| +}; |
| + |
| +static void |
| +findkind(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 int |
| +cppline(char *line) |
| +{ |
| + return (line == curline && *line == '#'); |
| +} |
| + |
| +static int |
| +directive(char *line) |
| +{ |
| + return (line == curline && *line == '%'); |
| +} |
| + |
| +static void |
| +printdirective(char *line) |
| +{ |
| + f_print(fout, "%s", line + 1); |
| +} |
| + |
| +static void |
| +docppline(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; |
| + free(file); |
| + } else { |
| + *fname = file; |
| + } |
| + *lineno = num - 1; |
| +} |
| diff --git a/rpcgen/rpc_scan.h b/rpcgen/rpc_scan.h |
| new file mode 100644 |
| index 0000000..16f688c |
| --- /dev/null |
| +++ b/rpcgen/rpc_scan.h |
| @@ -0,0 +1,103 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +/* @(#)rpc_scan.h 1.3 90/08/29 (C) 1987 SMI */ |
| + |
| +/* |
| + * rpc_scan.h, Definitions for the RPCL scanner |
| + */ |
| + |
| +/* |
| + * kinds of tokens |
| + */ |
| +enum tok_kind { |
| + TOK_IDENT, |
| + TOK_CHARCONST, |
| + 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_INT32, |
| + 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 scan(); |
| +void scan2(); |
| +void scan3(); |
| +void scan_num(); |
| +void peek(); |
| +int peekscan(); |
| +void get_token(); |
| +void expected1(tok_kind); |
| +void expected2(tok_kind, tok_kind); |
| +void expected3(tok_kind, tok_kind, tok_kind); |
| + |
| diff --git a/rpcgen/rpc_svcout.c b/rpcgen/rpc_svcout.c |
| new file mode 100644 |
| index 0000000..284a529 |
| --- /dev/null |
| +++ b/rpcgen/rpc_svcout.c |
| @@ -0,0 +1,882 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| + static char sccsid[] = "@(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI"; |
| +#endif |
| + |
| +/* |
| + * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler |
| + */ |
| +#include <stdio.h> |
| +#include <string.h> |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| +#include "rpc_output.h" |
| + |
| +static void write_real_program(definition *def); |
| +static void write_program(definition *def, char *storage); |
| +static void printerr(char *err, char *transp); |
| +static void printif(char *proc, char *transp, char *prefix, char *arg); |
| +static void write_inetmost(char *infile); |
| +static void print_return(char *space); |
| +static void print_pmapunset(char *space); |
| +static void print_err_message(char *space); |
| +static void write_timeout_func(void); |
| +static void write_pm_most(char *infile, int netflag); |
| +static void write_rpc_svc_fg(char *infile, char *sp); |
| +static void open_log_file(char *infile, char *sp); |
| + |
| +static char RQSTP[] = "rqstp"; |
| +static char TRANSP[] = "transp"; |
| +static char ARG[] = "argument"; |
| +static char RESULT[] = "result"; |
| +static char ROUTINE[] = "local"; |
| + |
| +char _errbuf[256]; /* For all messages */ |
| + |
| +static void |
| +p_xdrfunc(char *rname, char *typename) |
| +{ |
| + if (Cflag) |
| + f_print(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n", rname, |
| + stringfix(typename)); |
| + else |
| + f_print(fout, "\t\txdr_%s = xdr_%s;\n", rname, stringfix(typename)); |
| +} |
| + |
| +void |
| +internal_proctype(proc_list *plist) |
| +{ |
| + f_print(fout, "static "); |
| + ptype( plist->res_prefix, plist->res_type, 1 ); |
| + f_print( fout, "*" ); |
| +} |
| + |
| + |
| +/* |
| + * write most of the service, that is, everything but the registrations. |
| + */ |
| +void |
| +write_most(char *infile, int netflag, int nomain) |
| +{ |
| + if (inetdflag || pmflag) { |
| + char* var_type; |
| + var_type = (nomain? "extern" : "static"); |
| + f_print(fout, "%s int _rpcpmstart;", var_type ); |
| + f_print(fout, "\t\t/* Started by a port monitor ? */\n"); |
| + f_print(fout, "%s int _rpcfdtype;", var_type ); |
| + f_print(fout, "\t\t/* Whether Stream or Datagram ? */\n"); |
| + if (timerflag) { |
| + f_print(fout, "%s int _rpcsvcdirty;", var_type ); |
| + f_print(fout, "\t/* Still serving ? */\n"); |
| + } |
| + write_svc_aux( nomain ); |
| + } |
| + /* write out dispatcher and stubs */ |
| + write_programs( nomain? (char *)NULL : "static" ); |
| + |
| + if( nomain ) |
| + return; |
| + |
| + f_print(fout, "\nmain()\n"); |
| + f_print(fout, "{\n"); |
| + if (inetdflag) { |
| + write_inetmost(infile); /* Includes call to write_rpc_svc_fg() */ |
| + } else { |
| + if( tirpcflag ) { |
| + if (netflag) { |
| + f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP); |
| + f_print(fout, "\tstruct netconfig *nconf = NULL;\n"); |
| + } |
| + f_print(fout, "\tpid_t pid;\n"); |
| + f_print(fout, "\tint i;\n"); |
| + f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n"); |
| + write_pm_most(infile, netflag); |
| + f_print(fout, "\telse {\n"); |
| + write_rpc_svc_fg(infile, "\t\t"); |
| + f_print(fout, "\t}\n"); |
| + } else { |
| + f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP); |
| + f_print(fout, "\n"); |
| + print_pmapunset("\t"); |
| + } |
| + } |
| + |
| + if (logflag && !inetdflag) { |
| + open_log_file(infile, "\t"); |
| + } |
| +} |
| + |
| +/* |
| + * write a registration for the given transport |
| + */ |
| +void |
| +write_netid_register(char *transp) |
| +{ |
| + list *l; |
| + definition *def; |
| + version_list *vp; |
| + char *sp; |
| + char tmpbuf[32]; |
| + |
| + sp = ""; |
| + f_print(fout, "\n"); |
| + f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp); |
| + f_print(fout, "%s\tif (nconf == NULL) {\n", sp); |
| + (void) sprintf(_errbuf, "cannot find %s netid.", transp); |
| + sprintf(tmpbuf, "%s\t\t", sp); |
| + print_err_message(tmpbuf); |
| + f_print(fout, "%s\t\texit(1);\n", sp); |
| + f_print(fout, "%s\t}\n", sp); |
| + f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n", |
| + sp, TRANSP); |
| + f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); |
| + (void) sprintf(_errbuf, "cannot create %s service.", transp); |
| + print_err_message(tmpbuf); |
| + f_print(fout, "%s\t\texit(1);\n", sp); |
| + f_print(fout, "%s\t}\n", sp); |
| + |
| + 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, |
| + "%s\t(void) rpcb_unset(%s, %s, nconf);\n", |
| + sp, def->def_name, vp->vers_name); |
| + f_print(fout, |
| + "%s\tif (!svc_reg(%s, %s, %s, ", |
| + sp, TRANSP, def->def_name, vp->vers_name); |
| + pvname(def->def_name, vp->vers_num); |
| + f_print(fout, ", nconf)) {\n"); |
| + (void) sprintf(_errbuf, "unable to register (%s, %s, %s).", |
| + def->def_name, vp->vers_name, transp); |
| + print_err_message(tmpbuf); |
| + f_print(fout, "%s\t\texit(1);\n", sp); |
| + f_print(fout, "%s\t}\n", sp); |
| + } |
| + } |
| + f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp); |
| +} |
| + |
| +/* |
| + * write a registration for the given transport for TLI |
| + */ |
| +void |
| +write_nettype_register(char *transp) |
| +{ |
| + 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) { |
| + continue; |
| + } |
| + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { |
| + f_print(fout, "\tif (!svc_create("); |
| + pvname(def->def_name, vp->vers_num); |
| + f_print(fout, ", %s, %s, \"%s\")) {\n ", |
| + def->def_name, vp->vers_name, transp); |
| + (void) sprintf(_errbuf, |
| + "unable to create (%s, %s) for %s.", |
| + def->def_name, vp->vers_name, transp); |
| + print_err_message("\t\t"); |
| + f_print(fout, "\t\texit(1);\n"); |
| + f_print(fout, "\t}\n"); |
| + } |
| + } |
| +} |
| + |
| +/* |
| + * write the rest of the service |
| + */ |
| +void |
| +write_rest(void) |
| +{ |
| + f_print(fout, "\n"); |
| + if (inetdflag) { |
| + f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP); |
| + (void) sprintf(_errbuf, "could not create a handle"); |
| + print_err_message("\t\t"); |
| + f_print(fout, "\t\texit(1);\n"); |
| + f_print(fout, "\t}\n"); |
| + if (timerflag) { |
| + f_print(fout, "\tif (_rpcpmstart) {\n"); |
| + f_print(fout, |
| + "\t\t(void) signal(SIGALRM, %s closedown);\n", |
| + Cflag? "(SIG_PF)" : "(void(*)())" ); |
| + f_print(fout, "\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); |
| + f_print(fout, "\t}\n"); |
| + } |
| + } |
| + f_print(fout, "\tsvc_run();\n"); |
| + (void) sprintf(_errbuf, "svc_run returned"); |
| + print_err_message("\t"); |
| + f_print(fout, "\texit(1);\n"); |
| + f_print(fout, "\t/* NOTREACHED */\n"); |
| + f_print(fout, "}\n"); |
| +} |
| + |
| +void |
| +write_programs(char *storage) |
| +{ |
| + list *l; |
| + definition *def; |
| + |
| + /* write out stubs for procedure definitions */ |
| + for (l = defined; l != NULL; l = l->next) { |
| + def = (definition *) l->val; |
| + if (def->def_kind == DEF_PROGRAM) { |
| + write_real_program(def); |
| + } |
| + } |
| + |
| + /* write out dispatcher for each program */ |
| + for (l = defined; l != NULL; l = l->next) { |
| + def = (definition *) l->val; |
| + if (def->def_kind == DEF_PROGRAM) { |
| + write_program(def, storage); |
| + } |
| + } |
| + |
| + |
| +} |
| + |
| +/* write out definition of internal function (e.g. _printmsg_1(...)) |
| + which calls server's defintion of actual function (e.g. printmsg_1(...)). |
| + Unpacks single user argument of printmsg_1 to call-by-value format |
| + expected by printmsg_1. */ |
| +static void |
| +write_real_program(definition *def) |
| +{ |
| + version_list *vp; |
| + proc_list *proc; |
| + decl_list *l; |
| + |
| + if( !newstyle ) return; /* not needed for old style */ |
| + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { |
| + for (proc = vp->procs; proc != NULL; proc = proc->next) { |
| + f_print(fout, "\n"); |
| + internal_proctype(proc); |
| + f_print(fout, "\n_"); |
| + pvname(proc->proc_name, vp->vers_num); |
| + if( Cflag ) { |
| + f_print(fout, "(" ); |
| + /* arg name */ |
| + if (proc->arg_num > 1) |
| + f_print(fout, proc->args.argname); |
| + else |
| + ptype(proc->args.decls->decl.prefix, |
| + proc->args.decls->decl.type, 0); |
| + f_print(fout, " *argp, struct svc_req *%s)\n", |
| + RQSTP); |
| + } else { |
| + f_print(fout, "(argp, %s)\n", RQSTP ); |
| + /* arg name */ |
| + if (proc->arg_num > 1) |
| + f_print(fout, "\t%s *argp;\n", proc->args.argname); |
| + else { |
| + f_print(fout, "\t"); |
| + ptype(proc->args.decls->decl.prefix, |
| + proc->args.decls->decl.type, 0); |
| + f_print(fout, " *argp;\n"); |
| + } |
| + f_print(fout, " struct svc_req *%s;\n", RQSTP); |
| + } |
| + |
| + f_print(fout, "{\n"); |
| + f_print(fout, "\treturn("); |
| + if( Cflag ) |
| + pvname_svc(proc->proc_name, vp->vers_num); |
| + else |
| + pvname(proc->proc_name, vp->vers_num); |
| + f_print(fout, "("); |
| + if (proc->arg_num < 2) { /* single argument */ |
| + if (!streq( proc->args.decls->decl.type, "void")) |
| + f_print(fout, "*argp, "); /* non-void */ |
| + } else { |
| + for (l = proc->args.decls; l != NULL; l = l->next) |
| + f_print(fout, "argp->%s, ", l->decl.name); |
| + } |
| + f_print(fout, "%s));\n}\n", RQSTP); |
| + } |
| + } |
| +} |
| + |
| +static void |
| +write_program(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); |
| + |
| + if (Cflag) { |
| + f_print(fout, "(struct svc_req *%s, ", RQSTP); |
| + f_print(fout, "register SVCXPRT *%s)\n", TRANSP); |
| + } else { |
| + f_print(fout, "(%s, %s)\n", RQSTP, TRANSP); |
| + f_print(fout, " struct svc_req *%s;\n", RQSTP); |
| + f_print(fout, " register 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 (proc->arg_num < 2) { /* single argument */ |
| + if (streq(proc->args.decls->decl.type, |
| + "void")) { |
| + continue; |
| + } |
| + filled = 1; |
| + f_print(fout, "\t\t"); |
| + ptype(proc->args.decls->decl.prefix, |
| + proc->args.decls->decl.type, 0); |
| + pvname(proc->proc_name, vp->vers_num); |
| + f_print(fout, "_arg;\n"); |
| + |
| + } |
| + else { |
| + filled = 1; |
| + f_print(fout, "\t\t%s", proc->args.argname); |
| + f_print(fout, " "); |
| + 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); |
| + |
| + if (Cflag) { |
| + f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT); |
| + f_print(fout, |
| + "\tchar *(*%s)(char *, struct svc_req *);\n", |
| + ROUTINE); |
| + } else { |
| + f_print(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", ARG, RESULT); |
| + f_print(fout, "\tchar *(*%s)();\n", ROUTINE); |
| + } |
| + |
| + f_print(fout, "\n"); |
| + |
| + if (timerflag) |
| + f_print(fout, "\t_rpcsvcdirty = 1;\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, (xdrproc_t) xdr_void, (char *)NULL);\n", |
| + TRANSP); |
| + print_return("\t\t"); |
| + f_print(fout, "\n"); |
| + } |
| + for (proc = vp->procs; proc != NULL; proc = proc->next) { |
| + f_print(fout, "\tcase %s:\n", proc->proc_name); |
| + if (proc->arg_num < 2) { /* single argument */ |
| + p_xdrfunc( ARG, proc->args.decls->decl.type); |
| + } else { |
| + p_xdrfunc( ARG, proc->args.argname); |
| + } |
| + p_xdrfunc( RESULT, proc->res_type); |
| + if( Cflag ) |
| + f_print(fout, |
| + "\t\t%s = (char *(*)(char *, struct svc_req *)) ", |
| + ROUTINE); |
| + else |
| + f_print(fout, "\t\t%s = (char *(*)()) ", ROUTINE); |
| + |
| + if (newstyle) { /* new style: calls internal routine */ |
| + f_print(fout,"_"); |
| + } |
| + /* Not sure about the following... |
| + * rpc_hout always generates foobar_1_svc for |
| + * the service procedure, so why should we use |
| + * foobar_1 here?! --okir */ |
| +#if 0 |
| + if( Cflag && !newstyle ) |
| + pvname_svc(proc->proc_name, vp->vers_num); |
| + else |
| + pvname(proc->proc_name, vp->vers_num); |
| +#else |
| + pvname_svc(proc->proc_name, vp->vers_num); |
| +#endif |
| + f_print(fout, ";\n"); |
| + f_print(fout, "\t\tbreak;\n\n"); |
| + } |
| + f_print(fout, "\tdefault:\n"); |
| + printerr("noproc", TRANSP); |
| + print_return("\t\t"); |
| + f_print(fout, "\t}\n"); |
| + |
| + f_print(fout, "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", ARG, ARG); |
| + if (Cflag) |
| + printif("getargs", TRANSP, "(caddr_t) &", ARG); |
| + else |
| + printif("getargs", TRANSP, "&", ARG); |
| + printerr("decode", TRANSP); |
| + print_return("\t\t"); |
| + f_print(fout, "\t}\n"); |
| + |
| + if (Cflag) |
| + f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n", |
| + RESULT, ROUTINE, ARG, RQSTP); |
| + else |
| + f_print(fout, "\t%s = (*%s)(&%s, %s);\n", |
| + RESULT, ROUTINE, ARG, RQSTP); |
| + f_print(fout, |
| + "\tif (%s != NULL && !svc_sendreply(%s, " |
| + "(xdrproc_t) xdr_%s, %s)) {\n", |
| + RESULT, TRANSP, RESULT, RESULT); |
| + printerr("systemerr", TRANSP); |
| + f_print(fout, "\t}\n"); |
| + |
| + if (Cflag) |
| + printif("freeargs", TRANSP, "(caddr_t) &", ARG); |
| + else |
| + printif("freeargs", TRANSP, "&", ARG); |
| + (void) sprintf(_errbuf, "unable to free arguments"); |
| + print_err_message("\t\t"); |
| + f_print(fout, "\t\texit(1);\n"); |
| + f_print(fout, "\t}\n"); |
| + print_return("\t"); |
| + f_print(fout, "}\n"); |
| + } |
| +} |
| + |
| +static void |
| +printerr(char *err, char *transp) |
| +{ |
| + f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp); |
| +} |
| + |
| +static void |
| +printif(char *proc, char *transp, char *prefix, char *arg) |
| +{ |
| + f_print(fout, "\tif (!svc_%s(%s, (xdrproc_t) xdr_%s, (caddr_t) %s%s)) {\n", |
| + proc, transp, arg, prefix, arg); |
| +} |
| + |
| +int |
| +nullproc(proc_list *proc) |
| +{ |
| + for (; proc != NULL; proc = proc->next) { |
| + if (streq(proc->proc_num, "0")) { |
| + return (1); |
| + } |
| + } |
| + return (0); |
| +} |
| + |
| +static void |
| +write_inetmost(char *infile) |
| +{ |
| + f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP); |
| + f_print(fout, "\tint sock;\n"); |
| + f_print(fout, "\tint proto;\n"); |
| + f_print(fout, "\tstruct sockaddr_in saddr;\n"); |
| + f_print(fout, "\tint asize = sizeof (saddr);\n"); |
| + f_print(fout, "\n"); |
| + f_print(fout, |
| + "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n"); |
| + f_print(fout, "\t\tint ssize = sizeof (int);\n\n"); |
| + f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n"); |
| + f_print(fout, "\t\t\texit(1);\n"); |
| + f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n"); |
| + f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n"); |
| + f_print(fout, "\t\t\texit(1);\n"); |
| + f_print(fout, "\t\tsock = 0;\n"); |
| + f_print(fout, "\t\t_rpcpmstart = 1;\n"); |
| + f_print(fout, "\t\tproto = 0;\n"); |
| + open_log_file(infile, "\t\t"); |
| + f_print(fout, "\t} else {\n"); |
| + write_rpc_svc_fg(infile, "\t\t"); |
| + f_print(fout, "\t\tsock = RPC_ANYSOCK;\n"); |
| + print_pmapunset("\t\t"); |
| + f_print(fout, "\t}\n"); |
| +} |
| + |
| +static void |
| +print_return(char *space) |
| +{ |
| + if (exitnow) |
| + f_print(fout, "%sexit(0);\n", space); |
| + else { |
| + if (timerflag) |
| + f_print(fout, "%s_rpcsvcdirty = 0;\n", space); |
| + f_print(fout, "%sreturn;\n", space); |
| + } |
| +} |
| + |
| +static void |
| +print_pmapunset(char *space) |
| +{ |
| + 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, "%s(void) pmap_unset(%s, %s);\n", |
| + space, def->def_name, vp->vers_name); |
| + } |
| + } |
| + } |
| +} |
| + |
| +static void |
| +print_err_message(char *space) |
| +{ |
| + if (logflag) |
| + f_print(fout, "%ssyslog(LOG_ERR, \"%s\");\n", space, _errbuf); |
| + else if (inetdflag || pmflag) |
| + f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf); |
| + else |
| + f_print(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf); |
| +} |
| + |
| +/* |
| + * Write the server auxiliary function ( _msgout, timeout) |
| + */ |
| +void |
| +write_svc_aux(int nomain) |
| +{ |
| + if (!logflag) |
| + write_msg_out(); |
| + if( !nomain ) |
| + write_timeout_func(); |
| +} |
| + |
| +/* |
| + * Write the _msgout function |
| + */ |
| +void |
| +write_msg_out(void) |
| +{ |
| + f_print(fout, "\n"); |
| + f_print(fout, "static\n"); |
| + if( !Cflag ) { |
| + f_print(fout, "void _msgout(msg)\n"); |
| + f_print(fout, "\tchar *msg;\n"); |
| + } else { |
| + f_print(fout, "void _msgout(char* msg)\n"); |
| + } |
| + f_print(fout, "{\n"); |
| + f_print(fout, "#ifdef RPC_SVC_FG\n"); |
| + if (inetdflag || pmflag) |
| + f_print(fout, "\tif (_rpcpmstart)\n"); |
| + f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n"); |
| + f_print(fout, "\telse\n"); |
| + f_print(fout, "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n"); |
| + f_print(fout, "#else\n"); |
| + f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n"); |
| + f_print(fout, "#endif\n"); |
| + f_print(fout, "}\n"); |
| +} |
| + |
| +/* |
| + * Write the timeout function |
| + */ |
| +static void |
| +write_timeout_func(void) |
| +{ |
| + if (!timerflag) |
| + return; |
| + f_print(fout, "\n"); |
| + f_print(fout, "static void\n"); |
| + f_print(fout, "closedown()\n"); |
| + f_print(fout, "{\n"); |
| + f_print(fout, "\tif (_rpcsvcdirty == 0) {\n"); |
| + f_print(fout, "\t\tstatic int size;\n"); |
| + f_print(fout, "\t\tint i, openfd;\n"); |
| + if (tirpcflag && pmflag) { |
| + f_print(fout, "\t\tstruct t_info tinfo;\n\n"); |
| + f_print(fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n"); |
| + } else { |
| + f_print(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n"); |
| + } |
| + f_print(fout, "\t\t\texit(0);\n"); |
| + f_print(fout, "\t\tif (size == 0) {\n"); |
| + if( tirpcflag ) { |
| + f_print(fout, "\t\t\tstruct rlimit rl;\n\n"); |
| + f_print(fout, "\t\t\trl.rlim_max = 0;\n"); |
| + f_print(fout, "\t\t\tgetrlimit(RLIMIT_NOFILE, &rl);\n"); |
| + f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0)\n"); |
| + f_print(fout, "\t\t\t\treturn;\n"); |
| + } else { |
| + f_print(fout, "\t\t\tsize = getdtablesize();\n"); |
| + } |
| + f_print(fout, "\t\t}\n"); |
| + f_print(fout, "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n"); |
| + f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n"); |
| + f_print(fout, "\t\t\t\topenfd++;\n"); |
| + f_print(fout, "\t\tif (openfd <= 1)\n"); |
| + f_print(fout, "\t\t\texit(0);\n"); |
| + f_print(fout, "\t}\n"); |
| + f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); |
| + f_print(fout, "}\n"); |
| +} |
| + |
| +/* |
| + * Write the most of port monitor support |
| + */ |
| +static void |
| +write_pm_most(char *infile, int netflag) |
| +{ |
| + list *l; |
| + definition *def; |
| + version_list *vp; |
| + |
| + f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n"); |
| + f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||"); |
| + f_print(fout, " !strcmp(mname, \"timod\"))) {\n"); |
| + f_print(fout, "\t\tchar *netid;\n"); |
| + if (!netflag) { /* Not included by -n option */ |
| + f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n"); |
| + f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP); |
| + } |
| + if( timerflag ) |
| + f_print(fout, "\t\tint pmclose;\n"); |
| +/* not necessary, defined in /usr/include/stdlib */ |
| +/* f_print(fout, "\t\textern char *getenv();\n");*/ |
| + f_print(fout, "\n"); |
| + f_print(fout, "\t\t_rpcpmstart = 1;\n"); |
| + if (logflag) |
| + open_log_file(infile, "\t\t"); |
| + f_print(fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n"); |
| + sprintf(_errbuf, "cannot get transport name"); |
| + print_err_message("\t\t\t"); |
| + f_print(fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n"); |
| + sprintf(_errbuf, "cannot get transport info"); |
| + print_err_message("\t\t\t"); |
| + f_print(fout, "\t\t}\n"); |
| + /* |
| + * A kludgy support for inetd services. Inetd only works with |
| + * sockmod, and RPC works only with timod, hence all this jugglery |
| + */ |
| + f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n"); |
| + f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n"); |
| + sprintf(_errbuf, "could not get the right module"); |
| + print_err_message("\t\t\t\t"); |
| + f_print(fout, "\t\t\t\texit(1);\n"); |
| + f_print(fout, "\t\t\t}\n"); |
| + f_print(fout, "\t\t}\n"); |
| + if( timerflag ) |
| + f_print(fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n"); |
| + f_print(fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n", |
| + TRANSP); |
| + sprintf(_errbuf, "cannot create server handle"); |
| + print_err_message("\t\t\t"); |
| + f_print(fout, "\t\t\texit(1);\n"); |
| + f_print(fout, "\t\t}\n"); |
| + f_print(fout, "\t\tif (nconf)\n"); |
| + f_print(fout, "\t\t\tfreenetconfigent(nconf);\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\tif (!svc_reg(%s, %s, %s, ", |
| + TRANSP, def->def_name, vp->vers_name); |
| + pvname(def->def_name, vp->vers_num); |
| + f_print(fout, ", 0)) {\n"); |
| + (void) sprintf(_errbuf, "unable to register (%s, %s).", |
| + def->def_name, vp->vers_name); |
| + print_err_message("\t\t\t"); |
| + f_print(fout, "\t\t\texit(1);\n"); |
| + f_print(fout, "\t\t}\n"); |
| + } |
| + } |
| + if (timerflag) { |
| + f_print(fout, "\t\tif (pmclose) {\n"); |
| + f_print(fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n", |
| + Cflag? "(SIG_PF)" : "(void(*)())" ); |
| + f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); |
| + f_print(fout, "\t\t}\n"); |
| + } |
| + f_print(fout, "\t\tsvc_run();\n"); |
| + f_print(fout, "\t\texit(1);\n"); |
| + f_print(fout, "\t\t/* NOTREACHED */\n"); |
| + f_print(fout, "\t}\n"); |
| +} |
| + |
| +/* |
| + * Support for backgrounding the server if self started. |
| + */ |
| +static void |
| +write_rpc_svc_fg(char *infile, char *sp) |
| +{ |
| + f_print(fout, "#ifndef RPC_SVC_FG\n"); |
| + f_print(fout, "%sint size;\n", sp); |
| + if( tirpcflag ) |
| + f_print(fout, "%sstruct rlimit rl;\n", sp); |
| + if (inetdflag) |
| + f_print(fout, "%sint pid, i;\n\n", sp); |
| + f_print(fout, "%spid = fork();\n", sp); |
| + f_print(fout, "%sif (pid < 0) {\n", sp); |
| + f_print(fout, "%s\tperror(\"cannot fork\");\n", sp); |
| + f_print(fout, "%s\texit(1);\n", sp); |
| + f_print(fout, "%s}\n", sp); |
| + f_print(fout, "%sif (pid)\n", sp); |
| + f_print(fout, "%s\texit(0);\n", sp); |
| + /* get number of file descriptors */ |
| + if( tirpcflag ) { |
| + f_print(fout, "%srl.rlim_max = 0;\n", sp); |
| + f_print(fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp); |
| + f_print(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp); |
| + f_print(fout, "%s\texit(1);\n", sp); |
| + } else { |
| + f_print(fout, "%ssize = getdtablesize();\n", sp); |
| + } |
| + |
| + f_print(fout, "%sfor (i = 0; i < size; i++)\n", sp); |
| + f_print(fout, "%s\t(void) close(i);\n", sp); |
| + /* Redirect stderr and stdout to console */ |
| + f_print(fout, "%si = open(\"/dev/console\", 2);\n", sp); |
| + f_print(fout, "%s(void) dup2(i, 1);\n", sp); |
| + f_print(fout, "%s(void) dup2(i, 2);\n", sp); |
| + /* This removes control of the controlling terminal */ |
| + if( tirpcflag ) |
| + f_print(fout, "%ssetsid();\n", sp); |
| + else { |
| + f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp); |
| + f_print(fout, "%sif (i >= 0) {\n", sp); |
| + f_print(fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);; |
| + f_print(fout, "%s\t(void) close(i);\n", sp); |
| + f_print(fout, "%s}\n", sp); |
| + } |
| + if (!logflag) |
| + open_log_file(infile, sp); |
| + f_print(fout, "#endif\n"); |
| + if (logflag) |
| + open_log_file(infile, sp); |
| +} |
| + |
| +static void |
| +open_log_file(char *infile, char *sp) |
| +{ |
| + char *s; |
| + |
| + s = strrchr(infile, '.'); |
| + if (s) |
| + *s = '\0'; |
| + f_print(fout,"%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile); |
| + if (s) |
| + *s = '.'; |
| +} |
| + |
| + |
| + |
| + |
| +/* |
| + * write a registration for the given transport for Inetd |
| + */ |
| +void |
| +write_inetd_register(char *transp) |
| +{ |
| + list *l; |
| + definition *def; |
| + version_list *vp; |
| + char *sp; |
| + int isudp; |
| + char tmpbuf[32]; |
| + |
| + if (inetdflag) |
| + sp = "\t"; |
| + else |
| + sp = ""; |
| + if (streq(transp, "udp")) |
| + isudp = 1; |
| + else |
| + isudp = 0; |
| + f_print(fout, "\n"); |
| + if (inetdflag) { |
| + f_print(fout, "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n", |
| + isudp ? "SOCK_DGRAM" : "SOCK_STREAM"); |
| + } |
| + f_print(fout, "%s\t%s = svc%s_create(%s", |
| + sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK"); |
| + if (!isudp) |
| + f_print(fout, ", 0, 0"); |
| + f_print(fout, ");\n"); |
| + f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); |
| + (void) sprintf(_errbuf, "cannot create %s service.", transp); |
| + (void) sprintf(tmpbuf, "%s\t\t", sp); |
| + print_err_message(tmpbuf); |
| + f_print(fout, "%s\t\texit(1);\n", sp); |
| + f_print(fout, "%s\t}\n", sp); |
| + |
| + if (inetdflag) { |
| + f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp); |
| + f_print(fout, "%s\tproto = IPPROTO_%s;\n", |
| + sp, isudp ? "UDP": "TCP"); |
| + } |
| + 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, "%s\tif (!svc_register(%s, %s, %s, ", |
| + sp, TRANSP, def->def_name, vp->vers_name); |
| + pvname(def->def_name, vp->vers_num); |
| + if (inetdflag) |
| + f_print(fout, ", proto)) {\n"); |
| + else |
| + f_print(fout, ", IPPROTO_%s)) {\n", |
| + isudp ? "UDP": "TCP"); |
| + (void) sprintf(_errbuf, "unable to register (%s, %s, %s).", |
| + def->def_name, vp->vers_name, transp); |
| + print_err_message(tmpbuf); |
| + f_print(fout, "%s\t\texit(1);\n", sp); |
| + f_print(fout, "%s\t}\n", sp); |
| + } |
| + } |
| + if (inetdflag) |
| + f_print(fout, "\t}\n"); |
| +} |
| diff --git a/rpcgen/rpc_tblout.c b/rpcgen/rpc_tblout.c |
| new file mode 100644 |
| index 0000000..ae002f7 |
| --- /dev/null |
| +++ b/rpcgen/rpc_tblout.c |
| @@ -0,0 +1,165 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| +static char sccsid[] = "@(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI"; |
| +#endif |
| + |
| +/* |
| + * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler |
| + */ |
| +#include <stdio.h> |
| +#include <string.h> |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| +#include "rpc_output.h" |
| + |
| +static void write_table(definition *def); |
| +static void printit(char *prefix, char *type); |
| + |
| +#define TABSIZE 8 |
| +#define TABCOUNT 5 |
| +#define TABSTOP (TABSIZE*TABCOUNT) |
| + |
| +static char tabstr[TABCOUNT+1] = "\t\t\t\t\t"; |
| + |
| +static char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n"; |
| +static char tbl_end[] = "};\n"; |
| + |
| +static char null_entry[] = "\n\t(char *(*)())0,\n\ |
| + \t(xdrproc_t) xdr_void,\t\t\t0,\n\ |
| + \t(xdrproc_t) xdr_void,\t\t\t0,\n"; |
| + |
| + |
| +static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n"; |
| + |
| +void |
| +write_tables(void) |
| +{ |
| + list *l; |
| + definition *def; |
| + |
| + f_print(fout, "\n"); |
| + for (l = defined; l != NULL; l = l->next) { |
| + def = (definition *) l->val; |
| + if (def->def_kind == DEF_PROGRAM) { |
| + write_table(def); |
| + } |
| + } |
| +} |
| + |
| +static void |
| +write_table(definition *def) |
| +{ |
| + version_list *vp; |
| + proc_list *proc; |
| + int current; |
| + int expected; |
| + char progvers[100]; |
| + int warning; |
| + |
| + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { |
| + warning = 0; |
| + s_print(progvers, "%s_%s", |
| + locase(def->def_name), vp->vers_num); |
| + /* print the table header */ |
| + f_print(fout, tbl_hdr, progvers); |
| + |
| + if (nullproc(vp->procs)) { |
| + expected = 0; |
| + } else { |
| + expected = 1; |
| + f_print(fout, null_entry); |
| + } |
| + for (proc = vp->procs; proc != NULL; proc = proc->next) { |
| + current = atoi(proc->proc_num); |
| + if (current != expected++) { |
| + f_print(fout, |
| + "\n/*\n * WARNING: table out of order\n */\n"); |
| + if (warning == 0) { |
| + f_print(stderr, |
| + "WARNING %s table is out of order\n", |
| + progvers); |
| + warning = 1; |
| + nonfatalerrors = 1; |
| + } |
| + expected = current + 1; |
| + } |
| + f_print(fout, "\n\t(char *(*)())RPCGEN_ACTION("); |
| + |
| + /* routine to invoke */ |
| + if( Cflag && !newstyle ) |
| + pvname_svc(proc->proc_name, vp->vers_num); |
| + else { |
| + if( newstyle ) |
| + f_print( fout, "_"); /* calls internal func */ |
| + pvname(proc->proc_name, vp->vers_num); |
| + } |
| + f_print(fout, "),\n"); |
| + |
| + /* argument info */ |
| + if( proc->arg_num > 1 ) |
| + printit((char*) NULL, proc->args.argname ); |
| + else |
| + /* do we have to do something special for newstyle */ |
| + printit( proc->args.decls->decl.prefix, |
| + proc->args.decls->decl.type ); |
| + /* result info */ |
| + printit(proc->res_prefix, proc->res_type); |
| + } |
| + |
| + /* print the table trailer */ |
| + f_print(fout, tbl_end); |
| + f_print(fout, tbl_nproc, progvers, progvers, progvers); |
| + } |
| +} |
| + |
| +static void |
| +printit(char *prefix, char *type) |
| +{ |
| + int len; |
| + int tabs; |
| + |
| + |
| + len = fprintf(fout, "\txdr_%s,", stringfix(type)); |
| + /* account for leading tab expansion */ |
| + len += TABSIZE - 1; |
| + /* round up to tabs required */ |
| + tabs = (TABSTOP - len + TABSIZE - 1)/TABSIZE; |
| + f_print(fout, "%s", &tabstr[TABCOUNT-tabs]); |
| + |
| + if (streq(type, "void")) { |
| + f_print(fout, "0"); |
| + } else { |
| + f_print(fout, "sizeof ( "); |
| + /* XXX: should "follow" be 1 ??? */ |
| + ptype(prefix, type, 0); |
| + f_print(fout, ")"); |
| + } |
| + f_print(fout, ",\n"); |
| +} |
| diff --git a/rpcgen/rpc_util.c b/rpcgen/rpc_util.c |
| new file mode 100644 |
| index 0000000..b67be57 |
| --- /dev/null |
| +++ b/rpcgen/rpc_util.c |
| @@ -0,0 +1,479 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#if 0 |
| +static char sccsid[] = "@(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI"; |
| +#endif |
| + |
| +/* |
| + * rpc_util.c, Utility routines for the RPC protocol compiler |
| + */ |
| +#include <stdio.h> |
| +#include <memory.h> |
| +#include <ctype.h> |
| +#include <unistd.h> |
| +#include "rpc_scan.h" |
| +#include "rpc_parse.h" |
| +#include "rpc_util.h" |
| + |
| +static void printwhere(void); |
| + |
| + |
| +#define ARGEXT "argument" |
| + |
| +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 7 |
| +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 |
| + */ |
| +void |
| +reinitialize(void) |
| +{ |
| + memset(curline, 0, MAXLINESIZE); |
| + where = curline; |
| + linenum = 0; |
| + defined = NULL; |
| +} |
| + |
| +/* |
| + * string equality |
| + */ |
| +int |
| +streq(char *a, char *b) |
| +{ |
| + return (strcmp(a, b) == 0); |
| +} |
| + |
| +/* |
| + * find a value in a list |
| + */ |
| +definition * |
| +findval(list *lst, char *val, int (*cmp)(definition *, char *)) |
| +{ |
| + |
| + 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; |
| + definition *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 int |
| +findit(definition *def, char *type) |
| +{ |
| + return (streq(def->def_name, type)); |
| +} |
| + |
| +static char * |
| +fixit(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(char *type) |
| +{ |
| + return (fixit(type, type)); |
| +} |
| + |
| +char * |
| +stringfix(char *type) |
| +{ |
| + if (streq(type, "string")) { |
| + return ("wrapstring"); |
| + } else { |
| + return (type); |
| + } |
| +} |
| + |
| +void |
| +ptype(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 int |
| +typedefed(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)); |
| + } |
| +} |
| + |
| +int |
| +isvectordef(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; |
| + } |
| + } |
| +} |
| + |
| +char * |
| +locase(char *str) |
| +{ |
| + char c; |
| + static char buf[100]; |
| + char *p = buf; |
| + |
| + while ((c = *str++) != '\0') { |
| + *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; |
| + } |
| + *p = 0; |
| + return (buf); |
| +} |
| + |
| +void |
| +pvname_svc(char *pname, char *vnum) |
| +{ |
| + f_print(fout, "%s_%s_svc", locase(pname), vnum); |
| +} |
| + |
| +void |
| +pvname(char *pname, char *vnum) |
| +{ |
| + f_print(fout, "%s_%s", locase(pname), vnum); |
| +} |
| + |
| +/* |
| + * print a useful (?) error message, and then die |
| + */ |
| +void |
| +error(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. |
| + */ |
| +void |
| +crash(void) |
| +{ |
| + int i; |
| + |
| + for (i = 0; i < nfiles; i++) { |
| + (void) unlink(outfiles[i]); |
| + } |
| + exit(1); |
| +} |
| + |
| +void |
| +record_open(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_INT32, "int32"}, |
| + {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 void |
| +printbuf(void) |
| +{ |
| + char c; |
| + int i; |
| + int cnt; |
| + |
| +# define TABSIZE 4 |
| + |
| + for (i = 0; (c = curline[i]) != '\0'; i++) { |
| + if (c == '\t') { |
| + cnt = 8 - (i % TABSIZE); |
| + c = ' '; |
| + } else { |
| + cnt = 1; |
| + } |
| + while (cnt--) { |
| + (void) fputc(c, stderr); |
| + } |
| + } |
| +} |
| + |
| +static void |
| +printwhere(void) |
| +{ |
| + 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); |
| +} |
| + |
| +char * |
| +make_argname(char *pname, char *vname) |
| +{ |
| + char *name; |
| + |
| + name = malloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3); |
| + if (!name) { |
| + fprintf(stderr, "failed in malloc"); |
| + exit(1); |
| + } |
| + sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT); |
| + return(name); |
| +} |
| + |
| +bas_type *typ_list_h; |
| +bas_type *typ_list_t; |
| + |
| +void |
| +add_type(int len, char *type) |
| +{ |
| + bas_type *ptr; |
| + |
| + |
| + if ((ptr = (bas_type *) malloc(sizeof(bas_type))) == (bas_type *) NULL) { |
| + fprintf(stderr, "failed in malloc"); |
| + exit(1); |
| + } |
| + ptr->name = type; |
| + ptr->length = len; |
| + ptr->next = NULL; |
| + if (typ_list_t == NULL) { |
| + |
| + typ_list_t = ptr; |
| + typ_list_h = ptr; |
| + } else { |
| + |
| + typ_list_t->next = ptr; |
| + typ_list_t = ptr; |
| + } |
| +} |
| + |
| + |
| +bas_type * |
| +find_type(char *type) |
| +{ |
| + bas_type *ptr; |
| + |
| + ptr = typ_list_h; |
| + |
| + |
| + while (ptr != NULL) { |
| + if (strcmp(ptr->name, type) == 0) |
| + return (ptr); |
| + else |
| + ptr = ptr->next; |
| + }; |
| + return (NULL); |
| +} |
| + |
| diff --git a/rpcgen/rpc_util.h b/rpcgen/rpc_util.h |
| new file mode 100644 |
| index 0000000..fa115be |
| --- /dev/null |
| +++ b/rpcgen/rpc_util.h |
| @@ -0,0 +1,166 @@ |
| +/* |
| + * Copyright (c) 2009, Sun Microsystems, Inc. |
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are met: |
| + * - Redistributions of source code must retain the above copyright notice, |
| + * this list of conditions and the following disclaimer. |
| + * - Redistributions in binary form must reproduce the above copyright notice, |
| + * this list of conditions and the following disclaimer in the documentation |
| + * and/or other materials provided with the distribution. |
| + * - Neither the name of Sun Microsystems, Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived |
| + * from this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| + * POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */ |
| + |
| +/* |
| + * rpc_util.h, Useful definitions for the RPC protocol compiler |
| + */ |
| + |
| +#include <stdlib.h> |
| + |
| +#define alloc(size) malloc((unsigned)(size)) |
| +#define ALLOC(object) (object *) malloc(sizeof(object)) |
| + |
| +#define s_print (void) sprintf |
| +#define f_print (void) fprintf |
| + |
| +struct list { |
| + definition *val; |
| + struct list *next; |
| +}; |
| +typedef struct list list; |
| + |
| +#define PUT 1 |
| +#define GET 2 |
| + |
| +/* |
| + * Global variables |
| + */ |
| +#define MAXLINESIZE 1024 |
| +extern char curline[MAXLINESIZE]; |
| +extern char *where; |
| +extern int linenum; |
| + |
| +extern char *infilename; |
| +extern FILE *fout; |
| +extern FILE *fin; |
| + |
| +extern list *defined; |
| + |
| + |
| +extern bas_type *typ_list_h; |
| +extern bas_type *typ_list_t; |
| + |
| +/* |
| + * All the option flags |
| + */ |
| +extern int inetdflag; |
| +extern int pmflag; |
| +extern int tblflag; |
| +extern int logflag; |
| +extern int newstyle; |
| +extern int Cflag; /* C++ flag */ |
| +extern int tirpcflag; /* flag for generating tirpc code */ |
| +extern int Inline; /* if this is 0, then do not generate inline code */ |
| + |
| +/* |
| + * Other flags related with inetd jumpstart. |
| + */ |
| +extern int indefinitewait; |
| +extern int exitnow; |
| +extern int timerflag; |
| + |
| +extern int nonfatalerrors; |
| + |
| +/* |
| + * rpc_util routines |
| + */ |
| +void storeval(); |
| + |
| +#define STOREVAL(list,item) \ |
| + storeval(list,item) |
| + |
| +definition *findval(); |
| + |
| +#define FINDVAL(list,item,finder) \ |
| + findval(list, item, finder) |
| + |
| + |
| +/* |
| + * rpc_cout routines |
| + */ |
| +void cprint(void); |
| +void emit(definition *); |
| + |
| +/* |
| + * rpc_hout routines |
| + */ |
| +void print_datadef(definition *); |
| +void print_funcdef(definition *); |
| + |
| +/* |
| + * rpc_svcout routines |
| + */ |
| +void write_most(char *, int, int); |
| +void write_register(void); |
| +void write_netid_register(char *); |
| +void write_nettype_register(char *); |
| +void write_inetd_register(char *); |
| +void write_rest(void); |
| +void write_programs(char *); |
| +void write_svc_aux(int); |
| + |
| +/* |
| + * rpc_clntout routines |
| + */ |
| +void write_stubs(void); |
| +void printarglist(proc_list *, char *, char *); |
| + |
| +/* |
| + * rpc_tblout routines |
| + */ |
| +void write_tables(void); |
| + |
| +/* |
| + * rpc_util |
| + */ |
| +void pvname_svc(char *, char *); |
| +void pvname(char *, char *); |
| +void ptype(char *, char *, int); |
| +char * make_argname(char *, char *); |
| +void add_type(int, char *); |
| +void reinitialize(void); |
| +void crash(void); |
| +void error(char *); |
| +char *fixtype(char *); |
| +char *stringfix(char *); |
| +char *locase(char *); |
| +int isvectordef(char *, relation); |
| +int streq(char *, char *); |
| +void tabify(FILE *, int); |
| +void record_open(char *); |
| +bas_type *find_type(char *type); |
| + |
| +/* |
| + * rpc_sample |
| + */ |
| +void write_sample_svc(definition *); |
| +int write_sample_clnt(definition *); |
| +void write_sample_clnt_main(void); |
| +void add_sample_msg(void); |
| diff --git a/rpcgen/rpcgen.1 b/rpcgen/rpcgen.1 |
| new file mode 100644 |
| index 0000000..89df7ed |
| --- /dev/null |
| +++ b/rpcgen/rpcgen.1 |
| @@ -0,0 +1,521 @@ |
| +.\" @(#)rpcgen.1 1.35 93/06/02 SMI |
| +.\" $FreeBSD: src/usr.bin/rpcgen/rpcgen.1,v 1.12.2.4 2002/06/21 15:28:50 charnier Exp $ |
| +.\" Copyright 1985-1993 Sun Microsystems, Inc. |
| +.Dd March 28, 1993 |
| +.Dt RPCGEN 1 |
| +.Os |
| +.Sh NAME |
| +.Nm rpcgen |
| +.Nd an RPC protocol compiler |
| +.Sh SYNOPSIS |
| +.Nm |
| +.Ar infile |
| +.Nm |
| +.Op Fl a |
| +.Op Fl b |
| +.Op Fl C |
| +.Oo |
| +.Fl D Ns Ar name Ns Op Ar =value |
| +.Oc |
| +.Op Fl i Ar size |
| +.Op Fl I Op Fl K Ar seconds |
| +.Op Fl L |
| +.Op Fl M |
| +.Op Fl N |
| +.Op Fl T |
| +.Op Fl Y Ar pathname |
| +.Ar infile |
| +.Nm |
| +.Oo |
| +.Fl c | |
| +.Fl h | |
| +.Fl l | |
| +.Fl m | |
| +.Fl t | |
| +.Fl \&Sc | |
| +.Fl \&Ss | |
| +.Fl \&Sm |
| +.Oc |
| +.Op Fl o Ar outfile |
| +.Op Ar infile |
| +.Nm |
| +.Op Fl s Ar nettype |
| +.Op Fl o Ar outfile |
| +.Op Ar infile |
| +.Nm |
| +.Op Fl n Ar netid |
| +.Op Fl o Ar outfile |
| +.Op Ar infile |
| +.\" .SH AVAILABILITY |
| +.\" .LP |
| +.\" SUNWcsu |
| +.Sh DESCRIPTION |
| +The |
| +.Nm |
| +utility is a tool that generates C code to implement an |
| +.Tn RPC |
| +protocol. |
| +The input to |
| +.Nm |
| +is a language similar to C known as |
| +.Tn RPC |
| +Language (Remote Procedure Call Language). |
| +.Pp |
| +The |
| +.Nm |
| +utility is normally used as in the first synopsis where |
| +it takes an input file and generates three output files. |
| +If the |
| +.Ar infile |
| +is named |
| +.Pa proto.x , |
| +then |
| +.Nm |
| +generates a header in |
| +.Pa proto.h , |
| +XDR routines in |
| +.Pa proto_xdr.c , |
| +server-side stubs in |
| +.Pa proto_svc.c , |
| +and client-side stubs in |
| +.Pa proto_clnt.c . |
| +With the |
| +.Fl T |
| +option, |
| +it also generates the |
| +.Tn RPC |
| +dispatch table in |
| +.Pa proto_tbl.i . |
| +.Pp |
| +The |
| +.Nm |
| +utility can also generate sample client and server files |
| +that can be customized to suit a particular application. |
| +The |
| +.Fl \&Sc , |
| +.Fl \&Ss |
| +and |
| +.Fl \&Sm |
| +options generate sample client, server and makefile, respectively. |
| +The |
| +.Fl a |
| +option generates all files, including sample files. |
| +If the |
| +.Ar infile |
| +is |
| +.Pa proto.x , |
| +then the client side sample file is written to |
| +.Pa proto_client.c , |
| +the server side sample file to |
| +.Pa proto_server.c |
| +and the sample makefile to |
| +.Pa makefile.proto . |
| +.Pp |
| +The server created can be started both by the port monitors |
| +(for example, |
| +.Xr inetd 8 ) |
| +or by itself. |
| +When it is started by a port monitor, |
| +it creates servers only for the transport for which |
| +the file descriptor |
| +.Em 0 |
| +was passed. |
| +The name of the transport must be specified |
| +by setting up the environment variable |
| +.Ev PM_TRANSPORT . |
| +When the server generated by |
| +.Nm |
| +is executed, |
| +it creates server handles for all the transports |
| +specified in |
| +.Ev NETPATH |
| +environment variable, |
| +or if it is unset, |
| +it creates server handles for all the visible transports from |
| +.Pa /etc/netconfig |
| +file. |
| +Note: |
| +the transports are chosen at run time and not at compile time. |
| +When the server is self-started, |
| +it backgrounds itself by default. |
| +A special define symbol |
| +.Em RPC_SVC_FG |
| +can be used to run the server process in foreground. |
| +.Pp |
| +The second synopsis provides special features which allow |
| +for the creation of more sophisticated |
| +.Tn RPC |
| +servers. |
| +These features include support for user provided |
| +.Em #defines |
| +and |
| +.Tn RPC |
| +dispatch tables. |
| +The entries in the |
| +.Tn RPC |
| +dispatch table contain: |
| +.Bl -bullet -offset indent -compact |
| +.It |
| +pointers to the service routine corresponding to that procedure, |
| +.It |
| +a pointer to the input and output arguments, |
| +.It |
| +the size of these routines. |
| +.El |
| +A server can use the dispatch table to check authorization |
| +and then to execute the service routine; |
| +a client library may use it to deal with the details of storage |
| +management and XDR data conversion. |
| +.Pp |
| +The other three synopses shown above are used when |
| +one does not want to generate all the output files, |
| +but only a particular one. |
| +See the |
| +.Sx EXAMPLES |
| +section below for examples of |
| +.Nm |
| +usage. |
| +When |
| +.Nm |
| +is executed with the |
| +.Fl s |
| +option, |
| +it creates servers for that particular class of transports. |
| +When |
| +executed with the |
| +.Fl n |
| +option, |
| +it creates a server for the transport specified by |
| +.Ar netid . |
| +If |
| +.Ar infile |
| +is not specified, |
| +.Nm |
| +accepts the standard input. |
| +.Pp |
| +The C preprocessor, |
| +.Em cc -E |
| +is run on the input file before it is actually interpreted by |
| +.Nm . |
| +For each type of output file, |
| +.Nm |
| +defines a special preprocessor symbol for use by the |
| +.Nm |
| +programmer: |
| +.Bl -tag -width indent |
| +.It RPC_HDR |
| +defined when compiling into headers |
| +.It RPC_XDR |
| +defined when compiling into XDR routines |
| +.It RPC_SVC |
| +defined when compiling into server-side stubs |
| +.It RPC_CLNT |
| +defined when compiling into client-side stubs |
| +.It RPC_TBL |
| +defined when compiling into RPC dispatch tables |
| +.El |
| +.Pp |
| +Any line beginning with |
| +.Dq % |
| +is passed directly into the output file, |
| +uninterpreted by |
| +.Nm . |
| +To specify the path name of the C preprocessor use |
| +.Fl Y |
| +flag. |
| +.Pp |
| +For every data type referred to in |
| +.Ar infile , |
| +.Nm |
| +assumes that there exists a |
| +routine with the string |
| +.Em xdr_ |
| +prepended to the name of the data type. |
| +If this routine does not exist in the |
| +.Tn RPC/XDR |
| +library, it must be provided. |
| +Providing an undefined data type |
| +allows customization of |
| +.Xr xdr 3 |
| +routines. |
| +.Sh OPTIONS |
| +The following options are available: |
| +.Bl -tag -width indent |
| +.It Fl a |
| +Generate all files, including sample files. |
| +.It Fl b |
| +Backward compatibility mode. |
| +Generate transport specific |
| +.Tn RPC |
| +code for older versions |
| +of the operating system. |
| +.Pp |
| +Note: in |
| +.Fx , |
| +this compatibility flag is turned on by |
| +default since |
| +.Fx |
| +supports only the older |
| +.Tn ONC RPC |
| +library. |
| +.It Fl c |
| +Compile into |
| +.Tn XDR |
| +routines. |
| +.It Fl C |
| +Generate header and stub files which can be used with |
| +.Tn ANSI |
| +C compilers. Headers generated with this flag can also be |
| +used with C++ programs. |
| +.It Fl D Ns Ar name |
| +.It Fl D Ns Ar name=value |
| +.\".It Fl D Ns Ar name Ns Op Ar =value |
| +Define a symbol |
| +.Ar name . |
| +Equivalent to the |
| +.Em #define |
| +directive in the source. |
| +If no |
| +.Ar value |
| +is given, |
| +.Ar value |
| +is defined as |
| +.Em 1 . |
| +This option may be specified more than once. |
| +.It Fl h |
| +Compile into C data-definitions (a header). |
| +.Fl T |
| +option can be used in conjunction to produce a |
| +header which supports |
| +.Tn RPC |
| +dispatch tables. |
| +.It Fl i Ar size |
| +Size at which to start generating inline code. |
| +This option is useful for optimization. |
| +The default size is 5. |
| +.Pp |
| +Note: in order to provide backwards compatibility with the older |
| +.Nm |
| +on the |
| +.Fx |
| +platform, the default is actually 0 (which means |
| +that inline code generation is disabled by default). You must specify |
| +a non-zero value explicitly to override this default. |
| +.It Fl I |
| +Compile support for |
| +.Xr inetd 8 |
| +in the server side stubs. |
| +Such servers can be self-started or can be started by |
| +.Nm inetd . |
| +When the server is self-started, it backgrounds itself by default. |
| +A special define symbol |
| +.Em RPC_SVC_FG |
| +can be used to run the |
| +server process in foreground, or the user may simply compile without |
| +the |
| +.Fl I |
| +option. |
| +.Pp |
| +If there are no pending client requests, the |
| +.Nm inetd |
| +servers exit after 120 seconds (default). |
| +The default can be changed with the |
| +.Fl K |
| +option. |
| +All the error messages for |
| +.Nm inetd |
| +servers |
| +are always logged with |
| +.Xr syslog 3 . |
| +.\" .IP |
| +.\" Note: |
| +.\" this option is supported for backward compatibility only. |
| +.\" By default, |
| +.\" .B rpcgen |
| +.\" generates servers that can be invoked through portmonitors. |
| +.Pp |
| +.It Fl K Ar seconds |
| +By default, services created using |
| +.Nm |
| +and invoked through |
| +port monitors wait 120 seconds |
| +after servicing a request before exiting. |
| +That interval can be changed using the |
| +.Fl K |
| +flag. |
| +To create a server that exits immediately upon servicing a request, |
| +use |
| +.Fl K Ar 0 . |
| +To create a server that never exits, the appropriate argument is |
| +.Fl k Ar -1 . |
| +.Pp |
| +When monitoring for a server, |
| +some portmonitors |
| +.Em always |
| +spawn a new process in response to a service request. |
| +If it is known that a server will be used with such a monitor, the |
| +server should exit immediately on completion. |
| +For such servers, |
| +.Nm |
| +should be used with |
| +.Fl K Ar 0 . |
| +.It Fl l |
| +Compile into client-side stubs. |
| +.It Fl L |
| +When the servers are started in foreground, use |
| +.Xr syslog 3 |
| +to log the server errors instead of printing them on the standard |
| +error. |
| +.It Fl m |
| +Compile into server-side stubs, |
| +but do not generate a |
| +.Qq main |
| +routine. |
| +This option is useful for doing callback-routines |
| +and for users who need to write their own |
| +.Qq main |
| +routine to do initialization. |
| +.It Fl M |
| +Generate multithread-safe stubs for passing arguments and results between |
| +rpcgen generated code and user written code. |
| +This option is useful |
| +for users who want to use threads in their code. |
| +However, the |
| +.Xr rpc_svc_calls 3 |
| +functions are not yet MT-safe, which means that rpcgen generated server-side |
| +code will not be MT-safe. |
| +.It Fl N |
| +This option allows procedures to have multiple arguments. |
| +It also uses the style of parameter passing that closely resembles C. |
| +So, when passing an argument to a remote procedure, you do not have to |
| +pass a pointer to the argument, but can pass the argument itself. |
| +This behavior is different from the old style of |
| +.Nm |
| +generated code. |
| +To maintain backward compatibility, |
| +this option is not the default. |
| +.It Fl n Ar netid |
| +Compile into server-side stubs for the transport |
| +specified by |
| +.Ar netid . |
| +There should be an entry for |
| +.Ar netid |
| +in the |
| +netconfig database. |
| +This option may be specified more than once, |
| +so as to compile a server that serves multiple transports. |
| +.It Fl o Ar outfile |
| +Specify the name of the output file. |
| +If none is specified, |
| +standard output is used |
| +( |
| +.Fl c , |
| +.Fl h , |
| +.Fl l , |
| +.Fl m , |
| +.Fl n , |
| +.Fl s , |
| +.Fl \&Sc , |
| +.Fl \&Sm , |
| +.Fl \&Ss , |
| +and |
| +.Fl t |
| +modes only). |
| +.It Fl s Ar nettype |
| +Compile into server-side stubs for all the |
| +transports belonging to the class |
| +.Ar nettype . |
| +The supported classes are |
| +.Em netpath , |
| +.Em visible , |
| +.Em circuit_n , |
| +.Em circuit_v , |
| +.Em datagram_n , |
| +.Em datagram_v , |
| +.Em tcp , |
| +and |
| +.Em udp |
| +(see |
| +.Xr rpc 3 |
| +for the meanings associated with these classes). |
| +This option may be specified more than once. |
| +Note: |
| +the transports are chosen at run time and not at compile time. |
| +.It Fl \&Sc |
| +Generate sample client code that uses remote procedure calls. |
| +.It Fl \&Sm |
| +Generate a sample |
| +.Pa Makefile |
| +which can be used for compiling the application. |
| +.It Fl \&Ss |
| +Generate sample server code that uses remote procedure calls. |
| +.It Fl t |
| +Compile into |
| +.Tn RPC |
| +dispatch table. |
| +.It Fl T |
| +Generate the code to support |
| +.Tn RPC |
| +dispatch tables. |
| +.Pp |
| +The options |
| +.Fl c , |
| +.Fl h , |
| +.Fl l , |
| +.Fl m , |
| +.Fl s , |
| +.Fl \&Sc , |
| +.Fl \&Sm , |
| +.Fl \&Ss , |
| +and |
| +.Fl t |
| +are used exclusively to generate a particular type of file, |
| +while the options |
| +.Fl D |
| +and |
| +.Fl T |
| +are global and can be used with the other options. |
| +.It Fl Y Ar pathname |
| +Give the name of the directory where |
| +.Nm |
| +will start looking for the C-preprocessor. |
| +.El |
| +.Sh EXAMPLES |
| +The following example: |
| +.Dl example% rpcgen -T prot.x |
| +.Pp |
| +generates all the five files: |
| +.Pa prot.h , |
| +.Pa prot_clnt.c , |
| +.Pa prot_svc.c , |
| +.Pa prot_xdr.c |
| +and |
| +.Pa prot_tbl.i . |
| +.Pp |
| +The following example sends the C data-definitions (header) |
| +to the standard output. |
| +.Dl example% rpcgen -h prot.x |
| +.Pp |
| +To send the test version of the |
| +.Fl D Ns Ar TEST , |
| +server side stubs for |
| +all the transport belonging to the class |
| +.Ar datagram_n |
| +to standard output, use: |
| +.Dl example% rpcgen -s datagram_n -DTEST prot.x |
| +.Pp |
| +To create the server side stubs for the transport indicated |
| +by |
| +.Ar netid |
| +tcp, |
| +use: |
| +.Dl example% rpcgen -n tcp -o prot_svc.c prot.x |
| +.Sh SEE ALSO |
| +.Xr cc 1 , |
| +.Xr rpc 3 , |
| +.Xr syslog 3 , |
| +.Xr inetd 8 |
| +.\" .BR rpc_svc_calls (3) |
| +.Rs |
| +.%T The rpcgen chapter in the NETP manual |
| +.Re |
| -- |
| 1.9.1 |
| |