xref: /original-bsd/usr.sbin/config/mkmakefile.c (revision 35d77a20)
1 /*
2  * Copyright (c) 1980,1990 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)mkmakefile.c	5.32 (Berkeley) 05/24/91";
10 #endif /* not lint */
11 
12 /*
13  * Build the makefile for the system, from
14  * the information in the files files and the
15  * additional files for the machine being compiled to.
16  */
17 
18 #include <stdio.h>
19 #include <ctype.h>
20 #include "y.tab.h"
21 #include "config.h"
22 #include "pathnames.h"
23 
24 #define next_word(fp, wd) \
25 	{ register char *word = get_word(fp); \
26 	  if (word == (char *)EOF) \
27 		return; \
28 	  else \
29 		wd = word; \
30 	}
31 
32 static	struct file_list *fcur;
33 char *tail();
34 
35 /*
36  * Lookup a file, by name.
37  */
38 struct file_list *
39 fl_lookup(file)
40 	register char *file;
41 {
42 	register struct file_list *fp;
43 
44 	for (fp = ftab ; fp != 0; fp = fp->f_next) {
45 		if (eq(fp->f_fn, file))
46 			return (fp);
47 	}
48 	return (0);
49 }
50 
51 /*
52  * Lookup a file, by final component name.
53  */
54 struct file_list *
55 fltail_lookup(file)
56 	register char *file;
57 {
58 	register struct file_list *fp;
59 
60 	for (fp = ftab ; fp != 0; fp = fp->f_next) {
61 		if (eq(tail(fp->f_fn), tail(file)))
62 			return (fp);
63 	}
64 	return (0);
65 }
66 
67 /*
68  * Make a new file list entry
69  */
70 struct file_list *
71 new_fent()
72 {
73 	register struct file_list *fp;
74 
75 	fp = (struct file_list *) malloc(sizeof *fp);
76 	fp->f_needs = 0;
77 	fp->f_next = 0;
78 	fp->f_flags = 0;
79 	fp->f_type = 0;
80 	if (fcur == 0)
81 		fcur = ftab = fp;
82 	else
83 		fcur->f_next = fp;
84 	fcur = fp;
85 	return (fp);
86 }
87 
88 char	*COPTS;
89 static	struct users {
90 	int	u_default;
91 	int	u_min;
92 	int	u_max;
93 } users[] = {
94 	{ 24, 8, 1024 },		/* MACHINE_VAX */
95 	{ 4, 2, 128 },			/* MACHINE_TAHOE */
96 	{ 8, 2, 64 },			/* MACHINE_HP300 */
97 	{ 8, 2, 64 },			/* MACHINE_I386 */
98 };
99 #define	NUSERS	(sizeof (users) / sizeof (users[0]))
100 
101 /*
102  * Build the makefile from the skeleton
103  */
104 makefile()
105 {
106 	FILE *ifp, *ofp;
107 	char line[BUFSIZ];
108 	struct opt *op;
109 	struct users *up;
110 
111 	read_files();
112 	strcpy(line, "Makefile.");
113 	(void) strcat(line, machinename);
114 	ifp = fopen(line, "r");
115 	if (ifp == 0) {
116 		perror(line);
117 		exit(1);
118 	}
119 	ofp = fopen(path("Makefile"), "w");
120 	if (ofp == 0) {
121 		perror(path("Makefile"));
122 		exit(1);
123 	}
124 	fprintf(ofp, "IDENT=-D%s", raise(ident));
125 	if (profiling)
126 		fprintf(ofp, " -DGPROF");
127 	if (cputype == 0) {
128 		printf("cpu type must be specified\n");
129 		exit(1);
130 	}
131 	{ struct cputype *cp;
132 	  for (cp = cputype; cp; cp = cp->cpu_next)
133 		fprintf(ofp, " -D%s", cp->cpu_name);
134 	}
135 	for (op = opt; op; op = op->op_next)
136 		if (op->op_value)
137 			fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value);
138 		else
139 			fprintf(ofp, " -D%s", op->op_name);
140 	fprintf(ofp, "\n");
141 	if (hadtz == 0)
142 		printf("timezone not specified; gmt assumed\n");
143 	if ((unsigned)machine > NUSERS) {
144 		printf("maxusers config info isn't present, using vax\n");
145 		up = &users[MACHINE_VAX-1];
146 	} else
147 		up = &users[machine-1];
148 	if (maxusers == 0) {
149 		printf("maxusers not specified; %d assumed\n", up->u_default);
150 		maxusers = up->u_default;
151 	} else if (maxusers < up->u_min) {
152 		printf("minimum of %d maxusers assumed\n", up->u_min);
153 		maxusers = up->u_min;
154 	} else if (maxusers > up->u_max)
155 		printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers);
156 	fprintf(ofp, "PARAM=-DTIMEZONE=%d -DDST=%d -DMAXUSERS=%d\n",
157 	    zone, dst, maxusers);
158 	for (op = mkopt; op; op = op->op_next)
159 		fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
160 	while (fgets(line, BUFSIZ, ifp) != 0) {
161 		if (*line == '%')
162 			goto percent;
163 		if ((debugging || profiling) &&
164 		    strncmp(line, "COPTS=", 6) == 0) {
165 			register char *cp;
166 
167 			cp = index(line, '\n');
168 			if (cp)
169 				*cp = 0;
170 			if (profiling) {
171 				cp = line + 6;
172 				while (*cp && (*cp == ' ' || *cp == '\t'))
173 					cp++;
174 				COPTS = malloc((unsigned)(strlen(cp) + 1));
175 				if (COPTS == 0) {
176 					printf("config: out of memory\n");
177 					exit(1);
178 				}
179 				strcpy(COPTS, cp);
180 			}
181 			fprintf(ofp, "%s", line);
182 			if (debugging)
183 				fprintf(ofp, " -g");
184 			if (profiling) {
185 				fprintf(ofp, " -pg\n");
186 				fprintf(ofp, _PATH_GPROF, machinename);
187 			} else
188 				fprintf(ofp, "\n");
189 			continue;
190 		}
191 		fprintf(ofp, "%s", line);
192 		continue;
193 	percent:
194 		if (eq(line, "%OBJS\n"))
195 			do_objs(ofp);
196 		else if (eq(line, "%CFILES\n"))
197 			do_cfiles(ofp);
198 		else if (eq(line, "%RULES\n"))
199 			do_rules(ofp);
200 		else if (eq(line, "%LOAD\n"))
201 			do_load(ofp);
202 		else
203 			fprintf(stderr,
204 			    "Unknown %% construct in generic makefile: %s",
205 			    line);
206 	}
207 	(void) fclose(ifp);
208 	(void) fclose(ofp);
209 }
210 
211 /*
212  * Read in the information about files used in making the system.
213  * Store it in the ftab linked list.
214  */
215 read_files()
216 {
217 	FILE *fp;
218 	register struct file_list *tp, *pf;
219 	register struct device *dp;
220 	struct device *save_dp;
221 	register struct opt *op;
222 	char *wd, *this, *needs, *devorprof;
223 	char fname[32];
224 	int nreqs, first = 1, configdep, isdup, std;
225 
226 	ftab = 0;
227 	(void) strcpy(fname, "../../conf/files");
228 openit:
229 	fp = fopen(fname, "r");
230 	if (fp == 0) {
231 		perror(fname);
232 		exit(1);
233 	}
234 next:
235 	/*
236 	 * filename	[ standard | optional ] [ config-dependent ]
237 	 *	[ dev* | profiling-routine ] [ device-driver]
238 	 */
239 	wd = get_word(fp);
240 	if (wd == (char *)EOF) {
241 		(void) fclose(fp);
242 		if (first == 1) {
243 			(void) sprintf(fname, "files.%s", machinename);
244 			first++;
245 			goto openit;
246 		}
247 		if (first == 2) {
248 			(void) sprintf(fname, "files.%s", raise(ident));
249 			first++;
250 			fp = fopen(fname, "r");
251 			if (fp != 0)
252 				goto next;
253 		}
254 		return;
255 	}
256 	if (wd == 0)
257 		goto next;
258 	this = ns(wd);
259 	next_word(fp, wd);
260 	if (wd == 0) {
261 		printf("%s: No type for %s.\n",
262 		    fname, this);
263 		exit(1);
264 	}
265 	if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags))
266 		isdup = 1;
267 	else
268 		isdup = 0;
269 	tp = 0;
270 	if (first == 3 && (tp = fltail_lookup(this)) != 0)
271 		printf("%s: Local file %s overrides %s.\n",
272 		    fname, this, tp->f_fn);
273 	nreqs = 0;
274 	devorprof = "";
275 	configdep = 0;
276 	needs = 0;
277 	std = 0;
278 	if (eq(wd, "standard"))
279 		std = 1;
280 	else if (!eq(wd, "optional")) {
281 		printf("%s: %s must be optional or standard\n", fname, this);
282 		exit(1);
283 	}
284 nextparam:
285 	next_word(fp, wd);
286 	if (wd == 0)
287 		goto doneparam;
288 	if (eq(wd, "config-dependent")) {
289 		configdep++;
290 		goto nextparam;
291 	}
292 	devorprof = wd;
293 	if (eq(wd, "device-driver") || eq(wd, "profiling-routine")) {
294 		next_word(fp, wd);
295 		goto save;
296 	}
297 	nreqs++;
298 	if (needs == 0 && nreqs == 1)
299 		needs = ns(wd);
300 	if (isdup)
301 		goto invis;
302 	for (dp = dtab; dp != 0; save_dp = dp, dp = dp->d_next)
303 		if (eq(dp->d_name, wd)) {
304 			if (std &&
305 			    dp->d_type == PSEUDO_DEVICE && dp->d_slave <= 0)
306 				dp->d_slave = 1;
307 			goto nextparam;
308 		}
309 	if (std) {
310 		dp = (struct device *) malloc(sizeof *dp);
311 		init_dev(dp);
312 		dp->d_name = ns(wd);
313 		dp->d_type = PSEUDO_DEVICE;
314 		dp->d_slave = 1;
315 		save_dp->d_next = dp;
316 		goto nextparam;
317 	}
318 	for (op = opt; op != 0; op = op->op_next)
319 		if (op->op_value == 0 && opteq(op->op_name, wd)) {
320 			if (nreqs == 1) {
321 				free(needs);
322 				needs = 0;
323 			}
324 			goto nextparam;
325 		}
326 invis:
327 	while ((wd = get_word(fp)) != 0)
328 		;
329 	if (tp == 0)
330 		tp = new_fent();
331 	tp->f_fn = this;
332 	tp->f_type = INVISIBLE;
333 	tp->f_needs = needs;
334 	tp->f_flags = isdup;
335 	goto next;
336 
337 doneparam:
338 	if (std == 0 && nreqs == 0) {
339 		printf("%s: what is %s optional on?\n",
340 		    fname, this);
341 		exit(1);
342 	}
343 
344 save:
345 	if (wd) {
346 		printf("%s: syntax error describing %s\n",
347 		    fname, this);
348 		exit(1);
349 	}
350 	if (eq(devorprof, "profiling-routine") && profiling == 0)
351 		goto next;
352 	if (tp == 0)
353 		tp = new_fent();
354 	tp->f_fn = this;
355 	if (eq(devorprof, "device-driver"))
356 		tp->f_type = DRIVER;
357 	else if (eq(devorprof, "profiling-routine"))
358 		tp->f_type = PROFILING;
359 	else
360 		tp->f_type = NORMAL;
361 	tp->f_flags = 0;
362 	if (configdep)
363 		tp->f_flags |= CONFIGDEP;
364 	tp->f_needs = needs;
365 	if (pf && pf->f_type == INVISIBLE)
366 		pf->f_flags = 1;		/* mark as duplicate */
367 	goto next;
368 }
369 
370 opteq(cp, dp)
371 	char *cp, *dp;
372 {
373 	char c, d;
374 
375 	for (; ; cp++, dp++) {
376 		if (*cp != *dp) {
377 			c = isupper(*cp) ? tolower(*cp) : *cp;
378 			d = isupper(*dp) ? tolower(*dp) : *dp;
379 			if (c != d)
380 				return (0);
381 		}
382 		if (*cp == 0)
383 			return (1);
384 	}
385 }
386 
387 do_objs(fp)
388 	FILE *fp;
389 {
390 	register struct file_list *tp, *fl;
391 	register int lpos, len;
392 	register char *cp, och, *sp;
393 	char swapname[32];
394 
395 	fprintf(fp, "OBJS=");
396 	lpos = 6;
397 	for (tp = ftab; tp != 0; tp = tp->f_next) {
398 		if (tp->f_type == INVISIBLE)
399 			continue;
400 		sp = tail(tp->f_fn);
401 		for (fl = conf_list; fl; fl = fl->f_next) {
402 			if (fl->f_type != SWAPSPEC)
403 				continue;
404 			(void) sprintf(swapname, "swap%s.c", fl->f_fn);
405 			if (eq(sp, swapname))
406 				goto cont;
407 		}
408 		cp = sp + (len = strlen(sp)) - 1;
409 		och = *cp;
410 		*cp = 'o';
411 		if (len + lpos > 72) {
412 			lpos = 8;
413 			fprintf(fp, "\\\n\t");
414 		}
415 		fprintf(fp, "%s ", sp);
416 		lpos += len + 1;
417 		*cp = och;
418 cont:
419 		;
420 	}
421 	if (lpos != 8)
422 		putc('\n', fp);
423 }
424 
425 do_cfiles(fp)
426 	FILE *fp;
427 {
428 	register struct file_list *tp, *fl;
429 	register int lpos, len;
430 	char swapname[32];
431 
432 	fputs("CFILES=", fp);
433 	lpos = 8;
434 	for (tp = ftab; tp; tp = tp->f_next)
435 		if (tp->f_type != INVISIBLE) {
436 			len = strlen(tp->f_fn);
437 			if (tp->f_fn[len - 1] != 'c')
438 				continue;
439 			if ((len = 3 + len) + lpos > 72) {
440 				lpos = 8;
441 				fputs("\\\n\t", fp);
442 			}
443 			fprintf(fp, "$S/%s ", tp->f_fn);
444 			lpos += len + 1;
445 		}
446 	for (fl = conf_list; fl; fl = fl->f_next)
447 		if (fl->f_type == SYSTEMSPEC) {
448 			(void) sprintf(swapname, "swap%s.c", fl->f_fn);
449 			if ((len = 3 + strlen(swapname)) + lpos > 72) {
450 				lpos = 8;
451 				fputs("\\\n\t", fp);
452 			}
453 			if (eq(fl->f_fn, "generic"))
454 				fprintf(fp, "$S/%s/%s/%s ",
455 				    machinename, machinename, swapname);
456 			else
457 				fprintf(fp, "%s ", swapname);
458 			lpos += len + 1;
459 		}
460 	if (lpos != 8)
461 		putc('\n', fp);
462 }
463 
464 char *
465 tail(fn)
466 	char *fn;
467 {
468 	register char *cp;
469 
470 	cp = rindex(fn, '/');
471 	if (cp == 0)
472 		return (fn);
473 	return (cp+1);
474 }
475 
476 /*
477  * Create the makerules for each file
478  * which is part of the system.
479  * Devices are processed with the special c2 option -i
480  * which avoids any problem areas with i/o addressing
481  * (e.g. for the VAX); assembler files are processed by as.
482  */
483 do_rules(f)
484 	FILE *f;
485 {
486 	register char *cp, *np, och, *tp;
487 	register struct file_list *ftp;
488 	char *extras;
489 
490 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) {
491 	if (ftp->f_type == INVISIBLE)
492 		continue;
493 	cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
494 	och = *cp;
495 	*cp = '\0';
496 	if (och == 'o') {
497 		fprintf(f, "%so:\n\t-cp $S/%so .\n\n", tail(np), np);
498 		continue;
499 	}
500 	fprintf(f, "%so: $S/%s%c\n", tail(np), np, och);
501 	tp = tail(np);
502 	if (och == 's') {
503 		fprintf(f, "\t${CPP} ${COPTS} $S/%ss | ${AS} -o %so\n",
504 			np, tp);
505 		continue;
506 	}
507 	if (ftp->f_flags & CONFIGDEP)
508 		extras = "${PARAM} ";
509 	else
510 		extras = "";
511 	switch (ftp->f_type) {
512 
513 	case NORMAL:
514 		switch (machine) {
515 
516 		case MACHINE_VAX:
517 		case MACHINE_TAHOE:
518 			fprintf(f, "\t${CC} -c -S ${COPTS} %s$S/%sc\n",
519 				extras, np);
520 			fprintf(f, "\t${C2} %ss | ${INLINE} | ${AS} -o %so\n",
521 			    tp, tp);
522 			fprintf(f, "\trm -f %ss\n\n", tp);
523 			break;
524 
525 		case MACHINE_HP300:
526 		case MACHINE_I386:
527 			fprintf(f, "\t${CC} -c ${CFLAGS} %s$S/%sc\n\n",
528 				extras, np);
529 			break;
530 		}
531 		break;
532 
533 	case DRIVER:
534 		switch (machine) {
535 
536 		case MACHINE_VAX:
537 		case MACHINE_TAHOE:
538 			fprintf(f, "\t${CC} -c -S ${COPTS} %s$S/%sc\n",
539 				extras, np);
540 			fprintf(f,"\t${C2} -i %ss | ${INLINE} | ${AS} -o %so\n",
541 			    tp, tp);
542 			fprintf(f, "\trm -f %ss\n\n", tp);
543 			break;
544 
545 		case MACHINE_HP300:
546 		case MACHINE_I386:
547 			fprintf(f, "\t${CC} -c ${CFLAGS} %s$S/%sc\n\n",
548 				extras, np);
549 			break;
550 		}
551 		break;
552 
553 	case PROFILING:
554 		if (!profiling)
555 			continue;
556 		if (COPTS == 0) {
557 			fprintf(stderr,
558 			    "config: COPTS undefined in generic makefile");
559 			COPTS = "";
560 		}
561 		switch (machine) {
562 
563 		case MACHINE_TAHOE:
564 			fprintf(f, "\t${CC} -c -S %s %s$S/%sc\n",
565 				COPTS, extras, np);
566 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
567 			fprintf(f,"\t${C2} %ss | ${INLINE} | ${AS} -o %so\n",
568 			    tp, tp);
569 			fprintf(f, "\trm -f %ss\n\n", tp);
570 			break;
571 
572 		case MACHINE_VAX:
573 			fprintf(f, "\t${CC} -c -S %s %s$S/%sc\n",
574 				COPTS, extras, np);
575 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
576 			fprintf(f, "\t${INLINE} %ss | ${AS} -o %so\n", tp, tp);
577 			fprintf(f, "\trm -f %ss\n\n", tp);
578 			break;
579 
580 		case MACHINE_HP300:
581 		case MACHINE_I386:
582 			fprintf(f, "\t${CC} -c -S %s %s$S/%sc\n",
583 				COPTS, extras, np);
584 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
585 			fprintf(f, "\t${AS} -o %so %ss\n", tp, tp);
586 			fprintf(f, "\trm -f %ss\n\n", tp);
587 			break;
588 		}
589 		break;
590 
591 	default:
592 		printf("Don't know rules for %s\n", np);
593 		break;
594 	}
595 	*cp = och;
596 }
597 }
598 
599 /*
600  * Create the load strings
601  */
602 do_load(f)
603 	register FILE *f;
604 {
605 	register struct file_list *fl;
606 	register int first;
607 	struct file_list *do_systemspec();
608 
609 	for (first = 1, fl = conf_list; fl; first = 0)
610 		fl = fl->f_type == SYSTEMSPEC ?
611 			do_systemspec(f, fl, first) : fl->f_next;
612 	fputs("all:", f);
613 	for (fl = conf_list; fl; fl = fl->f_next)
614 		if (fl->f_type == SYSTEMSPEC)
615 			fprintf(f, " %s", fl->f_needs);
616 	putc('\n', f);
617 }
618 
619 struct file_list *
620 do_systemspec(f, fl, first)
621 	FILE *f;
622 	register struct file_list *fl;
623 	int first;
624 {
625 
626 	fprintf(f, "%s: Makefile symbols.sort", fl->f_needs);
627 	if (machine == MACHINE_VAX)
628 		fprintf(f, " ${INLINECMD} locore.o emulate.o");
629 	else if (machine == MACHINE_TAHOE)
630 		fprintf(f, " ${INLINE} locore.o");
631 	else
632 		fprintf(f, " locore.o");
633 	fprintf(f, " ${OBJS} param.o ioconf.o swap%s.o\n", fl->f_fn);
634 	fprintf(f, "\t@echo loading %s\n\t@rm -f %s\n",
635 	    fl->f_needs, fl->f_needs);
636 	if (first) {
637 		fprintf(f, "\t@sh $S/conf/newvers.sh\n");
638 		fprintf(f, "\t@${CC} ${CFLAGS} -c vers.c\n");
639 	}
640 	switch (machine) {
641 
642 	case MACHINE_VAX:
643 		fprintf(f, "\t@${LD} -n -o %s -e start -%c -T 80000000 ",
644 			fl->f_needs, debugging ? 'X' : 'x');
645 		fprintf(f,
646 		    "locore.o emulate.o ${OBJS} vers.o ioconf.o param.o ");
647 		break;
648 
649 	case MACHINE_TAHOE:
650 		fprintf(f, "\t@${LD} -n -o %s -e start -%c -T C0000800 ",
651 			fl->f_needs, debugging ? 'X' : 'x');
652 		fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o ");
653 		break;
654 
655 	case MACHINE_HP300:
656 		fprintf(f, "\t@${LD} -n -o %s -e start -%c ",
657 			fl->f_needs, debugging ? 'X' : 'x');
658 		fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o ");
659 		break;
660 
661 	case MACHINE_I386:
662 		fprintf(f, "\t@${LD} -n -T FE000000 -o %s -%c ",
663 			fl->f_needs, debugging ? 'X' : 'x');
664 		fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o ");
665 	}
666 	fprintf(f, "swap%s.o\n", fl->f_fn);
667 	fprintf(f, "\t@echo rearranging symbols\n");
668 	fprintf(f, "\t@-symorder symbols.sort %s\n", fl->f_needs);
669 	fprintf(f, "\t@size %s\n", fl->f_needs);
670 	fprintf(f, "\t@chmod 755 %s\n\n", fl->f_needs);
671 	do_swapspec(f, fl->f_fn);
672 	for (fl = fl->f_next; fl->f_type == SWAPSPEC; fl = fl->f_next)
673 		;
674 	return (fl);
675 }
676 
677 do_swapspec(f, name)
678 	FILE *f;
679 	register char *name;
680 {
681 
682 	if (!eq(name, "generic")) {
683 		fprintf(f, "swap%s.o: swap%s.c\n", name, name);
684 		fprintf(f, "\t${CC} -c -O ${COPTS} swap%s.c\n\n", name);
685 		return;
686 	}
687 	fprintf(f, "swapgeneric.o: $S/%s/%s/swapgeneric.c\n",
688 	    machinename, machinename);
689 	switch (machine) {
690 
691 	case MACHINE_VAX:
692 	case MACHINE_TAHOE:
693 		fprintf(f, "\t${CC} -c -S ${COPTS} ");
694 		fprintf(f, "$S/%s/%s/swapgeneric.c\n",
695 		    machinename, machinename);
696 		fprintf(f, "\t${C2} swapgeneric.s | ${INLINE}");
697 		fprintf(f, " | ${AS} -o swapgeneric.o\n");
698 		fprintf(f, "\trm -f swapgeneric.s\n\n");
699 		break;
700 
701 	case MACHINE_HP300:
702 	case MACHINE_I386:
703 		fprintf(f, "\t${CC} -c ${CFLAGS} ");
704 		fprintf(f, "$S/%s/%s/swapgeneric.c\n\n",
705 		    machinename, machinename);
706 		break;
707 	}
708 }
709 
710 char *
711 raise(str)
712 	register char *str;
713 {
714 	register char *cp = str;
715 
716 	while (*str) {
717 		if (islower(*str))
718 			*str = toupper(*str);
719 		str++;
720 	}
721 	return (cp);
722 }
723