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_cout.c, XDR routine outputter for the RPC protocol compiler
40 */
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <ctype.h>
45#include "rpc_parse.h"
46#include "rpc_util.h"
47
48extern void crash(void);
49
50static void print_header(definition *);
51static void print_trailer(void);
52static void emit_enum(definition *);
53static void emit_program(definition *);
54static void emit_union(definition *);
55static void emit_struct(definition *);
56static void emit_typedef(definition *);
57static void print_stat(int, declaration *);
58static void emit_inline(int, declaration *, int);
59static void emit_inline64(int, declaration *, int);
60static void emit_single_in_line(int, declaration *, int, relation);
61static void emit_single_in_line64(int, declaration *, int, relation);
62static char *upcase(char *);
63
64/*
65 * Emit the C-routine for the given definition
66 */
67void
68emit(definition *def)
69{
70	if (def->def_kind == DEF_CONST)
71		return;
72	if (def->def_kind == DEF_PROGRAM) {
73		emit_program(def);
74		return;
75	}
76	if (def->def_kind == DEF_TYPEDEF) {
77		/*
78		 * now we need to handle declarations like
79		 * struct typedef foo foo;
80		 * since we dont want this to be expanded into 2 calls
81		 * to xdr_foo
82		 */
83
84		if (strcmp(def->def.ty.old_type, def->def_name) == 0)
85			return;
86	};
87	print_header(def);
88	switch (def->def_kind) {
89	case DEF_UNION:
90		emit_union(def);
91		break;
92	case DEF_ENUM:
93		emit_enum(def);
94		break;
95	case DEF_STRUCT:
96		emit_struct(def);
97		break;
98	case DEF_TYPEDEF:
99		emit_typedef(def);
100		break;
101	}
102	print_trailer();
103}
104
105static int
106findtype(definition *def, char *type)
107{
108
109	if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST)
110		return (0);
111	return (streq(def->def_name, type));
112}
113
114static int
115undefined(char *type)
116{
117	definition *def;
118
119	def = (definition *)FINDVAL(defined, type, findtype);
120	return (def == NULL);
121}
122
123
124static void
125print_generic_header(char *procname, int pointerp)
126{
127	f_print(fout, "\n");
128	f_print(fout, "bool_t\n");
129	if (Cflag) {
130		f_print(fout, "xdr_%s(", procname);
131		f_print(fout, "XDR *xdrs, ");
132		f_print(fout, "%s ", procname);
133		if (pointerp)
134			f_print(fout, "*");
135		f_print(fout, "objp)\n{\n\n");
136	} else {
137		f_print(fout, "xdr_%s(xdrs, objp)\n", procname);
138		f_print(fout, "\tXDR *xdrs;\n");
139		f_print(fout, "\t%s ", procname);
140		if (pointerp)
141			f_print(fout, "*");
142		f_print(fout, "objp;\n{\n\n");
143	}
144}
145
146static void
147print_header(definition *def)
148{
149	print_generic_header(def->def_name,
150	    def->def_kind != DEF_TYPEDEF ||
151	    !isvectordef(def->def.ty.old_type, def->def.ty.rel));
152	/* Now add Inline support */
153
154	if (inlinelen == 0)
155		return;
156	/* May cause lint to complain. but  ... */
157	f_print(fout, "\trpc_inline_t *buf;\n\n");
158}
159
160static void
161print_prog_header(proc_list *plist)
162{
163	print_generic_header(plist->args.argname, 1);
164}
165
166static void
167print_trailer(void)
168{
169	f_print(fout, "\treturn (TRUE);\n");
170	f_print(fout, "}\n");
171}
172
173
174static void
175print_ifopen(int indent, char *name)
176{
177	tabify(fout, indent);
178	if (streq(name, "rpcprog_t") ||
179	    streq(name, "rpcvers_t") ||
180	    streq(name, "rpcproc_t") ||
181	    streq(name, "rpcprot_t") ||
182	    streq(name, "rpcport_t"))
183		(void) strtok(name, "_");
184	f_print(fout, "if (!xdr_%s(xdrs", name);
185}
186
187static void
188print_ifarg(char *arg)
189{
190	f_print(fout, ", %s", arg);
191}
192
193static void
194print_ifsizeof(int indent, char *prefix, char *type)
195{
196	if (indent) {
197		f_print(fout, ",\n");
198		tabify(fout, indent);
199	} else {
200		f_print(fout, ", ");
201	}
202	if (streq(type, "bool")) {
203		f_print(fout, "sizeof (bool_t), (xdrproc_t)xdr_bool");
204	} else {
205		f_print(fout, "sizeof (");
206		if (undefined(type) && prefix) {
207			f_print(fout, "%s ", prefix);
208		}
209		f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type);
210	}
211}
212
213static void
214print_ifclose(int indent)
215{
216	f_print(fout, "))\n");
217	tabify(fout, indent);
218	f_print(fout, "\treturn (FALSE);\n");
219}
220
221static void
222print_ifstat(int indent, char *prefix, char *type, relation rel,
223					char *amax, char *objname, char *name)
224{
225	char *alt = NULL;
226
227	switch (rel) {
228	case REL_POINTER:
229		print_ifopen(indent, "pointer");
230		print_ifarg("(char **)");
231		f_print(fout, "%s", objname);
232		print_ifsizeof(0, prefix, type);
233		break;
234	case REL_VECTOR:
235		if (streq(type, "string"))
236			alt = "string";
237		else if (streq(type, "opaque"))
238			alt = "opaque";
239		if (alt) {
240			print_ifopen(indent, alt);
241			print_ifarg(objname);
242		} else {
243			print_ifopen(indent, "vector");
244			print_ifarg("(char *)");
245			f_print(fout, "%s", objname);
246		}
247		print_ifarg(amax);
248		if (!alt)
249			print_ifsizeof(indent + 1, prefix, type);
250		break;
251	case REL_ARRAY:
252		if (streq(type, "string"))
253			alt = "string";
254		else if (streq(type, "opaque"))
255			alt = "bytes";
256		if (streq(type, "string")) {
257			print_ifopen(indent, alt);
258			print_ifarg(objname);
259		} else {
260			if (alt)
261				print_ifopen(indent, alt);
262			else
263				print_ifopen(indent, "array");
264			print_ifarg("(char **)");
265			if (*objname == '&')
266				f_print(fout, "%s.%s_val, (u_int *) %s.%s_len",
267				    objname, name, objname, name);
268			else
269				f_print(fout,
270				    "&%s->%s_val, (u_int *) &%s->%s_len",
271				    objname, name, objname, name);
272		}
273		print_ifarg(amax);
274		if (!alt)
275			print_ifsizeof(indent + 1, prefix, type);
276		break;
277	case REL_ALIAS:
278		print_ifopen(indent, type);
279		print_ifarg(objname);
280		break;
281	}
282	print_ifclose(indent);
283}
284
285/* ARGSUSED */
286static void
287emit_enum(definition *def)
288{
289	print_ifopen(1, "enum");
290	print_ifarg("(enum_t *)objp");
291	print_ifclose(1);
292}
293
294static void
295emit_program(definition *def)
296{
297	decl_list *dl;
298	version_list *vlist;
299	proc_list *plist;
300
301	for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next)
302		for (plist = vlist->procs; plist != NULL; plist = plist->next) {
303			if (!newstyle || plist->arg_num < 2)
304				continue; /* old style, or single argument */
305			print_prog_header(plist);
306			for (dl = plist->args.decls; dl != NULL;
307			    dl = dl->next)
308				print_stat(1, &dl->decl);
309			print_trailer();
310		}
311}
312
313
314static void
315emit_union(definition *def)
316{
317	declaration *dflt;
318	case_list *cl;
319	declaration *cs;
320	char *object;
321
322	print_stat(1, &def->def.un.enum_decl);
323	f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
324	for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
325
326		f_print(fout, "\tcase %s:\n", cl->case_name);
327		if (cl->contflag == 1) /* a continued case statement */
328			continue;
329		cs = &cl->case_decl;
330		if (!streq(cs->type, "void")) {
331			size_t len = strlen(def->def_name) +
332			    strlen("&objp->%s_u.%s") +
333			    strlen(cs->name) + 1;
334			object = malloc(len);
335			if (isvectordef(cs->type, cs->rel))
336				(void) snprintf(object, len, "objp->%s_u.%s",
337				    def->def_name, cs->name);
338			else
339				(void) snprintf(object, len, "&objp->%s_u.%s",
340				    def->def_name, cs->name);
341			print_ifstat(2, cs->prefix, cs->type, cs->rel,
342			    cs->array_max, object, cs->name);
343			free(object);
344		}
345		f_print(fout, "\t\tbreak;\n");
346	}
347	dflt = def->def.un.default_decl;
348	if (dflt != NULL) {
349		if (!streq(dflt->type, "void")) {
350			size_t len = strlen(def->def_name) +
351			    strlen("&objp->%s_u.%s") +
352			    strlen(dflt->name) + 1;
353			f_print(fout, "\tdefault:\n");
354			object = malloc(len);
355			if (isvectordef(dflt->type, dflt->rel))
356				(void) snprintf(object, len, "objp->%s_u.%s",
357				    def->def_name, dflt->name);
358			else
359				(void) snprintf(object, len, "&objp->%s_u.%s",
360				    def->def_name, dflt->name);
361
362			print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
363			    dflt->array_max, object, dflt->name);
364			free(object);
365			f_print(fout, "\t\tbreak;\n");
366		}
367	} else {
368		f_print(fout, "\tdefault:\n");
369		f_print(fout, "\t\treturn (FALSE);\n");
370	}
371
372	f_print(fout, "\t}\n");
373}
374
375static void
376expand_inline(int indent, const char *sizestr,
377    int size, int flag, decl_list *dl, decl_list *cur)
378{
379	decl_list *psav;
380
381	/*
382	 * were already looking at a xdr_inlineable structure
383	 */
384	tabify(fout, indent + 1);
385	if (sizestr == NULL)
386		f_print(fout,
387		    "buf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);",
388		    size);
389	else if (size == 0)
390		f_print(fout,
391		    "buf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);",
392		    sizestr);
393	else
394		f_print(fout,
395		    "buf = XDR_INLINE(xdrs, (%d + (%s)) "
396		    "* BYTES_PER_XDR_UNIT);", size, sizestr);
397
398	f_print(fout, "\n");
399	tabify(fout, indent + 1);
400	f_print(fout, "if (buf == NULL) {\n");
401
402	psav = cur;
403	while (cur != dl) {
404		print_stat(indent + 2,
405		    &cur->decl);
406		cur = cur->next;
407	}
408
409	tabify(fout, indent+1);
410	f_print(fout, "} else {\n");
411
412	f_print(fout, "#if defined(_LP64) || defined(_KERNEL)\n");
413	cur = psav;
414	while (cur != dl) {
415		emit_inline64(indent + 2, &cur->decl, flag);
416		cur = cur->next;
417	}
418	f_print(fout, "#else\n");
419	cur = psav;
420	while (cur != dl) {
421		emit_inline(indent + 2, &cur->decl, flag);
422		cur = cur->next;
423	}
424	f_print(fout, "#endif\n");
425
426	tabify(fout, indent + 1);
427	f_print(fout, "}\n");
428}
429
430/*
431 * An inline type is a base type (interger type) or a vector of base types.
432 */
433static int
434inline_type(declaration *dc, int *size)
435{
436	bas_type *ptr;
437
438	*size = 0;
439
440	if (dc->prefix == NULL &&
441	    (dc->rel == REL_ALIAS || dc->rel == REL_VECTOR)) {
442		ptr = find_type(dc->type);
443		if (ptr != NULL) {
444			*size = ptr->length;
445			return (1);
446		}
447	}
448
449	return (0);
450}
451
452static char *
453arraysize(char *sz, declaration *dc, int elsize)
454{
455	int len;
456	int elsz = elsize;
457	int digits;
458	int slen = 0;
459	char *plus = "";
460	char *tmp;
461	size_t tlen;
462
463	/*
464	 * Calculate the size of a string to hold the size of all arrays
465	 * to be inlined.
466	 *
467	 * We have the string representation of the total size that has already
468	 * been seen. (Null if this is the first array).
469	 * We have the string representation of array max from the declaration,
470	 * optionally the plus string, " + ", if this is not the first array,
471	 * and the number of digits for the element size for this declaration.
472	 */
473	if (sz != NULL) {
474		plus = " + ";
475		slen = strlen(sz);
476	}
477
478	/* Calculate the number of digits to hold the element size */
479	for (digits = 1; elsz >= 10; digits++)
480		elsz /= 10;
481
482	/*
483	 * If elsize != 1 the allocate 3 extra bytes for the times
484	 * string, " * ", the "()" below,  and the digits. One extra
485	 * for the trailing NULL
486	 */
487	len = strlen(dc->array_max) +  (elsize == 1 ? 0 : digits + 5) + 1;
488	tlen = slen + len + strlen(plus);
489	tmp = realloc(sz, tlen);
490	if (tmp == NULL) {
491		f_print(stderr, "Fatal error : no memory\n");
492		crash();
493	}
494
495	if (elsize == 1)
496		(void) snprintf(tmp + slen, tlen - slen, "%s%s",
497		    plus, dc->array_max);
498	else
499		(void) snprintf(tmp + slen, tlen - slen, "%s(%s) * %d",
500		    plus, dc->array_max, elsize);
501
502	return (tmp);
503}
504
505static void
506inline_struct(decl_list *dl, decl_list *last, int flag, int indent)
507{
508	int size, tsize;
509	decl_list *cur;
510	char *sizestr;
511
512	cur = NULL;
513	tsize = 0;
514	sizestr = NULL;
515	for (; dl != last; dl = dl->next) {
516		if (inline_type(&dl->decl, &size)) {
517			if (cur == NULL)
518				cur = dl;
519
520			if (dl->decl.rel == REL_ALIAS)
521				tsize += size;
522			else {
523				/* this code is required to handle arrays */
524				sizestr = arraysize(sizestr, &dl->decl, size);
525			}
526		} else {
527			if (cur != NULL)
528				if (sizestr == NULL && tsize < inlinelen) {
529					/*
530					 * don't expand into inline code
531					 * if tsize < inlinelen
532					 */
533					while (cur != dl) {
534						print_stat(indent + 1,
535						    &cur->decl);
536						cur = cur->next;
537					}
538				} else {
539					expand_inline(indent, sizestr,
540					    tsize, flag, dl, cur);
541				}
542			tsize = 0;
543			cur = NULL;
544			sizestr = NULL;
545			print_stat(indent + 1, &dl->decl);
546		}
547	}
548
549	if (cur == NULL)
550		return;
551	if (sizestr == NULL && tsize < inlinelen) {
552		/* don't expand into inline code if tsize < inlinelen */
553		while (cur != dl) {
554			print_stat(indent + 1, &cur->decl);
555			cur = cur->next;
556		}
557	} else {
558		expand_inline(indent, sizestr, tsize, flag, dl, cur);
559	}
560}
561
562/*
563 * Check if we can inline this structure. While we are at it check if the
564 * declaration list has any vectors defined of "basic" types.
565 */
566static int
567check_inline(decl_list *dl, int inlinelen, int *have_vector)
568{
569	int tsize = 0;
570	int size;
571	int doinline = 0;
572
573	*have_vector = 0;
574	if (inlinelen == 0)
575		return (0);
576
577	for (; dl != NULL; dl = dl->next) {
578		if (!inline_type(&dl->decl, &size)) {
579			tsize = 0;
580			continue;
581		}
582		if (dl->decl.rel == REL_VECTOR) {
583			*have_vector = 1;
584			return (1);
585		}
586		tsize += size;
587		if (tsize >= inlinelen)
588			doinline = 1;
589	}
590
591	return (doinline);
592}
593
594
595static void
596emit_struct_tail_recursion(definition *defp, int can_inline)
597{
598	int indent = 3;
599	struct_def *sp = &defp->def.st;
600	decl_list *dl;
601
602
603	f_print(fout, "\t%s *tmp_%s;\n",
604	    defp->def_name, defp->def_name);
605
606	f_print(fout, "\tbool_t more_data = TRUE;\n");
607	f_print(fout, "\tbool_t first_objp = TRUE;\n\n");
608
609	f_print(fout, "\n\tif (xdrs->x_op == XDR_DECODE) {\n");
610	f_print(fout, "\n\t\twhile (more_data) {\n");
611	f_print(fout, "\n\t\t\tvoid bzero();\n\n");
612
613	if (can_inline)
614		inline_struct(sp->decls, sp->tail, GET, indent);
615	else
616		for (dl = sp->decls; dl != NULL && dl != sp->tail;
617		    dl = dl->next)
618			print_stat(indent, &dl->decl);
619
620	f_print(fout, "\t\t\tif (!xdr_bool(xdrs, "
621	    "&more_data))\n\t\t\t\treturn (FALSE);\n");
622
623	f_print(fout, "\n\t\t\tif (!more_data) {\n");
624	f_print(fout, "\t\t\t\tobjp->%s = NULL;\n", sp->tail->decl.name);
625	f_print(fout, "\t\t\t\tbreak;\n");
626	f_print(fout, "\t\t\t}\n\n");
627	f_print(fout, "\t\t\tif (objp->%s == NULL) {\n", sp->tail->decl.name);
628	f_print(fout, "\t\t\t\tobjp->%s = "
629	    "(%s *)\n\t\t\t\t\tmem_alloc(sizeof (%s));\n",
630	    sp->tail->decl.name, defp->def_name, defp->def_name);
631
632	f_print(fout, "\t\t\t\tif (objp->%s == NULL)\n"
633	    "\t\t\t\t\treturn (FALSE);\n", sp->tail->decl.name);
634	f_print(fout, "\t\t\t\tbzero(objp->%s, sizeof (%s));\n",
635	    sp->tail->decl.name, defp->def_name);
636	f_print(fout, "\t\t\t}\n");
637	f_print(fout, "\t\t\tobjp = objp->%s;\n", sp->tail->decl.name);
638	f_print(fout, "\t\t}\n");
639
640	f_print(fout, "\n\t} else if (xdrs->x_op == XDR_ENCODE) {\n");
641	f_print(fout, "\n\t\twhile (more_data) {\n");
642
643	if (can_inline)
644		inline_struct(sp->decls, sp->tail, PUT, indent);
645	else
646		for (dl = sp->decls; dl != NULL && dl != sp->tail;
647		    dl = dl->next)
648			print_stat(indent, &dl->decl);
649
650	f_print(fout, "\t\t\tobjp = objp->%s;\n", sp->tail->decl.name);
651	f_print(fout, "\t\t\tif (objp == NULL)\n");
652	f_print(fout, "\t\t\t\tmore_data = FALSE;\n");
653
654	f_print(fout, "\t\t\tif (!xdr_bool(xdrs, &more_data))\n"
655	    "\t\t\t\treturn (FALSE);\n");
656
657	f_print(fout, "\t\t}\n");
658
659	f_print(fout, "\n\t} else {\n");
660	f_print(fout, "\n\t\twhile (more_data) {\n");
661
662	for (dl = sp->decls; dl != NULL && dl != sp->tail; dl = dl->next)
663		print_stat(indent, &dl->decl);
664
665	f_print(fout, "\t\t\ttmp_%s = objp;\n", defp->def_name);
666	f_print(fout, "\t\t\tobjp = objp->%s;\n", sp->tail->decl.name);
667
668	f_print(fout, "\t\t\tif (objp == NULL)\n");
669	f_print(fout, "\t\t\t\tmore_data = FALSE;\n");
670
671	f_print(fout, "\t\t\tif (!first_objp)\n");
672
673	f_print(fout, "\t\t\t\tmem_free(tmp_%s, sizeof (%s));\n",
674	    defp->def_name, defp->def_name);
675
676	f_print(fout, "\t\t\telse\n\t\t\t\tfirst_objp = FALSE;\n\t\t}\n");
677
678	f_print(fout, "\n\t}\n");
679}
680
681static void
682emit_struct(definition *def)
683{
684	decl_list *dl = def->def.st.decls;
685	int can_inline, have_vector;
686
687
688	can_inline = check_inline(dl, inlinelen, &have_vector);
689	if (have_vector)
690		f_print(fout, "\tint i;\n");
691
692
693	if (rflag && def->def.st.self_pointer) {
694		/* Handle tail recursion elimination */
695		emit_struct_tail_recursion(def, can_inline);
696		return;
697	}
698
699
700	if (can_inline) {
701		f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n");
702		inline_struct(dl, NULL, PUT, 1);
703
704		f_print(fout, "\t\treturn (TRUE);\n\t}"
705		    " else if (xdrs->x_op == XDR_DECODE) {\n");
706
707		inline_struct(dl, NULL, GET, 1);
708		f_print(fout, "\t\treturn (TRUE);\n\t}\n\n");
709	}
710
711	/* now take care of XDR_FREE inline  case or the non-inline cases */
712
713	for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
714		print_stat(1, &dl->decl);
715
716}
717
718static void
719emit_typedef(definition *def)
720{
721	char *prefix = def->def.ty.old_prefix;
722	char *type = def->def.ty.old_type;
723	char *amax = def->def.ty.array_max;
724	relation rel = def->def.ty.rel;
725
726	print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
727}
728
729static void
730print_stat(int indent, declaration *dec)
731{
732	char *prefix = dec->prefix;
733	char *type = dec->type;
734	char *amax = dec->array_max;
735	relation rel = dec->rel;
736	char name[256];
737
738	if (isvectordef(type, rel))
739		(void) snprintf(name, sizeof (name), "objp->%s", dec->name);
740	else
741		(void) snprintf(name, sizeof (name), "&objp->%s", dec->name);
742	print_ifstat(indent, prefix, type, rel, amax, name, dec->name);
743}
744
745
746static void
747emit_inline(int indent, declaration *decl, int flag)
748{
749	switch (decl->rel) {
750	case  REL_ALIAS :
751		emit_single_in_line(indent, decl, flag, REL_ALIAS);
752		break;
753	case REL_VECTOR :
754		tabify(fout, indent);
755		f_print(fout, "{\n");
756		tabify(fout, indent + 1);
757		f_print(fout, "%s *genp;\n\n", decl->type);
758		tabify(fout, indent + 1);
759		f_print(fout,
760		    "for (i = 0, genp = objp->%s;\n", decl->name);
761		tabify(fout, indent + 2);
762		f_print(fout, "i < %s; i++) {\n", decl->array_max);
763		emit_single_in_line(indent + 2, decl, flag, REL_VECTOR);
764		tabify(fout, indent + 1);
765		f_print(fout, "}\n");
766		tabify(fout, indent);
767		f_print(fout, "}\n");
768	}
769}
770
771static void
772emit_inline64(int indent, declaration *decl, int flag)
773{
774	switch (decl->rel) {
775	case  REL_ALIAS :
776		emit_single_in_line64(indent, decl, flag, REL_ALIAS);
777		break;
778	case REL_VECTOR :
779		tabify(fout, indent);
780		f_print(fout, "{\n");
781		tabify(fout, indent + 1);
782		f_print(fout, "%s *genp;\n\n", decl->type);
783		tabify(fout, indent + 1);
784		f_print(fout,
785		    "for (i = 0, genp = objp->%s;\n", decl->name);
786		tabify(fout, indent + 2);
787		f_print(fout, "i < %s; i++) {\n", decl->array_max);
788		emit_single_in_line64(indent + 2, decl, flag, REL_VECTOR);
789		tabify(fout, indent + 1);
790		f_print(fout, "}\n");
791		tabify(fout, indent);
792		f_print(fout, "}\n");
793	}
794}
795
796static void
797emit_single_in_line(int indent, declaration *decl, int flag, relation rel)
798{
799	char *upp_case;
800	int freed = 0;
801
802	tabify(fout, indent);
803	if (flag == PUT)
804		f_print(fout, "IXDR_PUT_");
805	else
806		if (rel == REL_ALIAS)
807			f_print(fout, "objp->%s = IXDR_GET_", decl->name);
808		else
809			f_print(fout, "*genp++ = IXDR_GET_");
810
811	upp_case = upcase(decl->type);
812
813	/* hack	 - XX */
814	if (strcmp(upp_case, "INT") == 0) {
815		free(upp_case);
816		freed = 1;
817		upp_case = "LONG";
818	}
819	if ((strcmp(upp_case, "U_INT") == 0) ||
820	    (strcmp(upp_case, "RPCPROG") == 0) ||
821	    (strcmp(upp_case, "RPCVERS") == 0) ||
822	    (strcmp(upp_case, "RPCPROC") == 0) ||
823	    (strcmp(upp_case, "RPCPROT") == 0) ||
824	    (strcmp(upp_case, "RPCPORT") == 0)) {
825		free(upp_case);
826		freed = 1;
827		upp_case = "U_LONG";
828	}
829
830	if (flag == PUT)
831		if (rel == REL_ALIAS)
832			f_print(fout,
833			    "%s(buf, objp->%s);\n", upp_case, decl->name);
834		else
835			f_print(fout, "%s(buf, *genp++);\n", upp_case);
836
837	else
838		f_print(fout, "%s(buf);\n", upp_case);
839	if (!freed)
840		free(upp_case);
841}
842
843static void
844emit_single_in_line64(int indent, declaration *decl, int flag, relation rel)
845{
846	char *upp_case;
847	int freed = 0;
848
849	tabify(fout, indent);
850	if (flag == PUT)
851		f_print(fout, "IXDR_PUT_");
852	else
853		if (rel == REL_ALIAS)
854			f_print(fout, "objp->%s = IXDR_GET_", decl->name);
855		else
856			f_print(fout, "*genp++ = IXDR_GET_");
857
858	upp_case = upcase(decl->type);
859
860	/* hack	 - XX */
861	if ((strcmp(upp_case, "INT") == 0)||(strcmp(upp_case, "LONG") == 0)) {
862		free(upp_case);
863		freed = 1;
864		upp_case = "INT32";
865	}
866	if ((strcmp(upp_case, "U_INT") == 0) ||
867	    (strcmp(upp_case, "U_LONG") == 0) ||
868	    (strcmp(upp_case, "RPCPROG") == 0) ||
869	    (strcmp(upp_case, "RPCVERS") == 0) ||
870	    (strcmp(upp_case, "RPCPROC") == 0) ||
871	    (strcmp(upp_case, "RPCPROT") == 0) ||
872	    (strcmp(upp_case, "RPCPORT") == 0)) {
873		free(upp_case);
874		freed = 1;
875		upp_case = "U_INT32";
876	}
877
878	if (flag == PUT)
879		if (rel == REL_ALIAS)
880			f_print(fout,
881			    "%s(buf, objp->%s);\n", upp_case, decl->name);
882		else
883			f_print(fout, "%s(buf, *genp++);\n", upp_case);
884
885	else
886		f_print(fout, "%s(buf);\n", upp_case);
887	if (!freed)
888		free(upp_case);
889}
890
891static char *
892upcase(char *str)
893{
894	char *ptr, *hptr;
895
896	ptr = malloc(strlen(str)+1);
897	if (ptr == NULL) {
898		f_print(stderr, "malloc failed\n");
899		exit(1);
900	};
901
902	hptr = ptr;
903	while (*str != '\0')
904		*ptr++ = toupper(*str++);
905
906	*ptr = '\0';
907	return (hptr);
908}
909