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