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