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