Import a newer and more functional version of rpcgen.

Obtained from: the Sun TI-RPC 2.3 source distribution
This commit is contained in:
Bill Paul 1995-12-13 03:21:09 +00:00
commit ee4f614e7e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/SUNRPC/; revision=12795
15 changed files with 7411 additions and 0 deletions

13
usr.bin/rpcgen/Makefile Normal file
View File

@ -0,0 +1,13 @@
SRCS= rpc_main.c rpc_clntout.c rpc_cout.c rpc_hout.c rpc_parse.c \
rpc_sample.c rpc_scan.c rpc_svcout.c rpc_tblout.c rpc_util.c
PROG= rpcgen
MAN1= rpcgen.1
#
# This is a kludge to work around the fact that this program
# uses 'inline' as a variable name.
#
CFLAGS+=-Dinline=rpcgen_inline
.include <bsd.prog.mk>

View File

@ -0,0 +1,331 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#ident "@(#)rpc_clntout.c 1.15 94/04/25 SMI"
#ifndef lint
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"
extern int pdeclaration __P(( char *, declaration *, int, char * ));
void printarglist __P(( proc_list *, char *, char *, char *));
static int write_program __P(( definition * ));
static int printbody __P(( proc_list * ));
static char RESULT[] = "clnt_res";
#define DEFAULT_TIMEOUT 25 /* in seconds */
void
write_stubs()
{
list *l;
definition *def;
f_print(fout,
"\n/* Default timeout can be changed using clnt_control() */\n");
f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
DEFAULT_TIMEOUT);
for (l = defined; l != NULL; l = l->next) {
def = (definition *) l->val;
if (def->def_kind == DEF_PROGRAM) {
write_program(def);
}
}
}
static
write_program(def)
definition *def;
{
version_list *vp;
proc_list *proc;
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
for (proc = vp->procs; proc != NULL; proc = proc->next) {
f_print(fout, "\n");
if (mtflag == 0) {
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "*\n");
pvname(proc->proc_name, vp->vers_num);
printarglist(proc, RESULT, "clnt", "CLIENT *");
} else {
f_print(fout, "enum clnt_stat \n");
pvname(proc->proc_name, vp->vers_num);
printarglist(proc, RESULT, "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, result, addargname, addargtype)
proc_list *proc;
char *result;
char* addargname, * addargtype;
{
decl_list *l;
if (!newstyle) {
/* old style: always pass argument by reference */
if (Cflag) { /* C++ style heading */
f_print(fout, "(");
ptype(proc->args.decls->decl.prefix,
proc->args.decls->decl.type, 1);
if (mtflag) {/* Generate result field */
f_print(fout, "*argp, ");
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "*%s, %s%s)\n",
result, addargtype, addargname);
} else
f_print(fout, "*argp, %s%s)\n", addargtype, addargname);
} else {
if (!mtflag)
f_print(fout, "(argp, %s)\n", addargname);
else
f_print(fout, "(argp, %s, %s)\n",
result, addargname);
f_print(fout, "\t");
ptype(proc->args.decls->decl.prefix,
proc->args.decls->decl.type, 1);
f_print(fout, "*argp;\n");
if (mtflag) {
f_print(fout, "\t");
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "*%s;\n", result);
}
}
} else if (streq(proc->args.decls->decl.type, "void")) {
/* newstyle, 0 argument */
if (mtflag) {
f_print(fout, "(");
if (Cflag) {
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "*%s, %s%s)\n",
result, addargtype, addargname);
}
else
f_print(fout, "(%s)\n", addargname);
} else
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);
if (mtflag)
f_print(fout, "%s, ", result);
f_print(fout, "%s)\n", addargname);
for (l = proc->args.decls; l != NULL; l = l->next) {
pdeclaration(proc->args.argname,
&l->decl, 1, ";\n");
}
if (mtflag) {
f_print(fout, "\t");
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "*%s;\n", result);
}
} else { /* C++ style header */
f_print(fout, "(");
for (l = proc->args.decls; l != NULL; l = l->next) {
pdeclaration(proc->args.argname, &l->decl, 0,
", ");
}
if (mtflag) {
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "*%s, ", result);
}
f_print(fout, "%s%s)\n", addargtype, addargname);
}
}
if (!Cflag)
f_print(fout, "\t%s%s;\n", addargtype, addargname);
}
static char *
ampr(type)
char *type;
{
if (isvectordef(type, REL_ALIAS)) {
return ("");
} else {
return ("&");
}
}
static
printbody(proc)
proc_list *proc;
{
decl_list *l;
bool_t args2 = (proc->arg_num > 1);
int i;
/*
* 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");
}
if (!mtflag) {
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 */
if (mtflag)
f_print(fout, "\t return ");
else
f_print(fout, "\t if ");
f_print(fout,
"(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_void, ",
proc->proc_name);
f_print(fout,
"(caddr_t) NULL,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
RESULT);
if (mtflag)
f_print(fout, "\n\t\tTIMEOUT));\n}\n");
else
f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
} 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);
}
if (mtflag)
f_print(fout, "\treturn ");
else
f_print(fout, "\tif ");
f_print(fout,
"(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s",
proc->proc_name,proc->args.argname);
f_print(fout,
", (caddr_t) &arg,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
RESULT);
if (mtflag)
f_print(fout, "\n\t\tTIMEOUT));\n");
else
f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
} else { /* single argument, new or old style */
if (!mtflag)
f_print(fout,
"\tif (clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT) != 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);
else
f_print(fout,
"\treturn (clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT));\n",
proc->proc_name,
stringfix(proc->args.decls->decl.type),
(newstyle ? "&" : ""),
(newstyle ? proc->args.decls->decl.name : "argp"),
stringfix(proc->res_type), "",
RESULT);
}
if (!mtflag) {
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);
}
}
}

752
usr.bin/rpcgen/rpc_cout.c Normal file
View File

