1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2017 RackTop Systems. 26 */ 27 28 /* 29 * read.c 30 * 31 * This file contains the makefile reader. 32 */ 33 34 /* 35 * Included files 36 */ 37 #include <mk/defs.h> 38 #include <mksh/dosys.h> /* sh_command2string() */ 39 #include <mksh/macro.h> /* expand_value() */ 40 #include <mksh/misc.h> /* retmem() */ 41 #include <stdarg.h> /* va_list, va_start(), va_end() */ 42 #include <libintl.h> 43 44 /* 45 * Defined macros 46 */ 47 48 /* 49 * typedefs & structs 50 */ 51 52 /* 53 * Static variables 54 */ 55 static Boolean built_last_make_run_seen; 56 57 /* 58 * File table of contents 59 */ 60 static Name_vector enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names); 61 extern Name normalize_name(register wchar_t *name_string, register int length); 62 static void read_suffixes_list(register Name_vector depes); 63 static void make_relative(wchar_t *to, wchar_t *result); 64 static void print_rule(register Cmd_line command); 65 static void sh_transform(Name *name, Name *value); 66 67 68 /* 69 * enter_name(string, tail_present, string_start, string_end, 70 * current_names, extra_names, target_group_seen) 71 * 72 * Take one string and enter it as a name. The string is passed in 73 * two parts. A make string and possibly a C string to append to it. 74 * The result is stuffed in the vector current_names. 75 * extra_names points to a vector that is used if current_names overflows. 76 * This is allocad in the calling routine. 77 * Here we handle the "lib.a[members]" notation. 78 * 79 * Return value: 80 * The name vector that was used 81 * 82 * Parameters: 83 * tail_present Indicates if both C and make string was passed 84 * string_start C string 85 * string_end Pointer to char after last in C string 86 * string make style string with head of name 87 * current_names Vector to deposit the name in 88 * extra_names Where to get next name vector if we run out 89 * target_group_seen Pointer to boolean that is set if "+" is seen 90 * 91 * Global variables used: 92 * makefile_type When we read a report file we normalize paths 93 * plus Points to the Name "+" 94 */ 95 96 Name_vector 97 enter_name(String string, Boolean tail_present, register wchar_t *string_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names, Boolean *target_group_seen) 98 { 99 Name name; 100 register wchar_t *cp; 101 wchar_t ch; 102 103 /* If we were passed a separate tail of the name we append it to the */ 104 /* make string with the rest of it */ 105 if (tail_present) { 106 append_string(string_start, string, string_end - string_start); 107 string_start = string->buffer.start; 108 string_end = string->text.p; 109 } 110 ch = *string_end; 111 *string_end = (int) nul_char; 112 /* 113 * Check if there are any ( or [ that are not prefixed with $. 114 * If there are, we have to deal with the lib.a(members) format. 115 */ 116 for (cp = (wchar_t *) wcschr(string_start, (int) parenleft_char); 117 cp != NULL; 118 cp = (wchar_t *) wcschr(cp + 1, (int) parenleft_char)) { 119 if (*(cp - 1) != (int) dollar_char) { 120 *string_end = ch; 121 return enter_member_name(string_start, 122 cp, 123 string_end, 124 current_names, 125 extra_names); 126 } 127 } 128 *string_end = ch; 129 130 if (makefile_type == reading_cpp_file) { 131 /* Remove extra ../ constructs if we are reading from a report file */ 132 name = normalize_name(string_start, string_end - string_start); 133 } else { 134 /* 135 * /tolik, fix bug 1197477/ 136 * Normalize every target name before entering. 137 * ..//obj/a.o and ../obj//a.o are not two different targets. 138 * There is only one target ../obj/a.o 139 */ 140 /*name = GETNAME(string_start, string_end - string_start);*/ 141 name = normalize_name(string_start, string_end - string_start); 142 } 143 144 /* Internalize the name. Detect the name "+" (target group here) */ 145 if(current_names->used != 0 && current_names->names[current_names->used-1] == plus) { 146 if(name == plus) { 147 return current_names; 148 } 149 } 150 /* If the current_names vector is full we patch in the one from */ 151 /* extra_names */ 152 if (current_names->used == VSIZEOF(current_names->names)) { 153 if (current_names->next != NULL) { 154 current_names = current_names->next; 155 } else { 156 current_names->next = *extra_names; 157 *extra_names = NULL; 158 current_names = current_names->next; 159 current_names->used = 0; 160 current_names->next = NULL; 161 } 162 } 163 current_names->target_group[current_names->used] = NULL; 164 current_names->names[current_names->used++] = name; 165 if (name == plus) { 166 *target_group_seen = true; 167 } 168 if (tail_present && string->free_after_use) { 169 retmem(string->buffer.start); 170 } 171 return current_names; 172 } 173 174 /* 175 * enter_member_name(lib_start, member_start, string_end, 176 * current_names, extra_names) 177 * 178 * A string has been found to contain member names. 179 * (The "lib.a[members]" and "lib.a(members)" notation) 180 * Handle it pretty much as enter_name() does for simple names. 181 * 182 * Return value: 183 * The name vector that was used 184 * 185 * Parameters: 186 * lib_start Points to the of start of "lib.a(member.o)" 187 * member_start Points to "member.o" from above string. 188 * string_end Points to char after last of above string. 189 * current_names Vector to deposit the name in 190 * extra_names Where to get next name vector if we run out 191 * 192 * Global variables used: 193 */ 194 static Name_vector 195 enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names) 196 { 197 register Boolean entry = false; 198 wchar_t buffer[STRING_BUFFER_LENGTH]; 199 Name lib; 200 Name member; 201 Name name; 202 Property prop; 203 wchar_t *memberp; 204 wchar_t *q; 205 register int paren_count; 206 register Boolean has_dollar; 207 register wchar_t *cq; 208 Name long_member_name = NULL; 209 210 /* Internalize the name of the library */ 211 lib = GETNAME(lib_start, member_start - lib_start); 212 lib->is_member = true; 213 member_start++; 214 if (*member_start == (int) parenleft_char) { 215 /* This is really the "lib.a((entries))" format */ 216 entry = true; 217 member_start++; 218 } 219 /* Move the library name to the buffer where we intend to build the */ 220 /* "lib.a(member)" for each member */ 221 (void) wcsncpy(buffer, lib_start, member_start - lib_start); 222 memberp = buffer + (member_start-lib_start); 223 while (1) { 224 long_member_name = NULL; 225 /* Skip leading spaces */ 226 for (; 227 (member_start < string_end) && iswspace(*member_start); 228 member_start++); 229 /* Find the end of the member name. Allow nested (). Detect $*/ 230 for (cq = memberp, has_dollar = false, paren_count = 0; 231 (member_start < string_end) && 232 ((*member_start != (int) parenright_char) || 233 (paren_count > 0)) && 234 !iswspace(*member_start); 235 *cq++ = *member_start++) { 236 switch (*member_start) { 237 case parenleft_char: 238 paren_count++; 239 break; 240 case parenright_char: 241 paren_count--; 242 break; 243 case dollar_char: 244 has_dollar = true; 245 } 246 } 247 /* Internalize the member name */ 248 member = GETNAME(memberp, cq - memberp); 249 *cq = 0; 250 if ((q = (wchar_t *) wcsrchr(memberp, (int) slash_char)) == NULL) { 251 q = memberp; 252 } 253 if ((cq - q > (int) ar_member_name_len) && 254 !has_dollar) { 255 *cq++ = (int) parenright_char; 256 if (entry) { 257 *cq++ = (int) parenright_char; 258 } 259 long_member_name = GETNAME(buffer, cq - buffer); 260 cq = q + (int) ar_member_name_len; 261 } 262 *cq++ = (int) parenright_char; 263 if (entry) { 264 *cq++ = (int) parenright_char; 265 } 266 /* Internalize the "lib.a(member)" notation for this member */ 267 name = GETNAME(buffer, cq - buffer); 268 name->is_member = lib->is_member; 269 if (long_member_name != NULL) { 270 prop = append_prop(name, long_member_name_prop); 271 name->has_long_member_name = true; 272 prop->body.long_member_name.member_name = 273 long_member_name; 274 } 275 /* And add the member prop */ 276 prop = append_prop(name, member_prop); 277 prop->body.member.library = lib; 278 if (entry) { 279 /* "lib.a((entry))" notation */ 280 prop->body.member.entry = member; 281 prop->body.member.member = NULL; 282 } else { 283 /* "lib.a(member)" Notation */ 284 prop->body.member.entry = NULL; 285 prop->body.member.member = member; 286 } 287 /* Handle overflow of current_names */ 288 if (current_names->used == VSIZEOF(current_names->names)) { 289 if (current_names->next != NULL) { 290 current_names = current_names->next; 291 } else { 292 if (*extra_names == NULL) { 293 current_names = 294 current_names->next = 295 ALLOC(Name_vector); 296 } else { 297 current_names = 298 current_names->next = 299 *extra_names; 300 *extra_names = NULL; 301 } 302 current_names->used = 0; 303 current_names->next = NULL; 304 } 305 } 306 current_names->target_group[current_names->used] = NULL; 307 current_names->names[current_names->used++] = name; 308 while (iswspace(*member_start)) { 309 member_start++; 310 } 311 /* Check if there are more members */ 312 if ((*member_start == (int) parenright_char) || 313 (member_start >= string_end)) { 314 return current_names; 315 } 316 } 317 /* NOTREACHED */ 318 } 319 320 /* 321 * normalize_name(name_string, length) 322 * 323 * Take a namestring and remove redundant ../, // and ./ constructs 324 * 325 * Return value: 326 * The normalized name 327 * 328 * Parameters: 329 * name_string Path string to normalize 330 * length Length of that string 331 * 332 * Global variables used: 333 * dot The Name ".", compared against 334 * dotdot The Name "..", compared against 335 */ 336 Name 337 normalize_name(register wchar_t *name_string, register int length) 338 { 339 static Name dotdot; 340 register wchar_t *string = ALLOC_WC(length + 1); 341 register wchar_t *string2; 342 register wchar_t *cdp; 343 wchar_t *current_component; 344 Name name; 345 register int count; 346 347 if (dotdot == NULL) { 348 MBSTOWCS(wcs_buffer, ".."); 349 dotdot = GETNAME(wcs_buffer, FIND_LENGTH); 350 } 351 352 /* 353 * Copy string removing ./ and //. 354 * First strip leading ./ 355 */ 356 while ((length > 1) && 357 (name_string[0] == (int) period_char) && 358 (name_string[1] == (int) slash_char)) { 359 name_string += 2; 360 length -= 2; 361 while ((length > 0) && (name_string[0] == (int) slash_char)) { 362 name_string++; 363 length--; 364 } 365 } 366 /* Then copy the rest of the string removing /./ & // */ 367 cdp = string; 368 while (length > 0) { 369 if (((length > 2) && 370 (name_string[0] == (int) slash_char) && 371 (name_string[1] == (int) period_char) && 372 (name_string[2] == (int) slash_char)) || 373 ((length == 2) && 374 (name_string[0] == (int) slash_char) && 375 (name_string[1] == (int) period_char))) { 376 name_string += 2; 377 length -= 2; 378 continue; 379 } 380 if ((length > 1) && 381 (name_string[0] == (int) slash_char) && 382 (name_string[1] == (int) slash_char)) { 383 name_string++; 384 length--; 385 continue; 386 } 387 *cdp++ = *name_string++; 388 length--; 389 } 390 *cdp = (int) nul_char; 391 /* 392 * Now scan for <name>/../ and remove such combinations iff <name> 393 * is not another .. 394 * Each time something is removed, the whole process is restarted. 395 */ 396 removed_one: 397 name_string = string; 398 string2 = name_string; /*save for free*/ 399 current_component = 400 cdp = 401 string = 402 ALLOC_WC((length = wcslen(name_string)) + 1); 403 while (length > 0) { 404 if (((length > 3) && 405 (name_string[0] == (int) slash_char) && 406 (name_string[1] == (int) period_char) && 407 (name_string[2] == (int) period_char) && 408 (name_string[3] == (int) slash_char)) || 409 ((length == 3) && 410 (name_string[0] == (int) slash_char) && 411 (name_string[1] == (int) period_char) && 412 (name_string[2] == (int) period_char))) { 413 /* Positioned on the / that starts a /.. sequence */ 414 if (((count = cdp - current_component) != 0) && 415 (exists(name = GETNAME(string, cdp - string)) > file_doesnt_exist) && 416 (!name->stat.is_sym_link)) { 417 name = GETNAME(current_component, count); 418 if(name != dotdot) { 419 cdp = current_component; 420 name_string += 3; 421 length -= 3; 422 if (length > 0) { 423 name_string++; /* skip slash */ 424 length--; 425 while (length > 0) { 426 *cdp++ = *name_string++; 427 length--; 428 } 429 } 430 *cdp = (int) nul_char; 431 retmem(string2); 432 goto removed_one; 433 } 434 } 435 } 436 if ((*cdp++ = *name_string++) == (int) slash_char) { 437 current_component = cdp; 438 } 439 length--; 440 } 441 *cdp = (int) nul_char; 442 if (string[0] == (int) nul_char) { 443 name = dot; 444 } else { 445 name = GETNAME(string, FIND_LENGTH); 446 } 447 retmem(string); 448 retmem(string2); 449 return name; 450 } 451 452 /* 453 * find_target_groups(target_list) 454 * 455 * If a "+" was seen when the target list was scanned we need to extract 456 * the groups. Each target in the name vector that is a member of a 457 * group gets a pointer to a chain of all the members stuffed in its 458 * target_group vector slot 459 * 460 * Parameters: 461 * target_list The list of targets that contains "+" 462 * 463 * Global variables used: 464 * plus The Name "+", compared against 465 */ 466 Chain 467 find_target_groups(register Name_vector target_list, register int i, Boolean reset) 468 { 469 static Chain target_group = NULL; 470 static Chain tail_target_group = NULL; 471 static Name *next; 472 static Boolean clear_target_group = false; 473 474 if (reset) { 475 target_group = NULL; 476 tail_target_group = NULL; 477 clear_target_group = false; 478 } 479 480 /* Scan the list of targets */ 481 /* If the previous target terminated a group */ 482 /* we flush the pointer to that member chain */ 483 if (clear_target_group) { 484 clear_target_group = false; 485 target_group = NULL; 486 } 487 /* Pick up a pointer to the cell with */ 488 /* the next target */ 489 if (i + 1 != target_list->used) { 490 next = &target_list->names[i + 1]; 491 } else { 492 next = (target_list->next != NULL) ? 493 &target_list->next->names[0] : NULL; 494 } 495 /* We have four states here : 496 * 0: No target group started and next element is not "+" 497 * This is not interesting. 498 * 1: A target group is being built and the next element 499 * is not "+". This terminates the group. 500 * 2: No target group started and the next member is "+" 501 * This is the first target in a group. 502 * 3: A target group started and the next member is a "+" 503 * The group continues. 504 */ 505 switch ((target_group ? 1 : 0) + 506 (next && (*next == plus) ? 507 2 : 0)) { 508 case 0: /* Not target_group */ 509 break; 510 case 1: /* Last group member */ 511 /* We need to keep this pointer so */ 512 /* we can stuff it for last member */ 513 clear_target_group = true; 514 /* fall into */ 515 case 3: /* Middle group member */ 516 /* Add this target to the */ 517 /* current chain */ 518 tail_target_group->next = ALLOC(Chain); 519 tail_target_group = tail_target_group->next; 520 tail_target_group->next = NULL; 521 tail_target_group->name = target_list->names[i]; 522 break; 523 case 2: /* First group member */ 524 /* Start a new chain */ 525 target_group = tail_target_group = ALLOC(Chain); 526 target_group->next = NULL; 527 target_group->name = target_list->names[i]; 528 break; 529 } 530 /* Stuff the current chain, if any, in the */ 531 /* targets group slot */ 532 target_list->target_group[i] = target_group; 533 if ((next != NULL) && 534 (*next == plus)) { 535 *next = NULL; 536 } 537 return (tail_target_group); 538 } 539 540 /* 541 * enter_dependencies(target, target_group, depes, command, separator) 542 * 543 * Take one target and a list of dependencies and process the whole thing. 544 * The target might be special in some sense in which case that is handled 545 * 546 * Parameters: 547 * target The target we want to enter 548 * target_group Non-NULL if target is part of a group this time 549 * depes A list of dependencies for the target 550 * command The command the target should be entered with 551 * separator Indicates if this is a ":" or a "::" rule 552 * 553 * Static variables used: 554 * built_last_make_run_seen If the previous target was 555 * .BUILT_LAST_MAKE_RUN we say to rewrite 556 * the state file later on 557 * 558 * Global variables used: 559 * command_changed Set to indicate if .make.state needs rewriting 560 * default_target_to_build Set to the target if reading makefile 561 * and this is the first regular target 562 * force The Name " FORCE", used with "::" targets 563 * makefile_type We do different things for makefile vs. report 564 * not_auto The Name ".NOT_AUTO", compared against 565 * recursive_name The Name ".RECURSIVE", compared against 566 * temp_file_number Used to figure out when to clear stale 567 * automatic dependencies 568 * trace_reader Indicates that we should echo stuff we read 569 */ 570 void 571 enter_dependencies(register Name target, Chain target_group, register Name_vector depes, register Cmd_line command, register Separator separator) 572 { 573 register int i; 574 register Property line; 575 Name name; 576 Name directory; 577 wchar_t *namep; 578 char *mb_namep; 579 Dependency dp; 580 Dependency *dpp; 581 Property line2; 582 wchar_t relative[MAXPATHLEN]; 583 register int recursive_state; 584 Boolean register_as_auto; 585 Boolean not_auto_found; 586 char *slash; 587 Wstring depstr; 588 589 /* Check if this is a .RECURSIVE line */ 590 if ((depes->used >= 3) && 591 (depes->names[0] == recursive_name)) { 592 target->has_recursive_dependency = true; 593 depes->names[0] = NULL; 594 recursive_state = 0; 595 dp = NULL; 596 dpp = &dp; 597 /* Read the dependencies. They are "<directory> <target-made>*/ 598 /* <makefile>*" */ 599 for (; depes != NULL; depes = depes->next) { 600 for (i = 0; i < depes->used; i++) { 601 if (depes->names[i] != NULL) { 602 switch (recursive_state++) { 603 case 0: /* Directory */ 604 { 605 depstr.init(depes->names[i]); 606 make_relative(depstr.get_string(), 607 relative); 608 directory = 609 GETNAME(relative, 610 FIND_LENGTH); 611 } 612 break; 613 case 1: /* Target */ 614 name = depes->names[i]; 615 break; 616 default: /* Makefiles */ 617 *dpp = ALLOC(Dependency); 618 (*dpp)->next = NULL; 619 (*dpp)->name = depes->names[i]; 620 (*dpp)->automatic = false; 621 (*dpp)->stale = false; 622 (*dpp)->built = false; 623 dpp = &((*dpp)->next); 624 break; 625 } 626 } 627 } 628 } 629 /* Check if this recursion already has been reported else */ 630 /* enter the recursive prop for the target */ 631 /* The has_built flag is used to tell if this .RECURSIVE */ 632 /* was discovered from this run (read from a tmp file) */ 633 /* or was from discovered from the original .make.state */ 634 /* file */ 635 for (line = get_prop(target->prop, recursive_prop); 636 line != NULL; 637 line = get_prop(line->next, recursive_prop)) { 638 if ((line->body.recursive.directory == directory) && 639 (line->body.recursive.target == name)) { 640 line->body.recursive.makefiles = dp; 641 line->body.recursive.has_built = 642 (Boolean) 643 (makefile_type == reading_cpp_file); 644 return; 645 } 646 } 647 line2 = append_prop(target, recursive_prop); 648 line2->body.recursive.directory = directory; 649 line2->body.recursive.target = name; 650 line2->body.recursive.makefiles = dp; 651 line2->body.recursive.has_built = 652 (Boolean) (makefile_type == reading_cpp_file); 653 line2->body.recursive.in_depinfo = false; 654 return; 655 } 656 /* If this is the first target that doesnt start with a "." in the */ 657 /* makefile we remember that */ 658 Wstring tstr(target); 659 wchar_t * wcb = tstr.get_string(); 660 if ((makefile_type == reading_makefile) && 661 (default_target_to_build == NULL) && 662 ((wcb[0] != (int) period_char) || 663 wcschr(wcb, (int) slash_char))) { 664 665 /* BID 1181577: $(EMPTY_MACRO) + $(EMPTY_MACRO): 666 ** The target with empty name cannot be default_target_to_build 667 */ 668 if (target->hash.length != 0) 669 default_target_to_build = target; 670 } 671 /* Check if the line is ":" or "::" */ 672 if (makefile_type == reading_makefile) { 673 if (target->colons == no_colon) { 674 target->colons = separator; 675 } else { 676 if (target->colons != separator) { 677 fatal_reader(gettext(":/:: conflict for target `%s'"), 678 target->string_mb); 679 } 680 } 681 if (target->colons == two_colon) { 682 if (depes->used == 0) { 683 /* If this is a "::" type line with no */ 684 /* dependencies we add one "FRC" type */ 685 /* dependency for free */ 686 depes->used = 1; /* Force :: targets with no 687 * depes to always run */ 688 depes->names[0] = force; 689 } 690 /* Do not delete "::" type targets when interrupted */ 691 target->stat.is_precious = true; 692 /* 693 * Build a synthetic target "<number>%target" 694 * for "target". 695 */ 696 mb_namep = getmem((int) (strlen(target->string_mb) + 10)); 697 namep = ALLOC_WC((int) (target->hash.length + 10)); 698 slash = strrchr(target->string_mb, (int) slash_char); 699 if (slash == NULL) { 700 (void) sprintf(mb_namep, 701 "%d@%s", 702 target->colon_splits++, 703 target->string_mb); 704 } else { 705 *slash = 0; 706 (void) sprintf(mb_namep, 707 "%s/%d@%s", 708 target->string_mb, 709 target->colon_splits++, 710 slash + 1); 711 *slash = (int) slash_char; 712 } 713 MBSTOWCS(namep, mb_namep); 714 retmem_mb(mb_namep); 715 name = GETNAME(namep, FIND_LENGTH); 716 retmem(namep); 717 if (trace_reader) { 718 (void) printf("%s:\t", target->string_mb); 719 } 720 /* Make "target" depend on "<number>%target */ 721 line2 = maybe_append_prop(target, line_prop); 722 enter_dependency(line2, name, true); 723 line2->body.line.target = target; 724 /* Put a prop on "<number>%target that makes */ 725 /* appear as "target" */ 726 /* when it is processed */ 727 maybe_append_prop(name, target_prop)-> 728 body.target.target = target; 729 target->is_double_colon_parent = true; 730 name->is_double_colon = true; 731 name->has_target_prop = true; 732 if (trace_reader) { 733 (void) printf("\n"); 734 } 735 (target = name)->stat.is_file = true; 736 } 737 } 738 /* This really is a regular dependency line. Just enter it */ 739 line = maybe_append_prop(target, line_prop); 740 line->body.line.target = target; 741 /* Depending on what kind of makefile we are reading we have to */ 742 /* treat things differently */ 743 switch (makefile_type) { 744 case reading_makefile: 745 /* Reading regular makefile. Just notice whether this */ 746 /* redefines the rule for the target */ 747 if (command != NULL) { 748 if (line->body.line.command_template != NULL) { 749 line->body.line.command_template_redefined = 750 true; 751 if ((wcb[0] == (int) period_char) && 752 !wcschr(wcb, (int) slash_char)) { 753 line->body.line.command_template = 754 command; 755 } 756 } else { 757 line->body.line.command_template = command; 758 } 759 } else { 760 if ((wcb[0] == (int) period_char) && 761 !wcschr(wcb, (int) slash_char)) { 762 line->body.line.command_template = command; 763 } 764 } 765 break; 766 case rereading_statefile: 767 /* Rereading the statefile. We only enter thing that changed */ 768 /* since the previous time we read it */ 769 if (!built_last_make_run_seen) { 770 for (Cmd_line next, cmd = command; cmd != NULL; cmd = next) { 771 next = cmd->next; 772 free(cmd); 773 } 774 return; 775 } 776 built_last_make_run_seen = false; 777 command_changed = true; 778 target->ran_command = true; 779 case reading_statefile: 780 /* Reading the statefile for the first time. Enter the rules */ 781 /* as "Commands used" not "templates to use" */ 782 if (command != NULL) { 783 for (Cmd_line next, cmd = line->body.line.command_used; 784 cmd != NULL; cmd = next) { 785 next = cmd->next; 786 free(cmd); 787 } 788 line->body.line.command_used = command; 789 } 790 case reading_cpp_file: 791 /* Reading report file from programs that reports */ 792 /* dependencies. If this is the first time the target is */ 793 /* read from this reportfile we clear all old */ 794 /* automatic depes */ 795 if (target->temp_file_number == temp_file_number) { 796 break; 797 } 798 target->temp_file_number = temp_file_number; 799 command_changed = true; 800 if (line != NULL) { 801 for (dp = line->body.line.dependencies; 802 dp != NULL; 803 dp = dp->next) { 804 if (dp->automatic) { 805 dp->stale = true; 806 } 807 } 808 } 809 break; 810 default: 811 fatal_reader(gettext("Internal error. Unknown makefile type %d"), 812 makefile_type); 813 } 814 /* A target may only be involved in one target group */ 815 if (line->body.line.target_group != NULL) { 816 if (target_group != NULL) { 817 fatal_reader(gettext("Too many target groups for target `%s'"), 818 target->string_mb); 819 } 820 } else { 821 line->body.line.target_group = target_group; 822 } 823 824 if (trace_reader) { 825 (void) printf("%s:\t", target->string_mb); 826 } 827 /* Enter the dependencies */ 828 register_as_auto = BOOLEAN(makefile_type != reading_makefile); 829 not_auto_found = false; 830 for (; 831 (depes != NULL) && !not_auto_found; 832 depes = depes->next) { 833 for (i = 0; i < depes->used; i++) { 834 /* the dependency .NOT_AUTO signals beginning of 835 * explicit dependancies which were put at end of 836 * list in .make.state file - we stop entering 837 * dependencies at this point 838 */ 839 if (depes->names[i] == not_auto) { 840 not_auto_found = true; 841 break; 842 } 843 enter_dependency(line, 844 depes->names[i], 845 register_as_auto); 846 } 847 } 848 if (trace_reader) { 849 (void) printf("\n"); 850 print_rule(command); 851 } 852 } 853 854 /* 855 * enter_dependency(line, depe, automatic) 856 * 857 * Enter one dependency. Do not enter duplicates. 858 * 859 * Parameters: 860 * line The line block that the dependeny is 861 * entered for 862 * depe The dependency to enter 863 * automatic Used to set the field "automatic" 864 * 865 * Global variables used: 866 * makefile_type We do different things for makefile vs. report 867 * trace_reader Indicates that we should echo stuff we read 868 * wait_name The Name ".WAIT", compared against 869 */ 870 void 871 enter_dependency(Property line, register Name depe, Boolean automatic) 872 { 873 register Dependency dp; 874 register Dependency *insert; 875 876 if (trace_reader) { 877 (void) printf("%s ", depe->string_mb); 878 } 879 /* Find the end of the list and check for duplicates */ 880 for (insert = &line->body.line.dependencies, dp = *insert; 881 dp != NULL; 882 insert = &dp->next, dp = *insert) { 883 if ((dp->name == depe) && (depe != wait_name)) { 884 if (dp->automatic) { 885 dp->automatic = automatic; 886 if (automatic) { 887 dp->built = false; 888 depe->stat.is_file = true; 889 } 890 } 891 dp->stale = false; 892 return; 893 } 894 } 895 /* Insert the new dependency since we couldnt find it */ 896 dp = *insert = ALLOC(Dependency); 897 dp->name = depe; 898 dp->next = NULL; 899 dp->automatic = automatic; 900 dp->stale = false; 901 dp->built = false; 902 depe->stat.is_file = true; 903 904 if ((makefile_type == reading_makefile) && 905 (line != NULL) && 906 (line->body.line.target != NULL)) { 907 line->body.line.target->has_regular_dependency = true; 908 } 909 } 910 911 /* 912 * enter_percent(target, depes, command) 913 * 914 * Enter "x%y : a%b" type lines 915 * % patterns are stored in four parts head and tail for target and source 916 * 917 * Parameters: 918 * target Left hand side of pattern 919 * depes The dependency list with the rh pattern 920 * command The command for the pattern 921 * 922 * Global variables used: 923 * empty_name The Name "", compared against 924 * percent_list The list of all percent rules, added to 925 * trace_reader Indicates that we should echo stuff we read 926 */ 927 Percent 928 enter_percent(register Name target, Chain target_group, register Name_vector depes, Cmd_line command) 929 { 930 register Percent result = ALLOC(Percent); 931 register Percent depe; 932 register Percent *depe_tail = &result->dependencies; 933 register Percent *insert; 934 register wchar_t *cp, *cp1; 935 Name_vector nvp; 936 int i; 937 int pattern; 938 939 result->next = NULL; 940 result->patterns = NULL; 941 result->patterns_total = 0; 942 result->command_template = command; 943 result->being_expanded = false; 944 result->name = target; 945 result->dependencies = NULL; 946 result->target_group = target_group; 947 948 /* get patterns count */ 949 Wstring wcb(target); 950 cp = wcb.get_string(); 951 while (true) { 952 cp = (wchar_t *) wcschr(cp, (int) percent_char); 953 if (cp != NULL) { 954 result->patterns_total++; 955 cp++; 956 } else { 957 break; 958 } 959 } 960 result->patterns_total++; 961 962 /* allocate storage for patterns */ 963 result->patterns = (Name *) getmem(sizeof(Name) * result->patterns_total); 964 965 /* then create patterns */ 966 cp = wcb.get_string(); 967 pattern = 0; 968 while (true) { 969 cp1 = (wchar_t *) wcschr(cp, (int) percent_char); 970 if (cp1 != NULL) { 971 result->patterns[pattern] = GETNAME(cp, cp1 - cp); 972 cp = cp1 + 1; 973 pattern++; 974 } else { 975 result->patterns[pattern] = GETNAME(cp, (int) target->hash.length - (cp - wcb.get_string())); 976 break; 977 } 978 } 979 980 Wstring wcb1; 981 982 /* build dependencies list */ 983 for (nvp = depes; nvp != NULL; nvp = nvp->next) { 984 for (i = 0; i < nvp->used; i++) { 985 depe = ALLOC(Percent); 986 depe->next = NULL; 987 depe->patterns = NULL; 988 depe->patterns_total = 0; 989 depe->name = nvp->names[i]; 990 depe->dependencies = NULL; 991 depe->command_template = NULL; 992 depe->being_expanded = false; 993 depe->target_group = NULL; 994 995 *depe_tail = depe; 996 depe_tail = &depe->next; 997 998 if (depe->name->percent) { 999 /* get patterns count */ 1000 wcb1.init(depe->name); 1001 cp = wcb1.get_string(); 1002 while (true) { 1003 cp = (wchar_t *) wcschr(cp, (int) percent_char); 1004 if (cp != NULL) { 1005 depe->patterns_total++; 1006 cp++; 1007 } else { 1008 break; 1009 } 1010 } 1011 depe->patterns_total++; 1012 1013 /* allocate storage for patterns */ 1014 depe->patterns = (Name *) getmem(sizeof(Name) * depe->patterns_total); 1015 1016 /* then create patterns */ 1017 cp = wcb1.get_string(); 1018 pattern = 0; 1019 while (true) { 1020 cp1 = (wchar_t *) wcschr(cp, (int) percent_char); 1021 if (cp1 != NULL) { 1022 depe->patterns[pattern] = GETNAME(cp, cp1 - cp); 1023 cp = cp1 + 1; 1024 pattern++; 1025 } else { 1026 depe->patterns[pattern] = GETNAME(cp, (int) depe->name->hash.length - (cp - wcb1.get_string())); 1027 break; 1028 } 1029 } 1030 } 1031 } 1032 } 1033 1034 /* Find the end of the percent list and append the new pattern */ 1035 for (insert = &percent_list; (*insert) != NULL; insert = &(*insert)->next); 1036 *insert = result; 1037 1038 if (trace_reader) { 1039 (void) printf("%s:", result->name->string_mb); 1040 1041 for (depe = result->dependencies; depe != NULL; depe = depe->next) { 1042 (void) printf(" %s", depe->name->string_mb); 1043 } 1044 1045 (void) printf("\n"); 1046 1047 print_rule(command); 1048 } 1049 1050 return result; 1051 } 1052 1053 /* 1054 * enter_dyntarget(target) 1055 * 1056 * Enter "$$(MACRO) : b" type lines 1057 * 1058 * Parameters: 1059 * target Left hand side of pattern 1060 * 1061 * Global variables used: 1062 * dyntarget_list The list of all percent rules, added to 1063 * trace_reader Indicates that we should echo stuff we read 1064 */ 1065 Dyntarget 1066 enter_dyntarget(register Name target) 1067 { 1068 register Dyntarget result = ALLOC(Dyntarget); 1069 Dyntarget p; 1070 Dyntarget *insert; 1071 int i; 1072 1073 result->next = NULL; 1074 result->name = target; 1075 1076 1077 /* Find the end of the dyntarget list and append the new pattern */ 1078 for (insert = &dyntarget_list, p = *insert; 1079 p != NULL; 1080 insert = &p->next, p = *insert); 1081 *insert = result; 1082 1083 if (trace_reader) { 1084 (void) printf("Dynamic target %s:\n", result->name->string_mb); 1085 } 1086 return( result); 1087 } 1088 1089 1090 /* 1091 * special_reader(target, depes, command) 1092 * 1093 * Read the pseudo targets make knows about 1094 * This handles the special targets that should not be entered as regular 1095 * target/dependency sets. 1096 * 1097 * Parameters: 1098 * target The special target 1099 * depes The list of dependencies it was entered with 1100 * command The command it was entered with 1101 * 1102 * Static variables used: 1103 * built_last_make_run_seen Set to indicate .BUILT_LAST... seen 1104 * 1105 * Global variables used: 1106 * all_parallel Set to indicate that everything runs parallel 1107 * svr4 Set when ".SVR4" target is read 1108 * svr4_name The Name ".SVR4" 1109 * posix Set when ".POSIX" target is read 1110 * posix_name The Name ".POSIX" 1111 * current_make_version The Name "<current version number>" 1112 * default_rule Set when ".DEFAULT" target is read 1113 * default_rule_name The Name ".DEFAULT", used for tracing 1114 * dot_keep_state The Name ".KEEP_STATE", used for tracing 1115 * ignore_errors Set if ".IGNORE" target is read 1116 * ignore_name The Name ".IGNORE", used for tracing 1117 * keep_state Set if ".KEEP_STATE" target is read 1118 * no_parallel_name The Name ".NO_PARALLEL", used for tracing 1119 * only_parallel Set to indicate only some targets runs parallel 1120 * parallel_name The Name ".PARALLEL", used for tracing 1121 * precious The Name ".PRECIOUS", used for tracing 1122 * sccs_get_name The Name ".SCCS_GET", used for tracing 1123 * sccs_get_posix_name The Name ".SCCS_GET_POSIX", used for tracing 1124 * get_name The Name ".GET", used for tracing 1125 * sccs_get_rule Set when ".SCCS_GET" target is read 1126 * silent Set when ".SILENT" target is read 1127 * silent_name The Name ".SILENT", used for tracing 1128 * trace_reader Indicates that we should echo stuff we read 1129 */ 1130 void 1131 special_reader(Name target, register Name_vector depes, Cmd_line command) 1132 { 1133 register int n; 1134 1135 switch (target->special_reader) { 1136 1137 case svr4_special: 1138 if (depes->used != 0) { 1139 fatal_reader(gettext("Illegal dependencies for target `%s'"), 1140 target->string_mb); 1141 } 1142 svr4 = true; 1143 posix = false; 1144 keep_state = false; 1145 all_parallel = false; 1146 only_parallel = false; 1147 if (trace_reader) { 1148 (void) printf("%s:\n", svr4_name->string_mb); 1149 } 1150 break; 1151 1152 case posix_special: 1153 if(svr4) 1154 break; 1155 if (depes->used != 0) { 1156 fatal_reader(gettext("Illegal dependencies for target `%s'"), 1157 target->string_mb); 1158 } 1159 posix = true; 1160 /* with posix on, use the posix get rule */ 1161 sccs_get_rule = sccs_get_posix_rule; 1162 /* turn keep state off being SunPro make specific */ 1163 keep_state = false; 1164 /* Use /usr/xpg4/bin/sh on Solaris */ 1165 MBSTOWCS(wcs_buffer, "/usr/xpg4/bin/sh"); 1166 (void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false); 1167 if (trace_reader) { 1168 (void) printf("%s:\n", posix_name->string_mb); 1169 } 1170 break; 1171 1172 case built_last_make_run_special: 1173 built_last_make_run_seen = true; 1174 break; 1175 1176 case default_special: 1177 if (depes->used != 0) { 1178 warning(gettext("Illegal dependency list for target `%s'"), 1179 target->string_mb); 1180 } 1181 default_rule = command; 1182 if (trace_reader) { 1183 (void) printf("%s:\n", 1184 default_rule_name->string_mb); 1185 print_rule(command); 1186 } 1187 break; 1188 1189 1190 case ignore_special: 1191 if ((depes->used != 0) &&(!posix)){ 1192 fatal_reader(gettext("Illegal dependencies for target `%s'"), 1193 target->string_mb); 1194 } 1195 if (depes->used == 0) 1196 { 1197 ignore_errors_all = true; 1198 } 1199 if(svr4) { 1200 ignore_errors_all = true; 1201 break; 1202 } 1203 for (; depes != NULL; depes = depes->next) { 1204 for (n = 0; n < depes->used; n++) { 1205 depes->names[n]->ignore_error_mode = true; 1206 } 1207 } 1208 if (trace_reader) { 1209 (void) printf("%s:\n", ignore_name->string_mb); 1210 } 1211 break; 1212 1213 case keep_state_special: 1214 if(svr4) 1215 break; 1216 /* ignore keep state, being SunPro make specific */ 1217 if(posix) 1218 break; 1219 if (depes->used != 0) { 1220 fatal_reader(gettext("Illegal dependencies for target `%s'"), 1221 target->string_mb); 1222 } 1223 keep_state = true; 1224 if (trace_reader) { 1225 (void) printf("%s:\n", 1226 dot_keep_state->string_mb); 1227 } 1228 break; 1229 1230 case keep_state_file_special: 1231 if(svr4) 1232 break; 1233 if(posix) 1234 break; 1235 /* it's not necessary to specify KEEP_STATE, if this 1236 ** is given, so set the keep_state. 1237 */ 1238 keep_state = true; 1239 if (depes->used != 0) { 1240 if((!make_state) ||(!strcmp(make_state->string_mb,".make.state"))) { 1241 make_state = depes->names[0]; 1242 } 1243 } 1244 break; 1245 case make_version_special: 1246 if(svr4) 1247 break; 1248 if (depes->used != 1) { 1249 fatal_reader(gettext("Illegal dependency list for target `%s'"), 1250 target->string_mb); 1251 } 1252 if (depes->names[0] != current_make_version) { 1253 /* 1254 * Special case the fact that version 1.0 and 1.1 1255 * are identical. 1256 */ 1257 if (!IS_EQUAL(depes->names[0]->string_mb, 1258 "VERSION-1.1") || 1259 !IS_EQUAL(current_make_version->string_mb, 1260 "VERSION-1.0")) { 1261 /* 1262 * Version mismatches should cause the 1263 * .make.state file to be skipped. 1264 * This is currently not true - it is read 1265 * anyway. 1266 */ 1267 warning(gettext("Version mismatch between current version `%s' and `%s'"), 1268 current_make_version->string_mb, 1269 depes->names[0]->string_mb); 1270 } 1271 } 1272 break; 1273 1274 case no_parallel_special: 1275 if(svr4) 1276 break; 1277 /* Set the no_parallel bit for all the targets on */ 1278 /* the dependency list */ 1279 if (depes->used == 0) { 1280 /* only those explicitly made parallel */ 1281 only_parallel = true; 1282 all_parallel = false; 1283 } else { 1284 only_parallel = false; 1285 all_parallel = true; 1286 } 1287 for (; depes != NULL; depes = depes->next) { 1288 for (n = 0; n < depes->used; n++) { 1289 if (trace_reader) { 1290 (void) printf("%s:\t%s\n", 1291 no_parallel_name->string_mb, 1292 depes->names[n]->string_mb); 1293 } 1294 depes->names[n]->no_parallel = true; 1295 depes->names[n]->parallel = false; 1296 } 1297 } 1298 break; 1299 1300 case parallel_special: 1301 if(svr4) 1302 break; 1303 if (depes->used == 0) { 1304 /* everything runs in parallel */ 1305 all_parallel = true; 1306 only_parallel = false; 1307 } else { 1308 all_parallel = false; 1309 only_parallel = true; 1310 } 1311 /* Set the parallel bit for all the targets on */ 1312 /* the dependency list */ 1313 for (; depes != NULL; depes = depes->next) { 1314 for (n = 0; n < depes->used; n++) { 1315 if (trace_reader) { 1316 (void) printf("%s:\t%s\n", 1317 parallel_name->string_mb, 1318 depes->names[n]->string_mb); 1319 } 1320 depes->names[n]->parallel = true; 1321 depes->names[n]->no_parallel = false; 1322 } 1323 } 1324 break; 1325 1326 case localhost_special: 1327 if(svr4) 1328 break; 1329 /* Set the no_parallel bit for all the targets on */ 1330 /* the dependency list */ 1331 if (depes->used == 0) { 1332 /* only those explicitly made parallel */ 1333 only_parallel = true; 1334 all_parallel = false; 1335 } 1336 for (; depes != NULL; depes = depes->next) { 1337 for (n = 0; n < depes->used; n++) { 1338 if (trace_reader) { 1339 (void) printf("%s:\t%s\n", 1340 localhost_name->string_mb, 1341 depes->names[n]->string_mb); 1342 } 1343 depes->names[n]->no_parallel = true; 1344 depes->names[n]->parallel = false; 1345 depes->names[n]->localhost = true; 1346 } 1347 } 1348 break; 1349 1350 case precious_special: 1351 if (depes->used == 0) { 1352 /* everything is precious */ 1353 all_precious = true; 1354 } else { 1355 all_precious = false; 1356 } 1357 if(svr4) { 1358 all_precious = true; 1359 break; 1360 } 1361 /* Set the precious bit for all the targets on */ 1362 /* the dependency list */ 1363 for (; depes != NULL; depes = depes->next) { 1364 for (n = 0; n < depes->used; n++) { 1365 if (trace_reader) { 1366 (void) printf("%s:\t%s\n", 1367 precious->string_mb, 1368 depes->names[n]->string_mb); 1369 } 1370 depes->names[n]->stat.is_precious = true; 1371 } 1372 } 1373 break; 1374 1375 case sccs_get_special: 1376 if (depes->used != 0) { 1377 fatal_reader(gettext("Illegal dependencies for target `%s'"), 1378 target->string_mb); 1379 } 1380 sccs_get_rule = command; 1381 sccs_get_org_rule = command; 1382 if (trace_reader) { 1383 (void) printf("%s:\n", sccs_get_name->string_mb); 1384 print_rule(command); 1385 } 1386 break; 1387 1388 case sccs_get_posix_special: 1389 if (depes->used != 0) { 1390 fatal_reader(gettext("Illegal dependencies for target `%s'"), 1391 target->string_mb); 1392 } 1393 sccs_get_posix_rule = command; 1394 if (trace_reader) { 1395 (void) printf("%s:\n", sccs_get_posix_name->string_mb); 1396 print_rule(command); 1397 } 1398 break; 1399 1400 case get_posix_special: 1401 if (depes->used != 0) { 1402 fatal_reader(gettext("Illegal dependencies for target `%s'"), 1403 target->string_mb); 1404 } 1405 get_posix_rule = command; 1406 if (trace_reader) { 1407 (void) printf("%s:\n", get_posix_name->string_mb); 1408 print_rule(command); 1409 } 1410 break; 1411 1412 case get_special: 1413 if(!svr4) { 1414 break; 1415 } 1416 if (depes->used != 0) { 1417 fatal_reader(gettext("Illegal dependencies for target `%s'"), 1418 target->string_mb); 1419 } 1420 get_rule = command; 1421 sccs_get_rule = command; 1422 if (trace_reader) { 1423 (void) printf("%s:\n", get_name->string_mb); 1424 print_rule(command); 1425 } 1426 break; 1427 1428 case silent_special: 1429 if ((depes->used != 0) && (!posix)){ 1430 fatal_reader(gettext("Illegal dependencies for target `%s'"), 1431 target->string_mb); 1432 } 1433 if (depes->used == 0) 1434 { 1435 silent_all = true; 1436 } 1437 if(svr4) { 1438 silent_all = true; 1439 break; 1440 } 1441 for (; depes != NULL; depes = depes->next) { 1442 for (n = 0; n < depes->used; n++) { 1443 depes->names[n]->silent_mode = true; 1444 } 1445 } 1446 if (trace_reader) { 1447 (void) printf("%s:\n", silent_name->string_mb); 1448 } 1449 break; 1450 1451 case suffixes_special: 1452 read_suffixes_list(depes); 1453 break; 1454 1455 default: 1456 1457 fatal_reader(gettext("Internal error: Unknown special reader")); 1458 } 1459 } 1460 1461 /* 1462 * read_suffixes_list(depes) 1463 * 1464 * Read the special list .SUFFIXES. If it is empty the old list is 1465 * cleared. Else the new one is appended. Suffixes with ~ are extracted 1466 * and marked. 1467 * 1468 * Parameters: 1469 * depes The list of suffixes 1470 * 1471 * Global variables used: 1472 * hashtab The central hashtable for Names. 1473 * suffixes The list of suffixes, set or appended to 1474 * suffixes_name The Name ".SUFFIXES", used for tracing 1475 * trace_reader Indicates that we should echo stuff we read 1476 */ 1477 static void 1478 read_suffixes_list(register Name_vector depes) 1479 { 1480 register int n; 1481 register Dependency dp; 1482 register Dependency *insert_dep; 1483 register Name np; 1484 Name np2; 1485 register Boolean first = true; 1486 1487 if (depes->used == 0) { 1488 /* .SUFFIXES with no dependency list clears the */ 1489 /* suffixes list */ 1490 for (Name_set::iterator np = hashtab.begin(), e = hashtab.end(); np != e; np++) { 1491 np->with_squiggle = 1492 np->without_squiggle = 1493 false; 1494 } 1495 suffixes = NULL; 1496 if (trace_reader) { 1497 (void) printf("%s:\n", suffixes_name->string_mb); 1498 } 1499 return; 1500 } 1501 Wstring str; 1502 /* Otherwise we append to the list */ 1503 for (; depes != NULL; depes = depes->next) { 1504 for (n = 0; n < depes->used; n++) { 1505 np = depes->names[n]; 1506 /* Find the end of the list and check if the */ 1507 /* suffix already has been entered */ 1508 for (insert_dep = &suffixes, dp = *insert_dep; 1509 dp != NULL; 1510 insert_dep = &dp->next, dp = *insert_dep) { 1511 if (dp->name == np) { 1512 goto duplicate_suffix; 1513 } 1514 } 1515 if (trace_reader) { 1516 if (first) { 1517 (void) printf("%s:\t", 1518 suffixes_name->string_mb); 1519 first = false; 1520 } 1521 (void) printf("%s ", depes->names[n]->string_mb); 1522 } 1523 if(!(posix|svr4)) { 1524 /* If the suffix is suffixed with "~" we */ 1525 /* strip that and mark the suffix nameblock */ 1526 str.init(np); 1527 wchar_t * wcb = str.get_string(); 1528 if (wcb[np->hash.length - 1] == 1529 (int) tilde_char) { 1530 np2 = GETNAME(wcb, 1531 (int)(np->hash.length - 1)); 1532 np2->with_squiggle = true; 1533 if (np2->without_squiggle) { 1534 continue; 1535 } 1536 np = np2; 1537 } 1538 } 1539 np->without_squiggle = true; 1540 /* Add the suffix to the list */ 1541 dp = *insert_dep = ALLOC(Dependency); 1542 insert_dep = &dp->next; 1543 dp->next = NULL; 1544 dp->name = np; 1545 dp->built = false; 1546 duplicate_suffix:; 1547 } 1548 } 1549 if (trace_reader) { 1550 (void) printf("\n"); 1551 } 1552 } 1553 1554 /* 1555 * make_relative(to, result) 1556 * 1557 * Given a file name compose a relative path name from it to the 1558 * current directory. 1559 * 1560 * Parameters: 1561 * to The path we want to make relative 1562 * result Where to put the resulting relative path 1563 * 1564 * Global variables used: 1565 */ 1566 static void 1567 make_relative(wchar_t *to, wchar_t *result) 1568 { 1569 wchar_t *from; 1570 wchar_t *allocated; 1571 wchar_t *cp; 1572 wchar_t *tocomp; 1573 int ncomps; 1574 int i; 1575 int len; 1576 1577 /* Check if the path is already relative. */ 1578 if (to[0] != (int) slash_char) { 1579 (void) wcscpy(result, to); 1580 return; 1581 } 1582 1583 MBSTOWCS(wcs_buffer, get_current_path()); 1584 from = allocated = (wchar_t *) wcsdup(wcs_buffer); 1585 1586 /* 1587 * Find the number of components in the from name. 1588 * ncomp = number of slashes + 1. 1589 */ 1590 ncomps = 1; 1591 for (cp = from; *cp != (int) nul_char; cp++) { 1592 if (*cp == (int) slash_char) { 1593 ncomps++; 1594 } 1595 } 1596 1597 /* 1598 * See how many components match to determine how many "..", 1599 * if any, will be needed. 1600 */ 1601 result[0] = (int) nul_char; 1602 tocomp = to; 1603 while ((*from != (int) nul_char) && (*from == *to)) { 1604 if (*from == (int) slash_char) { 1605 ncomps--; 1606 tocomp = &to[1]; 1607 } 1608 from++; 1609 to++; 1610 } 1611 1612 /* 1613 * Now for some special cases. Check for exact matches and 1614 * for either name terminating exactly. 1615 */ 1616 if (*from == (int) nul_char) { 1617 if (*to == (int) nul_char) { 1618 MBSTOWCS(wcs_buffer, "."); 1619 (void) wcscpy(result, wcs_buffer); 1620 retmem(allocated); 1621 return; 1622 } 1623 if (*to == (int) slash_char) { 1624 ncomps--; 1625 tocomp = &to[1]; 1626 } 1627 } else if ((*from == (int) slash_char) && (*to == (int) nul_char)) { 1628 ncomps--; 1629 tocomp = to; 1630 } 1631 /* Add on the ".."s. */ 1632 for (i = 0; i < ncomps; i++) { 1633 MBSTOWCS(wcs_buffer, "../"); 1634 (void) wcscat(result, wcs_buffer); 1635 } 1636 1637 /* Add on the remainder of the to name, if any. */ 1638 if (*tocomp == (int) nul_char) { 1639 len = wcslen(result); 1640 result[len - 1] = (int) nul_char; 1641 } else { 1642 (void) wcscat(result, tocomp); 1643 } 1644 retmem(allocated); 1645 return; 1646 } 1647 1648 /* 1649 * print_rule(command) 1650 * 1651 * Used when tracing the reading of rules 1652 * 1653 * Parameters: 1654 * command Command to print 1655 * 1656 * Global variables used: 1657 */ 1658 static void 1659 print_rule(register Cmd_line command) 1660 { 1661 for (; command != NULL; command = command->next) { 1662 (void) printf("\t%s\n", command->command_line->string_mb); 1663 } 1664 } 1665 1666 /* 1667 * enter_conditional(target, name, value, append) 1668 * 1669 * Enter "target := MACRO= value" constructs 1670 * 1671 * Parameters: 1672 * target The target the macro is for 1673 * name The name of the macro 1674 * value The value for the macro 1675 * append Indicates if the assignment is appending or not 1676 * 1677 * Global variables used: 1678 * conditionals A special Name that stores all conditionals 1679 * where the target is a % pattern 1680 * trace_reader Indicates that we should echo stuff we read 1681 */ 1682 void 1683 enter_conditional(register Name target, Name name, Name value, register Boolean append) 1684 { 1685 register Property conditional; 1686 static int sequence; 1687 Name orig_target = target; 1688 1689 if (name == target_arch) { 1690 enter_conditional(target, virtual_root, virtual_root, false); 1691 } 1692 1693 if (target->percent) { 1694 target = conditionals; 1695 } 1696 1697 if (name->colon) { 1698 sh_transform(&name, &value); 1699 } 1700 1701 /* Count how many conditionals we must activate before building the */ 1702 /* target */ 1703 if (target->percent) { 1704 target = conditionals; 1705 } 1706 1707 target->conditional_cnt++; 1708 maybe_append_prop(name, macro_prop)->body.macro.is_conditional = true; 1709 /* Add the property for the target */ 1710 conditional = append_prop(target, conditional_prop); 1711 conditional->body.conditional.target = orig_target; 1712 conditional->body.conditional.name = name; 1713 conditional->body.conditional.value = value; 1714 conditional->body.conditional.sequence = sequence++; 1715 conditional->body.conditional.append = append; 1716 if (trace_reader) { 1717 if (value == NULL) { 1718 (void) printf("%s := %s %c=\n", 1719 target->string_mb, 1720 name->string_mb, 1721 append ? 1722 (int) plus_char : (int) space_char); 1723 } else { 1724 (void) printf("%s := %s %c= %s\n", 1725 target->string_mb, 1726 name->string_mb, 1727 append ? 1728 (int) plus_char : (int) space_char, 1729 value->string_mb); 1730 } 1731 } 1732 } 1733 1734 /* 1735 * enter_equal(name, value, append) 1736 * 1737 * Enter "MACRO= value" constructs 1738 * 1739 * Parameters: 1740 * name The name of the macro 1741 * value The value for the macro 1742 * append Indicates if the assignment is appending or not 1743 * 1744 * Global variables used: 1745 * trace_reader Indicates that we should echo stuff we read 1746 */ 1747 void 1748 enter_equal(Name name, Name value, register Boolean append) 1749 { 1750 wchar_t *string; 1751 Name temp; 1752 1753 if (name->colon) { 1754 sh_transform(&name, &value); 1755 } 1756 (void) SETVAR(name, value, append); 1757 1758 /* if we're setting FC, we want to set F77 to the same value. */ 1759 Wstring nms(name); 1760 wchar_t * wcb = nms.get_string(); 1761 string = wcb; 1762 if (string[0]=='F' && 1763 string[1]=='C' && 1764 string[2]=='\0') { 1765 MBSTOWCS(wcs_buffer, "F77"); 1766 temp = GETNAME(wcs_buffer, FIND_LENGTH); 1767 (void) SETVAR(temp, value, append); 1768 /* 1769 fprintf(stderr, gettext("warning: FC is obsolete, use F77 instead\n")); 1770 */ 1771 } 1772 1773 if (trace_reader) { 1774 if (value == NULL) { 1775 (void) printf("%s %c=\n", 1776 name->string_mb, 1777 append ? 1778 (int) plus_char : (int) space_char); 1779 } else { 1780 (void) printf("%s %c= %s\n", 1781 name->string_mb, 1782 append ? 1783 (int) plus_char : (int) space_char, 1784 value->string_mb); 1785 } 1786 } 1787 } 1788 1789 /* 1790 * sh_transform(name, value) 1791 * 1792 * Parameters: 1793 * name The name of the macro we might transform 1794 * value The value to transform 1795 * 1796 */ 1797 static void 1798 sh_transform(Name *name, Name *value) 1799 { 1800 /* Check if we need :sh transform */ 1801 wchar_t *colon; 1802 String_rec command; 1803 String_rec destination; 1804 wchar_t buffer[1000]; 1805 wchar_t buffer1[1000]; 1806 1807 static wchar_t colon_sh[4]; 1808 static wchar_t colon_shell[7]; 1809 1810 if (colon_sh[0] == (int) nul_char) { 1811 MBSTOWCS(colon_sh, ":sh"); 1812 MBSTOWCS(colon_shell, ":shell"); 1813 } 1814 Wstring nms((*name)); 1815 wchar_t * wcb = nms.get_string(); 1816 1817 colon = (wchar_t *) wcsrchr(wcb, (int) colon_char); 1818 if ((colon != NULL) && (IS_WEQUAL(colon, colon_sh) || IS_WEQUAL(colon, colon_shell))) { 1819 INIT_STRING_FROM_STACK(destination, buffer); 1820 1821 if(*value == NULL) { 1822 buffer[0] = 0; 1823 } else { 1824 Wstring wcb1((*value)); 1825 if (IS_WEQUAL(colon, colon_shell)) { 1826 INIT_STRING_FROM_STACK(command, buffer1); 1827 expand_value(*value, &command, false); 1828 } else { 1829 command.text.p = wcb1.get_string() + (*value)->hash.length; 1830 command.text.end = command.text.p; 1831 command.buffer.start = wcb1.get_string(); 1832 command.buffer.end = command.text.p; 1833 } 1834 sh_command2string(&command, &destination); 1835 } 1836 1837 (*value) = GETNAME(destination.buffer.start, FIND_LENGTH); 1838 *colon = (int) nul_char; 1839 (*name) = GETNAME(wcb, FIND_LENGTH); 1840 *colon = (int) colon_char; 1841 } 1842 } 1843 1844 /* 1845 * fatal_reader(format, args...) 1846 * 1847 * Parameters: 1848 * format printf style format string 1849 * args arguments to match the format 1850 * 1851 * Global variables used: 1852 * file_being_read Name of the makefile being read 1853 * line_number Line that is being read 1854 * report_pwd Indicates whether current path should be shown 1855 * temp_file_name When reading tempfile we report that name 1856 */ 1857 /*VARARGS*/ 1858 void 1859 fatal_reader(char * pattern, ...) 1860 { 1861 va_list args; 1862 char message[1000]; 1863 1864 va_start(args, pattern); 1865 if (file_being_read != NULL) { 1866 WCSTOMBS(mbs_buffer, file_being_read); 1867 if (line_number != 0) { 1868 (void) sprintf(message, 1869 gettext("%s, line %d: %s"), 1870 mbs_buffer, 1871 line_number, 1872 pattern); 1873 } else { 1874 (void) sprintf(message, 1875 "%s: %s", 1876 mbs_buffer, 1877 pattern); 1878 } 1879 pattern = message; 1880 } 1881 1882 (void) fflush(stdout); 1883 (void) fprintf(stderr, gettext("%s: Fatal error in reader: "), 1884 getprogname()); 1885 (void) vfprintf(stderr, pattern, args); 1886 (void) fprintf(stderr, "\n"); 1887 va_end(args); 1888 1889 if (temp_file_name != NULL) { 1890 (void) fprintf(stderr, 1891 gettext("%s: Temp-file %s not removed\n"), 1892 getprogname(), 1893 temp_file_name->string_mb); 1894 temp_file_name = NULL; 1895 } 1896 1897 if (report_pwd) { 1898 (void) fprintf(stderr, 1899 gettext("Current working directory %s\n"), 1900 get_current_path()); 1901 } 1902 (void) fflush(stderr); 1903 exit_status = 1; 1904 exit(1); 1905 } 1906