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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * read.c 28 * 29 * This file contains the makefile reader. 30 */ 31 32 /* 33 * Included files 34 */ 35 #include <alloca.h> /* alloca() */ 36 #include <errno.h> /* errno */ 37 #include <fcntl.h> /* fcntl() */ 38 #include <mk/defs.h> 39 #include <mksh/macro.h> /* expand_value(), expand_macro() */ 40 #include <mksh/misc.h> /* getmem() */ 41 #include <mksh/read.h> /* get_next_block_fn() */ 42 #include <sys/uio.h> /* read() */ 43 #include <unistd.h> /* read(), unlink() */ 44 45 46 /* 47 * typedefs & structs 48 */ 49 50 /* 51 * Static variables 52 */ 53 54 static int line_started_with_space=0; // Used to diagnose spaces instead of tabs 55 56 /* 57 * File table of contents 58 */ 59 static void parse_makefile(register Name true_makefile_name, register Source source); 60 static Source push_macro_value(register Source bp, register wchar_t *buffer, int size, register Source source); 61 extern void enter_target_groups_and_dependencies(Name_vector target, Name_vector depes, Cmd_line command, Separator separator, Boolean target_group_seen); 62 extern Name normalize_name(register wchar_t *name_string, register int length); 63 64 /* 65 * read_simple_file(makefile_name, chase_path, doname_it, 66 * complain, must_exist, report_file, lock_makefile) 67 * 68 * Make the makefile and setup to read it. Actually read it if it is stdio 69 * 70 * Return value: 71 * false if the read failed 72 * 73 * Parameters: 74 * makefile_name Name of the file to read 75 * chase_path Use the makefile path when opening file 76 * doname_it Call doname() to build the file first 77 * complain Print message if doname/open fails 78 * must_exist Generate fatal if file is missing 79 * report_file Report file when running -P 80 * lock_makefile Lock the makefile when reading 81 * 82 * Static variables used: 83 * 84 * Global variables used: 85 * do_not_exec_rule Is -n on? 86 * file_being_read Set to the name of the new file 87 * line_number The number of the current makefile line 88 * makefiles_used A list of all makefiles used, appended to 89 */ 90 91 92 Boolean 93 read_simple_file(register Name makefile_name, register Boolean chase_path, register Boolean doname_it, Boolean complain, Boolean must_exist, Boolean report_file, Boolean lock_makefile) 94 { 95 static short max_include_depth; 96 register Property makefile = maybe_append_prop(makefile_name, 97 makefile_prop); 98 Boolean forget_after_parse = false; 99 static pathpt makefile_path; 100 register int n; 101 char *path; 102 register Source source = ALLOC(Source); 103 Property orig_makefile = makefile; 104 Dependency *dpp; 105 Dependency dp; 106 register int length; 107 wchar_t *previous_file_being_read = file_being_read; 108 int previous_line_number = line_number; 109 wchar_t previous_current_makefile[MAXPATHLEN]; 110 Makefile_type save_makefile_type; 111 Name normalized_makefile_name; 112 register wchar_t *string_start; 113 register wchar_t *string_end; 114 115 116 117 wchar_t * wcb = get_wstring(makefile_name->string_mb); 118 119 if (max_include_depth++ >= 40) { 120 fatal(catgets(catd, 1, 66, "Too many nested include statements")); 121 } 122 if (makefile->body.makefile.contents != NULL) { 123 retmem(makefile->body.makefile.contents); 124 } 125 source->inp_buf = 126 source->inp_buf_ptr = 127 source->inp_buf_end = NULL; 128 source->error_converting = false; 129 makefile->body.makefile.contents = NULL; 130 makefile->body.makefile.size = 0; 131 if ((makefile_name->hash.length != 1) || 132 (wcb[0] != (int) hyphen_char)) { 133 if ((makefile->body.makefile.contents == NULL) && 134 (doname_it)) { 135 if (makefile_path == NULL) { 136 add_dir_to_path(".", 137 &makefile_path, 138 -1); 139 add_dir_to_path(NOCATGETS("/usr/share/lib/make"), 140 &makefile_path, 141 -1); 142 add_dir_to_path(NOCATGETS("/etc/default"), 143 &makefile_path, 144 -1); 145 } 146 save_makefile_type = makefile_type; 147 makefile_type = reading_nothing; 148 if (doname(makefile_name, true, false) == build_dont_know) { 149 /* Try normalized filename */ 150 string_start=get_wstring(makefile_name->string_mb); 151 for (string_end=string_start+1; *string_end != L'\0'; string_end++); 152 normalized_makefile_name=normalize_name(string_start, string_end - string_start); 153 if ((strcmp(makefile_name->string_mb, normalized_makefile_name->string_mb) == 0) || 154 (doname(normalized_makefile_name, true, false) == build_dont_know)) { 155 n = access_vroot(makefile_name->string_mb, 156 4, 157 chase_path ? 158 makefile_path : NULL, 159 VROOT_DEFAULT); 160 if (n == 0) { 161 get_vroot_path((char **) NULL, 162 &path, 163 (char **) NULL); 164 if ((path[0] == (int) period_char) && 165 (path[1] == (int) slash_char)) { 166 path += 2; 167 } 168 MBSTOWCS(wcs_buffer, path); 169 makefile_name = GETNAME(wcs_buffer, 170 FIND_LENGTH); 171 } 172 } 173 retmem(string_start); 174 /* 175 * Commented out: retmem_mb(normalized_makefile_name->string_mb); 176 * We have to return this memory, but it seems to trigger a bug 177 * in dmake or in Sun C++ 5.7 compiler (it works ok if this code 178 * is compiled using Sun C++ 5.6). 179 */ 180 // retmem_mb(normalized_makefile_name->string_mb); 181 } 182 makefile_type = save_makefile_type; 183 } 184 source->string.free_after_use = false; 185 source->previous = NULL; 186 source->already_expanded = false; 187 /* Lock the file for read, but not when -n. */ 188 if (lock_makefile && 189 !do_not_exec_rule) { 190 191 make_state_lockfile = getmem(strlen(make_state->string_mb) + strlen(NOCATGETS(".lock")) + 1); 192 (void) sprintf(make_state_lockfile, 193 NOCATGETS("%s.lock"), 194 make_state->string_mb); 195 (void) file_lock(make_state->string_mb, 196 make_state_lockfile, 197 (int *) &make_state_locked, 198 0); 199 if(!make_state_locked) { 200 printf(NOCATGETS("-- NO LOCKING for read\n")); 201 retmem_mb(make_state_lockfile); 202 make_state_lockfile = 0; 203 return failed; 204 } 205 } 206 if (makefile->body.makefile.contents == NULL) { 207 save_makefile_type = makefile_type; 208 makefile_type = reading_nothing; 209 if ((doname_it) && 210 (doname(makefile_name, true, false) == build_failed)) { 211 if (complain) { 212 (void) fprintf(stderr, 213 #ifdef DISTRIBUTED 214 catgets(catd, 1, 67, "dmake: Couldn't dmake `%s'\n"), 215 #else 216 catgets(catd, 1, 237, "make: Couldn't make `%s'\n"), 217 #endif 218 makefile_name->string_mb); 219 } 220 max_include_depth--; 221 makefile_type = save_makefile_type; 222 return failed; 223 } 224 makefile_type = save_makefile_type; 225 // 226 // Before calling exists() make sure that we have the right timestamp 227 // 228 makefile_name->stat.time = file_no_time; 229 230 if (exists(makefile_name) == file_doesnt_exist) { 231 if (complain || 232 (makefile_name->stat.stat_errno != ENOENT)) { 233 if (must_exist) { 234 fatal(catgets(catd, 1, 68, "Can't find `%s': %s"), 235 makefile_name->string_mb, 236 errmsg(makefile_name-> 237 stat.stat_errno)); 238 } else { 239 warning(catgets(catd, 1, 69, "Can't find `%s': %s"), 240 makefile_name->string_mb, 241 errmsg(makefile_name-> 242 stat.stat_errno)); 243 } 244 } 245 max_include_depth--; 246 if(make_state_locked && (make_state_lockfile != NULL)) { 247 (void) unlink(make_state_lockfile); 248 retmem_mb(make_state_lockfile); 249 make_state_lockfile = NULL; 250 make_state_locked = false; 251 } 252 retmem(wcb); 253 retmem_mb((char *)source); 254 return failed; 255 } 256 /* 257 * These values are the size and bytes of 258 * the MULTI-BYTE makefile. 259 */ 260 orig_makefile->body.makefile.size = 261 makefile->body.makefile.size = 262 source->bytes_left_in_file = 263 makefile_name->stat.size; 264 if (report_file) { 265 for (dpp = &makefiles_used; 266 *dpp != NULL; 267 dpp = &(*dpp)->next); 268 dp = ALLOC(Dependency); 269 dp->next = NULL; 270 dp->name = makefile_name; 271 dp->automatic = false; 272 dp->stale = false; 273 dp->built = false; 274 *dpp = dp; 275 } 276 source->fd = open_vroot(makefile_name->string_mb, 277 O_RDONLY, 278 0, 279 NULL, 280 VROOT_DEFAULT); 281 if (source->fd < 0) { 282 if (complain || (errno != ENOENT)) { 283 if (must_exist) { 284 fatal(catgets(catd, 1, 70, "Can't open `%s': %s"), 285 makefile_name->string_mb, 286 errmsg(errno)); 287 } else { 288 warning(catgets(catd, 1, 71, "Can't open `%s': %s"), 289 makefile_name->string_mb, 290 errmsg(errno)); 291 } 292 } 293 max_include_depth--; 294 return failed; 295 } 296 (void) fcntl(source->fd, F_SETFD, 1); 297 orig_makefile->body.makefile.contents = 298 makefile->body.makefile.contents = 299 source->string.text.p = 300 source->string.buffer.start = 301 ALLOC_WC((int) (makefile_name->stat.size + 2)); 302 if (makefile_type == reading_cpp_file) { 303 forget_after_parse = true; 304 } 305 source->string.text.end = source->string.text.p; 306 source->string.buffer.end = 307 source->string.text.p + makefile_name->stat.size; 308 } else { 309 /* Do we ever reach here? */ 310 source->fd = -1; 311 source->string.text.p = 312 source->string.buffer.start = 313 makefile->body.makefile.contents; 314 source->string.text.end = 315 source->string.buffer.end = 316 source->string.text.p + makefile->body.makefile.size; 317 source->bytes_left_in_file = 318 makefile->body.makefile.size; 319 } 320 file_being_read = wcb; 321 } else { 322 char *stdin_text_p; 323 char *stdin_text_end; 324 char *stdin_buffer_start; 325 char *stdin_buffer_end; 326 char *p_mb; 327 int num_mb_chars; 328 size_t num_wc_chars; 329 330 MBSTOWCS(wcs_buffer, NOCATGETS("Standard in")); 331 makefile_name = GETNAME(wcs_buffer, FIND_LENGTH); 332 /* 333 * Memory to read standard in, then convert it 334 * to wide char strings. 335 */ 336 stdin_buffer_start = 337 stdin_text_p = getmem(length = 1024); 338 stdin_buffer_end = stdin_text_p + length; 339 MBSTOWCS(wcs_buffer, NOCATGETS("standard input")); 340 file_being_read = (wchar_t *) wsdup(wcs_buffer); 341 line_number = 0; 342 while ((n = read(fileno(stdin), 343 stdin_text_p, 344 length)) > 0) { 345 length -= n; 346 stdin_text_p += n; 347 if (length == 0) { 348 p_mb = getmem(length = 1024 + 349 (stdin_buffer_end - 350 stdin_buffer_start)); 351 (void) strncpy(p_mb, 352 stdin_buffer_start, 353 (stdin_buffer_end - 354 stdin_buffer_start)); 355 retmem_mb(stdin_buffer_start); 356 stdin_text_p = p_mb + 357 (stdin_buffer_end - stdin_buffer_start); 358 stdin_buffer_start = p_mb; 359 stdin_buffer_end = 360 stdin_buffer_start + length; 361 length = 1024; 362 } 363 } 364 if (n < 0) { 365 fatal(catgets(catd, 1, 72, "Error reading standard input: %s"), 366 errmsg(errno)); 367 } 368 stdin_text_p = stdin_buffer_start; 369 stdin_text_end = stdin_buffer_end - length; 370 num_mb_chars = stdin_text_end - stdin_text_p; 371 372 /* 373 * Now, convert the sequence of multibyte chars into 374 * a sequence of corresponding wide character codes. 375 */ 376 source->string.free_after_use = false; 377 source->previous = NULL; 378 source->bytes_left_in_file = 0; 379 source->fd = -1; 380 source->already_expanded = false; 381 source->string.buffer.start = 382 source->string.text.p = ALLOC_WC(num_mb_chars + 1); 383 source->string.buffer.end = 384 source->string.text.p + num_mb_chars; 385 num_wc_chars = mbstowcs(source->string.text.p, 386 stdin_text_p, 387 num_mb_chars); 388 if ((int) num_wc_chars >= 0) { 389 source->string.text.end = 390 source->string.text.p + num_wc_chars; 391 } 392 (void) retmem_mb(stdin_text_p); 393 } 394 line_number = 1; 395 if (trace_reader) { 396 (void) printf(catgets(catd, 1, 73, ">>>>>>>>>>>>>>>> Reading makefile %s\n"), 397 makefile_name->string_mb); 398 } 399 parse_makefile(makefile_name, source); 400 if (trace_reader) { 401 (void) printf(catgets(catd, 1, 74, ">>>>>>>>>>>>>>>> End of makefile %s\n"), 402 makefile_name->string_mb); 403 } 404 if(file_being_read) { 405 retmem(file_being_read); 406 } 407 file_being_read = previous_file_being_read; 408 line_number = previous_line_number; 409 makefile_type = reading_nothing; 410 max_include_depth--; 411 if (make_state_locked) { 412 /* Unlock .make.state. */ 413 unlink(make_state_lockfile); 414 make_state_locked = false; 415 retmem_mb(make_state_lockfile); 416 } 417 if (forget_after_parse) { 418 retmem(makefile->body.makefile.contents); 419 makefile->body.makefile.contents = NULL; 420 } 421 retmem_mb((char *)source); 422 return succeeded; 423 } 424 425 /* 426 * parse_makefile(true_makefile_name, source) 427 * 428 * Strings are read from Sources. 429 * When macros are found, their values are represented by a 430 * Source that is pushed on a stack. At end of string 431 * (that is returned from GET_CHAR() as 0), the block is popped. 432 * 433 * Parameters: 434 * true_makefile_name The name of makefile we are parsing 435 * source The source block to read from 436 * 437 * Global variables used: 438 * do_not_exec_rule Is -n on? 439 * line_number The number of the current makefile line 440 * makefile_type What kind of makefile are we reading? 441 * empty_name The Name "" 442 */ 443 static void 444 parse_makefile(register Name true_makefile_name, register Source source) 445 { 446 /* 447 char mb_buffer[MB_LEN_MAX]; 448 */ 449 register wchar_t *source_p; 450 register wchar_t *source_end; 451 register wchar_t *string_start; 452 wchar_t *string_end; 453 register Boolean macro_seen_in_string; 454 Boolean append; 455 String_rec name_string; 456 wchar_t name_buffer[STRING_BUFFER_LENGTH]; 457 register int distance; 458 register int paren_count; 459 int brace_count; 460 int char_number; 461 Cmd_line command; 462 Cmd_line command_tail; 463 Name macro_value; 464 465 Name_vector_rec target; 466 Name_vector_rec depes; 467 Name_vector_rec extra_name_vector; 468 Name_vector current_names; 469 Name_vector extra_names = &extra_name_vector; 470 Name_vector nvp; 471 Boolean target_group_seen; 472 473 register Reader_state state; 474 register Reader_state on_eoln_state; 475 register Separator separator; 476 477 wchar_t buffer[4 * STRING_BUFFER_LENGTH]; 478 Source extrap; 479 480 Boolean save_do_not_exec_rule = do_not_exec_rule; 481 Name makefile_name; 482 483 static Name sh_name; 484 static Name shell_name; 485 int i; 486 487 static wchar_t include_space[10]; 488 static wchar_t include_tab[10]; 489 int tmp_bytes_left_in_string; 490 Boolean tmp_maybe_include = false; 491 int emptycount = 0; 492 Boolean first_target; 493 494 String_rec include_name; 495 wchar_t include_buffer[STRING_BUFFER_LENGTH]; 496 497 target.next = depes.next = NULL; 498 /* Move some values from their struct to register declared locals */ 499 CACHE_SOURCE(0); 500 501 start_new_line: 502 /* 503 * Read whitespace on old line. Leave pointer on first char on 504 * next line. 505 */ 506 first_target = true; 507 on_eoln_state = exit_state; 508 /* 509 for (WCTOMB(mb_buffer, GET_CHAR()); 510 1; 511 source_p++, WCTOMB(mb_buffer, GET_CHAR())) 512 switch (mb_buffer[0]) { 513 */ 514 for (char_number=0; 1; source_p++,char_number++) switch (GET_CHAR()) { 515 case nul_char: 516 /* End of this string. Pop it and return to the previous one */ 517 GET_NEXT_BLOCK(source); 518 source_p--; 519 if (source == NULL) { 520 GOTO_STATE(on_eoln_state); 521 } 522 break; 523 case newline_char: 524 end_of_line: 525 source_p++; 526 if (source->fd >= 0) { 527 line_number++; 528 } 529 switch (GET_CHAR()) { 530 case nul_char: 531 GET_NEXT_BLOCK(source); 532 if (source == NULL) { 533 GOTO_STATE(on_eoln_state); 534 } 535 /* Go back to the top of this loop */ 536 goto start_new_line; 537 case newline_char: 538 case numbersign_char: 539 case dollar_char: 540 case space_char: 541 case tab_char: 542 /* 543 * Go back to the top of this loop since the 544 * new line does not start with a regular char. 545 */ 546 goto start_new_line; 547 default: 548 /* We found the first proper char on the new line */ 549 goto start_new_line_no_skip; 550 } 551 case space_char: 552 if (char_number == 0) 553 line_started_with_space=line_number; 554 case tab_char: 555 /* Whitespace. Just keep going in this loop */ 556 break; 557 case numbersign_char: 558 /* Comment. Skip over it */ 559 for (; 1; source_p++) { 560 switch (GET_CHAR()) { 561 case nul_char: 562 GET_NEXT_BLOCK_NOCHK(source); 563 if (source == NULL) { 564 GOTO_STATE(on_eoln_state); 565 } 566 if (source->error_converting) { 567 // Illegal byte sequence - skip its first byte 568 source->inp_buf_ptr++; 569 } 570 source_p--; 571 break; 572 case backslash_char: 573 /* Comments can be continued */ 574 if (*++source_p == (int) nul_char) { 575 GET_NEXT_BLOCK_NOCHK(source); 576 if (source == NULL) { 577 GOTO_STATE(on_eoln_state); 578 } 579 if (source->error_converting) { 580 // Illegal byte sequence - skip its first byte 581 source->inp_buf_ptr++; 582 source_p--; 583 break; 584 } 585 } 586 if(*source_p == (int) newline_char) { 587 if (source->fd >= 0) { 588 line_number++; 589 } 590 } 591 break; 592 case newline_char: 593 /* 594 * After we skip the comment we go to 595 * the end of line handler since end of 596 * line terminates comments. 597 */ 598 goto end_of_line; 599 } 600 } 601 case dollar_char: 602 /* Macro reference */ 603 if (source->already_expanded) { 604 /* 605 * If we are reading from the expansion of a 606 * macro we already expanded everything enough. 607 */ 608 goto start_new_line_no_skip; 609 } 610 /* 611 * Expand the value and push the Source on the stack of 612 * things being read. 613 */ 614 source_p++; 615 UNCACHE_SOURCE(); 616 { 617 Source t = (Source) alloca((int) sizeof (Source_rec)); 618 source = push_macro_value(t, 619 buffer, 620 sizeof buffer, 621 source); 622 } 623 CACHE_SOURCE(1); 624 break; 625 default: 626 /* We found the first proper char on the new line */ 627 goto start_new_line_no_skip; 628 } 629 630 /* 631 * We found the first normal char (one that starts an identifier) 632 * on the newline. 633 */ 634 start_new_line_no_skip: 635 /* Inspect that first char to see if it maybe is special anyway */ 636 switch (GET_CHAR()) { 637 case nul_char: 638 GET_NEXT_BLOCK(source); 639 if (source == NULL) { 640 GOTO_STATE(on_eoln_state); 641 } 642 goto start_new_line_no_skip; 643 case newline_char: 644 /* Just in case */ 645 goto start_new_line; 646 case exclam_char: 647 /* Evaluate the line before it is read */ 648 string_start = source_p + 1; 649 macro_seen_in_string = false; 650 /* Stuff the line in a string so we can eval it. */ 651 for (; 1; source_p++) { 652 switch (GET_CHAR()) { 653 case newline_char: 654 goto eoln_1; 655 case nul_char: 656 if (source->fd > 0) { 657 if (!macro_seen_in_string) { 658 macro_seen_in_string = true; 659 INIT_STRING_FROM_STACK( 660 name_string, name_buffer); 661 } 662 append_string(string_start, 663 &name_string, 664 source_p - string_start); 665 GET_NEXT_BLOCK(source); 666 string_start = source_p; 667 source_p--; 668 break; 669 } 670 eoln_1: 671 if (!macro_seen_in_string) { 672 INIT_STRING_FROM_STACK(name_string, 673 name_buffer); 674 } 675 append_string(string_start, 676 &name_string, 677 source_p - string_start); 678 extrap = (Source) 679 alloca((int) sizeof (Source_rec)); 680 extrap->string.buffer.start = NULL; 681 extrap->inp_buf = 682 extrap->inp_buf_ptr = 683 extrap->inp_buf_end = NULL; 684 extrap->error_converting = false; 685 if (*source_p == (int) nul_char) { 686 source_p++; 687 } 688 /* Eval the macro */ 689 expand_value(GETNAME(name_string.buffer.start, 690 FIND_LENGTH), 691 &extrap->string, 692 false); 693 if (name_string.free_after_use) { 694 retmem(name_string.buffer.start); 695 } 696 UNCACHE_SOURCE(); 697 extrap->string.text.p = 698 extrap->string.buffer.start; 699 extrap->fd = -1; 700 /* And push the value */ 701 extrap->previous = source; 702 source = extrap; 703 CACHE_SOURCE(0); 704 goto line_evald; 705 } 706 } 707 default: 708 goto line_evald; 709 } 710 711 /* We now have a line we can start reading */ 712 line_evald: 713 if (source == NULL) { 714 GOTO_STATE(exit_state); 715 } 716 /* Check if this is an include command */ 717 if ((makefile_type == reading_makefile) && 718 !source->already_expanded) { 719 if (include_space[0] == (int) nul_char) { 720 MBSTOWCS(include_space, NOCATGETS("include ")); 721 MBSTOWCS(include_tab, NOCATGETS("include\t")); 722 } 723 if ((IS_WEQUALN(source_p, include_space, 8)) || 724 (IS_WEQUALN(source_p, include_tab, 8))) { 725 source_p += 7; 726 if (iswspace(*source_p)) { 727 Makefile_type save_makefile_type; 728 wchar_t *name_start; 729 int name_length; 730 731 /* 732 * Yes, this is an include. 733 * Skip spaces to get to the filename. 734 */ 735 while (iswspace(*source_p) || 736 (*source_p == (int) nul_char)) { 737 switch (GET_CHAR()) { 738 case nul_char: 739 GET_NEXT_BLOCK(source); 740 if (source == NULL) { 741 GOTO_STATE(on_eoln_state); 742 } 743 break; 744 745 default: 746 source_p++; 747 break; 748 } 749 } 750 751 string_start = source_p; 752 /* Find the end of the filename */ 753 macro_seen_in_string = false; 754 while (!iswspace(*source_p) || 755 (*source_p == (int) nul_char)) { 756 switch (GET_CHAR()) { 757 case nul_char: 758 if (!macro_seen_in_string) { 759 INIT_STRING_FROM_STACK(name_string, 760 name_buffer); 761 } 762 append_string(string_start, 763 &name_string, 764 source_p - string_start); 765 macro_seen_in_string = true; 766 GET_NEXT_BLOCK(source); 767 string_start = source_p; 768 if (source == NULL) { 769 GOTO_STATE(on_eoln_state); 770 } 771 break; 772 773 default: 774 source_p++; 775 break; 776 } 777 } 778 779 source->string.text.p = source_p; 780 if (macro_seen_in_string) { 781 append_string(string_start, 782 &name_string, 783 source_p - string_start); 784 name_start = name_string.buffer.start; 785 name_length = name_string.text.p - name_start; 786 } else { 787 name_start = string_start; 788 name_length = source_p - string_start; 789 } 790 791 /* Strip "./" from the head of the name */ 792 if ((name_start[0] == (int) period_char) && 793 (name_start[1] == (int) slash_char)) { 794 name_start += 2; 795 name_length -= 2; 796 } 797 /* if include file name is surrounded by double quotes */ 798 if ((name_start[0] == (int) doublequote_char) && 799 (name_start[name_length - 1] == (int) doublequote_char)) { 800 name_start += 1; 801 name_length -= 2; 802 803 /* if name does not begin with a slash char */ 804 if (name_start[0] != (int) slash_char) { 805 if ((name_start[0] == (int) period_char) && 806 (name_start[1] == (int) slash_char)) { 807 name_start += 2; 808 name_length -= 2; 809 } 810 811 INIT_STRING_FROM_STACK(include_name, include_buffer); 812 APPEND_NAME(true_makefile_name, 813 &include_name, 814 true_makefile_name->hash.length); 815 816 wchar_t *slash = wsrchr(include_name.buffer.start, (int) slash_char); 817 if (slash != NULL) { 818 include_name.text.p = slash + 1; 819 append_string(name_start, 820 &include_name, 821 name_length); 822 823 name_start = include_name.buffer.start; 824 name_length = include_name.text.p - name_start; 825 } 826 } 827 } 828 829 /* Even when we run -n we want to create makefiles */ 830 do_not_exec_rule = false; 831 makefile_name = GETNAME(name_start, name_length); 832 if (makefile_name->dollar) { 833 String_rec destination; 834 wchar_t buffer[STRING_BUFFER_LENGTH]; 835 wchar_t *p; 836 wchar_t *q; 837 838 INIT_STRING_FROM_STACK(destination, buffer); 839 expand_value(makefile_name, 840 &destination, 841 false); 842 for (p = destination.buffer.start; 843 (*p != (int) nul_char) && iswspace(*p); 844 p++); 845 for (q = p; 846 (*q != (int) nul_char) && !iswspace(*q); 847 q++); 848 makefile_name = GETNAME(p, q-p); 849 if (destination.free_after_use) { 850 retmem(destination.buffer.start); 851 } 852 } 853 source_p++; 854 UNCACHE_SOURCE(); 855 /* Read the file */ 856 save_makefile_type = makefile_type; 857 if (read_simple_file(makefile_name, 858 true, 859 true, 860 true, 861 false, 862 true, 863 false) == failed) { 864 fatal_reader(catgets(catd, 1, 75, "Read of include file `%s' failed"), 865 makefile_name->string_mb); 866 } 867 makefile_type = save_makefile_type; 868 do_not_exec_rule = save_do_not_exec_rule; 869 CACHE_SOURCE(0); 870 goto start_new_line; 871 } else { 872 source_p -= 7; 873 } 874 } else { 875 /* Check if the word include was split across 8K boundary. */ 876 877 tmp_bytes_left_in_string = source->string.text.end - source_p; 878 if (tmp_bytes_left_in_string < 8) { 879 tmp_maybe_include = false; 880 if (IS_WEQUALN(source_p, 881 include_space, 882 tmp_bytes_left_in_string)) { 883 tmp_maybe_include = true; 884 } 885 if (tmp_maybe_include) { 886 GET_NEXT_BLOCK(source); 887 tmp_maybe_include = false; 888 goto line_evald; 889 } 890 } 891 } 892 } 893 894 /* Reset the status in preparation for the new line */ 895 for (nvp = ⌖ nvp != NULL; nvp = nvp->next) { 896 nvp->used = 0; 897 } 898 for (nvp = &depes; nvp != NULL; nvp = nvp->next) { 899 nvp->used = 0; 900 } 901 target_group_seen = false; 902 command = command_tail = NULL; 903 macro_value = NULL; 904 append = false; 905 current_names = ⌖ 906 SET_STATE(scan_name_state); 907 on_eoln_state = illegal_eoln_state; 908 separator = none_seen; 909 910 /* The state machine starts here */ 911 enter_state: 912 while (1) switch (state) { 913 914 /**************************************************************** 915 * Scan name state 916 */ 917 case scan_name_state: 918 /* Scan an identifier. We skip over chars until we find a break char */ 919 /* First skip white space. */ 920 for (; 1; source_p++) switch (GET_CHAR()) { 921 case nul_char: 922 GET_NEXT_BLOCK(source); 923 source_p--; 924 if (source == NULL) { 925 GOTO_STATE(on_eoln_state); 926 } 927 break; 928 case newline_char: 929 /* We found the end of the line. */ 930 /* Do postprocessing or return error */ 931 source_p++; 932 if (source->fd >= 0) { 933 line_number++; 934 } 935 GOTO_STATE(on_eoln_state); 936 case backslash_char: 937 /* Continuation */ 938 if (*++source_p == (int) nul_char) { 939 GET_NEXT_BLOCK(source); 940 if (source == NULL) { 941 GOTO_STATE(on_eoln_state); 942 } 943 } 944 if (*source_p == (int) newline_char) { 945 if (source->fd >= 0) { 946 line_number++; 947 } 948 } else { 949 source_p--; 950 } 951 break; 952 case tab_char: 953 case space_char: 954 /* Whitespace is skipped */ 955 break; 956 case numbersign_char: 957 /* Comment. Skip over it */ 958 for (; 1; source_p++) { 959 switch (GET_CHAR()) { 960 case nul_char: 961 GET_NEXT_BLOCK_NOCHK(source); 962 if (source == NULL) { 963 GOTO_STATE(on_eoln_state); 964 } 965 if (source->error_converting) { 966 // Illegal byte sequence - skip its first byte 967 source->inp_buf_ptr++; 968 } 969 source_p--; 970 break; 971 case backslash_char: 972 if (*++source_p == (int) nul_char) { 973 GET_NEXT_BLOCK_NOCHK(source); 974 if (source == NULL) { 975 GOTO_STATE(on_eoln_state); 976 } 977 if (source->error_converting) { 978 // Illegal byte sequence - skip its first byte 979 source->inp_buf_ptr++; 980 source_p--; 981 break; 982 } 983 } 984 if(*source_p == (int) newline_char) { 985 if (source->fd >= 0) { 986 line_number++; 987 } 988 } 989 break; 990 case newline_char: 991 source_p++; 992 if (source->fd >= 0) { 993 line_number++; 994 } 995 GOTO_STATE(on_eoln_state); 996 } 997 } 998 case dollar_char: 999 /* Macro reference. Expand and push value */ 1000 if (source->already_expanded) { 1001 goto scan_name; 1002 } 1003 source_p++; 1004 UNCACHE_SOURCE(); 1005 { 1006 Source t = (Source) alloca((int) sizeof (Source_rec)); 1007 source = push_macro_value(t, 1008 buffer, 1009 sizeof buffer, 1010 source); 1011 } 1012 CACHE_SOURCE(1); 1013 break; 1014 default: 1015 /* End of white space */ 1016 goto scan_name; 1017 } 1018 1019 /* First proper identifier character */ 1020 scan_name: 1021 1022 string_start = source_p; 1023 paren_count = brace_count = 0; 1024 macro_seen_in_string = false; 1025 resume_name_scan: 1026 for (; 1; source_p++) { 1027 switch (GET_CHAR()) { 1028 case nul_char: 1029 /* Save what we have seen so far of the identifier */ 1030 if (source_p != string_start) { 1031 if (!macro_seen_in_string) { 1032 INIT_STRING_FROM_STACK(name_string, 1033 name_buffer); 1034 } 1035 append_string(string_start, 1036 &name_string, 1037 source_p - string_start); 1038 macro_seen_in_string = true; 1039 } 1040 /* Get more text to read */ 1041 GET_NEXT_BLOCK(source); 1042 string_start = source_p; 1043 source_p--; 1044 if (source == NULL) { 1045 GOTO_STATE(on_eoln_state); 1046 } 1047 break; 1048 case newline_char: 1049 if (paren_count > 0) { 1050 fatal_reader(catgets(catd, 1, 76, "Unmatched `(' on line")); 1051 } 1052 if (brace_count > 0) { 1053 fatal_reader(catgets(catd, 1, 77, "Unmatched `{' on line")); 1054 } 1055 source_p++; 1056 /* Enter name */ 1057 current_names = enter_name(&name_string, 1058 macro_seen_in_string, 1059 string_start, 1060 source_p - 1, 1061 current_names, 1062 &extra_names, 1063 &target_group_seen); 1064 first_target = false; 1065 if (extra_names == NULL) { 1066 extra_names = (Name_vector) 1067 alloca((int) sizeof (Name_vector_rec)); 1068 } 1069 /* Do postprocessing or return error */ 1070 if (source->fd >= 0) { 1071 line_number++; 1072 } 1073 GOTO_STATE(on_eoln_state); 1074 case backslash_char: 1075 /* Check if this is a quoting backslash */ 1076 if (!macro_seen_in_string) { 1077 INIT_STRING_FROM_STACK(name_string, 1078 name_buffer); 1079 macro_seen_in_string = true; 1080 } 1081 append_string(string_start, 1082 &name_string, 1083 source_p - string_start); 1084 if (*++source_p == (int) nul_char) { 1085 GET_NEXT_BLOCK(source); 1086 if (source == NULL) { 1087 GOTO_STATE(on_eoln_state); 1088 } 1089 } 1090 if (*source_p == (int) newline_char) { 1091 if (source->fd >= 0) { 1092 line_number++; 1093 } 1094 *source_p = (int) space_char; 1095 string_start = source_p; 1096 goto resume_name_scan; 1097 } else { 1098 string_start = source_p; 1099 break; 1100 } 1101 break; 1102 case numbersign_char: 1103 if (paren_count + brace_count > 0) { 1104 break; 1105 } 1106 fatal_reader(catgets(catd, 1, 78, "Unexpected comment seen")); 1107 case dollar_char: 1108 if (source->already_expanded) { 1109 break; 1110 } 1111 /* Save the identifier so far */ 1112 if (source_p != string_start) { 1113 if (!macro_seen_in_string) { 1114 INIT_STRING_FROM_STACK(name_string, 1115 name_buffer); 1116 } 1117 append_string(string_start, 1118 &name_string, 1119 source_p - string_start); 1120 macro_seen_in_string = true; 1121 } 1122 /* Eval and push the macro */ 1123 source_p++; 1124 UNCACHE_SOURCE(); 1125 { 1126 Source t = 1127 (Source) alloca((int) sizeof (Source_rec)); 1128 source = push_macro_value(t, 1129 buffer, 1130 sizeof buffer, 1131 source); 1132 } 1133 CACHE_SOURCE(1); 1134 string_start = source_p + 1; 1135 break; 1136 case parenleft_char: 1137 paren_count++; 1138 break; 1139 case parenright_char: 1140 if (--paren_count < 0) { 1141 fatal_reader(catgets(catd, 1, 79, "Unmatched `)' on line")); 1142 } 1143 break; 1144 case braceleft_char: 1145 brace_count++; 1146 break; 1147 case braceright_char: 1148 if (--brace_count < 0) { 1149 fatal_reader(catgets(catd, 1, 80, "Unmatched `}' on line")); 1150 } 1151 break; 1152 case ampersand_char: 1153 case greater_char: 1154 case bar_char: 1155 if (paren_count + brace_count == 0) { 1156 source_p++; 1157 } 1158 /* Fall into */ 1159 case tab_char: 1160 case space_char: 1161 if (paren_count + brace_count > 0) { 1162 break; 1163 } 1164 current_names = enter_name(&name_string, 1165 macro_seen_in_string, 1166 string_start, 1167 source_p, 1168 current_names, 1169 &extra_names, 1170 &target_group_seen); 1171 first_target = false; 1172 if (extra_names == NULL) { 1173 extra_names = (Name_vector) 1174 alloca((int) sizeof (Name_vector_rec)); 1175 } 1176 goto enter_state; 1177 case colon_char: 1178 if (paren_count + brace_count > 0) { 1179 break; 1180 } 1181 if (separator == conditional_seen) { 1182 break; 1183 } 1184 /** POSIX **/ 1185 #if 0 1186 if(posix) { 1187 emptycount = 0; 1188 } 1189 #endif 1190 /** END POSIX **/ 1191 /* End of the target list. We now start reading */ 1192 /* dependencies or a conditional assignment */ 1193 if (separator != none_seen) { 1194 fatal_reader(catgets(catd, 1, 81, "Extra `:', `::', or `:=' on dependency line")); 1195 } 1196 /* Enter the last target */ 1197 if ((string_start != source_p) || 1198 macro_seen_in_string) { 1199 current_names = 1200 enter_name(&name_string, 1201 macro_seen_in_string, 1202 string_start, 1203 source_p, 1204 current_names, 1205 &extra_names, 1206 &target_group_seen); 1207 first_target = false; 1208 if (extra_names == NULL) { 1209 extra_names = (Name_vector) 1210 alloca((int) 1211 sizeof (Name_vector_rec)); 1212 } 1213 } 1214 /* Check if it is ":" "::" or ":=" */ 1215 scan_colon_label: 1216 switch (*++source_p) { 1217 case nul_char: 1218 GET_NEXT_BLOCK(source); 1219 source_p--; 1220 if (source == NULL) { 1221 GOTO_STATE(enter_dependencies_state); 1222 } 1223 goto scan_colon_label; 1224 case equal_char: 1225 if(svr4) { 1226 fatal_reader(catgets(catd, 1, 82, "syntax error")); 1227 } 1228 separator = conditional_seen; 1229 source_p++; 1230 current_names = &depes; 1231 GOTO_STATE(scan_name_state); 1232 case colon_char: 1233 separator = two_colon; 1234 source_p++; 1235 break; 1236 default: 1237 separator = one_colon; 1238 } 1239 current_names = &depes; 1240 on_eoln_state = enter_dependencies_state; 1241 GOTO_STATE(scan_name_state); 1242 case semicolon_char: 1243 if (paren_count + brace_count > 0) { 1244 break; 1245 } 1246 /* End of reading names. Start reading the rule */ 1247 if ((separator != one_colon) && 1248 (separator != two_colon)) { 1249 fatal_reader(catgets(catd, 1, 83, "Unexpected command seen")); 1250 } 1251 /* Enter the last dependency */ 1252 if ((string_start != source_p) || 1253 macro_seen_in_string) { 1254 current_names = 1255 enter_name(&name_string, 1256 macro_seen_in_string, 1257 string_start, 1258 source_p, 1259 current_names, 1260 &extra_names, 1261 &target_group_seen); 1262 first_target = false; 1263 if (extra_names == NULL) { 1264 extra_names = (Name_vector) 1265 alloca((int) 1266 sizeof (Name_vector_rec)); 1267 } 1268 } 1269 source_p++; 1270 /* Make sure to enter a rule even if the is */ 1271 /* no text here */ 1272 command = command_tail = ALLOC(Cmd_line); 1273 command->next = NULL; 1274 command->command_line = empty_name; 1275 command->make_refd = false; 1276 command->ignore_command_dependency = false; 1277 command->assign = false; 1278 command->ignore_error = false; 1279 command->silent = false; 1280 1281 GOTO_STATE(scan_command_state); 1282 case plus_char: 1283 /* 1284 ** following code drops the target separator plus char if it starts 1285 ** a line. 1286 */ 1287 if(first_target && !macro_seen_in_string && 1288 source_p == string_start) { 1289 for (; 1; source_p++) 1290 switch (GET_CHAR()) { 1291 case nul_char: 1292 if (source_p != string_start) { 1293 if (!macro_seen_in_string) { 1294 INIT_STRING_FROM_STACK(name_string, 1295 name_buffer); 1296 } 1297 append_string(string_start, 1298 &name_string, 1299 source_p - string_start); 1300 macro_seen_in_string = true; 1301 } 1302 GET_NEXT_BLOCK(source); 1303 string_start = source_p; 1304 source_p--; 1305 if (source == NULL) { 1306 GOTO_STATE(on_eoln_state); 1307 } 1308 break; 1309 case plus_char: 1310 source_p++; 1311 while (*source_p == (int) nul_char) { 1312 if (source_p != string_start) { 1313 if (!macro_seen_in_string) { 1314 INIT_STRING_FROM_STACK(name_string, 1315 name_buffer); 1316 } 1317 append_string(string_start, 1318 &name_string, 1319 source_p - string_start); 1320 macro_seen_in_string = true; 1321 } 1322 GET_NEXT_BLOCK(source); 1323 string_start = source_p; 1324 if (source == NULL) { 1325 GOTO_STATE(on_eoln_state); 1326 } 1327 } 1328 if (*source_p == (int) tab_char || 1329 *source_p == (int) space_char) { 1330 macro_seen_in_string = false; 1331 string_start = source_p + 1; 1332 } else { 1333 goto resume_name_scan; 1334 } 1335 break; 1336 case tab_char: 1337 case space_char: 1338 string_start = source_p + 1; 1339 break; 1340 default: 1341 goto resume_name_scan; 1342 } 1343 } 1344 if (paren_count + brace_count > 0) { 1345 break; 1346 } 1347 /* We found "+=" construct */ 1348 if (source_p != string_start) { 1349 /* "+" is not a break char. */ 1350 /* Ignore it if it is part of an identifier */ 1351 source_p++; 1352 goto resume_name_scan; 1353 } 1354 /* Make sure the "+" is followed by a "=" */ 1355 scan_append: 1356 switch (*++source_p) { 1357 case nul_char: 1358 if (!macro_seen_in_string) { 1359 INIT_STRING_FROM_STACK(name_string, 1360 name_buffer); 1361 } 1362 append_string(string_start, 1363 &name_string, 1364 source_p - string_start); 1365 GET_NEXT_BLOCK(source); 1366 source_p--; 1367 string_start = source_p; 1368 if (source == NULL) { 1369 GOTO_STATE(illegal_eoln_state); 1370 } 1371 goto scan_append; 1372 case equal_char: 1373 if(!svr4) { 1374 append = true; 1375 } else { 1376 fatal_reader(catgets(catd, 1, 84, "Must be a separator on rules")); 1377 } 1378 break; 1379 default: 1380 /* The "+" just starts a regular name. */ 1381 /* Start reading that name */ 1382 goto resume_name_scan; 1383 } 1384 /* Fall into */ 1385 case equal_char: 1386 if (paren_count + brace_count > 0) { 1387 break; 1388 } 1389 /* We found macro assignment. */ 1390 /* Check if it is legal and if it is appending */ 1391 switch (separator) { 1392 case none_seen: 1393 separator = equal_seen; 1394 on_eoln_state = enter_equal_state; 1395 break; 1396 case conditional_seen: 1397 on_eoln_state = enter_conditional_state; 1398 break; 1399 default: 1400 /* Reader must special check for "MACRO:sh=" */ 1401 /* notation */ 1402 if (sh_name == NULL) { 1403 MBSTOWCS(wcs_buffer, NOCATGETS("sh")); 1404 sh_name = GETNAME(wcs_buffer, FIND_LENGTH); 1405 MBSTOWCS(wcs_buffer, NOCATGETS("shell")); 1406 shell_name = GETNAME(wcs_buffer, FIND_LENGTH); 1407 } 1408 1409 if (!macro_seen_in_string) { 1410 INIT_STRING_FROM_STACK(name_string, 1411 name_buffer); 1412 } 1413 append_string(string_start, 1414 &name_string, 1415 source_p - string_start 1416 ); 1417 1418 if ( (((target.used == 1) && 1419 (depes.used == 1) && 1420 (depes.names[0] == sh_name)) || 1421 ((target.used == 1) && 1422 (depes.used == 0) && 1423 (separator == one_colon) && 1424 (GETNAME(name_string.buffer.start,FIND_LENGTH) == sh_name))) && 1425 (!svr4)) { 1426 String_rec macro_name; 1427 wchar_t buffer[100]; 1428 1429 INIT_STRING_FROM_STACK(macro_name, 1430 buffer); 1431 APPEND_NAME(target.names[0], 1432 ¯o_name, 1433 FIND_LENGTH); 1434 append_char((int) colon_char, 1435 ¯o_name); 1436 APPEND_NAME(sh_name, 1437 ¯o_name, 1438 FIND_LENGTH); 1439 target.names[0] = 1440 GETNAME(macro_name.buffer.start, 1441 FIND_LENGTH); 1442 separator = equal_seen; 1443 on_eoln_state = enter_equal_state; 1444 break; 1445 } else if ( (((target.used == 1) && 1446 (depes.used == 1) && 1447 (depes.names[0] == shell_name)) || 1448 ((target.used == 1) && 1449 (depes.used == 0) && 1450 (separator == one_colon) && 1451 (GETNAME(name_string.buffer.start,FIND_LENGTH) == shell_name))) && 1452 (!svr4)) { 1453 String_rec macro_name; 1454 wchar_t buffer[100]; 1455 1456 INIT_STRING_FROM_STACK(macro_name, 1457 buffer); 1458 APPEND_NAME(target.names[0], 1459 ¯o_name, 1460 FIND_LENGTH); 1461 append_char((int) colon_char, 1462 ¯o_name); 1463 APPEND_NAME(shell_name, 1464 ¯o_name, 1465 FIND_LENGTH); 1466 target.names[0] = 1467 GETNAME(macro_name.buffer.start, 1468 FIND_LENGTH); 1469 separator = equal_seen; 1470 on_eoln_state = enter_equal_state; 1471 break; 1472 } 1473 if(svr4) { 1474 fatal_reader(catgets(catd, 1, 85, "syntax error")); 1475 } 1476 else { 1477 fatal_reader(catgets(catd, 1, 86, "Macro assignment on dependency line")); 1478 } 1479 } 1480 if (append) { 1481 source_p--; 1482 } 1483 /* Enter the macro name */ 1484 if ((string_start != source_p) || 1485 macro_seen_in_string) { 1486 current_names = 1487 enter_name(&name_string, 1488 macro_seen_in_string, 1489 string_start, 1490 source_p, 1491 current_names, 1492 &extra_names, 1493 &target_group_seen); 1494 first_target = false; 1495 if (extra_names == NULL) { 1496 extra_names = (Name_vector) 1497 alloca((int) 1498 sizeof (Name_vector_rec)); 1499 } 1500 } 1501 if (append) { 1502 source_p++; 1503 } 1504 macro_value = NULL; 1505 source_p++; 1506 distance = 0; 1507 /* Skip whitespace to the start of the value */ 1508 macro_seen_in_string = false; 1509 for (; 1; source_p++) { 1510 switch (GET_CHAR()) { 1511 case nul_char: 1512 GET_NEXT_BLOCK(source); 1513 source_p--; 1514 if (source == NULL) { 1515 GOTO_STATE(on_eoln_state); 1516 } 1517 break; 1518 case backslash_char: 1519 if (*++source_p == (int) nul_char) { 1520 GET_NEXT_BLOCK(source); 1521 if (source == NULL) { 1522 GOTO_STATE(on_eoln_state); 1523 } 1524 } 1525 if (*source_p != (int) newline_char) { 1526 if (!macro_seen_in_string) { 1527 macro_seen_in_string = 1528 true; 1529 INIT_STRING_FROM_STACK(name_string, 1530 name_buffer); 1531 } 1532 append_char((int) 1533 backslash_char, 1534 &name_string); 1535 append_char(*source_p, 1536 &name_string); 1537 string_start = source_p+1; 1538 goto macro_value_start; 1539 } else { 1540 if (source->fd >= 0) { 1541 line_number++; 1542 } 1543 } 1544 break; 1545 case newline_char: 1546 case numbersign_char: 1547 string_start = source_p; 1548 goto macro_value_end; 1549 case tab_char: 1550 case space_char: 1551 break; 1552 default: 1553 string_start = source_p; 1554 goto macro_value_start; 1555 } 1556 } 1557 macro_value_start: 1558 /* Find the end of the value */ 1559 for (; 1; source_p++) { 1560 if (distance != 0) { 1561 *source_p = *(source_p + distance); 1562 } 1563 switch (GET_CHAR()) { 1564 case nul_char: 1565 if (!macro_seen_in_string) { 1566 macro_seen_in_string = true; 1567 INIT_STRING_FROM_STACK(name_string, 1568 name_buffer); 1569 } 1570 append_string(string_start, 1571 &name_string, 1572 source_p - string_start); 1573 GET_NEXT_BLOCK(source); 1574 string_start = source_p; 1575 source_p--; 1576 if (source == NULL) { 1577 GOTO_STATE(on_eoln_state); 1578 } 1579 break; 1580 case backslash_char: 1581 source_p++; 1582 if (distance != 0) { 1583 *source_p = 1584 *(source_p + distance); 1585 } 1586 if (*source_p == (int) nul_char) { 1587 if (!macro_seen_in_string) { 1588 macro_seen_in_string = 1589 true; 1590 INIT_STRING_FROM_STACK(name_string, 1591 name_buffer); 1592 } 1593 1594 /* BID_1225561 */ 1595 *(source_p - 1) = (int) space_char; 1596 append_string(string_start, 1597 &name_string, 1598 source_p - 1599 string_start - 1); 1600 GET_NEXT_BLOCK(source); 1601 string_start = source_p; 1602 if (source == NULL) { 1603 GOTO_STATE(on_eoln_state); 1604 } 1605 if (distance != 0) { 1606 *source_p = 1607 *(source_p + 1608 distance); 1609 } 1610 if (*source_p == (int) newline_char) { 1611 append_char((int) space_char, &name_string); 1612 } else { 1613 append_char((int) backslash_char, &name_string); 1614 } 1615 /****************/ 1616 } 1617 if (*source_p == (int) newline_char) { 1618 source_p--; 1619 line_number++; 1620 distance++; 1621 *source_p = (int) space_char; 1622 while ((*(source_p + 1623 distance + 1) == 1624 (int) tab_char) || 1625 (*(source_p + 1626 distance + 1) == 1627 (int) space_char)) { 1628 distance++; 1629 } 1630 } 1631 break; 1632 case newline_char: 1633 case numbersign_char: 1634 goto macro_value_end; 1635 } 1636 } 1637 macro_value_end: 1638 /* Complete the value in the string */ 1639 if (!macro_seen_in_string) { 1640 macro_seen_in_string = true; 1641 INIT_STRING_FROM_STACK(name_string, 1642 name_buffer); 1643 } 1644 append_string(string_start, 1645 &name_string, 1646 source_p - string_start); 1647 if (name_string.buffer.start != name_string.text.p) { 1648 macro_value = 1649 GETNAME(name_string.buffer.start, 1650 FIND_LENGTH); 1651 } 1652 if (name_string.free_after_use) { 1653 retmem(name_string.buffer.start); 1654 } 1655 for (; distance > 0; distance--) { 1656 *source_p++ = (int) space_char; 1657 } 1658 GOTO_STATE(on_eoln_state); 1659 } 1660 } 1661 1662 /**************************************************************** 1663 * enter dependencies state 1664 */ 1665 case enter_dependencies_state: 1666 enter_dependencies_label: 1667 /* Expects pointer on first non whitespace char after last dependency. (On */ 1668 /* next line.) We end up here after having read a "targets : dependencies" */ 1669 /* line. The state checks if there is a rule to read and if so dispatches */ 1670 /* to scan_command_state scan_command_state reads one rule line and the */ 1671 /* returns here */ 1672 1673 /* First check if the first char on the next line is special */ 1674 switch (GET_CHAR()) { 1675 case nul_char: 1676 GET_NEXT_BLOCK(source); 1677 if (source == NULL) { 1678 break; 1679 } 1680 goto enter_dependencies_label; 1681 case exclam_char: 1682 /* The line should be evaluate before it is read */ 1683 macro_seen_in_string = false; 1684 string_start = source_p + 1; 1685 for (; 1; source_p++) { 1686 switch (GET_CHAR()) { 1687 case newline_char: 1688 goto eoln_2; 1689 case nul_char: 1690 if (source->fd > 0) { 1691 if (!macro_seen_in_string) { 1692 macro_seen_in_string = true; 1693 INIT_STRING_FROM_STACK(name_string, 1694 name_buffer); 1695 } 1696 append_string(string_start, 1697 &name_string, 1698 source_p - string_start); 1699 GET_NEXT_BLOCK(source); 1700 string_start = source_p; 1701 source_p--; 1702 break; 1703 } 1704 eoln_2: 1705 if (!macro_seen_in_string) { 1706 INIT_STRING_FROM_STACK(name_string, 1707 name_buffer); 1708 } 1709 append_string(string_start, 1710 &name_string, 1711 source_p - string_start); 1712 extrap = (Source) 1713 alloca((int) sizeof (Source_rec)); 1714 extrap->string.buffer.start = NULL; 1715 extrap->inp_buf = 1716 extrap->inp_buf_ptr = 1717 extrap->inp_buf_end = NULL; 1718 extrap->error_converting = false; 1719 expand_value(GETNAME(name_string.buffer.start, 1720 FIND_LENGTH), 1721 &extrap->string, 1722 false); 1723 if (name_string.free_after_use) { 1724 retmem(name_string.buffer.start); 1725 } 1726 UNCACHE_SOURCE(); 1727 extrap->string.text.p = 1728 extrap->string.buffer.start; 1729 extrap->fd = -1; 1730 extrap->previous = source; 1731 source = extrap; 1732 CACHE_SOURCE(0); 1733 goto enter_dependencies_label; 1734 } 1735 } 1736 case dollar_char: 1737 if (source->already_expanded) { 1738 break; 1739 } 1740 source_p++; 1741 UNCACHE_SOURCE(); 1742 { 1743 Source t = (Source) alloca((int) sizeof (Source_rec)); 1744 source = push_macro_value(t, 1745 buffer, 1746 sizeof buffer, 1747 source); 1748 } 1749 CACHE_SOURCE(0); 1750 goto enter_dependencies_label; 1751 case numbersign_char: 1752 if (makefile_type != reading_makefile) { 1753 source_p++; 1754 GOTO_STATE(scan_command_state); 1755 } 1756 for (; 1; source_p++) { 1757 switch (GET_CHAR()) { 1758 case nul_char: 1759 GET_NEXT_BLOCK_NOCHK(source); 1760 if (source == NULL) { 1761 GOTO_STATE(on_eoln_state); 1762 } 1763 if (source->error_converting) { 1764 // Illegal byte sequence - skip its first byte 1765 source->inp_buf_ptr++; 1766 } 1767 source_p--; 1768 break; 1769 case backslash_char: 1770 if (*++source_p == (int) nul_char) { 1771 GET_NEXT_BLOCK_NOCHK(source); 1772 if (source == NULL) { 1773 GOTO_STATE(on_eoln_state); 1774 } 1775 if (source->error_converting) { 1776 // Illegal byte sequence - skip its first byte 1777 source->inp_buf_ptr++; 1778 source_p--; 1779 break; 1780 } 1781 } 1782 if(*source_p == (int) newline_char) { 1783 if (source->fd >= 0) { 1784 line_number++; 1785 } 1786 } 1787 break; 1788 case newline_char: 1789 source_p++; 1790 if (source->fd >= 0) { 1791 line_number++; 1792 } 1793 goto enter_dependencies_label; 1794 } 1795 } 1796 1797 case tab_char: 1798 GOTO_STATE(scan_command_state); 1799 } 1800 1801 /* We read all the command lines for the target/dependency line. */ 1802 /* Enter the stuff */ 1803 enter_target_groups_and_dependencies( &target, &depes, command, 1804 separator, target_group_seen); 1805 1806 goto start_new_line; 1807 1808 /**************************************************************** 1809 * scan command state 1810 */ 1811 case scan_command_state: 1812 /* We need to read one rule line. Do that and return to */ 1813 /* the enter dependencies state */ 1814 string_start = source_p; 1815 macro_seen_in_string = false; 1816 for (; 1; source_p++) { 1817 switch (GET_CHAR()) { 1818 case backslash_char: 1819 if (!macro_seen_in_string) { 1820 INIT_STRING_FROM_STACK(name_string, 1821 name_buffer); 1822 } 1823 append_string(string_start, 1824 &name_string, 1825 source_p - string_start); 1826 macro_seen_in_string = true; 1827 if (*++source_p == (int) nul_char) { 1828 GET_NEXT_BLOCK(source); 1829 if (source == NULL) { 1830 string_start = source_p; 1831 goto command_newline; 1832 } 1833 } 1834 append_char((int) backslash_char, &name_string); 1835 append_char(*source_p, &name_string); 1836 if (*source_p == (int) newline_char) { 1837 if (source->fd >= 0) { 1838 line_number++; 1839 } 1840 if (*++source_p == (int) nul_char) { 1841 GET_NEXT_BLOCK(source); 1842 if (source == NULL) { 1843 string_start = source_p; 1844 goto command_newline; 1845 } 1846 } 1847 if (*source_p == (int) tab_char) { 1848 source_p++; 1849 } 1850 } else { 1851 if (*++source_p == (int) nul_char) { 1852 GET_NEXT_BLOCK(source); 1853 if (source == NULL) { 1854 string_start = source_p; 1855 goto command_newline; 1856 } 1857 } 1858 } 1859 string_start = source_p; 1860 if ((*source_p == (int) newline_char) || 1861 (*source_p == (int) backslash_char) || 1862 (*source_p == (int) nul_char)) { 1863 source_p--; 1864 } 1865 break; 1866 case newline_char: 1867 command_newline: 1868 if ((string_start != source_p) || 1869 macro_seen_in_string) { 1870 if (macro_seen_in_string) { 1871 append_string(string_start, 1872 &name_string, 1873 source_p - string_start); 1874 string_start = 1875 name_string.buffer.start; 1876 string_end = name_string.text.p; 1877 } else { 1878 string_end = source_p; 1879 } 1880 while ((*string_start != (int) newline_char) && 1881 iswspace(*string_start)){ 1882 string_start++; 1883 } 1884 if ((string_end > string_start) || 1885 (makefile_type == reading_statefile)) { 1886 if (command_tail == NULL) { 1887 command = 1888 command_tail = 1889 ALLOC(Cmd_line); 1890 } else { 1891 command_tail->next = 1892 ALLOC(Cmd_line); 1893 command_tail = 1894 command_tail->next; 1895 } 1896 command_tail->next = NULL; 1897 command_tail->make_refd = false; 1898 command_tail->ignore_command_dependency = false; 1899 command_tail->assign = false; 1900 command_tail->ignore_error = false; 1901 command_tail->silent = false; 1902 command_tail->command_line = 1903 GETNAME(string_start, 1904 string_end - string_start); 1905 if (macro_seen_in_string && 1906 name_string.free_after_use) { 1907 retmem(name_string. 1908 buffer.start); 1909 } 1910 } 1911 } 1912 do { 1913 if ((source != NULL) && (source->fd >= 0)) { 1914 line_number++; 1915 } 1916 if ((source != NULL) && 1917 (*++source_p == (int) nul_char)) { 1918 GET_NEXT_BLOCK(source); 1919 if (source == NULL) { 1920 GOTO_STATE(on_eoln_state); 1921 } 1922 } 1923 } while (*source_p == (int) newline_char); 1924 1925 GOTO_STATE(enter_dependencies_state); 1926 case nul_char: 1927 if (!macro_seen_in_string) { 1928 INIT_STRING_FROM_STACK(name_string, 1929 name_buffer); 1930 } 1931 append_string(string_start, 1932 &name_string, 1933 source_p - string_start); 1934 macro_seen_in_string = true; 1935 GET_NEXT_BLOCK(source); 1936 string_start = source_p; 1937 source_p--; 1938 if (source == NULL) { 1939 GOTO_STATE(enter_dependencies_state); 1940 } 1941 break; 1942 } 1943 } 1944 1945 /**************************************************************** 1946 * enter equal state 1947 */ 1948 case enter_equal_state: 1949 if (target.used != 1) { 1950 GOTO_STATE(poorly_formed_macro_state); 1951 } 1952 enter_equal(target.names[0], macro_value, append); 1953 goto start_new_line; 1954 1955 /**************************************************************** 1956 * enter conditional state 1957 */ 1958 case enter_conditional_state: 1959 if (depes.used != 1) { 1960 GOTO_STATE(poorly_formed_macro_state); 1961 } 1962 for (nvp = ⌖ nvp != NULL; nvp = nvp->next) { 1963 for (i = 0; i < nvp->used; i++) { 1964 enter_conditional(nvp->names[i], 1965 depes.names[0], 1966 macro_value, 1967 append); 1968 } 1969 } 1970 goto start_new_line; 1971 1972 /**************************************************************** 1973 * Error states 1974 */ 1975 case illegal_bytes_state: 1976 fatal_reader(catgets(catd, 1, 340, "Invalid byte sequence")); 1977 case illegal_eoln_state: 1978 if (line_number > 1) { 1979 if (line_started_with_space == (line_number - 1)) { 1980 line_number--; 1981 fatal_reader(catgets(catd, 1, 90, "Unexpected end of line seen\n\t*** missing separator (did you mean TAB instead of 8 spaces?)")); 1982 } 1983 } 1984 fatal_reader(catgets(catd, 1, 87, "Unexpected end of line seen")); 1985 case poorly_formed_macro_state: 1986 fatal_reader(catgets(catd, 1, 88, "Badly formed macro assignment")); 1987 case exit_state: 1988 return; 1989 default: 1990 fatal_reader(catgets(catd, 1, 89, "Internal error. Unknown reader state")); 1991 } 1992 } 1993 1994 /* 1995 * push_macro_value(bp, buffer, size, source) 1996 * 1997 * Macro and function that evaluates one macro 1998 * and makes the reader read from the value of it 1999 * 2000 * Return value: 2001 * The source block to read the macro from 2002 * 2003 * Parameters: 2004 * bp The new source block to fill in 2005 * buffer Buffer to read from 2006 * size size of the buffer 2007 * source The old source block 2008 * 2009 * Global variables used: 2010 */ 2011 static Source 2012 push_macro_value(register Source bp, register wchar_t *buffer, int size, register Source source) 2013 { 2014 bp->string.buffer.start = bp->string.text.p = buffer; 2015 bp->string.text.end = NULL; 2016 bp->string.buffer.end = buffer + (size/SIZEOFWCHAR_T); 2017 bp->string.free_after_use = false; 2018 bp->inp_buf = 2019 bp->inp_buf_ptr = 2020 bp->inp_buf_end = NULL; 2021 bp->error_converting = false; 2022 expand_macro(source, &bp->string, (wchar_t *) NULL, false); 2023 bp->string.text.p = bp->string.buffer.start; 2024 2025 /* 4209588: 'make' doesn't understand a macro with whitespaces in the head as target. 2026 * strip whitespace from the begining of the macro value 2027 */ 2028 while (iswspace(*bp->string.text.p)) { 2029 bp->string.text.p++; 2030 } 2031 2032 bp->fd = -1; 2033 bp->already_expanded = true; 2034 bp->previous = source; 2035 return bp; 2036 } 2037 2038 /* 2039 * enter_target_groups_and_dependencies(target, depes, command, separator, 2040 * target_group_seen) 2041 * 2042 * Parameters: 2043 * target Structure that shows the target(s) on the line 2044 * we are currently parsing. This can looks like 2045 * target1 .. targetN : dependencies 2046 * commands 2047 * or 2048 * target1 + .. + targetN : dependencies 2049 * commands 2050 * depes Dependencies 2051 * command Points to the command(s) to be executed for 2052 * this target. 2053 * separator : or :: or := 2054 * target_group_seen Set if we have target1 + .. + targetN 2055 * 2056 * 2057 * After reading the command lines for a target, this routine 2058 * is called to setup the dependencies and the commands for it. 2059 * If the target is a % pattern or part of a target group, then 2060 * the appropriate routines are called. 2061 */ 2062 2063 void 2064 enter_target_groups_and_dependencies(Name_vector target, Name_vector depes, Cmd_line command, Separator separator, Boolean target_group_seen) 2065 { 2066 int i; 2067 Boolean reset= true; 2068 Chain target_group_member; 2069 Percent percent_ptr; 2070 2071 for (; target != NULL; target = target->next) { 2072 for (i = 0; i < target->used; i++) { 2073 if (target->names[i] != NULL) { 2074 if (target_group_seen) { 2075 target_group_member = 2076 find_target_groups(target, i, reset); 2077 if(target_group_member == NULL) { 2078 fatal_reader(catgets(catd, 1, 328, "Unexpected '+' on dependency line")); 2079 } 2080 } 2081 reset = false; 2082 2083 /* If we saw it in the makefile it must be 2084 * a file */ 2085 target->names[i]->stat.is_file = true; 2086 /* Make sure that we use dependencies 2087 * entered for makefiles */ 2088 target->names[i]->state = build_dont_know; 2089 2090 /* If the target is special we delegate 2091 * the processing */ 2092 if (target->names[i]->special_reader 2093 != no_special) { 2094 special_reader(target->names[i], 2095 depes, 2096 command); 2097 } 2098 /* Check if this is a "a%b : x%y" type rule */ 2099 else if (target->names[i]->percent) { 2100 percent_ptr = 2101 enter_percent(target->names[i], 2102 target->target_group[i], 2103 depes, command); 2104 if (target_group_seen) { 2105 target_group_member->percent_member = 2106 percent_ptr; 2107 } 2108 } else if (target->names[i]->dollar) { 2109 enter_dyntarget(target->names[i]); 2110 enter_dependencies 2111 (target->names[i], 2112 target->target_group[i], 2113 depes, 2114 command, 2115 separator); 2116 } else { 2117 if (target_group_seen) { 2118 target_group_member->percent_member = 2119 NULL; 2120 } 2121 2122 enter_dependencies 2123 (target->names[i], 2124 target->target_group[i], 2125 depes, 2126 command, 2127 separator); 2128 } 2129 } 2130 } 2131 } 2132 } 2133 2134