@ -0,0 +1,752 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#ident "@(#)rpc_cout.c 1.14 93/07/05 SMI"
#ifndef lint
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
* Copyright (C) 1987, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <string.h>
#include "rpc_parse.h"
#include "rpc_util.h"
static int print_header __P(( definition * ));
static int print_trailer __P(( void ));
static int print_stat __P(( int , declaration * ));
static int emit_enum __P(( definition * ));
static int emit_program __P(( definition * ));
static int emit_union __P(( definition * ));
static int emit_struct __P(( definition * ));
static int emit_typedef __P(( definition * ));
/*
* Emit the C-routine for the given definition
*/
void
emit(def)
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;
}
print_trailer();
}
static
findtype(def, type)
definition *def;
char *type;
{
if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) {
return (0);
} else {
return (streq(def->def_name, type));
}
}
static
undefined(type)
char *type;
{
definition *def;
def = (definition *) FINDVAL(defined, type, findtype);
return (def == NULL);
}
static
print_generic_header(procname, pointerp)
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, "register 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, "\tregister XDR *xdrs;\n");
f_print(fout, "\t%s ", procname);
if (pointerp)
f_print(fout, "*");
f_print(fout, "objp;\n{\n\n");
}
}
static
print_header(def)
definition *def;
{
decl_list *dl;
bas_type *ptr;
int i;
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;
/* May cause lint to complain. but ... */
f_print(fout, "\tregister long *buf;\n\n");
}
static
print_prog_header(plist)
proc_list *plist;
{
print_generic_header(plist->args.argname, 1);
}
static
print_trailer()
{
f_print(fout, "\treturn (TRUE);\n");
f_print(fout, "}\n");
}
static
print_ifopen(indent, name)
int indent;
char *name;
{
tabify(fout, indent);
f_print(fout, "if (!xdr_%s(xdrs", name);
}
static
print_ifarg(arg)
char *arg;
{
f_print(fout, ", %s", arg);
}
static
print_ifsizeof(indent, prefix, type)
int indent;
char *prefix;
char *type;
{
if (indent) {
f_print(fout, ",\n");
tabify(fout, indent);
} else {
f_print(fout, ", ");
}
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
print_ifclose(indent)
int indent;
{
f_print(fout, "))\n");
tabify(fout, indent);
f_print(fout, "\treturn (FALSE);\n");
}
static
print_ifstat(indent, prefix, type, rel, amax, objname, name)
int indent;
char *prefix;
char *type;
relation rel;
char *amax;
char *objname;
char *name;
{
char *alt = NULL;
switch (rel) {
case REL_POINTER:
print_ifopen(indent, "pointer");
print_ifarg("(char **)");
f_print(fout, "%s", objname);
print_ifsizeof(0, 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(indent + 1, prefix, type);
}
break;
case REL_ARRAY:
if (streq(type, "string")) {
alt = "string";
} else if (streq(type, "opaque")) {
alt = "bytes";
}
if (streq(type, "string")) {
print_ifopen(indent, alt);
print_ifarg(objname);
} else {
if (alt) {
print_ifopen(indent, alt);
} else {
print_ifopen(indent, "array");
}
print_ifarg("(char **)");
if (*objname == '&') {
f_print(fout, "%s.%s_val, (u_int *) %s.%s_len",
objname, name, objname, name);
} else {
f_print(fout,
"&%s->%s_val, (u_int *) &%s->%s_len",
objname, name, objname, name);
}
}
print_ifarg(amax);
if (!alt) {
print_ifsizeof(indent + 1, prefix, type);
}
break;
case REL_ALIAS:
print_ifopen(indent, type);
print_ifarg(objname);
break;
}
print_ifclose(indent);
}
/* ARGSUSED */
static
emit_enum(def)
definition *def;
{
print_ifopen(1, "enum");
print_ifarg("(enum_t *)objp");
print_ifclose(1);
}
static
emit_program(def)
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
emit_union(def)
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 {
f_print(fout, "\tdefault:\n");
f_print(fout, "\t\treturn (FALSE);\n");
}
f_print(fout, "\t}\n");
}
static void
inline_struct(def, flag)
definition *def;
int flag;
{
decl_list *dl;
int i, size;
decl_list *cur, *psav;
bas_type *ptr;
char *sizestr, *plus;
char ptemp[256];
int indent = 1;
if (flag == PUT)
f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n");
else
f_print(fout, "\t\treturn (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n");
i = 0;
size = 0;
sizestr = NULL;
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 code 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(indent + 1, &cur->decl);
cur = cur->next;
}
} else {
/* were already looking at a xdr_inlineable structure */
tabify(fout, indent + 1);
if (sizestr == NULL)
f_print(fout, "buf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);",
size);
else
if (size == 0)
f_print(fout,
"buf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);",
sizestr);
else
f_print(fout,
"buf = XDR_INLINE(xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);",
size, sizestr);
f_print(fout, "\n");
tabify(fout, indent + 1);
f_print(fout,
"if (buf == NULL) {\n");
psav = cur;
while (cur != dl){
print_stat(indent + 2, &cur->decl);
cur = cur->next;
}
f_print(fout, "\n\t\t} else {\n");
cur = psav;
while (cur != dl){
emit_inline(indent + 2, &cur->decl, flag);
cur = cur->next;
}
tabify(fout, indent + 1);
f_print(fout, "}\n");
}
size = 0;
i = 0;
sizestr = NULL;
print_stat(indent + 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(indent + 1, &cur->decl);
cur = cur->next;
}
} else {
/* were already looking at a xdr_inlineable structure */
if (sizestr == NULL)
f_print(fout, "\t\tbuf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);",
size);
else
if (size == 0)
f_print(fout,
"\t\tbuf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);",
sizestr);
else
f_print(fout,
"\t\tbuf = XDR_INLINE(xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);",
size, sizestr);
f_print(fout, "\n\t\tif (buf == NULL) {\n");
psav = cur;
while (cur != NULL){
print_stat(indent + 2, &cur->decl);
cur = cur->next;
}
f_print(fout, "\t\t} else {\n");
cur = psav;
while (cur != dl){
emit_inline(indent + 2, &cur->decl, flag);
cur = cur->next;
}
f_print(fout, "\t\t}\n");
}
}
static
emit_struct(def)
definition *def;
{
decl_list *dl;
int i, j, size, flag;
bas_type *ptr;
int can_inline;
if (inline == 0) {
/* No xdr_inlining at all */
for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
print_stat(1, &dl->decl);
return;
}
for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
if (dl->decl.rel == REL_VECTOR){
f_print(fout, "\tint i;\n");
break;
}
size = 0;
can_inline = 0;
/*
* Make a first pass and see if inling is possible.
*/
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++){
inline_struct(def, flag);
if (flag == PUT)
flag = GET;
}
f_print(fout, "\t\treturn (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
emit_typedef(def)
definition *def;
{
char *prefix = def->def.ty.old_prefix;
char *type = def->def.ty.old_type;
char *amax = def->def.ty.array_max;
relation rel = def->def.ty.rel;
print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
}
static
print_stat(indent, dec)
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);
}
char *upcase ();
emit_inline(indent, decl, flag)
int indent;
declaration *decl;
int flag;
{
switch (decl->rel) {
case REL_ALIAS :
emit_single_in_line(indent, decl, flag, REL_ALIAS);
break;
case REL_VECTOR :
tabify(fout, indent);
f_print(fout, "{\n");
tabify(fout, indent + 1);
f_print(fout, "register %s *genp;\n\n", decl->type);
tabify(fout, indent + 1);
f_print(fout,
"for (i = 0, genp = objp->%s;\n", decl->name);
tabify(fout, indent + 2);
f_print(fout, "i < %s; i++) {\n", decl->array_max);
emit_single_in_line(indent + 2, decl, flag, REL_VECTOR);
tabify(fout, indent + 1);
f_print(fout, "}\n");
tabify(fout, indent);
f_print(fout, "}\n");
}
}
emit_single_in_line(indent, decl, flag, rel)
int indent;
declaration *decl;
int flag;
relation rel;
{
char *upp_case;
int freed = 0;
tabify(fout, indent);
if (flag == PUT)
f_print(fout, "IXDR_PUT_");
else
if (rel == REL_ALIAS)
f_print(fout, "objp->%s = IXDR_GET_", decl->name);
else
f_print(fout, "*genp++ = IXDR_GET_");
upp_case = upcase(decl->type);
/* hack - XX */
if (strcmp(upp_case, "INT") == 0)
{
free(upp_case);
freed = 1;
upp_case = "LONG";
}
if (strcmp(upp_case, "U_INT") == 0)
{
free(upp_case);
freed = 1;
upp_case = "U_LONG";
}
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);
}
char *upcase(str)
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);
}

597
usr.bin/rpcgen/rpc_hout.c Normal file
View File

