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 #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 #include <sys/param.h> 44 45 #include <cerrno> 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 <string> 53 #include <unordered_map> 54 55 #include "y.tab.h" 56 #include "config.h" 57 #include "configvers.h" 58 59 typedef std::unordered_map<std::string, std::string> env_map; 60 61 static char *tail(char *); 62 static void do_clean(FILE *); 63 static void do_rules(FILE *); 64 static void do_xxfiles(char *, FILE *); 65 static void do_objs(FILE *); 66 static void do_before_depend(FILE *); 67 static void read_files(void); 68 static void sanitize_envline(char *result, const char *src); 69 static bool preprocess(char *line, char *result); 70 static void process_into_file(char *line, FILE *ofp); 71 static int process_into_map(char *line, env_map &emap); 72 static void dump_map(env_map &emap, FILE *ofp); 73 74 static void __printflike(1, 2) 75 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("Makefile.new", "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 int 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 if (s == NULL) 280 return (EINVAL); 281 *s = '\0'; 282 emap[result] = s + 1; 283 } 284 285 return (0); 286 } 287 288 static void 289 dump_map(env_map &emap, FILE *ofp) 290 { 291 292 for (auto iter : emap) { 293 fprintf(ofp, "\"%s=%s\\0\"\n", iter.first.c_str(), 294 iter.second.c_str()); 295 } 296 } 297 298 /* 299 * Build hints.c from the skeleton 300 */ 301 void 302 makehints(void) 303 { 304 FILE *ifp, *ofp; 305 env_map emap; 306 char line[BUFSIZ]; 307 struct hint *hint; 308 309 ofp = fopen(path("hints.c.new"), "w"); 310 if (ofp == NULL) 311 err(1, "%s", path("hints.c.new")); 312 fprintf(ofp, "#include <sys/types.h>\n"); 313 fprintf(ofp, "#include <sys/systm.h>\n"); 314 fprintf(ofp, "\n"); 315 /* 316 * Write out hintmode for older kernels. Remove when config(8) major 317 * version rolls over. 318 */ 319 if (versreq <= CONFIGVERS_ENVMODE_REQ) 320 fprintf(ofp, "int hintmode = %d;\n", 321 !STAILQ_EMPTY(&hints) ? 1 : 0); 322 fprintf(ofp, "char static_hints[] = {\n"); 323 STAILQ_FOREACH(hint, &hints, hint_next) { 324 ifp = fopen(hint->hint_name, "r"); 325 if (ifp == NULL) 326 err(1, "%s", hint->hint_name); 327 while (fgets(line, BUFSIZ, ifp) != NULL) { 328 if (process_into_map(line, emap) != 0) 329 errout("%s: malformed line: %s\n", 330 hint->hint_name, line); 331 } 332 dump_map(emap, ofp); 333 fclose(ifp); 334 } 335 fprintf(ofp, "\"\\0\"\n};\n"); 336 fclose(ofp); 337 moveifchanged("hints.c.new", "hints.c"); 338 } 339 340 /* 341 * Build env.c from the skeleton 342 */ 343 void 344 makeenv(void) 345 { 346 FILE *ifp, *ofp; 347 env_map emap; 348 char line[BUFSIZ]; 349 struct envvar *envvar; 350 351 ofp = fopen(path("env.c.new"), "w"); 352 if (ofp == NULL) 353 err(1, "%s", path("env.c.new")); 354 fprintf(ofp, "#include <sys/types.h>\n"); 355 fprintf(ofp, "#include <sys/systm.h>\n"); 356 fprintf(ofp, "\n"); 357 /* 358 * Write out envmode for older kernels. Remove when config(8) major 359 * version rolls over. 360 */ 361 if (versreq <= CONFIGVERS_ENVMODE_REQ) 362 fprintf(ofp, "int envmode = %d;\n", 363 !STAILQ_EMPTY(&envvars) ? 1 : 0); 364 fprintf(ofp, "char static_env[] = {\n"); 365 STAILQ_FOREACH(envvar, &envvars, envvar_next) { 366 if (envvar->env_is_file) { 367 ifp = fopen(envvar->env_str, "r"); 368 if (ifp == NULL) 369 err(1, "%s", envvar->env_str); 370 while (fgets(line, BUFSIZ, ifp) != NULL) { 371 if (process_into_map(line, emap) != 0) 372 errout("%s: malformed line: %s\n", 373 envvar->env_str, line); 374 } 375 dump_map(emap, ofp); 376 fclose(ifp); 377 } else 378 process_into_file(envvar->env_str, ofp); 379 } 380 fprintf(ofp, "\"\\0\"\n};\n"); 381 fclose(ofp); 382 moveifchanged("env.c.new", "env.c"); 383 } 384 385 static void 386 read_file(char *fname) 387 { 388 char ifname[MAXPATHLEN]; 389 FILE *fp; 390 struct file_list *tp; 391 struct device *dp; 392 struct opt *op; 393 configword wd; 394 char *rfile, *compilewith, *depends, *clean, *warning; 395 const char *objprefix; 396 int compile, match, nreqs, std, filetype, negate, 397 imp_rule, no_ctfconvert, no_obj, before_depend, nowerror; 398 399 fp = fopen(fname, "r"); 400 if (fp == NULL) 401 err(1, "%s", fname); 402 next: 403 /* 404 * include "filename" 405 * filename [ standard | optional ] 406 * [ dev* [ | dev* ... ] | [ no-obj ] 407 * [ compile-with "compile rule" [no-implicit-rule] ] 408 * [ dependency "dependency-list"] [ before-depend ] 409 * [ clean "file-list"] [ warning "text warning" ] 410 * [ obj-prefix "file prefix"] 411 * [ nowerror ] [ local ] 412 */ 413 wd = get_word(fp); 414 if (wd.eof()) { 415 (void) fclose(fp); 416 return; 417 } 418 if (wd.eol()) 419 goto next; 420 if (wd[0] == '#') 421 { 422 while (!(wd = get_word(fp)).eof() && !wd.eol()) 423 ; 424 goto next; 425 } 426 if (eq(wd, "include")) { 427 wd = get_quoted_word(fp); 428 if (wd.eof() || wd.eol()) 429 errout("%s: missing include filename.\n", fname); 430 (void) snprintf(ifname, sizeof(ifname), "../../%s", 431 wd->c_str()); 432 read_file(ifname); 433 while (!(wd = get_word(fp)).eof() && !wd.eol()) 434 ; 435 goto next; 436 } 437 rfile = ns(wd); 438 wd = get_word(fp); 439 if (wd.eof()) 440 return; 441 if (wd.eol()) 442 errout("%s: No type for %s.\n", fname, rfile); 443 tp = fl_lookup(rfile); 444 compile = 0; 445 match = 1; 446 nreqs = 0; 447 compilewith = NULL; 448 depends = NULL; 449 clean = NULL; 450 warning = NULL; 451 std = 0; 452 imp_rule = 0; 453 no_ctfconvert = 0; 454 no_obj = 0; 455 before_depend = 0; 456 nowerror = 0; 457 negate = 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->c_str(), rfile); 465 for (wd = get_word(fp); !wd.eol(); wd = get_word(fp)) { 466 if (wd.eof()) 467 return; 468 if (eq(wd, "!")) { 469 negate = 1; 470 continue; 471 } 472 if (eq(wd, "|")) { 473 if (nreqs == 0) 474 errout("%s: syntax error describing %s\n", 475 fname, rfile); 476 compile += match; 477 match = 1; 478 nreqs = 0; 479 continue; 480 } 481 if (eq(wd, "no-ctfconvert")) { 482 no_ctfconvert++; 483 continue; 484 } 485 if (eq(wd, "no-obj")) { 486 no_obj++; 487 continue; 488 } 489 if (eq(wd, "no-implicit-rule")) { 490 if (compilewith == NULL) 491 errout("%s: alternate rule required when " 492 "\"no-implicit-rule\" is specified for" 493 " %s.\n", 494 fname, rfile); 495 imp_rule++; 496 continue; 497 } 498 if (eq(wd, "before-depend")) { 499 before_depend++; 500 continue; 501 } 502 if (eq(wd, "dependency")) { 503 wd = get_quoted_word(fp); 504 if (wd.eof() || wd.eol()) 505 errout("%s: %s missing dependency string.\n", 506 fname, rfile); 507 depends = ns(wd); 508 continue; 509 } 510 if (eq(wd, "clean")) { 511 wd = get_quoted_word(fp); 512 if (wd.eof() || wd.eol()) 513 errout("%s: %s missing clean file list.\n", 514 fname, rfile); 515 clean = ns(wd); 516 continue; 517 } 518 if (eq(wd, "compile-with")) { 519 wd = get_quoted_word(fp); 520 if (wd.eof() || wd.eol()) 521 errout("%s: %s missing compile command string.\n", 522 fname, rfile); 523 compilewith = ns(wd); 524 continue; 525 } 526 if (eq(wd, "warning")) { 527 wd = get_quoted_word(fp); 528 if (wd.eof() || wd.eol()) 529 errout("%s: %s missing warning text string.\n", 530 fname, rfile); 531 warning = ns(wd); 532 continue; 533 } 534 if (eq(wd, "obj-prefix")) { 535 wd = get_quoted_word(fp); 536 if (wd.eof() || wd.eol()) 537 errout("%s: %s missing object prefix string.\n", 538 fname, rfile); 539 objprefix = ns(wd); 540 continue; 541 } 542 if (eq(wd, "nowerror")) { 543 nowerror = 1; 544 continue; 545 } 546 if (eq(wd, "local")) { 547 filetype = LOCAL; 548 continue; 549 } 550 if (eq(wd, "no-depend")) { 551 filetype = NODEPEND; 552 continue; 553 } 554 nreqs++; 555 if (std) 556 errout("standard entry %s has optional inclusion specifier %s!\n", 557 rfile, wd->c_str()); 558 STAILQ_FOREACH(dp, &dtab, d_next) 559 if (eq(dp->d_name, wd)) { 560 if (negate) 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 (negate) 570 match = 0; 571 goto nextparam; 572 } 573 match &= negate; 574 nextparam:; 575 negate = 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, rfile); 582 tp = new_fent(); 583 tp->f_fn = rfile; 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_ctfconvert) 592 tp->f_flags |= NO_CTFCONVERT; 593 if (no_obj) 594 tp->f_flags |= NO_OBJ | NO_CTFCONVERT; 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 */ 612 static void 613 read_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 631 static void 632 do_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) + strlen(tp->f_srcprefix); 642 if (len + lpos > 72) { 643 lpos = 8; 644 fputs("\\\n\t", fp); 645 } 646 if (tp->f_flags & NO_IMPLCT_RULE) 647 lpos += fprintf(fp, "%s ", tp->f_fn); 648 else 649 lpos += fprintf(fp, "%s%s ", tp->f_srcprefix, 650 tp->f_fn); 651 } 652 if (lpos != 8) 653 putc('\n', fp); 654 } 655 656 static void 657 do_objs(FILE *fp) 658 { 659 struct file_list *tp; 660 int lpos, len; 661 char *cp, och, *sp; 662 663 fprintf(fp, "OBJS="); 664 lpos = 6; 665 STAILQ_FOREACH(tp, &ftab, f_next) { 666 if (tp->f_flags & NO_OBJ) 667 continue; 668 sp = tail(tp->f_fn); 669 cp = sp + (len = strlen(sp)) - 1; 670 och = *cp; 671 *cp = 'o'; 672 len += strlen(tp->f_objprefix); 673 if (len + lpos > 72) { 674 lpos = 8; 675 fprintf(fp, "\\\n\t"); 676 } 677 fprintf(fp, "%s%s ", tp->f_objprefix, sp); 678 lpos += len + 1; 679 *cp = och; 680 } 681 if (lpos != 8) 682 putc('\n', fp); 683 } 684 685 static void 686 do_xxfiles(char *tag, FILE *fp) 687 { 688 struct file_list *tp; 689 int lpos, len, slen; 690 char *suff, *SUFF; 691 692 if (tag[strlen(tag) - 1] == '\n') 693 tag[strlen(tag) - 1] = '\0'; 694 695 suff = ns(tag + 7); 696 SUFF = ns(suff); 697 raisestr(SUFF); 698 slen = strlen(suff); 699 700 fprintf(fp, "%sFILES=", SUFF); 701 free(SUFF); 702 lpos = 8; 703 STAILQ_FOREACH(tp, &ftab, f_next) 704 if (tp->f_type != NODEPEND) { 705 len = strlen(tp->f_fn); 706 if (tp->f_fn[len - slen - 1] != '.') 707 continue; 708 if (strcasecmp(&tp->f_fn[len - slen], suff) != 0) 709 continue; 710 if (len + strlen(tp->f_srcprefix) + lpos > 72) { 711 lpos = 8; 712 fputs("\\\n\t", fp); 713 } 714 lpos += fprintf(fp, "%s%s ", tp->f_srcprefix, tp->f_fn); 715 } 716 free(suff); 717 if (lpos != 8) 718 putc('\n', fp); 719 } 720 721 static char * 722 tail(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 */ 736 static void 737 do_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%so: %s%s%c %s\n", 766 ftp->f_objprefix, tail(np), 767 ftp->f_srcprefix, np, och, 768 ftp->f_depends); 769 } 770 else { 771 fprintf(f, "%s%so: %s%s%c\n", 772 ftp->f_objprefix, tail(np), 773 ftp->f_srcprefix, np, och); 774 } 775 } 776 compilewith = ftp->f_compilewith; 777 if (compilewith == NULL) { 778 const char *ftype = NULL; 779 780 switch (ftp->f_type) { 781 case NORMAL: 782 ftype = "NORMAL"; 783 break; 784 default: 785 fprintf(stderr, 786 "config: don't know rules for %s\n", np); 787 break; 788 } 789 snprintf(cmd, sizeof(cmd), 790 "${%s_%c%s}", ftype, 791 toupper(och), 792 ftp->f_flags & NOWERROR ? "_NOWERROR" : ""); 793 compilewith = cmd; 794 } 795 *cp = och; 796 if (strlen(ftp->f_objprefix)) 797 fprintf(f, "\t%s %s%s\n", compilewith, 798 ftp->f_srcprefix, np); 799 else 800 fprintf(f, "\t%s\n", compilewith); 801 802 if (!(ftp->f_flags & NO_CTFCONVERT)) 803 fprintf(f, "\t${NORMAL_CTFCONVERT}\n\n"); 804 else 805 fprintf(f, "\n"); 806 } 807 } 808 809 static void 810 do_clean(FILE *fp) 811 { 812 struct file_list *tp; 813 int lpos, len; 814 815 fputs("CLEAN=", fp); 816 lpos = 7; 817 STAILQ_FOREACH(tp, &ftab, f_next) 818 if (tp->f_clean) { 819 len = strlen(tp->f_clean); 820 if (len + lpos > 72) { 821 lpos = 8; 822 fputs("\\\n\t", fp); 823 } 824 fprintf(fp, "%s ", tp->f_clean); 825 lpos += len + 1; 826 } 827 if (lpos != 8) 828 putc('\n', fp); 829 } 830 831 char * 832 raisestr(char *str) 833 { 834 char *cp = str; 835 836 while (*str) { 837 if (islower(*str)) 838 *str = toupper(*str); 839 str++; 840 } 841 return (cp); 842 } 843