| /* |
| * From: @(#)rpc_hout.c 1.12 89/02/22 |
| * |
| * Copyright (c) 2010, Oracle America, Inc. |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials |
| * provided with the distribution. |
| * * Neither the name of the "Oracle America, Inc." nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* |
| * rpc_hout.c, Header file outputter for the RPC protocol compiler |
| */ |
| #include <stdio.h> |
| #include <ctype.h> |
| #include "rpc_parse.h" |
| #include "rpc_util.h" |
| #include "proto.h" |
| |
| static void pconstdef (definition * def); |
| static void pargdef (definition * def); |
| static void pstructdef (definition * def); |
| static void puniondef (definition * def); |
| static void pdefine (const char *name, const char *num); |
| static int define_printed (proc_list * stop, version_list * start); |
| static void pprogramdef (definition * def); |
| static void parglist (proc_list * proc, const char *addargtype); |
| static void penumdef (definition * def); |
| static void ptypedef (definition * def); |
| static int undefined2 (const char *type, const char *stop); |
| |
| /* store away enough information to allow the XDR functions to be spat |
| out at the end of the file */ |
| |
| static void |
| storexdrfuncdecl (const char *name, int pointerp) |
| { |
| xdrfunc * xdrptr; |
| |
| xdrptr = (xdrfunc *) malloc(sizeof (struct xdrfunc)); |
| |
| xdrptr->name = (char *)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; |
| } |
| } |
| |
| /* |
| * Print the C-version of an xdr definition |
| */ |
| void |
| print_datadef (definition *def) |
| { |
| |
| if (def->def_kind == DEF_PROGRAM) /* handle data only */ |
| return; |
| |
| if (def->def_kind != DEF_CONST) |
| { |
| f_print (fout, "\n"); |
| } |
| switch (def->def_kind) |
| { |
| case DEF_STRUCT: |
| pstructdef (def); |
| break; |
| case DEF_UNION: |
| puniondef (def); |
| break; |
| case DEF_ENUM: |
| penumdef (def); |
| break; |
| case DEF_TYPEDEF: |
| ptypedef (def); |
| break; |
| case DEF_PROGRAM: |
| pprogramdef (def); |
| break; |
| case DEF_CONST: |
| pconstdef (def); |
| break; |
| } |
| if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) |
| { |
| storexdrfuncdecl(def->def_name, |
| def->def_kind != DEF_TYPEDEF || |
| !isvectordef(def->def.ty.old_type, |
| def->def.ty.rel)); |
| } |
| } |
| |
| |
| void |
| print_funcdef (definition *def) |
| { |
| switch (def->def_kind) |
| { |
| case DEF_PROGRAM: |
| f_print (fout, "\n"); |
| pprogramdef (def); |
| break; |
| default: |
| break; |
| /* ?... shouldn't happen I guess */ |
| } |
| } |
| |
| void |
| print_xdr_func_def (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 void |
| pconstdef (definition *def) |
| { |
| pdefine (def->def_name, def->def.co); |
| } |
| |
| /* print out the definitions for the arguments of functions in the |
| header file |
| */ |
| static void |
| pargdef (definition * def) |
| { |
| decl_list *l; |
| version_list *vers; |
| const 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 void |
| pstructdef (definition *def) |
| { |
| decl_list *l; |
| const char *name = def->def_name; |
| |
| f_print (fout, "struct %s {\n", name); |
| for (l = def->def.st.decls; l != NULL; l = l->next) |
| { |
| pdeclaration (name, &l->decl, 1, ";\n"); |
| } |
| f_print (fout, "};\n"); |
| f_print (fout, "typedef struct %s %s;\n", name, name); |
| } |
| |
| static void |
| puniondef (definition *def) |
| { |
| case_list *l; |
| const char *name = def->def_name; |
| declaration *decl; |
| |
| f_print (fout, "struct %s {\n", name); |
| decl = &def->def.un.enum_decl; |
| if (streq (decl->type, "bool")) |
| { |
| f_print (fout, "\tbool_t %s;\n", decl->name); |
| } |
| else |
| { |
| f_print (fout, "\t%s %s;\n", decl->type, decl->name); |
| } |
| f_print (fout, "\tunion {\n"); |
| for (l = def->def.un.cases; l != NULL; l = l->next) |
| { |
| if (l->contflag == 0) |
| pdeclaration (name, &l->case_decl, 2, ";\n"); |
| } |
| decl = def->def.un.default_decl; |
| if (decl && !streq (decl->type, "void")) |
| { |
| pdeclaration (name, decl, 2, ";\n"); |
| } |
| f_print (fout, "\t} %s_u;\n", name); |
| f_print (fout, "};\n"); |
| f_print (fout, "typedef struct %s %s;\n", name, name); |
| } |
| |
| static void |
| pdefine (const char *name, const char *num) |
| { |
| f_print (fout, "#define %s %s\n", name, num); |
| } |
| |
| static int |
| define_printed (proc_list *stop, version_list *start) |
| { |
| version_list *vers; |
| proc_list *proc; |
| |
| for (vers = start; vers != NULL; vers = vers->next) |
| { |
| for (proc = vers->procs; proc != NULL; proc = proc->next) |
| { |
| if (proc == stop) |
| { |
| return 0; |
| } |
| else if (streq (proc->proc_name, stop->proc_name)) |
| { |
| return 1; |
| } |
| } |
| } |
| abort (); |
| /* NOTREACHED */ |
| } |
| |
| static void |
| pfreeprocdef (const char *name, const 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 void |
| pprogramdef (definition *def) |
| { |
| version_list *vers; |
| proc_list *proc; |
| int i; |
| const char *ext; |
| |
| pargdef (def); |
| |
| pdefine (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); |
| } |
| pdefine (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)) |
| { |
| pdefine (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)) |
| { |
| pdefine(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"); |
| } |
| } |
| } |
| |
| void |
| pprocdef (proc_list * proc, version_list * vp, |
| const 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 void |
| parglist (proc_list *proc, const 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 void |
| penumdef (definition *def) |
| { |
| const char *name = def->def_name; |
| enumval_list *l; |
| const char *last = NULL; |
| int count = 0; |
| |
| f_print (fout, "enum %s {\n", name); |
| for (l = def->def.en.vals; l != NULL; l = l->next) |
| { |
| f_print (fout, "\t%s", l->name); |
| if (l->assignment) |
| { |
| f_print (fout, " = %s", l->assignment); |
| last = l->assignment; |
| count = 1; |
| } |
| else |
| { |
| if (last == NULL) |
| { |
| f_print (fout, " = %d", count++); |
| } |
| else |
| { |
| f_print (fout, " = %s + %d", last, count++); |
| } |
| } |
| f_print (fout, ",\n"); |
| } |
| f_print (fout, "};\n"); |
| f_print (fout, "typedef enum %s %s;\n", name, name); |
| } |
| |
| static void |
| ptypedef (definition *def) |
| { |
| const char *name = def->def_name; |
| const char *old = def->def.ty.old_type; |
| char prefix[8]; /* enough to contain "struct ", including NUL */ |
| relation rel = def->def.ty.rel; |
| |
| if (!streq (name, old)) |
| { |
| if (streq (old, "string")) |
| { |
| old = "char"; |
| rel = REL_POINTER; |
| } |
| else if (streq (old, "opaque")) |
| { |
| old = "char"; |
| } |
| else if (streq (old, "bool")) |
| { |
| old = "bool_t"; |
| } |
| if (undefined2 (old, name) && def->def.ty.old_prefix) |
| { |
| s_print (prefix, "%s ", def->def.ty.old_prefix); |
| } |
| else |
| { |
| prefix[0] = 0; |
| } |
| f_print (fout, "typedef "); |
| switch (rel) |
| { |
| case REL_ARRAY: |
| f_print (fout, "struct {\n"); |
| f_print (fout, "\tu_int %s_len;\n", name); |
| f_print (fout, "\t%s%s *%s_val;\n", prefix, old, name); |
| f_print (fout, "} %s", name); |
| break; |
| case REL_POINTER: |
| f_print (fout, "%s%s *%s", prefix, old, name); |
| break; |
| case REL_VECTOR: |
| f_print (fout, "%s%s %s[%s]", prefix, old, name, |
| def->def.ty.array_max); |
| break; |
| case REL_ALIAS: |
| f_print (fout, "%s%s %s", prefix, old, name); |
| break; |
| } |
| f_print (fout, ";\n"); |
| } |
| } |
| |
| void |
| pdeclaration (const char *name, declaration * dec, int tab, |
| const char *separator) |
| { |
| char buf[8]; /* enough to hold "struct ", include NUL */ |
| const char *prefix; |
| const 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, "%s", separator); |
| } |
| |
| static int |
| undefined2 (const char *type, const 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; |
| } |