@ -0,0 +1,597 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#ident "@(#)rpc_hout.c 1.16 94/04/25 SMI"
#ifndef lint
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
* Copyright (C) 1987, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <ctype.h>
#include "rpc_parse.h"
#include "rpc_util.h"
void storexdrfuncdecl __P(( char *, int ));
static int pconstdef __P(( definition * ));
static int pstructdef __P(( definition * ));
static int puniondef __P(( definition * ));
static int pprogramdef __P(( definition * ));
static int pstructdef __P(( definition * ));
static int penumdef __P(( definition * ));
static int ptypedef __P(( definition * ));
static int pdefine __P(( char *, char * ));
static int undefined2 __P(( char *, char * ));
static int parglist __P(( proc_list *, char * ));
static char RESULT[] = "clnt_res";
/*
* Print the C-version of an xdr definition
*/
void
print_datadef(def)
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) {
storexdrfuncdecl(def->def_name,
def->def_kind != DEF_TYPEDEF ||
!isvectordef(def->def.ty.old_type,
def->def.ty.rel));
}
}
void
print_funcdef(def)
definition *def;
{
switch (def->def_kind) {
case DEF_PROGRAM:
f_print(fout, "\n");
pprogramdef(def);
break;
}
}
/* store away enough information to allow the XDR functions to be spat
out at the end of the file */
void
storexdrfuncdecl(name, pointerp)
char *name;
int pointerp;
{
xdrfunc * xdrptr;
xdrptr = (xdrfunc *) malloc(sizeof (struct xdrfunc));
xdrptr->name = name;
xdrptr->pointerp = pointerp;
xdrptr->next = NULL;
if (xdrfunc_tail == NULL){
xdrfunc_head = xdrptr;
xdrfunc_tail = xdrptr;
} else {
xdrfunc_tail->next = xdrptr;
xdrfunc_tail = xdrptr;
}
}
void
print_xdr_func_def(name, pointerp, i)
char* name;
int pointerp;
int i;
{
if (i == 2) {
f_print(fout, "extern bool_t xdr_%s();\n", name);
return;
}
else
f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n", name,
name, pointerp ? "*" : "");
}
static
pconstdef(def)
definition *def;
{
pdefine(def->def_name, def->def.co);
}
/* print out the definitions for the arguments of functions in the
header file
*/
static
pargdef(def)
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);
storexdrfuncdecl(name, 1);
f_print(fout, "\n");
}
}
}
static
pstructdef(def)
definition *def;
{
decl_list *l;
char *name = def->def_name;
f_print(fout, "struct %s {\n", name);
for (l = def->def.st.decls; l != NULL; l = l->next) {
pdeclaration(name, &l->decl, 1, ";\n");
}
f_print(fout, "};\n");
f_print(fout, "typedef struct %s %s;\n", name, name);
}
static
puniondef(def)
definition *def;
{
case_list *l;
char *name = def->def_name;
declaration *decl;
f_print(fout, "struct %s {\n", name);
decl = &def->def.un.enum_decl;
if (streq(decl->type, "bool")) {
f_print(fout, "\tbool_t %s;\n", decl->name);
} else {
f_print(fout, "\t%s %s;\n", decl->type, decl->name);
}
f_print(fout, "\tunion {\n");
for (l = def->def.un.cases; l != NULL; l = l->next) {
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
pdefine(name, num)
char *name;
char *num;
{
f_print(fout, "#define\t%s %s\n", name, num);
}
static
puldefine(name, num)
char *name;
char *num;
{
f_print(fout, "#define\t%s ((unsigned long)(%s))\n", name, num);
}
static
define_printed(stop, start)
proc_list *stop;
version_list *start;
{
version_list *vers;
proc_list *proc;
for (vers = start; vers != NULL; vers = vers->next) {
for (proc = vers->procs; proc != NULL; proc = proc->next) {
if (proc == stop) {
return (0);
} else if (streq(proc->proc_name, stop->proc_name)) {
return (1);
}
}
}
abort();
/* NOTREACHED */
}
static
pfreeprocdef(char * name, char *vers, int mode)
{
f_print(fout, "extern int ");
pvname(name, vers);
if (mode == 1)
f_print(fout,"_freeresult(SVCXPRT *, xdrproc_t, caddr_t);\n");
else
f_print(fout,"_freeresult();\n");
}
static
pprogramdef(def)
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 2 definitions, one for ANSI-C, another for
* old K & R C
*/
if(!Cflag){
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, NULL, 0, 2);
if (mtflag) {
f_print(fout, "%s", ext);
pprocdef(proc, vers, NULL, 1, 2);
}
}
pfreeprocdef(def->def_name, vers->vers_num, 2);
} else {
for (i = 1; i < 3; i++){
if (i == 1){
f_print(fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n");
ext = "extern ";
}else{
f_print(fout, "\n#else /* K&R 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);
}
pfreeprocdef(def->def_name, vers->vers_num, i);
}
f_print(fout, "#endif /* K&R C */\n");
}
}
}
pprocdef(proc, vp, addargtype, server_p, mode)
proc_list *proc;
version_list *vp;
char* addargtype;
int server_p;
int mode;
{
if (mtflag) {/* Print MT style stubs */
if (server_p)
f_print(fout, "bool_t ");
else
f_print(fout, "enum clnt_stat ");
} else {
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 1 = ANSI-C, mode 2 = K&R C
*/
if ( mode == 1)
parglist(proc, addargtype);
else
f_print(fout, "();\n");
}
/* print out argument list of procedure */
static
parglist(proc, addargtype)
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, ", ");
}
}
if (mtflag) {
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "*, ");
}
f_print(fout, "%s);\n", addargtype);
}
static
penumdef(def)
definition *def;
{
char *name = def->def_name;
enumval_list *l;
char *last = NULL;
int count = 0;
f_print(fout, "enum %s {\n", name);
for (l = def->def.en.vals; l != NULL; l = l->next) {
f_print(fout, "\t%s", l->name);
if (l->assignment) {
f_print(fout, " = %s", l->assignment);
last = l->assignment;
count = 1;
} else {
if (last == NULL) {
f_print(fout, " = %d", count++);
} else {
f_print(fout, " = %s + %d", last, count++);
}
}
if (l->next)
f_print(fout, ",\n");
else
f_print(fout, "\n");
}
f_print(fout, "};\n");
f_print(fout, "typedef enum %s %s;\n", name, name);
}
static
ptypedef(def)
definition *def;
{
char *name = def->def_name;
char *old = def->def.ty.old_type;
char prefix[8]; /* enough to contain "struct ", including NUL */
relation rel = def->def.ty.rel;
if (!streq(name, old)) {
if (streq(old, "string")) {
old = "char";
rel = REL_POINTER;
} else if (streq(old, "opaque")) {
old = "char";
} else if (streq(old, "bool")) {
old = "bool_t";
}
if (undefined2(old, name) && def->def.ty.old_prefix) {
s_print(prefix, "%s ", def->def.ty.old_prefix);
} else {
prefix[0] = 0;
}
f_print(fout, "typedef ");
switch (rel) {
case REL_ARRAY:
f_print(fout, "struct {\n");
f_print(fout, "\tu_int %s_len;\n", name);
f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name);
f_print(fout, "} %s", name);
break;
case REL_POINTER:
f_print(fout, "%s%s *%s", prefix, old, name);
break;
case REL_VECTOR:
f_print(fout, "%s%s %s[%s]", prefix, old, name,
def->def.ty.array_max);
break;
case REL_ALIAS:
f_print(fout, "%s%s %s", prefix, old, name);
break;
}
f_print(fout, ";\n");
}
}
pdeclaration(name, dec, tab, separator)
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
undefined2(type, stop)
char *type;
char *stop;
{
list *l;
definition *def;
for (l = defined; l != NULL; l = l->next) {
def = (definition *) l->val;
if (def->def_kind != DEF_PROGRAM) {
if (streq(def->def_name, stop)) {
return (1);
} else if (streq(def->def_name, type)) {
return (0);
}
}
}
return (1);
}

1381
usr.bin/rpcgen/rpc_main.c Normal file

File diff suppressed because it is too large Load Diff

655
usr.bin/rpcgen/rpc_parse.c Normal file
View File

