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