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