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