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