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