1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
24 *
25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 /*
41 * rpc_hout.c, Header file outputter for the RPC protocol compiler
42 */
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <ctype.h>
46 #include "rpc_parse.h"
47 #include "rpc_util.h"
48
49 extern void pprocdef(proc_list *, version_list *, char *, int);
50 extern void pdeclaration(char *, declaration *, int, char *);
51
52 static void storexdrfuncdecl(char *, int);
53 static void pconstdef(definition *);
54 static void pstructdef(definition *);
55 static void puniondef(definition *);
56 static void pdefine(char *, char *);
57 static void pprogramdef(definition *);
58 static void parglist(proc_list *, char *);
59 static void penumdef(definition *);
60 static void ptypedef(definition *);
61 static uint_t undefined2(char *, char *);
62
63 enum rpc_gvc {
64 PROGRAM,
65 VERSION,
66 PROCEDURE
67 };
68
69 /*
70 * Print the C-version of an xdr definition
71 */
72 void
73 print_datadef(definition *def)
74 {
75 if (def->def_kind == DEF_PROGRAM) /* handle data only */
76 return;
77
78 if (def->def_kind != DEF_CONST)
79 f_print(fout, "\n");
80 switch (def->def_kind) {
81 case DEF_STRUCT:
82 pstructdef(def);
83 break;
84 case DEF_UNION:
85 puniondef(def);
86 break;
87 case DEF_ENUM:
88 penumdef(def);
89 break;
90 case DEF_TYPEDEF:
91 ptypedef(def);
92 break;
93 case DEF_PROGRAM:
94 pprogramdef(def);
95 break;
96 case DEF_CONST:
97 pconstdef(def);
98 break;
99 }
100 if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST)
101 storexdrfuncdecl(def->def_name, def->def_kind != DEF_TYPEDEF ||
102 !isvectordef(def->def.ty.old_type, def->def.ty.rel));
103 }
104
105
106 void
107 print_funcdef(definition *def)
108 {
109 switch (def->def_kind) {
110 case DEF_PROGRAM:
111 f_print(fout, "\n");
112 pprogramdef(def);
113 break;
114 }
115 }
116
117 /*
118 * store away enough information to allow the XDR functions to be spat
119 * out at the end of the file
120 */
121 static void
122 storexdrfuncdecl(char *name, int pointerp)
123 {
124 xdrfunc *xdrptr;
125
126 xdrptr = malloc(sizeof (struct xdrfunc));
127
128 xdrptr->name = name;
129 xdrptr->pointerp = pointerp;
130 xdrptr->next = NULL;
131
132 if (xdrfunc_tail == NULL) {
133 xdrfunc_head = xdrptr;
134 xdrfunc_tail = xdrptr;
135 } else {
136 xdrfunc_tail->next = xdrptr;
137 xdrfunc_tail = xdrptr;
138 }
139
140
141 }
142
143 void
144 print_xdr_func_def(char *name, int pointerp)
145 {
146 f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n", name,
147 name, pointerp ? "*" : "");
148 }
149
150
151 static void
152 pconstdef(definition *def)
153 {
154 pdefine(def->def_name, def->def.co);
155 }
156
157 /*
158 * print out the definitions for the arguments of functions in the
159 * header file
160 */
161 static void
162 pargdef(definition *def)
163 {
164 decl_list *l;
165 version_list *vers;
166 char *name;
167 proc_list *plist;
168
169 for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
170 for (plist = vers->procs; plist != NULL; plist = plist->next) {
171 if (!newstyle || plist->arg_num < 2)
172 continue; /* old style or single args */
173 name = plist->args.argname;
174 f_print(fout, "struct %s {\n", name);
175 for (l = plist->args.decls; l != NULL; l = l->next)
176 pdeclaration(name, &l->decl, 1, ";\n");
177 f_print(fout, "};\n");
178 f_print(fout, "typedef struct %s %s;\n", name, name);
179 storexdrfuncdecl(name, 1);
180 f_print(fout, "\n");
181 }
182 }
183 }
184
185
186 static void
187 pstructdef(definition *def)
188 {
189 decl_list *l;
190 char *name = def->def_name;
191
192 f_print(fout, "struct %s {\n", name);
193 for (l = def->def.st.decls; l != NULL; l = l->next)
194 pdeclaration(name, &l->decl, 1, ";\n");
195 f_print(fout, "};\n");
196 f_print(fout, "typedef struct %s %s;\n", name, name);
197 }
198
199 static void
200 puniondef(definition *def)
201 {
202 case_list *l;
203 char *name = def->def_name;
204 declaration *decl;
205
206 f_print(fout, "struct %s {\n", name);
207 decl = &def->def.un.enum_decl;
208 if (streq(decl->type, "bool"))
209 f_print(fout, "\tbool_t %s;\n", decl->name);
210 else
211 f_print(fout, "\t%s %s;\n", decl->type, decl->name);
212 f_print(fout, "\tunion {\n");
213 for (l = def->def.un.cases; l != NULL; l = l->next) {
214 if (l->contflag == 0)
215 pdeclaration(name, &l->case_decl, 2, ";\n");
216 }
217 decl = def->def.un.default_decl;
218 if (decl && !streq(decl->type, "void"))
219 pdeclaration(name, decl, 2, ";\n");
220 f_print(fout, "\t} %s_u;\n", name);
221 f_print(fout, "};\n");
222 f_print(fout, "typedef struct %s %s;\n", name, name);
223 }
224
225 static void
226 pdefine(char *name, char *num)
227 {
228 f_print(fout, "#define\t%s %s\n", name, num);
229 }
230
231 static void
232 puldefine(char *name, char *num, enum rpc_gvc which)
233 {
234 switch (which) {
235 case PROGRAM:
236 case VERSION:
237 case PROCEDURE:
238 f_print(fout, "#define\t%s\t%s\n", name, num);
239 break;
240 default:
241 break;
242 }
243 }
244
245 static uint_t
246 define_printed(proc_list *stop, version_list *start)
247 {
248 version_list *vers;
249 proc_list *proc;
250
251 for (vers = start; vers != NULL; vers = vers->next) {
252 for (proc = vers->procs; proc != NULL; proc = proc->next) {
253 if (proc == stop)
254 return (0);
255 if (streq(proc->proc_name, stop->proc_name))
256 return (1);
257 }
258 }
259 abort();
260 /* NOTREACHED */
261 }
262
263 static void
264 pfreeprocdef(char *name, char *vers)
265 {
266 f_print(fout, "extern int ");
267 pvname(name, vers);
268 f_print(fout, "_freeresult(SVCXPRT *, xdrproc_t, caddr_t);\n");
269 }
270
271 static void
272 pprogramdef(definition *def)
273 {
274 version_list *vers;
275 proc_list *proc;
276
277 pargdef(def);
278
279 puldefine(def->def_name, def->def.pr.prog_num, PROGRAM);
280 for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
281 if (tblflag) {
282 f_print(fout,
283 "extern struct rpcgen_table %s_%s_table[];\n",
284 locase(def->def_name), vers->vers_num);
285 f_print(fout,
286 "extern int %s_%s_nproc;\n",
287 locase(def->def_name), vers->vers_num);
288 }
289 puldefine(vers->vers_name, vers->vers_num, VERSION);
290
291 for (proc = vers->procs; proc != NULL;
292 proc = proc->next) {
293 if (!define_printed(proc,
294 def->def.pr.versions)) {
295 puldefine(proc->proc_name,
296 proc->proc_num, PROCEDURE);
297 }
298 f_print(fout, "extern ");
299 pprocdef(proc, vers, "CLIENT *", 0);
300 f_print(fout, "extern ");
301 pprocdef(proc, vers, "struct svc_req *", 1);
302 }
303 pfreeprocdef(def->def_name, vers->vers_num);
304 }
305 }
306
307 void
308 pprocdef(proc_list *proc, version_list *vp, char *addargtype, int server_p)
309 {
310 if (mtflag) {
311 /* Print MT style stubs */
312 if (server_p)
313 f_print(fout, "bool_t ");
314 else
315 f_print(fout, "enum clnt_stat ");
316 } else {
317 ptype(proc->res_prefix, proc->res_type, 1);
318 f_print(fout, "* ");
319 }
320 if (server_p)
321 pvname_svc(proc->proc_name, vp->vers_num);
322 else
323 pvname(proc->proc_name, vp->vers_num);
324
325 parglist(proc, addargtype);
326 }
327
328 /* print out argument list of procedure */
329 static void
330 parglist(proc_list *proc, char *addargtype)
331 {
332 decl_list *dl;
333 int oneway = streq(proc->res_type, "oneway");
334
335 f_print(fout, "(");
336 if (proc->arg_num < 2 && newstyle &&
337 streq(proc->args.decls->decl.type, "void")) {
338 /* 0 argument in new style: do nothing */
339 /* EMPTY */
340 } else {
341 for (dl = proc->args.decls; dl != NULL; dl = dl->next) {
342 ptype(dl->decl.prefix, dl->decl.type, 1);
343 if (!newstyle || (dl->decl.rel == REL_POINTER))
344 f_print(fout, "*");
345 /* old style passes by reference */
346 f_print(fout, ", ");
347 }
348 }
349
350 if (mtflag && !oneway) {
351 ptype(proc->res_prefix, proc->res_type, 1);
352 f_print(fout, "*, ");
353 }
354
355 f_print(fout, "%s);\n", addargtype);
356 }
357
358 static void
359 penumdef(definition *def)
360 {
361 char *name = def->def_name;
362 enumval_list *l;
363 char *last = NULL;
364 int count = 0;
365
366 f_print(fout, "enum %s {\n", name);
367 for (l = def->def.en.vals; l != NULL; l = l->next) {
368 f_print(fout, "\t%s", l->name);
369 if (l->assignment) {
370 f_print(fout, " = %s", l->assignment);
371 last = l->assignment;
372 count = 1;
373 } else {
374 if (last == NULL)
375 f_print(fout, " = %d", count++);
376 else
377 f_print(fout, " = %s + %d", last, count++);
378 }
379 if (l->next)
380 f_print(fout, ",\n");
381 else
382 f_print(fout, "\n");
383 }
384 f_print(fout, "};\n");
385 f_print(fout, "typedef enum %s %s;\n", name, name);
386 }
387
388 static void
389 ptypedef(definition *def)
390 {
391 char *name = def->def_name;
392 char *old = def->def.ty.old_type;
393 char prefix[8]; /* enough to contain "struct ", including NUL */
394 relation rel = def->def.ty.rel;
395
396
397 if (!streq(name, old)) {
398 if (streq(old, "string")) {
399 old = "char";
400 rel = REL_POINTER;
401 } else if (streq(old, "opaque")) {
402 old = "char";
403 } else if (streq(old, "bool")) {
404 old = "bool_t";
405 }
406 if (undefined2(old, name) && def->def.ty.old_prefix)
407 (void) snprintf(prefix, sizeof (prefix), "%s ",
408 def->def.ty.old_prefix);
409 else
410 prefix[0] = 0;
411 f_print(fout, "typedef ");
412 switch (rel) {
413 case REL_ARRAY:
414 f_print(fout, "struct {\n");
415 f_print(fout, "\tu_int %s_len;\n", name);
416 f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name);
417 f_print(fout, "} %s", name);
418 break;
419 case REL_POINTER:
420 f_print(fout, "%s%s *%s", prefix, old, name);
421 break;
422 case REL_VECTOR:
423 f_print(fout, "%s%s %s[%s]", prefix, old, name,
424 def->def.ty.array_max);
425 break;
426 case REL_ALIAS:
427 f_print(fout, "%s%s %s", prefix, old, name);
428 break;
429 }
430 f_print(fout, ";\n");
431 }
432 }
433
434 void
435 pdeclaration(char *name, declaration *dec, int tab, char *separator)
436 {
437 char buf[8]; /* enough to hold "struct ", include NUL */
438 char *prefix;
439 char *type;
440
441 if (streq(dec->type, "void"))
442 return;
443 tabify(fout, tab);
444 if (streq(dec->type, name) && !dec->prefix)
445 f_print(fout, "struct ");
446 if (streq(dec->type, "string")) {
447 f_print(fout, "char *%s", dec->name);
448 } else {
449 prefix = "";
450 if (streq(dec->type, "bool")) {
451 type = "bool_t";
452 } else if (streq(dec->type, "opaque")) {
453 type = "char";
454 } else {
455 if (dec->prefix) {
456 (void) snprintf(buf, sizeof (buf),
457 "%s ", dec->prefix);
458 prefix = buf;
459 }
460 type = dec->type;
461 }
462 switch (dec->rel) {
463 case REL_ALIAS:
464 f_print(fout, "%s%s %s", prefix, type, dec->name);
465 break;
466 case REL_VECTOR:
467 f_print(fout, "%s%s %s[%s]", prefix, type, dec->name,
468 dec->array_max);
469 break;
470 case REL_POINTER:
471 f_print(fout, "%s%s *%s", prefix, type, dec->name);
472 break;
473 case REL_ARRAY:
474 f_print(fout, "struct {\n");
475 tabify(fout, tab);
476 f_print(fout, "\tu_int %s_len;\n", dec->name);
477 tabify(fout, tab);
478 f_print(fout,
479 "\t%s%s *%s_val;\n", prefix, type, dec->name);
480 tabify(fout, tab);
481 f_print(fout, "} %s", dec->name);
482 break;
483 }
484 }
485 /* LINTED variable format */
486 f_print(fout, separator);
487 }
488
489 static uint_t
490 undefined2(char *type, char *stop)
491 {
492 list *l;
493 definition *def;
494
495 for (l = defined; l != NULL; l = l->next) {
496 def = (definition *) l->val;
497 if (def->def_kind != DEF_PROGRAM) {
498 if (streq(def->def_name, stop))
499 return (1);
500 if (streq(def->def_name, type))
501 return (0);
502 }
503 }
504 return (1);
505 }