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