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