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