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