@ -0,0 +1,655 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#ident "@(#)rpc_parse.c 1.12 93/07/05 SMI"
#ifndef lint
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 __P(( char *, char * ));
static int isdefined __P(( definition * ));
static int def_struct __P(( definition * ));
static int def_program __P(( definition * ));
static int def_enum __P(( definition * ));
static int def_const __P(( definition * ));
static int def_union __P(( definition * ));
static int def_typedef __P(( definition * ));
static int get_declaration __P(( declaration *, defkind ));
static int get_prog_declaration __P(( declaration *, defkind, int ));
static int get_type __P(( char **, char **, defkind ));
static int unsigned_dec __P(( char ** ));
#ifndef __FreeBSD__
extern char *strdup();
#endif
/*
* return the next definition you see
*/
definition *
get_definition()
{
definition *defp;
token tok;
defp = ALLOC(definition);
get_token(&tok);
switch (tok.kind) {
case TOK_STRUCT:
def_struct(defp);
break;
case TOK_UNION:
def_union(defp);
break;
case TOK_TYPEDEF:
def_typedef(defp);
break;
case TOK_ENUM:
def_enum(defp);
break;
case TOK_PROGRAM:
def_program(defp);
break;
case TOK_CONST:
def_const(defp);
break;
case TOK_EOF:
return (NULL);
default:
error("definition keyword expected");
}
scan(TOK_SEMICOLON, &tok);
isdefined(defp);
return (defp);
}
static
isdefined(defp)
definition *defp;
{
STOREVAL(&defined, defp);
}
static
def_struct(defp)
definition *defp;
{
token tok;
declaration dec;
decl_list *decls;
decl_list **tailp;
defp->def_kind = DEF_STRUCT;
scan(TOK_IDENT, &tok);
defp->def_name = tok.str;
scan(TOK_LBRACE, &tok);
tailp = &defp->def.st.decls;
do {
get_declaration(&dec, DEF_STRUCT);
decls = ALLOC(decl_list);
decls->decl = dec;
*tailp = decls;
tailp = &decls->next;
scan(TOK_SEMICOLON, &tok);
peek(&tok);
} while (tok.kind != TOK_RBRACE);
get_token(&tok);
*tailp = NULL;
}
static
def_program(defp)
definition *defp;
{
token tok;
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
def_enum(defp)
definition *defp;
{
token tok;
enumval_list *elist;
enumval_list **tailp;
defp->def_kind = DEF_ENUM;
scan(TOK_IDENT, &tok);
defp->def_name = tok.str;
scan(TOK_LBRACE, &tok);
tailp = &defp->def.en.vals;
do {
scan(TOK_IDENT, &tok);
elist = ALLOC(enumval_list);
elist->name = tok.str;
elist->assignment = NULL;
scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
if (tok.kind == TOK_EQUAL) {
scan_num(&tok);
elist->assignment = tok.str;
scan2(TOK_COMMA, TOK_RBRACE, &tok);
}
*tailp = elist;
tailp = &elist->next;
} while (tok.kind != TOK_RBRACE);
*tailp = NULL;
}
static
def_const(defp)
definition *defp;
{
token tok;
defp->def_kind = DEF_CONST;
scan(TOK_IDENT, &tok);
defp->def_name = tok.str;
scan(TOK_EQUAL, &tok);
scan2(TOK_IDENT, TOK_STRCONST, &tok);
defp->def.co = tok.str;
}
static
def_union(defp)
definition *defp;
{
token tok;
declaration dec;
case_list *cases, *tcase;
case_list **tailp;
int flag;
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 */
flag = 0;
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));
}
else
if (flag)
{
*tailp = cases;
tailp = &cases->next;
cases = ALLOC(case_list);
};
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 check_type_name(name, new_type)
int new_type;
char* name;
{
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
def_typedef(defp)
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
get_declaration(dec, dkind)
declaration *dec;
defkind dkind;
{
token tok;
get_type(&dec->prefix, &dec->type, dkind);
dec->rel = REL_ALIAS;
if (streq(dec->type, "void")) {
return;
}
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
get_prog_declaration(dec, dkind, num)
declaration *dec;
defkind dkind;
int num; /* arg number */
{
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
get_type(prefixp, typep, dkind)
char **prefixp;
char **typep;
defkind dkind;
{
token tok;
*prefixp = NULL;
get_token(&tok);
switch (tok.kind) {
case TOK_IDENT:
*typep = tok.str;
break;
case TOK_STRUCT:
case TOK_ENUM:
case TOK_UNION:
*prefixp = tok.str;
scan(TOK_IDENT, &tok);
*typep = tok.str;
break;
case TOK_UNSIGNED:
unsigned_dec(typep);
break;
case TOK_SHORT:
*typep = "short";
(void) peekscan(TOK_INT, &tok);
break;
case TOK_LONG:
*typep = "long";
(void) peekscan(TOK_INT, &tok);
break;
case TOK_HYPER:
*typep = "longlong_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:
case TOK_QUAD:
*typep = tok.str;
break;
default:
error("expected type specifier");
}
}
static
unsigned_dec(typep)
char **typep;
{
token tok;
peek(&tok);
switch (tok.kind) {
case TOK_CHAR:
get_token(&tok);
*typep = "u_char";
break;
case TOK_SHORT:
get_token(&tok);
*typep = "u_short";
(void) peekscan(TOK_INT, &tok);
break;
case TOK_LONG:
get_token(&tok);
*typep = "u_long";
(void) peekscan(TOK_INT, &tok);
break;
case TOK_HYPER:
get_token(&tok);
*typep = "ulonglong_t";
(void) peekscan(TOK_INT, &tok);
break;
case TOK_INT:
get_token(&tok);
*typep = "u_int";
break;
default:
*typep = "u_int";
break;
}
}

197
usr.bin/rpcgen/rpc_parse.h Normal file
View File

@ -0,0 +1,197 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#pragma ident "@(#)rpc_parse.h 1.10 94/05/15 SMI"
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* PROPRIETARY NOTICE (Combined)
*
* This source code is unpublished proprietary information
* constituting, or derived under license from AT&T's UNIX(r) System V.
* In addition, portions of such source code were derived from Berkeley
* 4.3 BSD under license from the Regents of the University of
* California.
*
*
*
* Copyright Notice
*
* Notice of copyright on this source code product does not indicate
* publication.
*
* (c) 1986,1987,1988.1989 Sun Microsystems, Inc
* (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
* All rights reserved.
*/
/* @(#)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;

311
usr.bin/rpcgen/rpc_sample.c Normal file
View File

@ -0,0 +1,311 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#pragma ident "@(#)rpc_sample.c 1.9 94/04/25 SMI"
/*
* rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler
* Copyright (C) 1987, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <string.h>
#include "rpc_parse.h"
#include "rpc_util.h"
static char RQSTP[] = "rqstp";
extern void printarglist __P(( proc_list *, char *, char *, char *));
static int write_sample_client __P(( char *, version_list * ));
static int write_sample_server __P(( definition * ));
static int return_type __P(( proc_list * ));
void
write_sample_svc(def)
definition *def;
{
if (def->def_kind != DEF_PROGRAM)
return;
write_sample_server(def);
}
int
write_sample_clnt(def)
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
write_sample_client(program_name, vp)
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)\n\tchar *host;\n{\n");
f_print(fout, "\tCLIENT *clnt;\n");
i = 0;
for (proc = vp->procs; proc != NULL; proc = proc->next) {
f_print(fout, "\t");
if (mtflag) {
f_print(fout, "enum clnt_stat retval_%d;\n\t", ++i);
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "result_%d;\n", i);
} else {
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);
if (strcmp(l->decl.type,"string") == 1)
f_print(fout, " ");
pvname(proc->proc_name, vp->vers_num);
f_print(fout, "_%s;\n", l->decl.name);
}
}
}
/* generate creation of client handle */
f_print(fout, "\n#ifndef\tDEBUG\n");
f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n",
program_name, vp->vers_name, tirpcflag? "netpath" : "udp");
f_print(fout, "\tif (clnt == (CLIENT *) NULL) {\n");
f_print(fout, "\t\tclnt_pcreateerror(host);\n");
f_print(fout, "\t\texit(1);\n\t}\n");
f_print(fout, "#endif\t/* DEBUG */\n\n");
/* generate calls to procedures */
i = 0;
for (proc = vp->procs; proc != NULL; proc = proc->next) {
if (mtflag)
f_print(fout, "\tretval_%d = ",++i);
else
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);
if (mtflag)
f_print(fout, "_arg, &result_%d, clnt);\n",
i);
else
f_print(fout, "_arg, clnt);\n");
} else if (streq(proc->args.decls->decl.type, "void")) {
if (mtflag)
f_print(fout, "(&result_%d, clnt);\n", i);
else
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);
}
if (mtflag)
f_print(fout, "&result_%d, ", i);
f_print(fout, "clnt);\n");
}
if (mtflag) {
f_print(fout, "\tif (retval_%d != RPC_SUCCESS) {\n", i);
} else {
f_print(fout, "\tif (result_%d == (", i);
ptype(proc->res_prefix, proc->res_type, 1);
f_print(fout, "*) NULL) {\n");
}
f_print(fout, "\t\tclnt_perror(clnt, \"call failed\");\n");
f_print(fout, "\t}\n");
}
f_print(fout, "#ifndef\tDEBUG\n");
f_print(fout, "\tclnt_destroy(clnt);\n");
f_print(fout, "#endif\t /* DEBUG */\n");
f_print(fout, "}\n");
}
static
write_sample_server(def)
definition *def;
{
version_list *vp;
proc_list *proc;
for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
for (proc = vp->procs; proc != NULL; proc = proc->next) {
f_print(fout, "\n");
if (!mtflag) {
return_type(proc);
f_print(fout, "*\n");
} else
f_print(fout, "bool_t\n");
if (Cflag || mtflag)
pvname_svc(proc->proc_name, vp->vers_num);
else
pvname(proc->proc_name, vp->vers_num);
printarglist(proc, "result", RQSTP, "struct svc_req *");
f_print(fout, "{\n");
if (!mtflag) {
f_print(fout, "\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);
}
else
f_print(fout, "\tbool_t retval;\n");
f_print(fout,
"\n\t/*\n\t * insert server code here\n\t */\n\n");
if (!mtflag)
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");
else
f_print(fout, "\treturn (retval);\n}\n");
}
/* put in sample freeing routine */
if (mtflag) {
f_print(fout, "\nint\n");
pvname(def->def_name, vp->vers_num);
if (Cflag)
f_print(fout,"_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)\n");
else {
f_print(fout,"_freeresult(transp, xdr_result, result)\n");
f_print(fout,"\tSVCXPRT *transp;\n");
f_print(fout,"\txdrproc_t xdr_result;\n");
f_print(fout,"\tcaddr_t result;\n");
}
f_print(fout, "{\n");
f_print(fout, "\t(void) xdr_free(xdr_result, result);\n");
f_print(fout,
"\n\t/*\n\t * Insert additional freeing code here, if needed\n\t */\n");
f_print(fout, "\n}\n");
}
}
}
static
return_type(plist)
proc_list *plist;
{
ptype(plist->res_prefix, plist->res_type, 1);
}
add_sample_msg()
{
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()
{
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)\n\tint argc;\n\tchar *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");
}

