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