xref: /openbsd-src/usr.bin/rpcgen/rpc_cout.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: rpc_cout.c,v 1.6 2001/07/18 22:26:00 deraadt Exp $	*/
2 /*	$NetBSD: rpc_cout.c,v 1.6 1996/10/01 04:13:53 cgd Exp $	*/
3 /*
4  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5  * unrestricted use provided that this legend is included on all tape
6  * media and as a part of the software program in whole or part.  Users
7  * may copy or modify Sun RPC without charge, but are not authorized
8  * to license or distribute it to anyone else except as part of a product or
9  * program developed by the user or with the express written consent of
10  * Sun Microsystems, Inc.
11  *
12  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
13  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
14  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
15  *
16  * Sun RPC is provided with no support and without any obligation on the
17  * part of Sun Microsystems, Inc. to assist in its use, correction,
18  * modification or enhancement.
19  *
20  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
21  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
22  * OR ANY PART THEREOF.
23  *
24  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
25  * or profits or other special, indirect and consequential damages, even if
26  * Sun has been advised of the possibility of such damages.
27  *
28  * Sun Microsystems, Inc.
29  * 2550 Garcia Avenue
30  * Mountain View, California  94043
31  */
32 
33 #ifndef lint
34 static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI";
35 #endif
36 
37 /*
38  * rpc_cout.c, XDR routine outputter for the RPC protocol compiler
39  */
40 #include <sys/cdefs.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include "rpc_parse.h"
45 #include "rpc_util.h"
46 
47 static findtype __P((definition *, char *));
48 static undefined __P((char *));
49 static print_generic_header __P((char *, int));
50 static print_header __P((definition *));
51 static print_prog_header __P((proc_list *));
52 static print_trailer __P((void));
53 static print_ifopen __P((int, char *));
54 static print_ifarg __P((char *));
55 static print_ifsizeof __P((char *, char *));
56 static print_ifclose __P((int));
57 static print_ifstat __P((int, char *, char *, relation, char *, char *, char *));
58 static emit_num __P((definition *));
59 static emit_program __P((definition *));
60 static emit_enum __P((definition *));
61 static emit_union __P((definition *));
62 static emit_struct __P((definition *));
63 static emit_typedef __P((definition *));
64 static print_stat __P((int, declaration *));
65 
66 
67 /*
68  * Emit the C-routine for the given definition
69  */
70 void
71 emit(def)
72 	definition *def;
73 {
74 	if (def->def_kind == DEF_CONST) {
75 		return;
76 	}
77 	if (def->def_kind == DEF_PROGRAM) {
78 		emit_program(def);
79 		return;
80 	}
81 	if (def->def_kind == DEF_TYPEDEF) {
82 		/* now we need to handle declarations like struct typedef foo
83 		 * foo; since we dont want this to be expanded into 2 calls to
84 		 * xdr_foo */
85 
86 		if (strcmp(def->def.ty.old_type, def->def_name) == 0)
87 			return;
88 	};
89 
90 	print_header(def);
91 	switch (def->def_kind) {
92 	case DEF_UNION:
93 		emit_union(def);
94 		break;
95 	case DEF_ENUM:
96 		emit_enum(def);
97 		break;
98 	case DEF_STRUCT:
99 		emit_struct(def);
100 		break;
101 	case DEF_TYPEDEF:
102 		emit_typedef(def);
103 		break;
104 	}
105 	print_trailer();
106 }
107 
108 static
109 findtype(def, type)
110 	definition *def;
111 	char   *type;
112 {
113 
114 	if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) {
115 		return (0);
116 	} else {
117 		return (streq(def->def_name, type));
118 	}
119 }
120 
121 static
122 undefined(type)
123 	char   *type;
124 {
125 	definition *def;
126 
127 	def = (definition *) FINDVAL(defined, type, findtype);
128 
129 
130 	return (def == NULL);
131 }
132 
133 static
134 print_generic_header(procname, pointerp)
135 	char   *procname;
136 	int     pointerp;
137 {
138 	f_print(fout, "\n");
139 	f_print(fout, "bool_t\n");
140 	if (Cflag) {
141 		f_print(fout, "xdr_%s(", procname);
142 		f_print(fout, "XDR *xdrs, ");
143 		f_print(fout, "%s ", procname);
144 		if (pointerp)
145 			f_print(fout, "*");
146 		f_print(fout, "objp)\n{\n\n");
147 	} else {
148 		f_print(fout, "xdr_%s(xdrs, objp)\n", procname);
149 		f_print(fout, "\tXDR *xdrs;\n");
150 		f_print(fout, "\t%s ", procname);
151 		if (pointerp)
152 			f_print(fout, "*");
153 		f_print(fout, "objp;\n{\n\n");
154 	}
155 }
156 
157 static
158 print_header(def)
159 	definition *def;
160 {
161 
162 	decl_list *dl;
163 	bas_type *ptr;
164 	int     i;
165 
166 
167 	print_generic_header(def->def_name,
168 	    def->def_kind != DEF_TYPEDEF ||
169 	    !isvectordef(def->def.ty.old_type, def->def.ty.rel));
170 
171 	/* Now add Inline support */
172 
173 
174 	if (doinline == 0)
175 		return;
176 	/* May cause lint to complain. but  ... */
177 	f_print(fout, "\t register int32_t *buf;\n\n");
178 
179 }
180 
181 static
182 print_prog_header(plist)
183 	proc_list *plist;
184 {
185 	print_generic_header(plist->args.argname, 1);
186 }
187 
188 static
189 print_trailer()
190 {
191 	f_print(fout, "\treturn (TRUE);\n");
192 	f_print(fout, "}\n");
193 }
194 
195 
196 static
197 print_ifopen(indent, name)
198 	int     indent;
199 	char   *name;
200 {
201 	tabify(fout, indent);
202 	f_print(fout, " if (!xdr_%s(xdrs", name);
203 }
204 
205 static
206 print_ifarg(arg)
207 	char   *arg;
208 {
209 	f_print(fout, ", %s", arg);
210 }
211 
212 static
213 print_ifsizeof(prefix, type)
214 	char   *prefix;
215 	char   *type;
216 {
217 	if (streq(type, "bool")) {
218 		f_print(fout, ", sizeof(bool_t), (xdrproc_t)xdr_bool");
219 	} else {
220 		f_print(fout, ", sizeof(");
221 		if (undefined(type) && prefix) {
222 			f_print(fout, "%s ", prefix);
223 		}
224 		f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type);
225 	}
226 }
227 
228 static
229 print_ifclose(indent)
230 	int     indent;
231 {
232 	f_print(fout, ")) {\n");
233 	tabify(fout, indent);
234 	f_print(fout, "\t return (FALSE);\n");
235 	tabify(fout, indent);
236 	f_print(fout, " }\n");
237 }
238 
239 static
240 print_ifstat(indent, prefix, type, rel, amax, objname, name)
241 	int     indent;
242 	char   *prefix;
243 	char   *type;
244 	relation rel;
245 	char   *amax;
246 	char   *objname;
247 	char   *name;
248 {
249 	char   *alt = NULL;
250 
251 	switch (rel) {
252 	case REL_POINTER:
253 		print_ifopen(indent, "pointer");
254 		print_ifarg("(char **)");
255 		f_print(fout, "%s", objname);
256 		print_ifsizeof(prefix, type);
257 		break;
258 	case REL_VECTOR:
259 		if (streq(type, "string")) {
260 			alt = "string";
261 		} else
262 			if (streq(type, "opaque")) {
263 				alt = "opaque";
264 			}
265 		if (alt) {
266 			print_ifopen(indent, alt);
267 			print_ifarg(objname);
268 		} else {
269 			print_ifopen(indent, "vector");
270 			print_ifarg("(char *)");
271 			f_print(fout, "%s", objname);
272 		}
273 		print_ifarg(amax);
274 		if (!alt) {
275 			print_ifsizeof(prefix, type);
276 		}
277 		break;
278 	case REL_ARRAY:
279 		if (streq(type, "string")) {
280 			alt = "string";
281 		} else
282 			if (streq(type, "opaque")) {
283 				alt = "bytes";
284 			}
285 		if (streq(type, "string")) {
286 			print_ifopen(indent, alt);
287 			print_ifarg(objname);
288 		} else {
289 			if (alt) {
290 				print_ifopen(indent, alt);
291 			} else {
292 				print_ifopen(indent, "array");
293 			}
294 			print_ifarg("(char **)");
295 			if (*objname == '&') {
296 				f_print(fout, "%s.%s_val, (u_int *)%s.%s_len",
297 				    objname, name, objname, name);
298 			} else {
299 				f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len",
300 				    objname, name, objname, name);
301 			}
302 		}
303 		print_ifarg(amax);
304 		if (!alt) {
305 			print_ifsizeof(prefix, type);
306 		}
307 		break;
308 	case REL_ALIAS:
309 		print_ifopen(indent, type);
310 		print_ifarg(objname);
311 		break;
312 	}
313 	print_ifclose(indent);
314 }
315 
316 /* ARGSUSED */
317 static
318 emit_enum(def)
319 	definition *def;
320 {
321 	print_ifopen(1, "enum");
322 	print_ifarg("(enum_t *)objp");
323 	print_ifclose(1);
324 }
325 
326 static
327 emit_program(def)
328 	definition *def;
329 {
330 	decl_list *dl;
331 	version_list *vlist;
332 	proc_list *plist;
333 
334 	for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next)
335 		for (plist = vlist->procs; plist != NULL; plist = plist->next) {
336 			if (!newstyle || plist->arg_num < 2)
337 				continue;	/* old style, or single
338 						 * argument */
339 			print_prog_header(plist);
340 			for (dl = plist->args.decls; dl != NULL;
341 			    dl = dl->next)
342 				print_stat(1, &dl->decl);
343 			print_trailer();
344 		}
345 }
346 
347 
348 static
349 emit_union(def)
350 	definition *def;
351 {
352 	declaration *dflt;
353 	case_list *cl;
354 	declaration *cs;
355 	char   *object;
356 	char   *vecformat = "objp->%s_u.%s";
357 	char   *format = "&objp->%s_u.%s";
358 
359 	print_stat(1, &def->def.un.enum_decl);
360 	f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
361 	for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
362 
363 		f_print(fout, "\tcase %s:\n", cl->case_name);
364 		if (cl->contflag == 1)	/* a continued case statement */
365 			continue;
366 		cs = &cl->case_decl;
367 		if (!streq(cs->type, "void")) {
368 			object = alloc(strlen(def->def_name) + strlen(format) +
369 			    strlen(cs->name) + 1);
370 			if (isvectordef(cs->type, cs->rel)) {
371 				s_print(object, vecformat, def->def_name,
372 				    cs->name);
373 			} else {
374 				s_print(object, format, def->def_name,
375 				    cs->name);
376 			}
377 			print_ifstat(2, cs->prefix, cs->type, cs->rel, cs->array_max,
378 			    object, cs->name);
379 			free(object);
380 		}
381 		f_print(fout, "\t\tbreak;\n");
382 	}
383 	dflt = def->def.un.default_decl;
384 	if (dflt != NULL) {
385 		if (!streq(dflt->type, "void")) {
386 			f_print(fout, "\tdefault:\n");
387 			object = alloc(strlen(def->def_name) + strlen(format) +
388 			    strlen(dflt->name) + 1);
389 			if (isvectordef(dflt->type, dflt->rel)) {
390 				s_print(object, vecformat, def->def_name,
391 				    dflt->name);
392 			} else {
393 				s_print(object, format, def->def_name,
394 				    dflt->name);
395 			}
396 
397 			print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
398 			    dflt->array_max, object, dflt->name);
399 			free(object);
400 			f_print(fout, "\t\tbreak;\n");
401 		}
402 	} else {
403 		f_print(fout, "\tdefault:\n");
404 		f_print(fout, "\t\treturn (FALSE);\n");
405 	}
406 
407 	f_print(fout, "\t}\n");
408 }
409 
410 static
411 emit_struct(def)
412 	definition *def;
413 {
414 	decl_list *dl;
415 	int     i, j, size, flag;
416 	decl_list *cur, *psav;
417 	bas_type *ptr;
418 	char   *sizestr, *plus;
419 	char    ptemp[256];
420 	int     can_inline;
421 
422 
423 	if (doinline == 0) {
424 		for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
425 			print_stat(1, &dl->decl);
426 		return;
427 	}
428 	for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
429 		if (dl->decl.rel == REL_VECTOR) {
430 			f_print(fout, "\t int i;\n");
431 			break;
432 		}
433 	size = 0;
434 	can_inline = 0;
435 	for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
436 		if ((dl->decl.prefix == NULL) &&
437 		    ((ptr = find_type(dl->decl.type)) != NULL) &&
438 		    ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
439 
440 			if (dl->decl.rel == REL_ALIAS)
441 				size += ptr->length;
442 			else {
443 				can_inline = 1;
444 				break;	/* can be inlined */
445 			};
446 		} else {
447 			if (size >= doinline) {
448 				can_inline = 1;
449 				break;	/* can be inlined */
450 			}
451 			size = 0;
452 		}
453 	if (size > doinline)
454 		can_inline = 1;
455 
456 	if (can_inline == 0) {	/* can not inline, drop back to old mode */
457 		for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
458 			print_stat(1, &dl->decl);
459 		return;
460 	};
461 
462 
463 
464 
465 	flag = PUT;
466 	for (j = 0; j < 2; j++) {
467 
468 		if (flag == PUT)
469 			f_print(fout, "\n\t if (xdrs->x_op == XDR_ENCODE) {\n");
470 		else
471 			f_print(fout, "\n \t return (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n");
472 
473 
474 		i = 0;
475 		size = 0;
476 		sizestr = NULL;
477 		for (dl = def->def.st.decls; dl != NULL; dl = dl->next) {	/* xxx */
478 
479 			/* now walk down the list and check for basic types */
480 			if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
481 				if (i == 0)
482 					cur = dl;
483 				i++;
484 
485 				if (dl->decl.rel == REL_ALIAS)
486 					size += ptr->length;
487 				else {
488 					/* this is required to handle arrays */
489 
490 					if (sizestr == NULL)
491 						plus = " ";
492 					else
493 						plus = "+";
494 
495 					if (ptr->length != 1)
496 						s_print(ptemp, " %s %s * %d", plus, dl->decl.array_max, ptr->length);
497 					else
498 						s_print(ptemp, " %s %s ", plus, dl->decl.array_max);
499 
500 					/* now concatenate to sizestr !!!! */
501 					if (sizestr == NULL)
502 						sizestr = strdup(ptemp);
503 					else {
504 						sizestr = (char *)realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1);
505 						if (sizestr == NULL) {
506 
507 							f_print(stderr, "Fatal error : no memory \n");
508 							crash();
509 						};
510 						sizestr = strcat(sizestr, ptemp);	/* build up length of
511 											 * array */
512 
513 					}
514 				}
515 
516 			} else {
517 				if (i > 0)
518 					if (sizestr == NULL && size < doinline) {
519 						/* don't expand into inline
520 						 * code if size < doinline */
521 						while (cur != dl) {
522 							print_stat(1, &cur->decl);
523 							cur = cur->next;
524 						}
525 					} else {
526 
527 
528 
529 						/* were already looking at a
530 						 * xdr_inlineable structure */
531 						if (sizestr == NULL)
532 							f_print(fout, "\t buf = (int32_t *)XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);",
533 							    size);
534 						else
535 							if (size == 0)
536 								f_print(fout,
537 								    "\t buf = (int32_t *)XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);",
538 								    sizestr);
539 							else
540 								f_print(fout,
541 								    "\t buf = (int32_t *)XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);",
542 								    size, sizestr);
543 
544 						f_print(fout, "\n\t   if (buf == NULL) {\n");
545 
546 						psav = cur;
547 						while (cur != dl) {
548 							print_stat(2, &cur->decl);
549 							cur = cur->next;
550 						}
551 
552 						f_print(fout, "\n\t  }\n\t  else {\n");
553 
554 						cur = psav;
555 						while (cur != dl) {
556 							emit_inline(&cur->decl, flag);
557 							cur = cur->next;
558 						}
559 
560 						f_print(fout, "\t  }\n");
561 					}
562 				size = 0;
563 				i = 0;
564 				sizestr = NULL;
565 				print_stat(1, &dl->decl);
566 			}
567 
568 		}
569 		if (i > 0)
570 			if (sizestr == NULL && size < doinline) {
571 				/* don't expand into inline code if size <
572 				 * doinline */
573 				while (cur != dl) {
574 					print_stat(1, &cur->decl);
575 					cur = cur->next;
576 				}
577 			} else {
578 
579 				/* were already looking at a xdr_inlineable
580 				 * structure */
581 				if (sizestr == NULL)
582 					f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);",
583 					    size);
584 				else
585 					if (size == 0)
586 						f_print(fout,
587 						    "\t\tbuf = (int32_t *)XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);",
588 						    sizestr);
589 					else
590 						f_print(fout,
591 						    "\t\tbuf = (int32_t *)XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);",
592 						    size, sizestr);
593 
594 				f_print(fout, "\n\t\tif (buf == NULL) {\n");
595 
596 				psav = cur;
597 				while (cur != NULL) {
598 					print_stat(2, &cur->decl);
599 					cur = cur->next;
600 				}
601 				f_print(fout, "\n\t  }\n\t  else {\n");
602 
603 				cur = psav;
604 				while (cur != dl) {
605 					emit_inline(&cur->decl, flag);
606 					cur = cur->next;
607 				}
608 
609 				f_print(fout, "\t  }\n");
610 
611 			}
612 		flag = GET;
613 	}
614 	f_print(fout, "\t return(TRUE);\n\t}\n\n");
615 
616 	/* now take care of XDR_FREE case */
617 
618 	for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
619 		print_stat(1, &dl->decl);
620 }
621 
622 static
623 emit_typedef(def)
624 	definition *def;
625 {
626 	char   *prefix = def->def.ty.old_prefix;
627 	char   *type = def->def.ty.old_type;
628 	char   *amax = def->def.ty.array_max;
629 	relation rel = def->def.ty.rel;
630 
631 
632 	print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
633 }
634 
635 static
636 print_stat(indent, dec)
637 	declaration *dec;
638 	int     indent;
639 {
640 	char   *prefix = dec->prefix;
641 	char   *type = dec->type;
642 	char   *amax = dec->array_max;
643 	relation rel = dec->rel;
644 	char    name[256];
645 
646 	if (isvectordef(type, rel)) {
647 		s_print(name, "objp->%s", dec->name);
648 	} else {
649 		s_print(name, "&objp->%s", dec->name);
650 	}
651 	print_ifstat(indent, prefix, type, rel, amax, name, dec->name);
652 }
653 
654 
655 char   *upcase __P((char *));
656 
657 
658 emit_inline(decl, flag)
659 	declaration *decl;
660 	int     flag;
661 {
662 
663 /*check whether an array or not */
664 
665 	switch (decl->rel) {
666 	case REL_ALIAS:
667 		emit_single_in_line(decl, flag, REL_ALIAS);
668 		break;
669 	case REL_VECTOR:
670 		f_print(fout, "\t\t{ register %s *genp; \n", decl->type);
671 		f_print(fout, "\t\t  for ( i = 0,genp=objp->%s;\n \t\t\ti < %s; i++){\n\t\t",
672 		    decl->name, decl->array_max);
673 		emit_single_in_line(decl, flag, REL_VECTOR);
674 		f_print(fout, "\t\t   }\n\t\t };\n");
675 
676 	}
677 }
678 
679 emit_single_in_line(decl, flag, rel)
680 	declaration *decl;
681 	int     flag;
682 	relation rel;
683 {
684 	char   *upp_case;
685 	int     freed = 0;
686 
687 
688 
689 	if (flag == PUT)
690 		f_print(fout, "\t\t IXDR_PUT_");
691 	else
692 		if (rel == REL_ALIAS)
693 			f_print(fout, "\t\t objp->%s = IXDR_GET_", decl->name);
694 		else
695 			f_print(fout, "\t\t *genp++ = IXDR_GET_");
696 
697 	upp_case = upcase(decl->type);
698 
699 	/* hack  - XX */
700 	if (strcmp(upp_case, "INT") == 0) {
701 		free(upp_case);
702 		freed = 1;
703 		upp_case = "LONG";
704 	}
705 	if (strcmp(upp_case, "U_INT") == 0) {
706 		free(upp_case);
707 		freed = 1;
708 		upp_case = "U_LONG";
709 	}
710 	if (flag == PUT)
711 		if (rel == REL_ALIAS)
712 			f_print(fout, "%s(buf,objp->%s);\n", upp_case, decl->name);
713 		else
714 			f_print(fout, "%s(buf,*genp++);\n", upp_case);
715 
716 	else
717 		f_print(fout, "%s(buf);\n", upp_case);
718 	if (!freed)
719 		free(upp_case);
720 
721 }
722 
723 
724 char *
725 upcase(str)
726 	char   *str;
727 {
728 	char   *ptr, *hptr;
729 
730 
731 	ptr = (char *) malloc(strlen(str)+1);
732 	if (ptr == (char *) NULL) {
733 		f_print(stderr, "malloc failed \n");
734 		exit(1);
735 	};
736 
737 	hptr = ptr;
738 	while (*str != '\0')
739 		*ptr++ = toupper(*str++);
740 
741 	*ptr = '\0';
742 	return (hptr);
743 
744 }
745