517
usr.bin/rpcgen/rpc_scan.c Normal file
View File

@ -0,0 +1,517 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#ident "@(#)rpc_scan.c 1.13 93/07/05 SMI"
#ifndef lint
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 <sys/wait.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
#define startcomment(where) (where[0] == '/' && where[1] == '*')
#define endcomment(where) (where[-1] == '*' && where[0] == '/')
static int pushed = 0; /* is a token pushed */
static token lasttok; /* last token, if pushed */
static int unget_token __P(( token * ));
static int findstrconst __P(( char **, char **));
static int findchrconst __P(( char **, char **));
static int findconst __P(( char **, char **));
static int findkind __P(( char **, token * ));
static int cppline __P(( char * ));
static int directive __P(( char * ));
static int printdirective __P(( char * ));
static int docppline __P(( char *, int *, char ** ));
/*
* scan expecting 1 given token
*/
void
scan(expect, tokp)
tok_kind expect;
token *tokp;
{
get_token(tokp);
if (tokp->kind != expect) {
expected1(expect);
}
}
/*
* scan expecting any of the 2 given tokens
*/
void
scan2(expect1, expect2, tokp)
tok_kind expect1;
tok_kind expect2;
token *tokp;
{
get_token(tokp);
if (tokp->kind != expect1 && tokp->kind != expect2) {
expected2(expect1, expect2);
}
}
/*
* scan expecting any of the 3 given token
*/
void
scan3(expect1, expect2, expect3, tokp)
tok_kind expect1;
tok_kind expect2;
tok_kind expect3;
token *tokp;
{
get_token(tokp);
if (tokp->kind != expect1 && tokp->kind != expect2
&& tokp->kind != expect3) {
expected3(expect1, expect2, expect3);
}
}
/*
* scan expecting a constant, possibly symbolic
*/
void
scan_num(tokp)
token *tokp;
{
get_token(tokp);
switch (tokp->kind) {
case TOK_IDENT:
break;
default:
error("constant or identifier expected");
}
}
/*
* Peek at the next token
*/
void
peek(tokp)
token *tokp;
{
get_token(tokp);
unget_token(tokp);
}
/*
* Peek at the next token and scan it if it matches what you expect
*/
int
peekscan(expect, tokp)
tok_kind expect;
token *tokp;
{
peek(tokp);
if (tokp->kind == expect) {
get_token(tokp);
return (1);
}
return (0);
}
/*
* Get the next token, printing out any directive that are encountered.
*/
void
get_token(tokp)
token *tokp;
{
int commenting;
int stat = 0;
if (pushed) {
pushed = 0;
*tokp = lasttok;
return;
}
commenting = 0;
for (;;) {
if (*where == 0) {
for (;;) {
if (!fgets(curline, MAXLINESIZE, fin)) {
tokp->kind = TOK_EOF;
/* now check if cpp returned non NULL value */
waitpid(childpid, &stat, WUNTRACED);
if (stat > 0) {
/* Set return value from rpcgen */
nonfatalerrors = stat >> 8;
}
*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
unget_token(tokp)
token *tokp;
{
lasttok = *tokp;
pushed = 1;
}
static
findstrconst(str, val)
char **str;
char **val;
{
char *p;
int size;
p = *str;
do {
*p++;
} while (*p && *p != '"');
if (*p == 0) {
error("unterminated string constant");
}
p++;
size = p - *str;
*val = alloc(size + 1);
(void) strncpy(*val, *str, size);
(*val)[size] = 0;
*str = p;
}
static
findchrconst(str, val)
char **str;
char **val;
{
char *p;
int size;
p = *str;
do {
*p++;
} while (*p && *p != '\'');
if (*p == 0) {
error("unterminated string constant");
}
p++;
size = p - *str;
if (size != 3) {
error("empty char string");
}
*val = alloc(size + 1);
(void) strncpy(*val, *str, size);
(*val)[size] = 0;
*str = p;
}
static
findconst(str, val)
char **str;
char **val;
{
char *p;
int size;
p = *str;
if (*p == '0' && *(p + 1) == 'x') {
p++;
do {
p++;
} while (isxdigit(*p));
} else {
do {
p++;
} while (isdigit(*p));
}
size = p - *str;
*val = alloc(size + 1);
(void) strncpy(*val, *str, size);
(*val)[size] = 0;
*str = p;
}
static token symbols[] = {
{TOK_CONST, "const"},
{TOK_UNION, "union"},
{TOK_SWITCH, "switch"},
{TOK_CASE, "case"},
{TOK_DEFAULT, "default"},
{TOK_STRUCT, "struct"},
{TOK_TYPEDEF, "typedef"},
{TOK_ENUM, "enum"},
{TOK_OPAQUE, "opaque"},
{TOK_BOOL, "bool"},
{TOK_VOID, "void"},
{TOK_CHAR, "char"},
{TOK_INT, "int"},
{TOK_UNSIGNED, "unsigned"},
{TOK_SHORT, "short"},
{TOK_LONG, "long"},
{TOK_HYPER, "hyper"},
{TOK_FLOAT, "float"},
{TOK_DOUBLE, "double"},
{TOK_QUAD, "quadruple"},
{TOK_STRING, "string"},
{TOK_PROGRAM, "program"},
{TOK_VERSION, "version"},
{TOK_EOF, "??????"},
};
static
findkind(mark, tokp)
char **mark;
token *tokp;
{
int len;
token *s;
char *str;
str = *mark;
for (s = symbols; s->kind != TOK_EOF; s++) {
len = strlen(s->str);
if (strncmp(str, s->str, len) == 0) {
if (!isalnum(str[len]) && str[len] != '_') {
tokp->kind = s->kind;
tokp->str = s->str;
*mark = str + len;
return;
}
}
}
tokp->kind = TOK_IDENT;
for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
tokp->str = alloc(len + 1);
(void) strncpy(tokp->str, str, len);
tokp->str[len] = 0;
*mark = str + len;
}
static
cppline(line)
char *line;
{
return (line == curline && *line == '#');
}
static
directive(line)
char *line;
{
return (line == curline && *line == '%');
}
static
printdirective(line)
char *line;
{
f_print(fout, "%s", line + 1);
}
static
docppline(line, lineno, fname)
char *line;
int *lineno;
char **fname;
{
char *file;
int num;
char *p;
line++;
while (isspace(*line)) {
line++;
}
num = atoi(line);
while (isdigit(*line)) {
line++;
}
while (isspace(*line)) {
line++;
}
if (*line != '"') {
error("preprocessor error");
}
line++;
p = file = alloc(strlen(line) + 1);
while (*line && *line != '"') {
*p++ = *line++;
}
if (*line == 0) {
error("preprocessor error");
}
*p = 0;
if (*file == 0) {
*fname = NULL;
} else {
*fname = file;
}
*lineno = num - 1;
}

133
usr.bin/rpcgen/rpc_scan.h Normal file
View File

@ -0,0 +1,133 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#pragma ident "@(#)rpc_scan.h 1.11 94/05/15 SMI"
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* PROPRIETARY NOTICE (Combined)
*
* This source code is unpublished proprietary information
* constituting, or derived under license from AT&T's UNIX(r) System V.
* In addition, portions of such source code were derived from Berkeley
* 4.3 BSD under license from the Regents of the University of
* California.
*
*
*
* Copyright Notice
*
* Notice of copyright on this source code product does not indicate
* publication.
*
* (c) 1986,1987,1988.1989 Sun Microsystems, Inc
* (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
* All rights reserved.
*/
/* @(#)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_LONG,
TOK_HYPER,
TOK_UNSIGNED,
TOK_FLOAT,
TOK_DOUBLE,
TOK_QUAD,
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();

1082
usr.bin/rpcgen/rpc_svcout.c Normal file

File diff suppressed because it is too large Load Diff

171
usr.bin/rpcgen/rpc_tblout.c Normal file
View File

@ -0,0 +1,171 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#ident "@(#)rpc_tblout.c 1.11 93/07/05 SMI"
#ifndef lint
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
* Copyright (C) 1989, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <string.h>
#include "rpc_parse.h"
#include "rpc_util.h"
#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";
static int write_table __P(( definition * ));
static int printit __P(( char *, char * ));
void
write_tables()
{
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
write_table(def)
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
printit(prefix, type)
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");
}

508
usr.bin/rpcgen/rpc_util.c Normal file
View File

@ -0,0 +1,508 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#ident "@(#)rpc_util.c 1.14 93/07/05 SMI"
#ifndef lint
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
* Copyright (C) 1989, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <ctype.h>
#include "rpc_scan.h"
#include "rpc_parse.h"
#include "rpc_util.h"
#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 */
static int printwhere __P(( void ));
/*
* Reinitialize the world
*/
reinitialize()
{
memset(curline, 0, MAXLINESIZE);
where = curline;
linenum = 0;
defined = NULL;
}
/*
* string equality
*/
streq(a, b)
char *a;
char *b;
{
return (strcmp(a, b) == 0);
}
/*
* find a value in a list
*/
definition *
findval(lst, val, cmp)
list *lst;
char *val;
int (*cmp) ();
{
for (; lst != NULL; lst = lst->next) {
if ((*cmp) (lst->val, val)) {
return (lst->val);
}
}
return (NULL);
}
/*
* store a value in a list
*/
void
storeval(lstp, val)
list **lstp;
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
findit(def, type)
definition *def;
char *type;
{
return (streq(def->def_name, type));
}
static char *
fixit(type, orig)
char *type;
char *orig;
{
definition *def;
def = (definition *) FINDVAL(defined, type, findit);
if (def == NULL || def->def_kind != DEF_TYPEDEF) {
return (orig);
}
switch (def->def.ty.rel) {
case REL_VECTOR:
if (streq(def->def.ty.old_type, "opaque"))
return ("char");
else
return (def->def.ty.old_type);
case REL_ALIAS:
return (fixit(def->def.ty.old_type, orig));
default:
return (orig);
}
}
char *
fixtype(type)
char *type;
{
return (fixit(type, type));
}
char *
stringfix(type)
char *type;
{
if (streq(type, "string")) {
return ("wrapstring");
} else {
return (type);
}
}
void
ptype(prefix, type, follow)
char *prefix;
char *type;
int follow;
{
if (prefix != NULL) {
if (streq(prefix, "enum")) {
f_print(fout, "enum ");
} else {
f_print(fout, "struct ");
}
}
if (streq(type, "bool")) {
f_print(fout, "bool_t ");
} else if (streq(type, "string")) {
f_print(fout, "char *");
} else {
f_print(fout, "%s ", follow ? fixtype(type) : type);
}
}
static
typedefed(def, type)
definition *def;
char *type;
{
if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) {
return (0);
} else {
return (streq(def->def_name, type));
}
}
isvectordef(type, rel)
char *type;
relation rel;
{
definition *def;
for (;;) {
switch (rel) {
case REL_VECTOR:
return (!streq(type, "string"));
case REL_ARRAY:
return (0);
case REL_POINTER:
return (0);
case REL_ALIAS:
def = (definition *) FINDVAL(defined, type, typedefed);
if (def == NULL) {
return (0);
}
type = def->def.ty.old_type;
rel = def->def.ty.rel;
}
}
}
char *
locase(str)
char *str;
{
char c;
static char buf[100];
char *p = buf;
while (c = *str++) {
*p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
}
*p = 0;
return (buf);
}
void
pvname_svc(pname, vnum)
char *pname;
char *vnum;
{
f_print(fout, "%s_%s_svc", locase(pname), vnum);
}
void
pvname(pname, vnum)
char *pname;
char *vnum;
{
f_print(fout, "%s_%s", locase(pname), vnum);
}
/*
* print a useful (?) error message, and then die
*/
void
error(msg)
char *msg;
{
printwhere();
f_print(stderr, "%s, line %d: ", infilename, linenum);
f_print(stderr, "%s\n", msg);
crash();
}
/*
* Something went wrong, unlink any files that we may have created and then
* die.
*/
crash()
{
int i;
for (i = 0; i < nfiles; i++) {
(void) unlink(outfiles[i]);
}
exit(1);
}
void
record_open(file)
char *file;
{
if (nfiles < NFILES) {
outfiles[nfiles++] = file;
} else {
f_print(stderr, "too many files!\n");
crash();
}
}
static char expectbuf[100];
static char *toktostr();
/*
* error, token encountered was not the expected one
*/
void
expected1(exp1)
tok_kind exp1;
{
s_print(expectbuf, "expected '%s'",
toktostr(exp1));
error(expectbuf);
}
/*
* error, token encountered was not one of two expected ones
*/
void
expected2(exp1, exp2)
tok_kind exp1, exp2;
{
s_print(expectbuf, "expected '%s' or '%s'",
toktostr(exp1),
toktostr(exp2));
error(expectbuf);
}
/*
* error, token encountered was not one of 3 expected ones
*/
void
expected3(exp1, exp2, exp3)
tok_kind exp1, exp2, exp3;
{
s_print(expectbuf, "expected '%s', '%s' or '%s'",
toktostr(exp1),
toktostr(exp2),
toktostr(exp3));
error(expectbuf);
}
void
tabify(f, tab)
FILE *f;
int tab;
{
while (tab--) {
(void) fputc('\t', f);
}
}
static token tokstrings[] = {
{TOK_IDENT, "identifier"},
{TOK_CONST, "const"},
{TOK_RPAREN, ")"},
{TOK_LPAREN, "("},
{TOK_RBRACE, "}"},
{TOK_LBRACE, "{"},
{TOK_LBRACKET, "["},
{TOK_RBRACKET, "]"},
{TOK_STAR, "*"},
{TOK_COMMA, ","},
{TOK_EQUAL, "="},
{TOK_COLON, ":"},
{TOK_SEMICOLON, ";"},
{TOK_UNION, "union"},
{TOK_STRUCT, "struct"},
{TOK_SWITCH, "switch"},
{TOK_CASE, "case"},
{TOK_DEFAULT, "default"},
{TOK_ENUM, "enum"},
{TOK_TYPEDEF, "typedef"},
{TOK_INT, "int"},
{TOK_SHORT, "short"},
{TOK_LONG, "long"},
{TOK_UNSIGNED, "unsigned"},
{TOK_DOUBLE, "double"},
{TOK_FLOAT, "float"},
{TOK_CHAR, "char"},
{TOK_STRING, "string"},
{TOK_OPAQUE, "opaque"},
{TOK_BOOL, "bool"},
{TOK_VOID, "void"},
{TOK_PROGRAM, "program"},
{TOK_VERSION, "version"},
{TOK_EOF, "??????"}
};
static char *
toktostr(kind)
tok_kind kind;
{
token *sp;
for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++);
return (sp->str);
}
static
printbuf()
{
char c;
int i;
int cnt;
# define TABSIZE 4
for (i = 0; c = curline[i]; i++) {
if (c == '\t') {
cnt = 8 - (i % TABSIZE);
c = ' ';
} else {
cnt = 1;
}
while (cnt--) {
(void) fputc(c, stderr);
}
}
}
static
printwhere()
{
int i;
char c;
int cnt;
printbuf();
for (i = 0; i < where - curline; i++) {
c = curline[i];
if (c == '\t') {
cnt = 8 - (i % TABSIZE);
} else {
cnt = 1;
}
while (cnt--) {
(void) fputc('^', stderr);
}
}
(void) fputc('\n', stderr);
}
char *
make_argname(pname, vname)
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;
add_type(len, 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(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);
}

209
usr.bin/rpcgen/rpc_util.h Normal file
View File

@ -0,0 +1,209 @@
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#pragma ident "@(#)rpc_util.h 1.16 94/05/15 SMI"
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* PROPRIETARY NOTICE (Combined)
*
* This source code is unpublished proprietary information
* constituting, or derived under license from AT&T's UNIX(r) System V.
* In addition, portions of such source code were derived from Berkeley
* 4.3 BSD under license from the Regents of the University of
* California.
*
*
*
* Copyright Notice
*
* Notice of copyright on this source code product does not indicate
* publication.
*
* (c) 1986,1987,1988.1989 Sun Microsystems, Inc
* (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
* All rights reserved.
*/
/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */
/*
* rpc_util.h, Useful definitions for the RPC protocol compiler
*/
#include <sys/types.h>
#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;
struct xdrfunc {
char *name;
int pointerp;
struct xdrfunc *next;
};
typedef struct xdrfunc xdrfunc;
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 */
int makefileflag; /* Generate a template Makefile */
char *infile; /* input module name */
char *outfile; /* output module name */
};
#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;
extern xdrfunc *xdrfunc_head, *xdrfunc_tail;
/*
* All the option flags
*/
extern int inetdflag;
extern int pmflag;
extern int tblflag;
extern int logflag;
extern int newstyle;
extern int Cflag; /* ANSI-C/C++ flag */
extern int CCflag; /* C++ flag */
extern int tirpcflag; /* flag for generating tirpc code */
extern int inline; /* if this is 0, then do not generate inline code */
extern int mtflag;
/*
* Other flags related with inetd jumpstart.
*/
extern int indefinitewait;
extern int exitnow;
extern int timerflag;
extern int nonfatalerrors;
extern pid_t childpid;
/*
* rpc_util routines
*/
void storeval();
#define STOREVAL(list,item) \
storeval(list,item)
definition *findval();
#define FINDVAL(list,item,finder) \
findval(list, item, finder)
char *fixtype();
char *stringfix();
char *locase();
void pvname_svc();
void pvname();
void ptype();
int isvectordef();
int streq();
void error();
void expected1();
void expected2();
void expected3();
void tabify();
void record_open();
bas_type *find_type();
/*
* rpc_cout routines
*/
void cprint();
void emit();
/*
* rpc_hout routines
*/
void print_datadef();
void print_funcdef();
void print_xdr_func_def();
/*
* rpc_svcout routines
*/
void write_most();
void write_register();
void write_rest();
void write_programs();
void write_svc_aux();
void write_inetd_register();
void write_netid_register();
void write_nettype_register();
/*
* rpc_clntout routines
*/
void write_stubs();
/*
* rpc_tblout routines
*/
void write_tables();

554
usr.bin/rpcgen/rpcgen.1 Normal file
View File

@ -0,0 +1,554 @@
.\" @(#)rpcgen.1 1.35 93/06/02 SMI
'\"macro stdmacro
.\" Copyright 1985-1993 Sun Microsystems, Inc.
.nr X
.TH rpcgen 1 "28 Mar 1993"
.SH NAME
rpcgen \- an RPC protocol compiler
.SH SYNOPSIS
.BI rpcgen " infile"
.LP
.B rpcgen
[
.B \-a
] [
.B \-b
] [
.B \-C
] [
.BI \-D name
[ =
.I value
] ]
.if n .ti +5n
[
.BI \-i " size"
]
[
.B \-I
[
.BI \-K " seconds"
] ]
[
.B \-L
] [
.B \-M
]
.if n .ti +5n
.if t .ti +5n
[
.B \-N
]
[
.B \-T
] [
.BI \-Y " pathname"
]
.I infile
.LP
.B rpcgen
[
.B \-c
|
.B \-h
|
.B \-l
|
.B \-m
|
.B \-t
|
.B \-Sc
|
.B \-Ss
|
.B \-Sm
]
.if n .ti +5n
[
.BI \-o " outfile"
] [
.I infile
]
.LP
.B rpcgen
[
.BI \-s " nettype"
] [
.BI \-o " outfile"
] [
.I infile
]
.LP
.B rpcgen
[
.BI \-n " netid"
] [
.BI \-o " outfile"
] [
.I infile
]
.\" .SH AVAILABILITY
.\" .LP
.\" SUNWcsu
.SH DESCRIPTION
.IX "rpcgen" "" "\fLrpcgen\fP \(em RPC protocol compiler"
.IX "RPC" "protocol compiler" "" "protocol compiler \(em \fLrpcgen\fP"
.IX "RPC Language" "RPC protocol compiler" "" "RPC protocol compiler \(em \fLrpcgen\fP"
.IX "compilers" "RPC protocol compiler" "" "RPC protocol compiler \(em \fLrpcgen\fP"
.IX "programming tools" "RPC protocol compiler" "" "RPC protocol compiler \(em \fLrpcgen\fP"
.LP
\f3rpcgen\f1
is a tool that generates C code to implement an RPC protocol.
The input to
\f3rpcgen\f1
is a language similar to C known as
RPC Language (Remote Procedure Call Language).
.LP
\f3rpcgen\f1
is normally used as in the first synopsis where
it takes an input file and generates three output files.
If the
\f2infile\f1
is named
\f3proto.x\f1,
then
\f3rpcgen\f1
generates a header in
\f3proto.h\f1,
XDR routines in
\f3proto_xdr.c\f1,
server-side stubs in
\f3proto_svc.c\f1,
and client-side stubs in
\f3proto_clnt.c\f1.
With the
\f3\-T\f1
option,
it also generates the RPC dispatch table in
\f3proto_tbl.i\f1.
.LP
.B rpcgen
can also generate sample client and server files
that can be customized to suit a particular application. The
\f3\-Sc\f1,
\f3\-Ss\f1
and
\f3\-Sm\f1
options generate sample client, server and makefile, respectively.
The
\f3\-a\f1
option generates all files, including sample files. If the infile
is \f3proto.x\f1, then the client side sample file is written to
\f3proto_client.c\f1, the server side sample file to \f3proto_server.c\f1
and the sample makefile to \f3makefile.proto\f1.
.LP
The server created can be started both by the port monitors
(for example, \f3inetd\f1 or \f3listen\f1)
or by itself.
When it is started by a port monitor,
it creates servers only for the transport for which
the file descriptor \f30\fP was passed.
The name of the transport must be specified
by setting up the environment variable
\f3PM_TRANSPORT\f1.
When the server generated by
\f3rpcgen\f1
is executed,
it creates server handles for all the transports
specified in
\f3NETPATH\f1
environment variable,
or if it is unset,
it creates server handles for all the visible transports from
\f3/etc/netconfig\f1
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
\f3RPC_SVC_FG\f1
can be used to run the server process in foreground.
.LP
The second synopsis provides special features which allow
for the creation of more sophisticated RPC servers.
These features include support for user provided
\f3#defines\f1
and RPC dispatch tables.
The entries in the RPC dispatch table contain:
.RS
.PD 0
.TP 3
\(bu
pointers to the service routine corresponding to that procedure,
.TP
\(bu
a pointer to the input and output arguments
.TP
\(bu
the size of these routines
.PD
.RE
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.
.LP
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
.SM EXAMPLES
section below for examples of
.B rpcgen
usage.
When
\f3rpcgen\f1
is executed with the
\f3\-s\f1
option,
it creates servers for that particular class of transports.
When
executed with the
\f3\-n\f1
option,
it creates a server for the transport specified by
\f2netid\f1.
If
\f2infile\f1
is not specified,
\f3rpcgen\f1
accepts the standard input.
.LP
The C preprocessor,
\f3cc \-E\f1
is run on the input file before it is actually interpreted by
\f3rpcgen\f1.
For each type of output file,
\f3rpcgen\f1
defines a special preprocessor symbol for use by the
\f3rpcgen\f1
programmer:
.LP
.PD 0
.RS
.TP 12
\f3RPC_HDR\f1
defined when compiling into headers
.TP
\f3RPC_XDR\f1
defined when compiling into XDR routines
.TP
\f3RPC_SVC\f1
defined when compiling into server-side stubs
.TP
\f3RPC_CLNT\f1
defined when compiling into client-side stubs
.TP
\f3RPC_TBL\f1
defined when compiling into RPC dispatch tables
.RE
.PD
.LP
Any line beginning with
``\f3%\f1''
is passed directly into the output file,
uninterpreted by
\f3rpcgen\f1.
To specify the path name of the C preprocessor use \f3\-Y\f1 flag.
.LP
For every data type referred to in
\f2infile\f1,
\f3rpcgen\f1
assumes that there exists a
routine with the string
\f3xdr_\f1
prepended to the name of the data type.
If this routine does not exist in the RPC/XDR
library, it must be provided.
Providing an undefined data type
allows customization of XDR routines.
.br
.ne 10
.SH OPTIONS
.TP 15
\f3\-a\f1
Generate all files, including sample files.
.TP
\f3\-b\f1
Backward compatibility mode.
Generate transport specific RPC code for older versions
of the operating system.
.IP
Note: in FreeBSD, this compatibility flag is turned on by
default since FreeBSD supports only the older ONC RPC library.
.TP
\f3\-c\f1
Compile into XDR routines.
.TP
\f3\-C\f1
Generate header and stub files which can be used with
.SM ANSI C
compilers. Headers generated with this flag can also be
used with C++ programs.
.TP
\f3\-D\f2name\f3[=\f2value\f3]\f1
Define a symbol
\f2name\f1.
Equivalent to the
\f3#define\f1
directive in the source.
If no
\f2value\f1
is given,
\f2value\f1
is defined as \f31\f1.
This option may be specified more than once.
.TP
\f3\-h\f1
Compile into
\f3C\f1
data-definitions (a header).
\f3\-T\f1
option can be used in conjunction to produce a
header which supports RPC dispatch tables.
.TP
\f3\-i \f2size\f1
Size at which to start generating inline code.
This option is useful for optimization. The default size is 5.
.IP
Note: in order to provide backwards compatibility with the older
.B rpcgen
on the FreeBSD 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.
.TP
\f3\-I\f1
Compile support for
.BR inetd (1M)
in the server side stubs.
Such servers can be self-started or can be started by \f3inetd\f1.
When the server is self-started, it backgrounds itself by default.
A special define symbol \f3RPC_SVC_FG\f1 can be used to run the
server process in foreground, or the user may simply compile without
the \f3\-I\f1 option.
.br
.ne 5
.IP
If there are no pending client requests, the
\f3inetd\f1 servers exit after 120 seconds (default).
The default can be changed with the
.B \-K
option.
All the error messages for \f3inetd\f1 servers
are always logged with
.BR syslog (3).
.\" .IP
.\" Note:
.\" this option is supported for backward compatibility only.
.\" By default,
.\" .B rpcgen
.\" generates servers that can be invoked through portmonitors.
.TP
.BI \-K " seconds"
By default, services created using \f3rpcgen\fP and invoked through
port monitors wait \f3120\fP seconds
after servicing a request before exiting.
That interval can be changed using the \f3\-K\fP flag.
To create a server that exits immediately upon servicing a request,
use
.BR "\-K\ 0".
To create a server that never exits, the appropriate argument is
\f3\-K \-1\fP.
.IP
When monitoring for a server,
some portmonitors, like
.BR listen (1M),
.I 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, \f3rpcgen\fP should be used with \f3\-K 0\fP.
.TP
\f3\-l\f1
Compile into client-side stubs.
.TP
.B \-L
When the servers are started in foreground, use
.BR syslog (3)
to log the server errors instead of printing them on the standard
error.
.TP
\f3\-m\f1
Compile into server-side stubs,
but do not generate a \(lqmain\(rq routine.
This option is useful for doing callback-routines
and for users who need to write their own
\(lqmain\(rq routine to do initialization.
.TP
\f3\-M\f1
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
.BR rpc_svc_calls (3N)
functions are not yet MT-safe, which means that rpcgen generated server-side
code will not be MT-safe.
.TP
.B \-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
.B rpcgen
generated code.
To maintain backward compatibility,
this option is not the default.
.TP
\f3\-n \f2netid\f1
Compile into server-side stubs for the transport
specified by
\f2netid\f1.
There should be an entry for
\f2netid\f1
in the
netconfig database.
This option may be specified more than once,
so as to compile a server that serves multiple transports.
.TP
\f3\-o \f2outfile\f1
Specify the name of the output file.
If none is specified,
standard output is used
(\f3\-c\f1,
\f3\-h\f1,
\f3\-l\f1,
\f3\-m\f1,
\f3\-n\f1,
\f3\-s\f1,
\f3\-Sc\f1,
\f3\-Sm\f1,
\f3\-Ss\f1,
and
\f3\-t\f1
modes only).
.TP
\f3\-s \f2nettype\f1
Compile into server-side stubs for all the
transports belonging to the class
\f2nettype\f1.
The supported classes are
\f3netpath\f1,
\f3visible\f1,
\f3circuit_n\f1,
\f3circuit_v\f1,
\f3datagram_n\f1,
\f3datagram_v\f1,
\f3tcp\f1,
and
\f3udp\f1
(see
.BR rpc (3N)
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.
.TP
\f3\-Sc\f1
Generate sample client code that uses remote procedure calls.
.br
.ne 5
.TP
\f3\-Sm\f1
Generate a sample Makefile which can be used for compiling the
application.
.TP
\f3\-Ss\f1
Generate sample server code that uses remote procedure calls.
.TP
\f3\-t\f1
Compile into RPC dispatch table.
.TP
\f3\-T\f1
Generate the code to support RPC dispatch tables.
.IP
The options
\f3\-c\f1,
\f3\-h\f1,
\f3\-l\f1,
\f3\-m\f1,
\f3\-s\f1,
\f3\-Sc\f1,
\f3\-Sm\f1,
\f3\-Ss\f1,
and
\f3\-t\f1
are used exclusively to generate a particular type of file,
while the options
\f3\-D\f1
and
\f3\-T\f1
are global and can be used with the other options.
.TP
\f3\-Y\f2 pathname\f1
Give the name of the directory where
.B rpcgen
will start looking for the C-preprocessor.
.br
.ne 5
.SH EXAMPLES
The following example:
.LP
.RS
.B example% rpcgen \-T prot.x
.RE
.LP
generates all the five files:
.BR prot.h ,
.BR prot_clnt.c ,
.BR prot_svc.c ,
.B prot_xdr.c
and
.BR prot_tbl.i .
.LP
The following example sends the C data-definitions (header)
to the standard output.
.LP
.RS
.B example% rpcgen \-h prot.x
.RE
.LP
To send the test version of the
.BR -DTEST ,
server side stubs for
all the transport belonging to the class
.B datagram_n
to standard output, use:
.LP
.RS
.B example% rpcgen \-s datagram_n \-DTEST prot.x
.RE
.LP
To create the server side stubs for the transport indicated
by
\f2netid\f1
\f3tcp\f1,
use:
.LP
.RS
.B example% rpcgen \-n tcp \-o prot_svc.c prot.x
.RE
.SH "SEE ALSO"
.BR cc (1B),
.BR inetd (1M),
.BR listen (1M),
.BR syslog (3),
.BR rpc (3N),
.\" .BR rpc_svc_calls (3N)
.LP
The
.B rpcgen
chapter in the
.TZ NETP
manual.