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