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