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