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