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