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