xref: /netbsd-src/usr.bin/rpcgen/rpc_cout.c (revision 1ca5c1b28139779176bd5c13ad7c5f25c0bcd5f8)
1 /*	$NetBSD: rpc_cout.c,v 1.17 2000/10/11 14:46:16 is 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 #ifndef 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.17 2000/10/11 14:46:16 is Exp $");
38 #endif
39 #endif
40 
41 /*
42  * rpc_cout.c, XDR routine outputter for the RPC protocol compiler
43  */
44 #include <stdio.h>
45 #include <ctype.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <err.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