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