mkmakefile.c revision 218544
1/* 2 * Copyright (c) 1993, 19801990 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#ifndef lint 31#if 0 32static char sccsid[] = "@(#)mkmakefile.c 8.1 (Berkeley) 6/6/93"; 33#endif 34static const char rcsid[] = 35 "$FreeBSD: head/usr.sbin/config/mkmakefile.c 218544 2011-02-11 06:35:53Z imp $"; 36#endif /* not lint */ 37 38/* 39 * Build the makefile for the system, from 40 * the information in the files files and the 41 * additional files for the machine being compiled to. 42 */ 43 44#include <ctype.h> 45#include <err.h> 46#include <stdio.h> 47#include <string.h> 48#include <sys/param.h> 49#include "y.tab.h" 50#include "config.h" 51#include "configvers.h" 52 53#define next_word(fp, wd) \ 54 { char *word = get_word(fp); \ 55 if (word == (char *)EOF) \ 56 return; \ 57 else \ 58 wd = word; \ 59 } 60#define next_quoted_word(fp, wd) \ 61 { char *word = get_quoted_word(fp); \ 62 if (word == (char *)EOF) \ 63 return; \ 64 else \ 65 wd = word; \ 66 } 67 68static char *tail(char *); 69static void do_clean(FILE *); 70static void do_rules(FILE *); 71static void do_xxfiles(char *, FILE *); 72static void do_objs(FILE *); 73static void do_before_depend(FILE *); 74static int opteq(const char *, const char *); 75static void read_files(void); 76 77/* 78 * Lookup a file, by name. 79 */ 80static struct file_list * 81fl_lookup(char *file) 82{ 83 struct file_list *fp; 84 85 STAILQ_FOREACH(fp, &ftab, f_next) { 86 if (eq(fp->f_fn, file)) 87 return (fp); 88 } 89 return (0); 90} 91 92/* 93 * Make a new file list entry 94 */ 95static struct file_list * 96new_fent(void) 97{ 98 struct file_list *fp; 99 100 fp = (struct file_list *) calloc(1, sizeof *fp); 101 if (fp == NULL) 102 err(EXIT_FAILURE, "calloc"); 103 STAILQ_INSERT_TAIL(&ftab, fp, f_next); 104 return (fp); 105} 106 107/* 108 * Open the correct Makefile and return it, or error out. 109 */ 110FILE * 111open_makefile_template(void) 112{ 113 FILE *ifp; 114 char line[BUFSIZ]; 115 116 snprintf(line, sizeof(line), "../../conf/Makefile.%s", machinename); 117 ifp = fopen(line, "r"); 118 if (ifp == 0) { 119 snprintf(line, sizeof(line), "Makefile.%s", machinename); 120 ifp = fopen(line, "r"); 121 } 122 if (ifp == 0) 123 err(1, "%s", line); 124 return (ifp); 125} 126 127/* 128 * Build the makefile from the skeleton 129 */ 130void 131makefile(void) 132{ 133 FILE *ifp, *ofp; 134 char line[BUFSIZ]; 135 struct opt *op, *t; 136 137 read_files(); 138 ifp = open_makefile_template(); 139 ofp = fopen(path("Makefile.new"), "w"); 140 if (ofp == 0) 141 err(1, "%s", path("Makefile.new")); 142 fprintf(ofp, "KERN_IDENT=%s\n", ident); 143 fprintf(ofp, "MACHINE=%s\n", machinename); 144 fprintf(ofp, "MACHINE_ARCH=%s\n", machinearch); 145 SLIST_FOREACH_SAFE(op, &mkopt, op_next, t) { 146 fprintf(ofp, "%s=%s", op->op_name, op->op_value); 147 while ((op = SLIST_NEXT(op, op_append)) != NULL) 148 fprintf(ofp, " %s", op->op_value); 149 fprintf(ofp, "\n"); 150 } 151 if (debugging) 152 fprintf(ofp, "DEBUG=-g\n"); 153 if (profiling) 154 fprintf(ofp, "PROFLEVEL=%d\n", profiling); 155 if (*srcdir != '\0') 156 fprintf(ofp,"S=%s\n", srcdir); 157 while (fgets(line, BUFSIZ, ifp) != 0) { 158 if (*line != '%') { 159 fprintf(ofp, "%s", line); 160 continue; 161 } 162 if (eq(line, "%BEFORE_DEPEND\n")) 163 do_before_depend(ofp); 164 else if (eq(line, "%OBJS\n")) 165 do_objs(ofp); 166 else if (strncmp(line, "%FILES.", 7) == 0) 167 do_xxfiles(line, ofp); 168 else if (eq(line, "%RULES\n")) 169 do_rules(ofp); 170 else if (eq(line, "%CLEAN\n")) 171 do_clean(ofp); 172 else if (strncmp(line, "%VERSREQ=", 9) == 0) 173 line[0] = '\0'; /* handled elsewhere */ 174 else 175 fprintf(stderr, 176 "Unknown %% construct in generic makefile: %s", 177 line); 178 } 179 (void) fclose(ifp); 180 (void) fclose(ofp); 181 moveifchanged(path("Makefile.new"), path("Makefile")); 182} 183 184/* 185 * Build hints.c from the skeleton 186 */ 187void 188makehints(void) 189{ 190 FILE *ifp, *ofp; 191 char line[BUFSIZ]; 192 char *s; 193 struct hint *hint; 194 195 ofp = fopen(path("hints.c.new"), "w"); 196 if (ofp == NULL) 197 err(1, "%s", path("hints.c.new")); 198 fprintf(ofp, "#include <sys/types.h>\n"); 199 fprintf(ofp, "#include <sys/systm.h>\n"); 200 fprintf(ofp, "\n"); 201 fprintf(ofp, "int hintmode = %d;\n", hintmode); 202 fprintf(ofp, "char static_hints[] = {\n"); 203 STAILQ_FOREACH(hint, &hints, hint_next) { 204 ifp = fopen(hint->hint_name, "r"); 205 if (ifp == NULL) 206 err(1, "%s", hint->hint_name); 207 while (fgets(line, BUFSIZ, ifp) != 0) { 208 /* zap trailing CR and/or LF */ 209 while ((s = rindex(line, '\n')) != NULL) 210 *s = '\0'; 211 while ((s = rindex(line, '\r')) != NULL) 212 *s = '\0'; 213 /* remove # comments */ 214 s = index(line, '#'); 215 if (s) 216 *s = '\0'; 217 /* remove any whitespace and " characters */ 218 s = line; 219 while (*s) { 220 if (*s == ' ' || *s == '\t' || *s == '"') { 221 while (*s) { 222 s[0] = s[1]; 223 s++; 224 } 225 /* start over */ 226 s = line; 227 continue; 228 } 229 s++; 230 } 231 /* anything left? */ 232 if (*line == '\0') 233 continue; 234 fprintf(ofp, "\"%s\\0\"\n", line); 235 } 236 fclose(ifp); 237 } 238 fprintf(ofp, "\"\\0\"\n};\n"); 239 fclose(ofp); 240 moveifchanged(path("hints.c.new"), path("hints.c")); 241} 242 243/* 244 * Build env.c from the skeleton 245 */ 246void 247makeenv(void) 248{ 249 FILE *ifp, *ofp; 250 char line[BUFSIZ]; 251 char *s; 252 253 if (env) { 254 ifp = fopen(env, "r"); 255 if (ifp == NULL) 256 err(1, "%s", env); 257 } else { 258 ifp = NULL; 259 } 260 ofp = fopen(path("env.c.new"), "w"); 261 if (ofp == NULL) 262 err(1, "%s", path("env.c.new")); 263 fprintf(ofp, "#include <sys/types.h>\n"); 264 fprintf(ofp, "#include <sys/systm.h>\n"); 265 fprintf(ofp, "\n"); 266 fprintf(ofp, "int envmode = %d;\n", envmode); 267 fprintf(ofp, "char static_env[] = {\n"); 268 if (ifp) { 269 while (fgets(line, BUFSIZ, ifp) != 0) { 270 /* zap trailing CR and/or LF */ 271 while ((s = rindex(line, '\n')) != NULL) 272 *s = '\0'; 273 while ((s = rindex(line, '\r')) != NULL) 274 *s = '\0'; 275 /* remove # comments */ 276 s = index(line, '#'); 277 if (s) 278 *s = '\0'; 279 /* remove any whitespace and " characters */ 280 s = line; 281 while (*s) { 282 if (*s == ' ' || *s == '\t' || *s == '"') { 283 while (*s) { 284 s[0] = s[1]; 285 s++; 286 } 287 /* start over */ 288 s = line; 289 continue; 290 } 291 s++; 292 } 293 /* anything left? */ 294 if (*line == '\0') 295 continue; 296 fprintf(ofp, "\"%s\\0\"\n", line); 297 } 298 } 299 fprintf(ofp, "\"\\0\"\n};\n"); 300 if (ifp) 301 fclose(ifp); 302 fclose(ofp); 303 moveifchanged(path("env.c.new"), path("env.c")); 304} 305 306static void 307read_file(char *fname) 308{ 309 char ifname[MAXPATHLEN]; 310 FILE *fp; 311 struct file_list *tp; 312 struct device *dp; 313 struct opt *op; 314 char *wd, *this, *compilewith, *depends, *clean, *warning; 315 int compile, match, nreqs, std, filetype, 316 imp_rule, no_obj, before_depend, mandatory, nowerror; 317 318 fp = fopen(fname, "r"); 319 if (fp == 0) 320 err(1, "%s", fname); 321next: 322 /* 323 * include "filename" 324 * filename [ standard | mandatory | optional ] 325 * [ dev* [ | dev* ... ] | profiling-routine ] [ no-obj ] 326 * [ compile-with "compile rule" [no-implicit-rule] ] 327 * [ dependency "dependency-list"] [ before-depend ] 328 * [ clean "file-list"] [ warning "text warning" ] 329 */ 330 wd = get_word(fp); 331 if (wd == (char *)EOF) { 332 (void) fclose(fp); 333 return; 334 } 335 if (wd == 0) 336 goto next; 337 if (wd[0] == '#') 338 { 339 while (((wd = get_word(fp)) != (char *)EOF) && wd) 340 ; 341 goto next; 342 } 343 if (eq(wd, "include")) { 344 next_quoted_word(fp, wd); 345 if (wd == 0) { 346 fprintf(stderr, "%s: missing include filename.\n", 347 fname); 348 exit(1); 349 } 350 (void) snprintf(ifname, sizeof(ifname), "../../%s", wd); 351 read_file(ifname); 352 while (((wd = get_word(fp)) != (char *)EOF) && wd) 353 ; 354 goto next; 355 } 356 this = ns(wd); 357 next_word(fp, wd); 358 if (wd == 0) { 359 fprintf(stderr, "%s: No type for %s.\n", fname, this); 360 exit(1); 361 } 362 tp = fl_lookup(this); 363 compile = 0; 364 match = 1; 365 nreqs = 0; 366 compilewith = 0; 367 depends = 0; 368 clean = 0; 369 warning = 0; 370 std = mandatory = 0; 371 imp_rule = 0; 372 no_obj = 0; 373 before_depend = 0; 374 nowerror = 0; 375 filetype = NORMAL; 376 if (eq(wd, "standard")) { 377 std = 1; 378 /* 379 * If an entry is marked "mandatory", config will abort if it's 380 * not called by a configuration line in the config file. Apart 381 * from this, the device is handled like one marked "optional". 382 */ 383 } else if (eq(wd, "mandatory")) { 384 mandatory = 1; 385 } else if (!eq(wd, "optional")) { 386 fprintf(stderr, 387 "%s: \"%s\" %s must be optional, mandatory or standard\n", 388 fname, wd, this); 389 exit(1); 390 } 391nextparam: 392 next_word(fp, wd); 393 if (wd == 0) { 394 compile += match; 395 if (compile && tp == NULL) 396 goto doneparam; 397 goto next; 398 } 399 if (eq(wd, "|")) { 400 if (nreqs == 0) { 401 fprintf(stderr, "%s: syntax error describing %s\n", 402 fname, this); 403 exit(1); 404 } 405 compile += match; 406 match = 1; 407 nreqs = 0; 408 goto nextparam; 409 } 410 if (eq(wd, "no-obj")) { 411 no_obj++; 412 goto nextparam; 413 } 414 if (eq(wd, "no-implicit-rule")) { 415 if (compilewith == 0) { 416 fprintf(stderr, "%s: alternate rule required when " 417 "\"no-implicit-rule\" is specified.\n", 418 fname); 419 } 420 imp_rule++; 421 goto nextparam; 422 } 423 if (eq(wd, "before-depend")) { 424 before_depend++; 425 goto nextparam; 426 } 427 if (eq(wd, "dependency")) { 428 next_quoted_word(fp, wd); 429 if (wd == 0) { 430 fprintf(stderr, 431 "%s: %s missing compile command string.\n", 432 fname, this); 433 exit(1); 434 } 435 depends = ns(wd); 436 goto nextparam; 437 } 438 if (eq(wd, "clean")) { 439 next_quoted_word(fp, wd); 440 if (wd == 0) { 441 fprintf(stderr, "%s: %s missing clean file list.\n", 442 fname, this); 443 exit(1); 444 } 445 clean = ns(wd); 446 goto nextparam; 447 } 448 if (eq(wd, "compile-with")) { 449 next_quoted_word(fp, wd); 450 if (wd == 0) { 451 fprintf(stderr, 452 "%s: %s missing compile command string.\n", 453 fname, this); 454 exit(1); 455 } 456 compilewith = ns(wd); 457 goto nextparam; 458 } 459 if (eq(wd, "warning")) { 460 next_quoted_word(fp, wd); 461 if (wd == 0) { 462 fprintf(stderr, 463 "%s: %s missing warning text string.\n", 464 fname, this); 465 exit(1); 466 } 467 warning = ns(wd); 468 goto nextparam; 469 } 470 nreqs++; 471 if (eq(wd, "local")) { 472 filetype = LOCAL; 473 goto nextparam; 474 } 475 if (eq(wd, "no-depend")) { 476 filetype = NODEPEND; 477 goto nextparam; 478 } 479 if (eq(wd, "profiling-routine")) { 480 filetype = PROFILING; 481 goto nextparam; 482 } 483 if (eq(wd, "nowerror")) { 484 nowerror = 1; 485 goto nextparam; 486 } 487 STAILQ_FOREACH(dp, &dtab, d_next) 488 if (eq(dp->d_name, wd)) { 489 dp->d_done |= DEVDONE; 490 goto nextparam; 491 } 492 if (mandatory) { 493 fprintf(stderr, "%s: mandatory device \"%s\" not found\n", 494 fname, wd); 495 exit(1); 496 } 497 if (std) { 498 fprintf(stderr, 499 "standard entry %s has a device keyword - %s!\n", 500 this, wd); 501 exit(1); 502 } 503 SLIST_FOREACH(op, &opt, op_next) 504 if (op->op_value == 0 && opteq(op->op_name, wd)) 505 goto nextparam; 506 match = 0; 507 goto nextparam; 508 509doneparam: 510 if (std == 0 && nreqs == 0) { 511 fprintf(stderr, "%s: what is %s optional on?\n", 512 fname, this); 513 exit(1); 514 } 515 516 if (wd) { 517 fprintf(stderr, "%s: syntax error describing %s\n", 518 fname, this); 519 exit(1); 520 } 521 if (filetype == PROFILING && profiling == 0) 522 goto next; 523 tp = new_fent(); 524 tp->f_fn = this; 525 tp->f_type = filetype; 526 if (imp_rule) 527 tp->f_flags |= NO_IMPLCT_RULE; 528 if (no_obj) 529 tp->f_flags |= NO_OBJ; 530 if (before_depend) 531 tp->f_flags |= BEFORE_DEPEND; 532 if (nowerror) 533 tp->f_flags |= NOWERROR; 534 tp->f_compilewith = compilewith; 535 tp->f_depends = depends; 536 tp->f_clean = clean; 537 tp->f_warn = warning; 538 goto next; 539} 540 541/* 542 * Read in the information about files used in making the system. 543 * Store it in the ftab linked list. 544 */ 545static void 546read_files(void) 547{ 548 char fname[MAXPATHLEN]; 549 struct files_name *nl, *tnl; 550 551 (void) snprintf(fname, sizeof(fname), "../../conf/files"); 552 read_file(fname); 553 (void) snprintf(fname, sizeof(fname), 554 "../../conf/files.%s", machinename); 555 read_file(fname); 556 for (nl = STAILQ_FIRST(&fntab); nl != NULL; nl = tnl) { 557 read_file(nl->f_name); 558 tnl = STAILQ_NEXT(nl, f_next); 559 free(nl->f_name); 560 free(nl); 561 } 562} 563 564static int 565opteq(const char *cp, const char *dp) 566{ 567 char c, d; 568 569 for (; ; cp++, dp++) { 570 if (*cp != *dp) { 571 c = isupper(*cp) ? tolower(*cp) : *cp; 572 d = isupper(*dp) ? tolower(*dp) : *dp; 573 if (c != d) 574 return (0); 575 } 576 if (*cp == 0) 577 return (1); 578 } 579} 580 581static void 582do_before_depend(FILE *fp) 583{ 584 struct file_list *tp; 585 int lpos, len; 586 587 fputs("BEFORE_DEPEND=", fp); 588 lpos = 15; 589 STAILQ_FOREACH(tp, &ftab, f_next) 590 if (tp->f_flags & BEFORE_DEPEND) { 591 len = strlen(tp->f_fn); 592 if ((len = 3 + len) + lpos > 72) { 593 lpos = 8; 594 fputs("\\\n\t", fp); 595 } 596 if (tp->f_flags & NO_IMPLCT_RULE) 597 fprintf(fp, "%s ", tp->f_fn); 598 else 599 fprintf(fp, "$S/%s ", tp->f_fn); 600 lpos += len + 1; 601 } 602 if (lpos != 8) 603 putc('\n', fp); 604} 605 606static void 607do_objs(FILE *fp) 608{ 609 struct file_list *tp; 610 int lpos, len; 611 char *cp, och, *sp; 612 613 fprintf(fp, "OBJS="); 614 lpos = 6; 615 STAILQ_FOREACH(tp, &ftab, f_next) { 616 if (tp->f_flags & NO_OBJ) 617 continue; 618 sp = tail(tp->f_fn); 619 cp = sp + (len = strlen(sp)) - 1; 620 och = *cp; 621 *cp = 'o'; 622 if (len + lpos > 72) { 623 lpos = 8; 624 fprintf(fp, "\\\n\t"); 625 } 626 fprintf(fp, "%s ", sp); 627 lpos += len + 1; 628 *cp = och; 629 } 630 if (lpos != 8) 631 putc('\n', fp); 632} 633 634static void 635do_xxfiles(char *tag, FILE *fp) 636{ 637 struct file_list *tp; 638 int lpos, len, slen; 639 char *suff, *SUFF; 640 641 if (tag[strlen(tag) - 1] == '\n') 642 tag[strlen(tag) - 1] = '\0'; 643 644 suff = ns(tag + 7); 645 SUFF = ns(suff); 646 raisestr(SUFF); 647 slen = strlen(suff); 648 649 fprintf(fp, "%sFILES=", SUFF); 650 lpos = 8; 651 STAILQ_FOREACH(tp, &ftab, f_next) 652 if (tp->f_type != NODEPEND) { 653 len = strlen(tp->f_fn); 654 if (tp->f_fn[len - slen - 1] != '.') 655 continue; 656 if (strcasecmp(&tp->f_fn[len - slen], suff) != 0) 657 continue; 658 if ((len = 3 + len) + lpos > 72) { 659 lpos = 8; 660 fputs("\\\n\t", fp); 661 } 662 if (tp->f_type != LOCAL) 663 fprintf(fp, "$S/%s ", tp->f_fn); 664 else 665 fprintf(fp, "%s ", tp->f_fn); 666 lpos += len + 1; 667 } 668 if (lpos != 8) 669 putc('\n', fp); 670} 671 672static char * 673tail(char *fn) 674{ 675 char *cp; 676 677 cp = rindex(fn, '/'); 678 if (cp == 0) 679 return (fn); 680 return (cp+1); 681} 682 683/* 684 * Create the makerules for each file 685 * which is part of the system. 686 */ 687static void 688do_rules(FILE *f) 689{ 690 char *cp, *np, och; 691 struct file_list *ftp; 692 char *compilewith; 693 char cmd[128]; 694 695 STAILQ_FOREACH(ftp, &ftab, f_next) { 696 if (ftp->f_warn) 697 fprintf(stderr, "WARNING: %s\n", ftp->f_warn); 698 cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1; 699 och = *cp; 700 if (ftp->f_flags & NO_IMPLCT_RULE) { 701 if (ftp->f_depends) 702 fprintf(f, "%s: %s\n", np, ftp->f_depends); 703 else 704 fprintf(f, "%s: \n", np); 705 } 706 else { 707 *cp = '\0'; 708 if (och == 'o') { 709 fprintf(f, "%so:\n\t-cp $S/%so .\n\n", 710 tail(np), np); 711 continue; 712 } 713 if (ftp->f_depends) { 714 fprintf(f, "%sln: $S/%s%c %s\n", tail(np), 715 np, och, ftp->f_depends); 716 fprintf(f, "\t${NORMAL_LINT}\n\n"); 717 fprintf(f, "%so: $S/%s%c %s\n", tail(np), 718 np, och, ftp->f_depends); 719 } 720 else { 721 fprintf(f, "%sln: $S/%s%c\n", tail(np), 722 np, och); 723 fprintf(f, "\t${NORMAL_LINT}\n\n"); 724 fprintf(f, "%so: $S/%s%c\n", tail(np), 725 np, och); 726 } 727 } 728 compilewith = ftp->f_compilewith; 729 if (compilewith == 0) { 730 const char *ftype = NULL; 731 732 switch (ftp->f_type) { 733 case NORMAL: 734 ftype = "NORMAL"; 735 break; 736 case PROFILING: 737 if (!profiling) 738 continue; 739 ftype = "PROFILE"; 740 break; 741 default: 742 fprintf(stderr, 743 "config: don't know rules for %s\n", np); 744 break; 745 } 746 snprintf(cmd, sizeof(cmd), 747 "${%s_%c%s}\n\t@${NORMAL_CTFCONVERT}", ftype, 748 toupper(och), 749 ftp->f_flags & NOWERROR ? "_NOWERROR" : ""); 750 compilewith = cmd; 751 } 752 *cp = och; 753 fprintf(f, "\t%s\n\n", compilewith); 754 } 755} 756 757static void 758do_clean(FILE *fp) 759{ 760 struct file_list *tp; 761 int lpos, len; 762 763 fputs("CLEAN=", fp); 764 lpos = 7; 765 STAILQ_FOREACH(tp, &ftab, f_next) 766 if (tp->f_clean) { 767 len = strlen(tp->f_clean); 768 if (len + lpos > 72) { 769 lpos = 8; 770 fputs("\\\n\t", fp); 771 } 772 fprintf(fp, "%s ", tp->f_clean); 773 lpos += len + 1; 774 } 775 if (lpos != 8) 776 putc('\n', fp); 777} 778 779char * 780raisestr(char *str) 781{ 782 char *cp = str; 783 784 while (*str) { 785 if (islower(*str)) 786 *str = toupper(*str); 787 str++; 788 } 789 return (cp); 790} 791