xref: /illumos-gate/usr/src/cmd/make/bin/read2.cc (revision e7afc443)
110d63b7dSRichard Lowe /*
210d63b7dSRichard Lowe  * CDDL HEADER START
310d63b7dSRichard Lowe  *
410d63b7dSRichard Lowe  * The contents of this file are subject to the terms of the
510d63b7dSRichard Lowe  * Common Development and Distribution License (the "License").
610d63b7dSRichard Lowe  * You may not use this file except in compliance with the License.
710d63b7dSRichard Lowe  *
810d63b7dSRichard Lowe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910d63b7dSRichard Lowe  * or http://www.opensolaris.org/os/licensing.
1010d63b7dSRichard Lowe  * See the License for the specific language governing permissions
1110d63b7dSRichard Lowe  * and limitations under the License.
1210d63b7dSRichard Lowe  *
1310d63b7dSRichard Lowe  * When distributing Covered Code, include this CDDL HEADER in each
1410d63b7dSRichard Lowe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510d63b7dSRichard Lowe  * If applicable, add the following below this CDDL HEADER, with the
1610d63b7dSRichard Lowe  * fields enclosed by brackets "[]" replaced with your own identifying
1710d63b7dSRichard Lowe  * information: Portions Copyright [yyyy] [name of copyright owner]
1810d63b7dSRichard Lowe  *
1910d63b7dSRichard Lowe  * CDDL HEADER END
2010d63b7dSRichard Lowe  */
2110d63b7dSRichard Lowe /*
2210d63b7dSRichard Lowe  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
2310d63b7dSRichard Lowe  * Use is subject to license terms.
248e0c8248SAndrew Stormont  *
258e0c8248SAndrew Stormont  * Copyright 2019 RackTop Systems.
2610d63b7dSRichard Lowe  */
2710d63b7dSRichard Lowe 
2810d63b7dSRichard Lowe /*
2910d63b7dSRichard Lowe  *	read.c
3010d63b7dSRichard Lowe  *
3110d63b7dSRichard Lowe  *	This file contains the makefile reader.
3210d63b7dSRichard Lowe  */
3310d63b7dSRichard Lowe 
3410d63b7dSRichard Lowe /*
3510d63b7dSRichard Lowe  * Included files
3610d63b7dSRichard Lowe  */
3710d63b7dSRichard Lowe #include <mk/defs.h>
3810d63b7dSRichard Lowe #include <mksh/dosys.h>		/* sh_command2string() */
3910d63b7dSRichard Lowe #include <mksh/macro.h>		/* expand_value() */
4010d63b7dSRichard Lowe #include <mksh/misc.h>		/* retmem() */
4110d63b7dSRichard Lowe #include <stdarg.h>		/* va_list, va_start(), va_end() */
4210d63b7dSRichard Lowe #include <libintl.h>
4310d63b7dSRichard Lowe 
4410d63b7dSRichard Lowe /*
4510d63b7dSRichard Lowe  * Defined macros
4610d63b7dSRichard Lowe  */
4710d63b7dSRichard Lowe 
4810d63b7dSRichard Lowe /*
4910d63b7dSRichard Lowe  * typedefs & structs
5010d63b7dSRichard Lowe  */
5110d63b7dSRichard Lowe 
5210d63b7dSRichard Lowe /*
5310d63b7dSRichard Lowe  * Static variables
5410d63b7dSRichard Lowe  */
5510d63b7dSRichard Lowe static	Boolean		built_last_make_run_seen;
5610d63b7dSRichard Lowe 
5710d63b7dSRichard Lowe /*
5810d63b7dSRichard Lowe  * File table of contents
5910d63b7dSRichard Lowe  */
60*e7afc443SToomas Soome static	Name_vector	enter_member_name(wchar_t *lib_start, wchar_t *member_start, wchar_t *string_end, Name_vector current_names, Name_vector *extra_names);
61*e7afc443SToomas Soome extern	Name		normalize_name(wchar_t *name_string, int length);
62*e7afc443SToomas Soome static	void		read_suffixes_list(Name_vector depes);
6310d63b7dSRichard Lowe static	void		make_relative(wchar_t *to, wchar_t *result);
64*e7afc443SToomas Soome static	void		print_rule(Cmd_line command);
6510d63b7dSRichard Lowe static	void		sh_transform(Name *name, Name *value);
6610d63b7dSRichard Lowe 
6710d63b7dSRichard Lowe 
6810d63b7dSRichard Lowe /*
6910d63b7dSRichard Lowe  *	enter_name(string, tail_present, string_start, string_end,
7010d63b7dSRichard Lowe  *	      current_names, extra_names, target_group_seen)
7110d63b7dSRichard Lowe  *
7210d63b7dSRichard Lowe  *	Take one string and enter it as a name. The string is passed in
7310d63b7dSRichard Lowe  *	two parts. A make string and possibly a C string to append to it.
7410d63b7dSRichard Lowe  *	The result is stuffed in the vector current_names.
7510d63b7dSRichard Lowe  *	extra_names points to a vector that is used if current_names overflows.
7610d63b7dSRichard Lowe  *	This is allocad in the calling routine.
7710d63b7dSRichard Lowe  *	Here we handle the "lib.a[members]" notation.
7810d63b7dSRichard Lowe  *
7910d63b7dSRichard Lowe  *	Return value:
8010d63b7dSRichard Lowe  *				The name vector that was used
8110d63b7dSRichard Lowe  *
8210d63b7dSRichard Lowe  *	Parameters:
8310d63b7dSRichard Lowe  *		tail_present	Indicates if both C and make string was passed
8410d63b7dSRichard Lowe  *		string_start	C string
8510d63b7dSRichard Lowe  *		string_end	Pointer to char after last in C string
8610d63b7dSRichard Lowe  *		string		make style string with head of name
8710d63b7dSRichard Lowe  *		current_names	Vector to deposit the name in
8810d63b7dSRichard Lowe  *		extra_names	Where to get next name vector if we run out
8910d63b7dSRichard Lowe  *		target_group_seen Pointer to boolean that is set if "+" is seen
9010d63b7dSRichard Lowe  *
9110d63b7dSRichard Lowe  *	Global variables used:
9210d63b7dSRichard Lowe  *		makefile_type	When we read a report file we normalize paths
9310d63b7dSRichard Lowe  *		plus		Points to the Name "+"
9410d63b7dSRichard Lowe  */
9510d63b7dSRichard Lowe 
9610d63b7dSRichard Lowe Name_vector
enter_name(String string,Boolean tail_present,wchar_t * string_start,wchar_t * string_end,Name_vector current_names,Name_vector * extra_names,Boolean * target_group_seen)97*e7afc443SToomas Soome enter_name(String string, Boolean tail_present, wchar_t *string_start, wchar_t *string_end, Name_vector current_names, Name_vector *extra_names, Boolean *target_group_seen)
9810d63b7dSRichard Lowe {
9910d63b7dSRichard Lowe 	Name			name;
100*e7afc443SToomas Soome 	wchar_t	*cp;
10110d63b7dSRichard Lowe 	wchar_t			ch;
10210d63b7dSRichard Lowe 
10310d63b7dSRichard Lowe 	/* If we were passed a separate tail of the name we append it to the */
10410d63b7dSRichard Lowe 	/* make string with the rest of it */
10510d63b7dSRichard Lowe 	if (tail_present) {
10610d63b7dSRichard Lowe 		append_string(string_start, string, string_end - string_start);
10710d63b7dSRichard Lowe 		string_start = string->buffer.start;
10810d63b7dSRichard Lowe 		string_end = string->text.p;
10910d63b7dSRichard Lowe 	}
11010d63b7dSRichard Lowe 	ch = *string_end;
11110d63b7dSRichard Lowe 	*string_end = (int) nul_char;
11210d63b7dSRichard Lowe 	/*
11310d63b7dSRichard Lowe 	 * Check if there are any ( or [ that are not prefixed with $.
11410d63b7dSRichard Lowe 	 * If there are, we have to deal with the lib.a(members) format.
11510d63b7dSRichard Lowe 	 */
11610d63b7dSRichard Lowe 	for (cp = (wchar_t *) wcschr(string_start, (int) parenleft_char);
11710d63b7dSRichard Lowe 	     cp != NULL;
11810d63b7dSRichard Lowe 	     cp = (wchar_t *) wcschr(cp + 1, (int) parenleft_char)) {
11910d63b7dSRichard Lowe 		if (*(cp - 1) != (int) dollar_char) {
12010d63b7dSRichard Lowe 			*string_end = ch;
12110d63b7dSRichard Lowe 			return enter_member_name(string_start,
12210d63b7dSRichard Lowe 						 cp,
12310d63b7dSRichard Lowe 						 string_end,
12410d63b7dSRichard Lowe 						 current_names,
12510d63b7dSRichard Lowe 						 extra_names);
12610d63b7dSRichard Lowe 		}
12710d63b7dSRichard Lowe 	}
12810d63b7dSRichard Lowe 	*string_end = ch;
12910d63b7dSRichard Lowe 
13010d63b7dSRichard Lowe 	if (makefile_type == reading_cpp_file) {
13110d63b7dSRichard Lowe 		/* Remove extra ../ constructs if we are reading from a report file */
13210d63b7dSRichard Lowe 		name = normalize_name(string_start, string_end - string_start);
13310d63b7dSRichard Lowe 	} else {
13410d63b7dSRichard Lowe 		/*
13510d63b7dSRichard Lowe 		 * /tolik, fix bug 1197477/
13610d63b7dSRichard Lowe 		 * Normalize every target name before entering.
13710d63b7dSRichard Lowe 		 * ..//obj/a.o and ../obj//a.o are not two different targets.
13810d63b7dSRichard Lowe 		 * There is only one target ../obj/a.o
13910d63b7dSRichard Lowe 		 */
14010d63b7dSRichard Lowe 		/*name = GETNAME(string_start, string_end - string_start);*/
14110d63b7dSRichard Lowe 		name = normalize_name(string_start, string_end - string_start);
14210d63b7dSRichard Lowe 	}
14310d63b7dSRichard Lowe 
14410d63b7dSRichard Lowe 	/* Internalize the name. Detect the name "+" (target group here) */
14510d63b7dSRichard Lowe if(current_names->used != 0 && current_names->names[current_names->used-1] == plus) {
14610d63b7dSRichard Lowe 	if(name == plus) {
14710d63b7dSRichard Lowe 		return current_names;
14810d63b7dSRichard Lowe 	}
14910d63b7dSRichard Lowe }
15010d63b7dSRichard Lowe 	/* If the current_names vector is full we patch in the one from */
15110d63b7dSRichard Lowe 	/* extra_names */
15210d63b7dSRichard Lowe 	if (current_names->used == VSIZEOF(current_names->names)) {
15310d63b7dSRichard Lowe 		if (current_names->next != NULL) {
15410d63b7dSRichard Lowe 			current_names = current_names->next;
15510d63b7dSRichard Lowe 		} else {
15610d63b7dSRichard Lowe 			current_names->next = *extra_names;
15710d63b7dSRichard Lowe 			*extra_names = NULL;
15810d63b7dSRichard Lowe 			current_names = current_names->next;
15910d63b7dSRichard Lowe 			current_names->used = 0;
16010d63b7dSRichard Lowe 			current_names->next = NULL;
16110d63b7dSRichard Lowe 		}
16210d63b7dSRichard Lowe 	}
16310d63b7dSRichard Lowe 	current_names->target_group[current_names->used] = NULL;
16410d63b7dSRichard Lowe 	current_names->names[current_names->used++] = name;
16510d63b7dSRichard Lowe 	if (name == plus) {
16610d63b7dSRichard Lowe 		*target_group_seen = true;
16710d63b7dSRichard Lowe 	}
16810d63b7dSRichard Lowe 	if (tail_present && string->free_after_use) {
16910d63b7dSRichard Lowe 		retmem(string->buffer.start);
17010d63b7dSRichard Lowe 	}
17110d63b7dSRichard Lowe 	return current_names;
17210d63b7dSRichard Lowe }
17310d63b7dSRichard Lowe 
17410d63b7dSRichard Lowe /*
17510d63b7dSRichard Lowe  *	enter_member_name(lib_start, member_start, string_end,
17610d63b7dSRichard Lowe  *		  current_names, extra_names)
17710d63b7dSRichard Lowe  *
17810d63b7dSRichard Lowe  *	A string has been found to contain member names.
17910d63b7dSRichard Lowe  *	(The "lib.a[members]" and "lib.a(members)" notation)
18010d63b7dSRichard Lowe  *	Handle it pretty much as enter_name() does for simple names.
18110d63b7dSRichard Lowe  *
18210d63b7dSRichard Lowe  *	Return value:
18310d63b7dSRichard Lowe  *				The name vector that was used
18410d63b7dSRichard Lowe  *
18510d63b7dSRichard Lowe  *	Parameters:
18610d63b7dSRichard Lowe  *		lib_start	Points to the of start of "lib.a(member.o)"
18710d63b7dSRichard Lowe  *		member_start	Points to "member.o" from above string.
18810d63b7dSRichard Lowe  *		string_end	Points to char after last of above string.
18910d63b7dSRichard Lowe  *		current_names	Vector to deposit the name in
19010d63b7dSRichard Lowe  *		extra_names	Where to get next name vector if we run out
19110d63b7dSRichard Lowe  *
19210d63b7dSRichard Lowe  *	Global variables used:
19310d63b7dSRichard Lowe  */
19410d63b7dSRichard Lowe static Name_vector
enter_member_name(wchar_t * lib_start,wchar_t * member_start,wchar_t * string_end,Name_vector current_names,Name_vector * extra_names)195*e7afc443SToomas Soome enter_member_name(wchar_t *lib_start, wchar_t *member_start, wchar_t *string_end, Name_vector current_names, Name_vector *extra_names)
19610d63b7dSRichard Lowe {
197*e7afc443SToomas Soome 	Boolean	entry = false;
19810d63b7dSRichard Lowe 	wchar_t			buffer[STRING_BUFFER_LENGTH];
19910d63b7dSRichard Lowe 	Name			lib;
20010d63b7dSRichard Lowe 	Name			member;
20110d63b7dSRichard Lowe 	Name			name;
20210d63b7dSRichard Lowe 	Property		prop;
20310d63b7dSRichard Lowe 	wchar_t			*memberp;
20410d63b7dSRichard Lowe 	wchar_t			*q;
205*e7afc443SToomas Soome 	int		paren_count;
206*e7afc443SToomas Soome 	Boolean	has_dollar;
207*e7afc443SToomas Soome 	wchar_t	*cq;
20810d63b7dSRichard Lowe 	Name			long_member_name = NULL;
20910d63b7dSRichard Lowe 
21010d63b7dSRichard Lowe 	/* Internalize the name of the library */
21110d63b7dSRichard Lowe 	lib = GETNAME(lib_start, member_start - lib_start);
21210d63b7dSRichard Lowe 	lib->is_member = true;
21310d63b7dSRichard Lowe 	member_start++;
21410d63b7dSRichard Lowe 	if (*member_start == (int) parenleft_char) {
21510d63b7dSRichard Lowe 		/* This is really the "lib.a((entries))" format */
21610d63b7dSRichard Lowe 		entry = true;
21710d63b7dSRichard Lowe 		member_start++;
21810d63b7dSRichard Lowe 	}
21910d63b7dSRichard Lowe 	/* Move the library name to the buffer where we intend to build the */
22010d63b7dSRichard Lowe 	/* "lib.a(member)" for each member */
22110d63b7dSRichard Lowe 	(void) wcsncpy(buffer, lib_start, member_start - lib_start);
22210d63b7dSRichard Lowe 	memberp = buffer + (member_start-lib_start);
22310d63b7dSRichard Lowe 	while (1) {
22410d63b7dSRichard Lowe 		long_member_name = NULL;
22510d63b7dSRichard Lowe 		/* Skip leading spaces */
22610d63b7dSRichard Lowe 		for (;
22710d63b7dSRichard Lowe 		     (member_start < string_end) && iswspace(*member_start);
22810d63b7dSRichard Lowe 		     member_start++);
22910d63b7dSRichard Lowe 		/* Find the end of the member name. Allow nested (). Detect $*/
23010d63b7dSRichard Lowe 		for (cq = memberp, has_dollar = false, paren_count = 0;
23110d63b7dSRichard Lowe 		     (member_start < string_end) &&
23210d63b7dSRichard Lowe 		     ((*member_start != (int) parenright_char) ||
23310d63b7dSRichard Lowe 		      (paren_count > 0)) &&
23410d63b7dSRichard Lowe 		     !iswspace(*member_start);
23510d63b7dSRichard Lowe 		     *cq++ = *member_start++) {
23610d63b7dSRichard Lowe 			switch (*member_start) {
23710d63b7dSRichard Lowe 			case parenleft_char:
23810d63b7dSRichard Lowe 				paren_count++;
23910d63b7dSRichard Lowe 				break;
24010d63b7dSRichard Lowe 			case parenright_char:
24110d63b7dSRichard Lowe 				paren_count--;
24210d63b7dSRichard Lowe 				break;
24310d63b7dSRichard Lowe 			case dollar_char:
24410d63b7dSRichard Lowe 				has_dollar = true;
24510d63b7dSRichard Lowe 			}
24610d63b7dSRichard Lowe 		}
24710d63b7dSRichard Lowe 		/* Internalize the member name */
24810d63b7dSRichard Lowe 		member = GETNAME(memberp, cq - memberp);
24910d63b7dSRichard Lowe 		*cq = 0;
25010d63b7dSRichard Lowe 		if ((q = (wchar_t *) wcsrchr(memberp, (int) slash_char)) == NULL) {
25110d63b7dSRichard Lowe 			q = memberp;
25210d63b7dSRichard Lowe 		}
25310d63b7dSRichard Lowe 		if ((cq - q > (int) ar_member_name_len) &&
25410d63b7dSRichard Lowe 		    !has_dollar) {
25510d63b7dSRichard Lowe 			*cq++ = (int) parenright_char;
25610d63b7dSRichard Lowe 			if (entry) {
25710d63b7dSRichard Lowe 				*cq++ = (int) parenright_char;
25810d63b7dSRichard Lowe 			}
25910d63b7dSRichard Lowe 			long_member_name = GETNAME(buffer, cq - buffer);
26010d63b7dSRichard Lowe 			cq = q + (int) ar_member_name_len;
26110d63b7dSRichard Lowe 		}
26210d63b7dSRichard Lowe 		*cq++ = (int) parenright_char;
26310d63b7dSRichard Lowe 		if (entry) {
26410d63b7dSRichard Lowe 			*cq++ = (int) parenright_char;
26510d63b7dSRichard Lowe 		}
26610d63b7dSRichard Lowe 		/* Internalize the "lib.a(member)" notation for this member */
26710d63b7dSRichard Lowe 		name = GETNAME(buffer, cq - buffer);
26810d63b7dSRichard Lowe 		name->is_member = lib->is_member;
26910d63b7dSRichard Lowe 		if (long_member_name != NULL) {
27010d63b7dSRichard Lowe 			prop = append_prop(name, long_member_name_prop);
27110d63b7dSRichard Lowe 			name->has_long_member_name = true;
27210d63b7dSRichard Lowe 			prop->body.long_member_name.member_name =
27310d63b7dSRichard Lowe 			  long_member_name;
27410d63b7dSRichard Lowe 		}
27510d63b7dSRichard Lowe 		/* And add the member prop */
27610d63b7dSRichard Lowe 		prop = append_prop(name, member_prop);
27710d63b7dSRichard Lowe 		prop->body.member.library = lib;
27810d63b7dSRichard Lowe 		if (entry) {
27910d63b7dSRichard Lowe 			/* "lib.a((entry))" notation */
28010d63b7dSRichard Lowe 			prop->body.member.entry = member;
28110d63b7dSRichard Lowe 			prop->body.member.member = NULL;
28210d63b7dSRichard Lowe 		} else {
28310d63b7dSRichard Lowe 			/* "lib.a(member)" Notation */
28410d63b7dSRichard Lowe 			prop->body.member.entry = NULL;
28510d63b7dSRichard Lowe 			prop->body.member.member = member;
28610d63b7dSRichard Lowe 		}
28710d63b7dSRichard Lowe 		/* Handle overflow of current_names */
28810d63b7dSRichard Lowe 		if (current_names->used == VSIZEOF(current_names->names)) {
28910d63b7dSRichard Lowe 			if (current_names->next != NULL) {
29010d63b7dSRichard Lowe 				current_names = current_names->next;
29110d63b7dSRichard Lowe 			} else {
29210d63b7dSRichard Lowe 				if (*extra_names == NULL) {
29310d63b7dSRichard Lowe 					current_names =
29410d63b7dSRichard Lowe 					  current_names->next =
29510d63b7dSRichard Lowe 					    ALLOC(Name_vector);
29610d63b7dSRichard Lowe 				} else {
29710d63b7dSRichard Lowe 					current_names =
29810d63b7dSRichard Lowe 					  current_names->next =
29910d63b7dSRichard Lowe 					    *extra_names;
30010d63b7dSRichard Lowe 					*extra_names = NULL;
30110d63b7dSRichard Lowe 				}
30210d63b7dSRichard Lowe 				current_names->used = 0;
30310d63b7dSRichard Lowe 				current_names->next = NULL;
30410d63b7dSRichard Lowe 			}
30510d63b7dSRichard Lowe 		}
30610d63b7dSRichard Lowe 		current_names->target_group[current_names->used] = NULL;
30710d63b7dSRichard Lowe 		current_names->names[current_names->used++] = name;
30810d63b7dSRichard Lowe 		while (iswspace(*member_start)) {
30910d63b7dSRichard Lowe 			member_start++;
31010d63b7dSRichard Lowe 		}
31110d63b7dSRichard Lowe 		/* Check if there are more members */
31210d63b7dSRichard Lowe 		if ((*member_start == (int) parenright_char) ||
31310d63b7dSRichard Lowe 		    (member_start >= string_end)) {
31410d63b7dSRichard Lowe 			return current_names;
31510d63b7dSRichard Lowe 		}
31610d63b7dSRichard Lowe 	}
31710d63b7dSRichard Lowe 	/* NOTREACHED */
31810d63b7dSRichard Lowe }
31910d63b7dSRichard Lowe 
32010d63b7dSRichard Lowe /*
32110d63b7dSRichard Lowe  *	normalize_name(name_string, length)
32210d63b7dSRichard Lowe  *
32310d63b7dSRichard Lowe  *	Take a namestring and remove redundant ../, // and ./ constructs
32410d63b7dSRichard Lowe  *
32510d63b7dSRichard Lowe  *	Return value:
32610d63b7dSRichard Lowe  *				The normalized name
32710d63b7dSRichard Lowe  *
32810d63b7dSRichard Lowe  *	Parameters:
32910d63b7dSRichard Lowe  *		name_string	Path string to normalize
33010d63b7dSRichard Lowe  *		length		Length of that string
33110d63b7dSRichard Lowe  *
33210d63b7dSRichard Lowe  *	Global variables used:
33310d63b7dSRichard Lowe  *		dot		The Name ".", compared against
33410d63b7dSRichard Lowe  *		dotdot		The Name "..", compared against
33510d63b7dSRichard Lowe  */
33610d63b7dSRichard Lowe Name
normalize_name(wchar_t * name_string,int length)337*e7afc443SToomas Soome normalize_name(wchar_t *name_string, int length)
33810d63b7dSRichard Lowe {
33910d63b7dSRichard Lowe 	static Name		dotdot;
340*e7afc443SToomas Soome 	wchar_t	*string = ALLOC_WC(length + 1);
341*e7afc443SToomas Soome 	wchar_t	*string2;
342*e7afc443SToomas Soome 	wchar_t	*cdp;
34310d63b7dSRichard Lowe 	wchar_t			*current_component;
34410d63b7dSRichard Lowe 	Name			name;
345*e7afc443SToomas Soome 	int		count;
34610d63b7dSRichard Lowe 
34710d63b7dSRichard Lowe 	if (dotdot == NULL) {
34810d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "..");
34910d63b7dSRichard Lowe 		dotdot = GETNAME(wcs_buffer, FIND_LENGTH);
35010d63b7dSRichard Lowe 	}
35110d63b7dSRichard Lowe 
35210d63b7dSRichard Lowe 	/*
35310d63b7dSRichard Lowe 	 * Copy string removing ./ and //.
35410d63b7dSRichard Lowe 	 * First strip leading ./
35510d63b7dSRichard Lowe 	 */
35610d63b7dSRichard Lowe 	while ((length > 1) &&
35710d63b7dSRichard Lowe 	       (name_string[0] == (int) period_char) &&
35810d63b7dSRichard Lowe 	       (name_string[1] == (int) slash_char)) {
35910d63b7dSRichard Lowe 		name_string += 2;
36010d63b7dSRichard Lowe 		length -= 2;
36110d63b7dSRichard Lowe 		while ((length > 0) && (name_string[0] == (int) slash_char)) {
36210d63b7dSRichard Lowe 			name_string++;
36310d63b7dSRichard Lowe 			length--;
36410d63b7dSRichard Lowe 		}
36510d63b7dSRichard Lowe 	}
36610d63b7dSRichard Lowe 	/* Then copy the rest of the string removing /./ & // */
36710d63b7dSRichard Lowe 	cdp = string;
36810d63b7dSRichard Lowe 	while (length > 0) {
36910d63b7dSRichard Lowe 		if (((length > 2) &&
37010d63b7dSRichard Lowe 		     (name_string[0] == (int) slash_char) &&
37110d63b7dSRichard Lowe 		     (name_string[1] == (int) period_char) &&
37210d63b7dSRichard Lowe 		     (name_string[2] == (int) slash_char)) ||
37310d63b7dSRichard Lowe 		    ((length == 2) &&
37410d63b7dSRichard Lowe 		     (name_string[0] == (int) slash_char) &&
37510d63b7dSRichard Lowe 		     (name_string[1] == (int) period_char))) {
37610d63b7dSRichard Lowe 			name_string += 2;
37710d63b7dSRichard Lowe 			length -= 2;
37810d63b7dSRichard Lowe 			continue;
37910d63b7dSRichard Lowe 		}
38010d63b7dSRichard Lowe 		if ((length > 1) &&
38110d63b7dSRichard Lowe 		    (name_string[0] == (int) slash_char) &&
38210d63b7dSRichard Lowe 		    (name_string[1] == (int) slash_char)) {
38310d63b7dSRichard Lowe 			name_string++;
38410d63b7dSRichard Lowe 			length--;
38510d63b7dSRichard Lowe 			continue;
38610d63b7dSRichard Lowe 		}
38710d63b7dSRichard Lowe 		*cdp++ = *name_string++;
38810d63b7dSRichard Lowe 		length--;
38910d63b7dSRichard Lowe 	}
39010d63b7dSRichard Lowe 	*cdp = (int) nul_char;
39110d63b7dSRichard Lowe 	/*
39210d63b7dSRichard Lowe 	 * Now scan for <name>/../ and remove such combinations iff <name>
39310d63b7dSRichard Lowe 	 * is not another ..
39410d63b7dSRichard Lowe 	 * Each time something is removed, the whole process is restarted.
39510d63b7dSRichard Lowe 	 */
39610d63b7dSRichard Lowe removed_one:
39710d63b7dSRichard Lowe 	name_string = string;
39810d63b7dSRichard Lowe 	string2 = name_string;		/*save for free*/
39910d63b7dSRichard Lowe 	current_component =
40010d63b7dSRichard Lowe 	  cdp =
40110d63b7dSRichard Lowe 	    string =
40210d63b7dSRichard Lowe 	      ALLOC_WC((length = wcslen(name_string)) + 1);
40310d63b7dSRichard Lowe 	while (length > 0) {
40410d63b7dSRichard Lowe 		if (((length > 3) &&
40510d63b7dSRichard Lowe 		     (name_string[0] == (int) slash_char) &&
40610d63b7dSRichard Lowe 		     (name_string[1] == (int) period_char) &&
40710d63b7dSRichard Lowe 		     (name_string[2] == (int) period_char) &&
40810d63b7dSRichard Lowe 		     (name_string[3] == (int) slash_char)) ||
40910d63b7dSRichard Lowe 		    ((length == 3) &&
41010d63b7dSRichard Lowe 		     (name_string[0] == (int) slash_char) &&
41110d63b7dSRichard Lowe 		     (name_string[1] == (int) period_char) &&
41210d63b7dSRichard Lowe 		     (name_string[2] == (int) period_char))) {
41310d63b7dSRichard Lowe 			/* Positioned on the / that starts a /.. sequence */
41410d63b7dSRichard Lowe 			if (((count = cdp - current_component) != 0) &&
41510d63b7dSRichard Lowe 			    (exists(name = GETNAME(string, cdp - string)) > file_doesnt_exist) &&
41610d63b7dSRichard Lowe 			    (!name->stat.is_sym_link)) {
41710d63b7dSRichard Lowe 				name = GETNAME(current_component, count);
41810d63b7dSRichard Lowe 				if(name != dotdot) {
41910d63b7dSRichard Lowe 					cdp = current_component;
42010d63b7dSRichard Lowe 					name_string += 3;
42110d63b7dSRichard Lowe 					length -= 3;
42210d63b7dSRichard Lowe 					if (length > 0) {
42310d63b7dSRichard Lowe 						name_string++;	/* skip slash */
42410d63b7dSRichard Lowe 						length--;
42510d63b7dSRichard Lowe 						while (length > 0) {
42610d63b7dSRichard Lowe 							*cdp++ = *name_string++;
42710d63b7dSRichard Lowe 							length--;
42810d63b7dSRichard Lowe 						}
42910d63b7dSRichard Lowe 					}
43010d63b7dSRichard Lowe 					*cdp = (int) nul_char;
43110d63b7dSRichard Lowe 					retmem(string2);
43210d63b7dSRichard Lowe 					goto removed_one;
43310d63b7dSRichard Lowe 				}
43410d63b7dSRichard Lowe 			}
43510d63b7dSRichard Lowe 		}
43610d63b7dSRichard Lowe 		if ((*cdp++ = *name_string++) == (int) slash_char) {
43710d63b7dSRichard Lowe 			current_component = cdp;
43810d63b7dSRichard Lowe 		}
43910d63b7dSRichard Lowe 		length--;
44010d63b7dSRichard Lowe 	}
44110d63b7dSRichard Lowe 	*cdp = (int) nul_char;
44210d63b7dSRichard Lowe 	if (string[0] == (int) nul_char) {
44310d63b7dSRichard Lowe 		name = dot;
44410d63b7dSRichard Lowe 	} else {
44510d63b7dSRichard Lowe 		name = GETNAME(string, FIND_LENGTH);
44610d63b7dSRichard Lowe 	}
44710d63b7dSRichard Lowe 	retmem(string);
44810d63b7dSRichard Lowe 	retmem(string2);
44910d63b7dSRichard Lowe 	return name;
45010d63b7dSRichard Lowe }
45110d63b7dSRichard Lowe 
45210d63b7dSRichard Lowe /*
45310d63b7dSRichard Lowe  *	find_target_groups(target_list)
45410d63b7dSRichard Lowe  *
45510d63b7dSRichard Lowe  *	If a "+" was seen when the target list was scanned we need to extract
45610d63b7dSRichard Lowe  *	the groups. Each target in the name vector that is a member of a
45710d63b7dSRichard Lowe  *	group gets a pointer to a chain of all the members stuffed in its
45810d63b7dSRichard Lowe  *	target_group vector slot
45910d63b7dSRichard Lowe  *
46010d63b7dSRichard Lowe  *	Parameters:
46110d63b7dSRichard Lowe  *		target_list	The list of targets that contains "+"
46210d63b7dSRichard Lowe  *
46310d63b7dSRichard Lowe  *	Global variables used:
46410d63b7dSRichard Lowe  *		plus		The Name "+", compared against
46510d63b7dSRichard Lowe  */
46610d63b7dSRichard Lowe Chain
find_target_groups(Name_vector target_list,int i,Boolean reset)467*e7afc443SToomas Soome find_target_groups(Name_vector target_list, int i, Boolean reset)
46810d63b7dSRichard Lowe {
46910d63b7dSRichard Lowe 	static Chain		target_group = NULL;
47010d63b7dSRichard Lowe 	static Chain		tail_target_group = NULL;
47110d63b7dSRichard Lowe 	static Name		*next;
47210d63b7dSRichard Lowe 	static Boolean	clear_target_group = false;
47310d63b7dSRichard Lowe 
47410d63b7dSRichard Lowe 	if (reset) {
47510d63b7dSRichard Lowe 		target_group = NULL;
47610d63b7dSRichard Lowe 		tail_target_group = NULL;
47710d63b7dSRichard Lowe 		clear_target_group = false;
47810d63b7dSRichard Lowe 	}
47910d63b7dSRichard Lowe 
48010d63b7dSRichard Lowe 	/* Scan the list of targets */
48110d63b7dSRichard Lowe 	/* If the previous target terminated a group */
48210d63b7dSRichard Lowe 	/* we flush the pointer to that member chain */
48310d63b7dSRichard Lowe 	if (clear_target_group) {
48410d63b7dSRichard Lowe 		clear_target_group = false;
48510d63b7dSRichard Lowe 		target_group = NULL;
48610d63b7dSRichard Lowe 	}
48710d63b7dSRichard Lowe 	/* Pick up a pointer to the cell with */
48810d63b7dSRichard Lowe 	/* the next target */
48910d63b7dSRichard Lowe 	if (i + 1 != target_list->used) {
49010d63b7dSRichard Lowe 		next = &target_list->names[i + 1];
49110d63b7dSRichard Lowe 	} else {
49210d63b7dSRichard Lowe 		next = (target_list->next != NULL) ?
49310d63b7dSRichard Lowe 		  &target_list->next->names[0] : NULL;
49410d63b7dSRichard Lowe 	}
49510d63b7dSRichard Lowe 	/* We have four states here :
496ae389aa9SAndy Fiddaman 	 *	0:	No target group started and next element is not "+"
49710d63b7dSRichard Lowe 	 *		This is not interesting.
498ae389aa9SAndy Fiddaman 	 *	1:	A target group is being built and the next element
49910d63b7dSRichard Lowe 	 *		is not "+". This terminates the group.
500ae389aa9SAndy Fiddaman 	 *	2:	No target group started and the next member is "+"
50110d63b7dSRichard Lowe 	 *		This is the first target in a group.
502ae389aa9SAndy Fiddaman 	 *	3:	A target group started and the next member is a "+"
50310d63b7dSRichard Lowe 	 *		The group continues.
50410d63b7dSRichard Lowe 	 */
50510d63b7dSRichard Lowe 	switch ((target_group ? 1 : 0) +
50610d63b7dSRichard Lowe 		(next && (*next == plus) ?
50710d63b7dSRichard Lowe 		 2 : 0)) {
50810d63b7dSRichard Lowe 	      case 0:	/* Not target_group */
50910d63b7dSRichard Lowe 		break;
51010d63b7dSRichard Lowe 	      case 1:	/* Last group member */
51110d63b7dSRichard Lowe 		/* We need to keep this pointer so */
51210d63b7dSRichard Lowe 		/* we can stuff it for last member */
51310d63b7dSRichard Lowe 		clear_target_group = true;
5148e0c8248SAndrew Stormont 		/* FALLTHROUGH */
51510d63b7dSRichard Lowe 	      case 3:	/* Middle group member */
51610d63b7dSRichard Lowe 		/* Add this target to the */
51710d63b7dSRichard Lowe 		/* current chain */
51810d63b7dSRichard Lowe 		tail_target_group->next = ALLOC(Chain);
51910d63b7dSRichard Lowe 		tail_target_group = tail_target_group->next;
52010d63b7dSRichard Lowe 		tail_target_group->next = NULL;
52110d63b7dSRichard Lowe 		tail_target_group->name = target_list->names[i];
52210d63b7dSRichard Lowe 		break;
52310d63b7dSRichard Lowe 	      case 2:	/* First group member */
52410d63b7dSRichard Lowe 		/* Start a new chain */
52510d63b7dSRichard Lowe 		target_group = tail_target_group = ALLOC(Chain);
52610d63b7dSRichard Lowe 		target_group->next = NULL;
52710d63b7dSRichard Lowe 		target_group->name = target_list->names[i];
52810d63b7dSRichard Lowe 		break;
52910d63b7dSRichard Lowe 	}
53010d63b7dSRichard Lowe 	/* Stuff the current chain, if any, in the */
53110d63b7dSRichard Lowe 	/* targets group slot */
53210d63b7dSRichard Lowe 	target_list->target_group[i] = target_group;
53310d63b7dSRichard Lowe 	if ((next != NULL) &&
53410d63b7dSRichard Lowe 	    (*next == plus)) {
53510d63b7dSRichard Lowe 		*next = NULL;
53610d63b7dSRichard Lowe 	}
53710d63b7dSRichard Lowe 	return (tail_target_group);
53810d63b7dSRichard Lowe }
53910d63b7dSRichard Lowe 
54010d63b7dSRichard Lowe /*
54110d63b7dSRichard Lowe  *	enter_dependencies(target, target_group, depes, command, separator)
54210d63b7dSRichard Lowe  *
54310d63b7dSRichard Lowe  *	Take one target and a list of dependencies and process the whole thing.
54410d63b7dSRichard Lowe  *	The target might be special in some sense in which case that is handled
54510d63b7dSRichard Lowe  *
54610d63b7dSRichard Lowe  *	Parameters:
54710d63b7dSRichard Lowe  *		target		The target we want to enter
54810d63b7dSRichard Lowe  *		target_group	Non-NULL if target is part of a group this time
54910d63b7dSRichard Lowe  *		depes		A list of dependencies for the target
55010d63b7dSRichard Lowe  *		command		The command the target should be entered with
55110d63b7dSRichard Lowe  *		separator	Indicates if this is a ":" or a "::" rule
55210d63b7dSRichard Lowe  *
55310d63b7dSRichard Lowe  *	Static variables used:
55410d63b7dSRichard Lowe  *		built_last_make_run_seen If the previous target was
55510d63b7dSRichard Lowe  *					.BUILT_LAST_MAKE_RUN we say to rewrite
55610d63b7dSRichard Lowe  *					the state file later on
55710d63b7dSRichard Lowe  *
55810d63b7dSRichard Lowe  *	Global variables used:
55910d63b7dSRichard Lowe  *		command_changed	Set to indicate if .make.state needs rewriting
56010d63b7dSRichard Lowe  *		default_target_to_build Set to the target if reading makefile
56110d63b7dSRichard Lowe  *					and this is the first regular target
56210d63b7dSRichard Lowe  *		force		The Name " FORCE", used with "::" targets
56310d63b7dSRichard Lowe  *		makefile_type	We do different things for makefile vs. report
56410d63b7dSRichard Lowe  *		not_auto	The Name ".NOT_AUTO", compared against
56510d63b7dSRichard Lowe  *		recursive_name	The Name ".RECURSIVE", compared against
56610d63b7dSRichard Lowe  *		temp_file_number Used to figure out when to clear stale
56710d63b7dSRichard Lowe  *					automatic dependencies
56810d63b7dSRichard Lowe  *		trace_reader	Indicates that we should echo stuff we read
56910d63b7dSRichard Lowe  */
57010d63b7dSRichard Lowe void
enter_dependencies(Name target,Chain target_group,Name_vector depes,Cmd_line command,Separator separator)571*e7afc443SToomas Soome enter_dependencies(Name target, Chain target_group, Name_vector depes, Cmd_line command, Separator separator)
57210d63b7dSRichard Lowe {
573*e7afc443SToomas Soome 	int		i;
574*e7afc443SToomas Soome 	Property	line;
57510d63b7dSRichard Lowe 	Name			name;
57610d63b7dSRichard Lowe 	Name			directory;
57710d63b7dSRichard Lowe 	wchar_t			*namep;
57810d63b7dSRichard Lowe 	char			*mb_namep;
57910d63b7dSRichard Lowe 	Dependency		dp;
58010d63b7dSRichard Lowe 	Dependency		*dpp;
58110d63b7dSRichard Lowe 	Property		line2;
58210d63b7dSRichard Lowe 	wchar_t			relative[MAXPATHLEN];
583*e7afc443SToomas Soome 	int		recursive_state;
58410d63b7dSRichard Lowe 	Boolean			register_as_auto;
58510d63b7dSRichard Lowe 	Boolean			not_auto_found;
58610d63b7dSRichard Lowe 	char			*slash;
58710d63b7dSRichard Lowe 	Wstring			depstr;
58810d63b7dSRichard Lowe 
58910d63b7dSRichard Lowe 	/* Check if this is a .RECURSIVE line */
59010d63b7dSRichard Lowe 	if ((depes->used >= 3) &&
59110d63b7dSRichard Lowe 	    (depes->names[0] == recursive_name)) {
59210d63b7dSRichard Lowe 		target->has_recursive_dependency = true;
59310d63b7dSRichard Lowe 		depes->names[0] = NULL;
59410d63b7dSRichard Lowe 		recursive_state = 0;
59510d63b7dSRichard Lowe 		dp = NULL;
59610d63b7dSRichard Lowe 		dpp = &dp;
59710d63b7dSRichard Lowe 		/* Read the dependencies. They are "<directory> <target-made>*/
59810d63b7dSRichard Lowe 		/* <makefile>*" */
59910d63b7dSRichard Lowe 		for (; depes != NULL; depes = depes->next) {
60010d63b7dSRichard Lowe 			for (i = 0; i < depes->used; i++) {
60110d63b7dSRichard Lowe 				if (depes->names[i] != NULL) {
60210d63b7dSRichard Lowe 					switch (recursive_state++) {
60310d63b7dSRichard Lowe 					case 0:	/* Directory */
60410d63b7dSRichard Lowe 					{
60510d63b7dSRichard Lowe 						depstr.init(depes->names[i]);
60610d63b7dSRichard Lowe 						make_relative(depstr.get_string(),
60710d63b7dSRichard Lowe 							      relative);
60810d63b7dSRichard Lowe 						directory =
60910d63b7dSRichard Lowe 						  GETNAME(relative,
61010d63b7dSRichard Lowe 							  FIND_LENGTH);
61110d63b7dSRichard Lowe 					}
61210d63b7dSRichard Lowe 						break;
61310d63b7dSRichard Lowe 					case 1:	/* Target */
61410d63b7dSRichard Lowe 						name = depes->names[i];
61510d63b7dSRichard Lowe 						break;
61610d63b7dSRichard Lowe 					default:	/* Makefiles */
61710d63b7dSRichard Lowe 						*dpp = ALLOC(Dependency);
61810d63b7dSRichard Lowe 						(*dpp)->next = NULL;
61910d63b7dSRichard Lowe 						(*dpp)->name = depes->names[i];
62010d63b7dSRichard Lowe 						(*dpp)->automatic = false;
62110d63b7dSRichard Lowe 						(*dpp)->stale = false;
62210d63b7dSRichard Lowe 						(*dpp)->built = false;
62310d63b7dSRichard Lowe 						dpp = &((*dpp)->next);
62410d63b7dSRichard Lowe 						break;
62510d63b7dSRichard Lowe 					}
62610d63b7dSRichard Lowe 				}
62710d63b7dSRichard Lowe 			}
62810d63b7dSRichard Lowe 		}
62910d63b7dSRichard Lowe 		/* Check if this recursion already has been reported else */
63010d63b7dSRichard Lowe 		/* enter the recursive prop for the target */
63110d63b7dSRichard Lowe 		/* The has_built flag is used to tell if this .RECURSIVE */
63210d63b7dSRichard Lowe 		/* was discovered from this run (read from a tmp file) */
63310d63b7dSRichard Lowe 		/* or was from discovered from the original .make.state */
63410d63b7dSRichard Lowe 		/* file */
63510d63b7dSRichard Lowe 		for (line = get_prop(target->prop, recursive_prop);
63610d63b7dSRichard Lowe 		     line != NULL;
63710d63b7dSRichard Lowe 		     line = get_prop(line->next, recursive_prop)) {
63810d63b7dSRichard Lowe 			if ((line->body.recursive.directory == directory) &&
63910d63b7dSRichard Lowe 			    (line->body.recursive.target == name)) {
64010d63b7dSRichard Lowe 				line->body.recursive.makefiles = dp;
641ae389aa9SAndy Fiddaman 				line->body.recursive.has_built =
64210d63b7dSRichard Lowe 				  (Boolean)
64310d63b7dSRichard Lowe 				    (makefile_type == reading_cpp_file);
64410d63b7dSRichard Lowe 				return;
64510d63b7dSRichard Lowe 			}
64610d63b7dSRichard Lowe 		}
64710d63b7dSRichard Lowe 		line2 = append_prop(target, recursive_prop);
64810d63b7dSRichard Lowe 		line2->body.recursive.directory = directory;
64910d63b7dSRichard Lowe 		line2->body.recursive.target = name;
65010d63b7dSRichard Lowe 		line2->body.recursive.makefiles = dp;
651ae389aa9SAndy Fiddaman 		line2->body.recursive.has_built =
65210d63b7dSRichard Lowe 		    (Boolean) (makefile_type == reading_cpp_file);
65310d63b7dSRichard Lowe 		line2->body.recursive.in_depinfo = false;
65410d63b7dSRichard Lowe 		return;
65510d63b7dSRichard Lowe 	}
65610d63b7dSRichard Lowe 	/* If this is the first target that doesnt start with a "." in the */
65710d63b7dSRichard Lowe 	/* makefile we remember that */
65810d63b7dSRichard Lowe 	Wstring tstr(target);
65910d63b7dSRichard Lowe 	wchar_t * wcb = tstr.get_string();
66010d63b7dSRichard Lowe 	if ((makefile_type == reading_makefile) &&
66110d63b7dSRichard Lowe 	    (default_target_to_build == NULL) &&
66210d63b7dSRichard Lowe 	    ((wcb[0] != (int) period_char) ||
66310d63b7dSRichard Lowe 	     wcschr(wcb, (int) slash_char))) {
66410d63b7dSRichard Lowe 
66510d63b7dSRichard Lowe /* BID 1181577: $(EMPTY_MACRO) + $(EMPTY_MACRO):
66610d63b7dSRichard Lowe ** The target with empty name cannot be default_target_to_build
66710d63b7dSRichard Lowe */
66810d63b7dSRichard Lowe 		if (target->hash.length != 0)
66910d63b7dSRichard Lowe 			default_target_to_build = target;
67010d63b7dSRichard Lowe 	}
67110d63b7dSRichard Lowe 	/* Check if the line is ":" or "::" */
67210d63b7dSRichard Lowe 	if (makefile_type == reading_makefile) {
67310d63b7dSRichard Lowe 		if (target->colons == no_colon) {
67410d63b7dSRichard Lowe 			target->colons = separator;
67510d63b7dSRichard Lowe 		} else {
67610d63b7dSRichard Lowe 			if (target->colons != separator) {
67710d63b7dSRichard Lowe 				fatal_reader(gettext(":/:: conflict for target `%s'"),
67810d63b7dSRichard Lowe 					     target->string_mb);
67910d63b7dSRichard Lowe 			}
68010d63b7dSRichard Lowe 		}
68110d63b7dSRichard Lowe 		if (target->colons == two_colon) {
68210d63b7dSRichard Lowe 			if (depes->used == 0) {
68310d63b7dSRichard Lowe 				/* If this is a "::" type line with no */
68410d63b7dSRichard Lowe 				/* dependencies we add one "FRC" type */
68510d63b7dSRichard Lowe 				/* dependency for free */
68610d63b7dSRichard Lowe 				depes->used = 1; /* Force :: targets with no
68710d63b7dSRichard Lowe 						  * depes to always run */
68810d63b7dSRichard Lowe 				depes->names[0] = force;
68910d63b7dSRichard Lowe 			}
69010d63b7dSRichard Lowe 			/* Do not delete "::" type targets when interrupted */
69110d63b7dSRichard Lowe 			target->stat.is_precious = true;
69210d63b7dSRichard Lowe 			/*
69310d63b7dSRichard Lowe 			 * Build a synthetic target "<number>%target"
69410d63b7dSRichard Lowe 			 * for "target".
69510d63b7dSRichard Lowe 			 */
69610d63b7dSRichard Lowe 			mb_namep = getmem((int) (strlen(target->string_mb) + 10));
69710d63b7dSRichard Lowe 			namep = ALLOC_WC((int) (target->hash.length + 10));
69810d63b7dSRichard Lowe 			slash = strrchr(target->string_mb, (int) slash_char);
69910d63b7dSRichard Lowe 			if (slash == NULL) {
70010d63b7dSRichard Lowe 				(void) sprintf(mb_namep,
70110d63b7dSRichard Lowe 					        "%d@%s",
70210d63b7dSRichard Lowe 					        target->colon_splits++,
70310d63b7dSRichard Lowe 					        target->string_mb);
70410d63b7dSRichard Lowe 			} else {
70510d63b7dSRichard Lowe 				*slash = 0;
70610d63b7dSRichard Lowe 				(void) sprintf(mb_namep,
70710d63b7dSRichard Lowe 					        "%s/%d@%s",
70810d63b7dSRichard Lowe 					        target->string_mb,
70910d63b7dSRichard Lowe 					        target->colon_splits++,
71010d63b7dSRichard Lowe 					        slash + 1);
71110d63b7dSRichard Lowe 				*slash = (int) slash_char;
71210d63b7dSRichard Lowe 			}
71310d63b7dSRichard Lowe 			MBSTOWCS(namep, mb_namep);
71410d63b7dSRichard Lowe 			retmem_mb(mb_namep);
71510d63b7dSRichard Lowe 			name = GETNAME(namep, FIND_LENGTH);
71610d63b7dSRichard Lowe 			retmem(namep);
71710d63b7dSRichard Lowe 			if (trace_reader) {
71810d63b7dSRichard Lowe 				(void) printf("%s:\t", target->string_mb);
71910d63b7dSRichard Lowe 			}
72010d63b7dSRichard Lowe 			/* Make "target" depend on "<number>%target */
72110d63b7dSRichard Lowe 			line2 = maybe_append_prop(target, line_prop);
72210d63b7dSRichard Lowe 			enter_dependency(line2, name, true);
72310d63b7dSRichard Lowe 			line2->body.line.target = target;
72410d63b7dSRichard Lowe 			/* Put a prop on "<number>%target that makes */
72510d63b7dSRichard Lowe 			/* appear as "target" */
72610d63b7dSRichard Lowe 			/* when it is processed */
72710d63b7dSRichard Lowe 			maybe_append_prop(name, target_prop)->
72810d63b7dSRichard Lowe 			  body.target.target = target;
72910d63b7dSRichard Lowe 			target->is_double_colon_parent = true;
73010d63b7dSRichard Lowe 			name->is_double_colon = true;
73110d63b7dSRichard Lowe 			name->has_target_prop = true;
73210d63b7dSRichard Lowe 			if (trace_reader) {
73310d63b7dSRichard Lowe 				(void) printf("\n");
73410d63b7dSRichard Lowe 			}
73510d63b7dSRichard Lowe 			(target = name)->stat.is_file = true;
73610d63b7dSRichard Lowe 		}
73710d63b7dSRichard Lowe 	}
73810d63b7dSRichard Lowe 	/* This really is a regular dependency line. Just enter it */
73910d63b7dSRichard Lowe 	line = maybe_append_prop(target, line_prop);
74010d63b7dSRichard Lowe 	line->body.line.target = target;
74110d63b7dSRichard Lowe 	/* Depending on what kind of makefile we are reading we have to */
74210d63b7dSRichard Lowe 	/* treat things differently */
74310d63b7dSRichard Lowe 	switch (makefile_type) {
74410d63b7dSRichard Lowe 	case reading_makefile:
74510d63b7dSRichard Lowe 		/* Reading regular makefile. Just notice whether this */
74610d63b7dSRichard Lowe 		/* redefines the rule for the  target */
74710d63b7dSRichard Lowe 		if (command != NULL) {
74810d63b7dSRichard Lowe 			if (line->body.line.command_template != NULL) {
74910d63b7dSRichard Lowe 				line->body.line.command_template_redefined =
75010d63b7dSRichard Lowe 				  true;
75110d63b7dSRichard Lowe 				if ((wcb[0] == (int) period_char) &&
75210d63b7dSRichard Lowe 				    !wcschr(wcb, (int) slash_char)) {
75310d63b7dSRichard Lowe 					line->body.line.command_template =
75410d63b7dSRichard Lowe 					  command;
75510d63b7dSRichard Lowe 				}
75610d63b7dSRichard Lowe 			} else {
75710d63b7dSRichard Lowe 				line->body.line.command_template = command;
75810d63b7dSRichard Lowe 			}
75910d63b7dSRichard Lowe 		} else {
76010d63b7dSRichard Lowe 			if ((wcb[0] == (int) period_char) &&
76110d63b7dSRichard Lowe 			    !wcschr(wcb, (int) slash_char)) {
76210d63b7dSRichard Lowe 				line->body.line.command_template = command;
76310d63b7dSRichard Lowe 			}
76410d63b7dSRichard Lowe 		}
76510d63b7dSRichard Lowe 		break;
76610d63b7dSRichard Lowe 	case rereading_statefile:
76710d63b7dSRichard Lowe 		/* Rereading the statefile. We only enter thing that changed */
76810d63b7dSRichard Lowe 		/* since the previous time we read it */
76910d63b7dSRichard Lowe 		if (!built_last_make_run_seen) {
77010d63b7dSRichard Lowe 			for (Cmd_line next, cmd = command; cmd != NULL; cmd = next) {
77110d63b7dSRichard Lowe 				next = cmd->next;
77210d63b7dSRichard Lowe 				free(cmd);
77310d63b7dSRichard Lowe 			}
77410d63b7dSRichard Lowe 			return;
77510d63b7dSRichard Lowe 		}
77610d63b7dSRichard Lowe 		built_last_make_run_seen = false;
77710d63b7dSRichard Lowe 		command_changed = true;
77810d63b7dSRichard Lowe 		target->ran_command = true;
7798e0c8248SAndrew Stormont 		/* FALLTHROUGH */
78010d63b7dSRichard Lowe 	case reading_statefile:
78110d63b7dSRichard Lowe 		/* Reading the statefile for the first time. Enter the rules */
78210d63b7dSRichard Lowe 		/* as "Commands used" not "templates to use" */
78310d63b7dSRichard Lowe 		if (command != NULL) {
78410d63b7dSRichard Lowe 			for (Cmd_line next, cmd = line->body.line.command_used;
78510d63b7dSRichard Lowe 			     cmd != NULL; cmd = next) {
78610d63b7dSRichard Lowe 				next = cmd->next;
78710d63b7dSRichard Lowe 				free(cmd);
78810d63b7dSRichard Lowe 			}
78910d63b7dSRichard Lowe 			line->body.line.command_used = command;
79010d63b7dSRichard Lowe 		}
7918e0c8248SAndrew Stormont 		/* FALLTHROUGH */
79210d63b7dSRichard Lowe 	case reading_cpp_file:
79310d63b7dSRichard Lowe 		/* Reading report file from programs that reports */
79410d63b7dSRichard Lowe 		/* dependencies. If this is the first time the target is */
79510d63b7dSRichard Lowe 		/* read from this reportfile we clear all old */
79610d63b7dSRichard Lowe 		/* automatic depes */
79710d63b7dSRichard Lowe 		if (target->temp_file_number == temp_file_number) {
79810d63b7dSRichard Lowe 			break;
79910d63b7dSRichard Lowe 		}
80010d63b7dSRichard Lowe 		target->temp_file_number = temp_file_number;
80110d63b7dSRichard Lowe 		command_changed = true;
80210d63b7dSRichard Lowe 		if (line != NULL) {
80310d63b7dSRichard Lowe 			for (dp = line->body.line.dependencies;
80410d63b7dSRichard Lowe 			     dp != NULL;
80510d63b7dSRichard Lowe 			     dp = dp->next) {
80610d63b7dSRichard Lowe 				if (dp->automatic) {
80710d63b7dSRichard Lowe 					dp->stale = true;
80810d63b7dSRichard Lowe 				}
80910d63b7dSRichard Lowe 			}
81010d63b7dSRichard Lowe 		}
81110d63b7dSRichard Lowe 		break;
81210d63b7dSRichard Lowe 	default:
81310d63b7dSRichard Lowe 		fatal_reader(gettext("Internal error. Unknown makefile type %d"),
81410d63b7dSRichard Lowe 			     makefile_type);
81510d63b7dSRichard Lowe 	}
81610d63b7dSRichard Lowe 	/* A target may only be involved in one target group */
81710d63b7dSRichard Lowe 	if (line->body.line.target_group != NULL) {
81810d63b7dSRichard Lowe 		if (target_group != NULL) {
81910d63b7dSRichard Lowe 			fatal_reader(gettext("Too many target groups for target `%s'"),
82010d63b7dSRichard Lowe 				     target->string_mb);
82110d63b7dSRichard Lowe 		}
82210d63b7dSRichard Lowe 	} else {
82310d63b7dSRichard Lowe 		line->body.line.target_group = target_group;
82410d63b7dSRichard Lowe 	}
82510d63b7dSRichard Lowe 
82610d63b7dSRichard Lowe 	if (trace_reader) {
82710d63b7dSRichard Lowe 		(void) printf("%s:\t", target->string_mb);
82810d63b7dSRichard Lowe 	}
82910d63b7dSRichard Lowe 	/* Enter the dependencies */
83010d63b7dSRichard Lowe 	register_as_auto = BOOLEAN(makefile_type != reading_makefile);
83110d63b7dSRichard Lowe 	not_auto_found = false;
83210d63b7dSRichard Lowe 	for (;
83310d63b7dSRichard Lowe 	     (depes != NULL) && !not_auto_found;
83410d63b7dSRichard Lowe 	     depes = depes->next) {
83510d63b7dSRichard Lowe 		for (i = 0; i < depes->used; i++) {
83610d63b7dSRichard Lowe 			/* the dependency .NOT_AUTO signals beginning of
83710d63b7dSRichard Lowe 			 * explicit dependancies which were put at end of
83810d63b7dSRichard Lowe 			 * list in .make.state file - we stop entering
83910d63b7dSRichard Lowe 			 * dependencies at this point
84010d63b7dSRichard Lowe 			 */
84110d63b7dSRichard Lowe 			if (depes->names[i] == not_auto) {
84210d63b7dSRichard Lowe 				not_auto_found = true;
84310d63b7dSRichard Lowe 				break;
84410d63b7dSRichard Lowe 			}
84510d63b7dSRichard Lowe 			enter_dependency(line,
84610d63b7dSRichard Lowe 					 depes->names[i],
84710d63b7dSRichard Lowe 					 register_as_auto);
84810d63b7dSRichard Lowe 		}
84910d63b7dSRichard Lowe 	}
85010d63b7dSRichard Lowe 	if (trace_reader) {
85110d63b7dSRichard Lowe 		(void) printf("\n");
85210d63b7dSRichard Lowe 		print_rule(command);
85310d63b7dSRichard Lowe 	}
85410d63b7dSRichard Lowe }
85510d63b7dSRichard Lowe 
85610d63b7dSRichard Lowe /*
85710d63b7dSRichard Lowe  *	enter_dependency(line, depe, automatic)
85810d63b7dSRichard Lowe  *
85910d63b7dSRichard Lowe  *	Enter one dependency. Do not enter duplicates.
86010d63b7dSRichard Lowe  *
86110d63b7dSRichard Lowe  *	Parameters:
86210d63b7dSRichard Lowe  *		line		The line block that the dependeny is
86310d63b7dSRichard Lowe  *				entered for
86410d63b7dSRichard Lowe  *		depe		The dependency to enter
86510d63b7dSRichard Lowe  *		automatic	Used to set the field "automatic"
86610d63b7dSRichard Lowe  *
86710d63b7dSRichard Lowe  *	Global variables used:
86810d63b7dSRichard Lowe  *		makefile_type	We do different things for makefile vs. report
86910d63b7dSRichard Lowe  *		trace_reader	Indicates that we should echo stuff we read
87010d63b7dSRichard Lowe  *		wait_name	The Name ".WAIT", compared against
87110d63b7dSRichard Lowe  */
87210d63b7dSRichard Lowe void
enter_dependency(Property line,Name depe,Boolean automatic)873*e7afc443SToomas Soome enter_dependency(Property line, Name depe, Boolean automatic)
87410d63b7dSRichard Lowe {
875*e7afc443SToomas Soome 	Dependency	dp;
876*e7afc443SToomas Soome 	Dependency	*insert;
87710d63b7dSRichard Lowe 
87810d63b7dSRichard Lowe 	if (trace_reader) {
87910d63b7dSRichard Lowe 		(void) printf("%s ", depe->string_mb);
88010d63b7dSRichard Lowe 	}
88110d63b7dSRichard Lowe 	/* Find the end of the list and check for duplicates */
88210d63b7dSRichard Lowe 	for (insert = &line->body.line.dependencies, dp = *insert;
88310d63b7dSRichard Lowe 	     dp != NULL;
88410d63b7dSRichard Lowe 	     insert = &dp->next, dp = *insert) {
88510d63b7dSRichard Lowe 		if ((dp->name == depe) && (depe != wait_name)) {
88610d63b7dSRichard Lowe 			if (dp->automatic) {
88710d63b7dSRichard Lowe 				dp->automatic = automatic;
88810d63b7dSRichard Lowe 				if (automatic) {
88910d63b7dSRichard Lowe 					dp->built = false;
89010d63b7dSRichard Lowe 					depe->stat.is_file = true;
89110d63b7dSRichard Lowe 				}
89210d63b7dSRichard Lowe 			}
89310d63b7dSRichard Lowe 			dp->stale = false;
89410d63b7dSRichard Lowe 			return;
89510d63b7dSRichard Lowe 		}
89610d63b7dSRichard Lowe 	}
89710d63b7dSRichard Lowe 	/* Insert the new dependency since we couldnt find it */
89810d63b7dSRichard Lowe 	dp = *insert = ALLOC(Dependency);
89910d63b7dSRichard Lowe 	dp->name = depe;
90010d63b7dSRichard Lowe 	dp->next = NULL;
90110d63b7dSRichard Lowe 	dp->automatic = automatic;
90210d63b7dSRichard Lowe 	dp->stale = false;
90310d63b7dSRichard Lowe 	dp->built = false;
90410d63b7dSRichard Lowe 	depe->stat.is_file = true;
90510d63b7dSRichard Lowe 
90610d63b7dSRichard Lowe 	if ((makefile_type == reading_makefile) &&
90710d63b7dSRichard Lowe 	    (line != NULL) &&
90810d63b7dSRichard Lowe 	    (line->body.line.target != NULL)) {
90910d63b7dSRichard Lowe 		line->body.line.target->has_regular_dependency = true;
91010d63b7dSRichard Lowe 	}
91110d63b7dSRichard Lowe }
91210d63b7dSRichard Lowe 
91310d63b7dSRichard Lowe /*
91410d63b7dSRichard Lowe  *	enter_percent(target, depes, command)
91510d63b7dSRichard Lowe  *
91610d63b7dSRichard Lowe  *	Enter "x%y : a%b" type lines
91710d63b7dSRichard Lowe  *	% patterns are stored in four parts head and tail for target and source
91810d63b7dSRichard Lowe  *
91910d63b7dSRichard Lowe  *	Parameters:
92010d63b7dSRichard Lowe  *		target		Left hand side of pattern
92110d63b7dSRichard Lowe  *		depes		The dependency list with the rh pattern
92210d63b7dSRichard Lowe  *		command		The command for the pattern
92310d63b7dSRichard Lowe  *
92410d63b7dSRichard Lowe  *	Global variables used:
92510d63b7dSRichard Lowe  *		empty_name	The Name "", compared against
92610d63b7dSRichard Lowe  *		percent_list	The list of all percent rules, added to
92710d63b7dSRichard Lowe  *		trace_reader	Indicates that we should echo stuff we read
92810d63b7dSRichard Lowe  */
92910d63b7dSRichard Lowe Percent
enter_percent(Name target,Chain target_group,Name_vector depes,Cmd_line command)930*e7afc443SToomas Soome enter_percent(Name target, Chain target_group, Name_vector depes, Cmd_line command)
93110d63b7dSRichard Lowe {
932*e7afc443SToomas Soome 	Percent	result = ALLOC(Percent);
933*e7afc443SToomas Soome 	Percent	depe;
934*e7afc443SToomas Soome 	Percent	*depe_tail = &result->dependencies;
935*e7afc443SToomas Soome 	Percent	*insert;
936*e7afc443SToomas Soome 	wchar_t	*cp, *cp1;
93710d63b7dSRichard Lowe 	Name_vector		nvp;
93810d63b7dSRichard Lowe 	int			i;
93910d63b7dSRichard Lowe 	int			pattern;
94010d63b7dSRichard Lowe 
94110d63b7dSRichard Lowe 	result->next = NULL;
94210d63b7dSRichard Lowe 	result->patterns = NULL;
94310d63b7dSRichard Lowe 	result->patterns_total = 0;
94410d63b7dSRichard Lowe 	result->command_template = command;
94510d63b7dSRichard Lowe 	result->being_expanded = false;
94610d63b7dSRichard Lowe 	result->name = target;
94710d63b7dSRichard Lowe 	result->dependencies = NULL;
94810d63b7dSRichard Lowe 	result->target_group = target_group;
94910d63b7dSRichard Lowe 
95010d63b7dSRichard Lowe 	/* get patterns count */
95110d63b7dSRichard Lowe 	Wstring wcb(target);
95210d63b7dSRichard Lowe 	cp = wcb.get_string();
95310d63b7dSRichard Lowe 	while (true) {
95410d63b7dSRichard Lowe 		cp = (wchar_t *) wcschr(cp, (int) percent_char);
95510d63b7dSRichard Lowe 		if (cp != NULL) {
95610d63b7dSRichard Lowe 			result->patterns_total++;
95710d63b7dSRichard Lowe 			cp++;
95810d63b7dSRichard Lowe 		} else {
95910d63b7dSRichard Lowe 			break;
96010d63b7dSRichard Lowe 		}
96110d63b7dSRichard Lowe 	}
96210d63b7dSRichard Lowe 	result->patterns_total++;
96310d63b7dSRichard Lowe 
96410d63b7dSRichard Lowe 	/* allocate storage for patterns */
96510d63b7dSRichard Lowe 	result->patterns = (Name *) getmem(sizeof(Name) * result->patterns_total);
96610d63b7dSRichard Lowe 
96710d63b7dSRichard Lowe 	/* then create patterns */
96810d63b7dSRichard Lowe 	cp = wcb.get_string();
96910d63b7dSRichard Lowe 	pattern = 0;
97010d63b7dSRichard Lowe 	while (true) {
97110d63b7dSRichard Lowe 		cp1 = (wchar_t *) wcschr(cp, (int) percent_char);
97210d63b7dSRichard Lowe 		if (cp1 != NULL) {
97310d63b7dSRichard Lowe 			result->patterns[pattern] = GETNAME(cp, cp1 - cp);
97410d63b7dSRichard Lowe 			cp = cp1 + 1;
97510d63b7dSRichard Lowe 			pattern++;
97610d63b7dSRichard Lowe 		} else {
97710d63b7dSRichard Lowe 			result->patterns[pattern] = GETNAME(cp, (int) target->hash.length - (cp - wcb.get_string()));
97810d63b7dSRichard Lowe 			break;
97910d63b7dSRichard Lowe 		}
98010d63b7dSRichard Lowe 	}
98110d63b7dSRichard Lowe 
98210d63b7dSRichard Lowe 	Wstring wcb1;
98310d63b7dSRichard Lowe 
98410d63b7dSRichard Lowe 	/* build dependencies list */
98510d63b7dSRichard Lowe 	for (nvp = depes; nvp != NULL; nvp = nvp->next) {
98610d63b7dSRichard Lowe 		for (i = 0; i < nvp->used; i++) {
98710d63b7dSRichard Lowe 			depe = ALLOC(Percent);
98810d63b7dSRichard Lowe 			depe->next = NULL;
98910d63b7dSRichard Lowe 			depe->patterns = NULL;
99010d63b7dSRichard Lowe 			depe->patterns_total = 0;
99110d63b7dSRichard Lowe 			depe->name = nvp->names[i];
99210d63b7dSRichard Lowe 			depe->dependencies = NULL;
99310d63b7dSRichard Lowe 			depe->command_template = NULL;
99410d63b7dSRichard Lowe 			depe->being_expanded = false;
99510d63b7dSRichard Lowe 			depe->target_group = NULL;
99610d63b7dSRichard Lowe 
99710d63b7dSRichard Lowe 			*depe_tail = depe;
99810d63b7dSRichard Lowe 			depe_tail = &depe->next;
99910d63b7dSRichard Lowe 
100010d63b7dSRichard Lowe 			if (depe->name->percent) {
100110d63b7dSRichard Lowe 				/* get patterns count */
100210d63b7dSRichard Lowe 				wcb1.init(depe->name);
100310d63b7dSRichard Lowe 				cp = wcb1.get_string();
100410d63b7dSRichard Lowe 				while (true) {
100510d63b7dSRichard Lowe 					cp = (wchar_t *) wcschr(cp, (int) percent_char);
100610d63b7dSRichard Lowe 					if (cp != NULL) {
100710d63b7dSRichard Lowe 						depe->patterns_total++;
100810d63b7dSRichard Lowe 						cp++;
100910d63b7dSRichard Lowe 					} else {
101010d63b7dSRichard Lowe 						break;
101110d63b7dSRichard Lowe 					}
101210d63b7dSRichard Lowe 				}
101310d63b7dSRichard Lowe 				depe->patterns_total++;
101410d63b7dSRichard Lowe 
101510d63b7dSRichard Lowe 				/* allocate storage for patterns */
101610d63b7dSRichard Lowe 				depe->patterns = (Name *) getmem(sizeof(Name) * depe->patterns_total);
101710d63b7dSRichard Lowe 
101810d63b7dSRichard Lowe 				/* then create patterns */
101910d63b7dSRichard Lowe 				cp = wcb1.get_string();
102010d63b7dSRichard Lowe 				pattern = 0;
102110d63b7dSRichard Lowe 				while (true) {
102210d63b7dSRichard Lowe 					cp1 = (wchar_t *) wcschr(cp, (int) percent_char);
102310d63b7dSRichard Lowe 					if (cp1 != NULL) {
102410d63b7dSRichard Lowe 						depe->patterns[pattern] = GETNAME(cp, cp1 - cp);
102510d63b7dSRichard Lowe 						cp = cp1 + 1;
102610d63b7dSRichard Lowe 						pattern++;
102710d63b7dSRichard Lowe 					} else {
102810d63b7dSRichard Lowe 						depe->patterns[pattern] = GETNAME(cp, (int) depe->name->hash.length - (cp - wcb1.get_string()));
102910d63b7dSRichard Lowe 						break;
103010d63b7dSRichard Lowe 					}
103110d63b7dSRichard Lowe 				}
103210d63b7dSRichard Lowe 			}
103310d63b7dSRichard Lowe 		}
103410d63b7dSRichard Lowe 	}
103510d63b7dSRichard Lowe 
103610d63b7dSRichard Lowe 	/* Find the end of the percent list and append the new pattern */
103710d63b7dSRichard Lowe 	for (insert = &percent_list; (*insert) != NULL; insert = &(*insert)->next);
103810d63b7dSRichard Lowe 	*insert = result;
103910d63b7dSRichard Lowe 
104010d63b7dSRichard Lowe 	if (trace_reader) {
104110d63b7dSRichard Lowe 		(void) printf("%s:", result->name->string_mb);
104210d63b7dSRichard Lowe 
104310d63b7dSRichard Lowe 		for (depe = result->dependencies; depe != NULL; depe = depe->next) {
104410d63b7dSRichard Lowe 			(void) printf(" %s", depe->name->string_mb);
104510d63b7dSRichard Lowe 		}
104610d63b7dSRichard Lowe 
104710d63b7dSRichard Lowe 		(void) printf("\n");
104810d63b7dSRichard Lowe 
104910d63b7dSRichard Lowe 		print_rule(command);
105010d63b7dSRichard Lowe 	}
105110d63b7dSRichard Lowe 
105210d63b7dSRichard Lowe 	return result;
105310d63b7dSRichard Lowe }
105410d63b7dSRichard Lowe 
105510d63b7dSRichard Lowe /*
105610d63b7dSRichard Lowe  *	enter_dyntarget(target)
105710d63b7dSRichard Lowe  *
105810d63b7dSRichard Lowe  *	Enter "$$(MACRO) : b" type lines
105910d63b7dSRichard Lowe  *
106010d63b7dSRichard Lowe  *	Parameters:
106110d63b7dSRichard Lowe  *		target		Left hand side of pattern
106210d63b7dSRichard Lowe  *
106310d63b7dSRichard Lowe  *	Global variables used:
106410d63b7dSRichard Lowe  *		dyntarget_list	The list of all percent rules, added to
106510d63b7dSRichard Lowe  *		trace_reader	Indicates that we should echo stuff we read
106610d63b7dSRichard Lowe  */
106710d63b7dSRichard Lowe Dyntarget
enter_dyntarget(Name target)1068*e7afc443SToomas Soome enter_dyntarget(Name target)
106910d63b7dSRichard Lowe {
1070*e7afc443SToomas Soome 	Dyntarget	result = ALLOC(Dyntarget);
107110d63b7dSRichard Lowe 	Dyntarget		p;
107210d63b7dSRichard Lowe 	Dyntarget		*insert;
107310d63b7dSRichard Lowe 	int				i;
107410d63b7dSRichard Lowe 
107510d63b7dSRichard Lowe 	result->next = NULL;
107610d63b7dSRichard Lowe 	result->name = target;
107710d63b7dSRichard Lowe 
107810d63b7dSRichard Lowe 
107910d63b7dSRichard Lowe 	/* Find the end of the dyntarget list and append the new pattern */
108010d63b7dSRichard Lowe 	for (insert = &dyntarget_list, p = *insert;
108110d63b7dSRichard Lowe 	     p != NULL;
108210d63b7dSRichard Lowe 	     insert = &p->next, p = *insert);
108310d63b7dSRichard Lowe 	*insert = result;
108410d63b7dSRichard Lowe 
108510d63b7dSRichard Lowe 	if (trace_reader) {
108610d63b7dSRichard Lowe 		(void) printf("Dynamic target %s:\n", result->name->string_mb);
108710d63b7dSRichard Lowe 	}
108810d63b7dSRichard Lowe 	return( result);
108910d63b7dSRichard Lowe }
109010d63b7dSRichard Lowe 
109110d63b7dSRichard Lowe 
109210d63b7dSRichard Lowe /*
109310d63b7dSRichard Lowe  *	special_reader(target, depes, command)
109410d63b7dSRichard Lowe  *
109510d63b7dSRichard Lowe  *	Read the pseudo targets make knows about
109610d63b7dSRichard Lowe  *	This handles the special targets that should not be entered as regular
109710d63b7dSRichard Lowe  *	target/dependency sets.
109810d63b7dSRichard Lowe  *
109910d63b7dSRichard Lowe  *	Parameters:
110010d63b7dSRichard Lowe  *		target		The special target
110110d63b7dSRichard Lowe  *		depes		The list of dependencies it was entered with
110210d63b7dSRichard Lowe  *		command		The command it was entered with
110310d63b7dSRichard Lowe  *
110410d63b7dSRichard Lowe  *	Static variables used:
110510d63b7dSRichard Lowe  *		built_last_make_run_seen Set to indicate .BUILT_LAST... seen
110610d63b7dSRichard Lowe  *
110710d63b7dSRichard Lowe  *	Global variables used:
110810d63b7dSRichard Lowe  *		all_parallel	Set to indicate that everything runs parallel
1109ae389aa9SAndy Fiddaman  *		svr4		Set when ".SVR4" target is read
111010d63b7dSRichard Lowe  *		svr4_name	The Name ".SVR4"
1111ae389aa9SAndy Fiddaman  *		posix		Set when ".POSIX" target is read
111210d63b7dSRichard Lowe  *		posix_name	The Name ".POSIX"
111310d63b7dSRichard Lowe  *		current_make_version The Name "<current version number>"
111410d63b7dSRichard Lowe  *		default_rule	Set when ".DEFAULT" target is read
111510d63b7dSRichard Lowe  *		default_rule_name The Name ".DEFAULT", used for tracing
111610d63b7dSRichard Lowe  *		dot_keep_state	The Name ".KEEP_STATE", used for tracing
111710d63b7dSRichard Lowe  *		ignore_errors	Set if ".IGNORE" target is read
111810d63b7dSRichard Lowe  *		ignore_name	The Name ".IGNORE", used for tracing
111910d63b7dSRichard Lowe  *		keep_state	Set if ".KEEP_STATE" target is read
112010d63b7dSRichard Lowe  *		no_parallel_name The Name ".NO_PARALLEL", used for tracing
112110d63b7dSRichard Lowe  *		only_parallel	Set to indicate only some targets runs parallel
112210d63b7dSRichard Lowe  *		parallel_name	The Name ".PARALLEL", used for tracing
112310d63b7dSRichard Lowe  *		precious	The Name ".PRECIOUS", used for tracing
112410d63b7dSRichard Lowe  *		sccs_get_name	The Name ".SCCS_GET", used for tracing
112510d63b7dSRichard Lowe  *		sccs_get_posix_name The Name ".SCCS_GET_POSIX", used for tracing
112610d63b7dSRichard Lowe  *		get_name	The Name ".GET", used for tracing
112710d63b7dSRichard Lowe  *		sccs_get_rule	Set when ".SCCS_GET" target is read
112810d63b7dSRichard Lowe  *		silent		Set when ".SILENT" target is read
112910d63b7dSRichard Lowe  *		silent_name	The Name ".SILENT", used for tracing
113010d63b7dSRichard Lowe  *		trace_reader	Indicates that we should echo stuff we read
113110d63b7dSRichard Lowe  */
113210d63b7dSRichard Lowe void
special_reader(Name target,Name_vector depes,Cmd_line command)1133*e7afc443SToomas Soome special_reader(Name target, Name_vector depes, Cmd_line command)
113410d63b7dSRichard Lowe {
1135*e7afc443SToomas Soome 	int		n;
113610d63b7dSRichard Lowe 
113710d63b7dSRichard Lowe 	switch (target->special_reader) {
113810d63b7dSRichard Lowe 
113910d63b7dSRichard Lowe 	case svr4_special:
114010d63b7dSRichard Lowe 		if (depes->used != 0) {
114110d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependencies for target `%s'"),
114210d63b7dSRichard Lowe 				     target->string_mb);
114310d63b7dSRichard Lowe 		}
114410d63b7dSRichard Lowe 		svr4  = true;
114510d63b7dSRichard Lowe 		posix  = false;
114610d63b7dSRichard Lowe 		keep_state = false;
114710d63b7dSRichard Lowe 		all_parallel = false;
114810d63b7dSRichard Lowe 		only_parallel = false;
114910d63b7dSRichard Lowe 		if (trace_reader) {
115010d63b7dSRichard Lowe 			(void) printf("%s:\n", svr4_name->string_mb);
115110d63b7dSRichard Lowe 		}
115210d63b7dSRichard Lowe 		break;
115310d63b7dSRichard Lowe 
115410d63b7dSRichard Lowe 	case posix_special:
115510d63b7dSRichard Lowe 		if(svr4)
115610d63b7dSRichard Lowe 		  break;
115710d63b7dSRichard Lowe 		if (depes->used != 0) {
115810d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependencies for target `%s'"),
115910d63b7dSRichard Lowe 				     target->string_mb);
116010d63b7dSRichard Lowe 		}
116110d63b7dSRichard Lowe 		posix  = true;
116210d63b7dSRichard Lowe 			/* with posix on, use the posix get rule */
116310d63b7dSRichard Lowe 		sccs_get_rule = sccs_get_posix_rule;
116410d63b7dSRichard Lowe 			/* turn keep state off being SunPro make specific */
116510d63b7dSRichard Lowe 		keep_state = false;
116610d63b7dSRichard Lowe 		/* Use /usr/xpg4/bin/sh on Solaris */
116710d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "/usr/xpg4/bin/sh");
116810d63b7dSRichard Lowe 		(void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false);
116910d63b7dSRichard Lowe 		if (trace_reader) {
117010d63b7dSRichard Lowe 			(void) printf("%s:\n", posix_name->string_mb);
117110d63b7dSRichard Lowe 		}
117210d63b7dSRichard Lowe 		break;
117310d63b7dSRichard Lowe 
117410d63b7dSRichard Lowe 	case built_last_make_run_special:
117510d63b7dSRichard Lowe 		built_last_make_run_seen = true;
117610d63b7dSRichard Lowe 		break;
117710d63b7dSRichard Lowe 
117810d63b7dSRichard Lowe 	case default_special:
117910d63b7dSRichard Lowe 		if (depes->used != 0) {
118010d63b7dSRichard Lowe 			warning(gettext("Illegal dependency list for target `%s'"),
118110d63b7dSRichard Lowe 				target->string_mb);
118210d63b7dSRichard Lowe 		}
118310d63b7dSRichard Lowe 		default_rule = command;
118410d63b7dSRichard Lowe 		if (trace_reader) {
118510d63b7dSRichard Lowe 			(void) printf("%s:\n",
118610d63b7dSRichard Lowe 				      default_rule_name->string_mb);
118710d63b7dSRichard Lowe 			print_rule(command);
118810d63b7dSRichard Lowe 		}
118910d63b7dSRichard Lowe 		break;
119010d63b7dSRichard Lowe 
119110d63b7dSRichard Lowe 
119210d63b7dSRichard Lowe 	case ignore_special:
119310d63b7dSRichard Lowe 		if ((depes->used != 0) &&(!posix)){
119410d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependencies for target `%s'"),
119510d63b7dSRichard Lowe 				     target->string_mb);
119610d63b7dSRichard Lowe 		}
119710d63b7dSRichard Lowe 		if (depes->used == 0)
119810d63b7dSRichard Lowe 		{
119910d63b7dSRichard Lowe 		   ignore_errors_all = true;
120010d63b7dSRichard Lowe 		}
120110d63b7dSRichard Lowe 		if(svr4) {
120210d63b7dSRichard Lowe 		  ignore_errors_all = true;
120310d63b7dSRichard Lowe 		  break;
120410d63b7dSRichard Lowe 		}
120510d63b7dSRichard Lowe 		for (; depes != NULL; depes = depes->next) {
120610d63b7dSRichard Lowe 			for (n = 0; n < depes->used; n++) {
120710d63b7dSRichard Lowe 				depes->names[n]->ignore_error_mode = true;
120810d63b7dSRichard Lowe 			}
120910d63b7dSRichard Lowe 		}
121010d63b7dSRichard Lowe 		if (trace_reader) {
121110d63b7dSRichard Lowe 			(void) printf("%s:\n", ignore_name->string_mb);
121210d63b7dSRichard Lowe 		}
121310d63b7dSRichard Lowe 		break;
121410d63b7dSRichard Lowe 
121510d63b7dSRichard Lowe 	case keep_state_special:
121610d63b7dSRichard Lowe 		if(svr4)
121710d63b7dSRichard Lowe 		  break;
121810d63b7dSRichard Lowe 			/* ignore keep state, being SunPro make specific */
121910d63b7dSRichard Lowe 		if(posix)
122010d63b7dSRichard Lowe 		  break;
122110d63b7dSRichard Lowe 		if (depes->used != 0) {
122210d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependencies for target `%s'"),
122310d63b7dSRichard Lowe 				     target->string_mb);
122410d63b7dSRichard Lowe 		}
122510d63b7dSRichard Lowe 		keep_state = true;
122610d63b7dSRichard Lowe 		if (trace_reader) {
122710d63b7dSRichard Lowe 			(void) printf("%s:\n",
122810d63b7dSRichard Lowe 				      dot_keep_state->string_mb);
122910d63b7dSRichard Lowe 		}
123010d63b7dSRichard Lowe 		break;
123110d63b7dSRichard Lowe 
123210d63b7dSRichard Lowe 	case keep_state_file_special:
123310d63b7dSRichard Lowe 		if(svr4)
123410d63b7dSRichard Lowe 		  break;
123510d63b7dSRichard Lowe 		if(posix)
123610d63b7dSRichard Lowe 		  break;
1237ae389aa9SAndy Fiddaman 			/* it's not necessary to specify KEEP_STATE, if this
123810d63b7dSRichard Lowe 			** is given, so set the keep_state.
123910d63b7dSRichard Lowe 			*/
124010d63b7dSRichard Lowe 		keep_state = true;
124110d63b7dSRichard Lowe 		if (depes->used != 0) {
124210d63b7dSRichard Lowe 		   if((!make_state) ||(!strcmp(make_state->string_mb,".make.state"))) {
124310d63b7dSRichard Lowe 		     make_state = depes->names[0];
124410d63b7dSRichard Lowe 		   }
124510d63b7dSRichard Lowe 		}
124610d63b7dSRichard Lowe 		break;
124710d63b7dSRichard Lowe 	case make_version_special:
124810d63b7dSRichard Lowe 		if(svr4)
124910d63b7dSRichard Lowe 		  break;
125010d63b7dSRichard Lowe 		if (depes->used != 1) {
125110d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependency list for target `%s'"),
125210d63b7dSRichard Lowe 				     target->string_mb);
125310d63b7dSRichard Lowe 		}
125410d63b7dSRichard Lowe 		if (depes->names[0] != current_make_version) {
125510d63b7dSRichard Lowe 			/*
125610d63b7dSRichard Lowe 			 * Special case the fact that version 1.0 and 1.1
125710d63b7dSRichard Lowe 			 * are identical.
125810d63b7dSRichard Lowe 			 */
125910d63b7dSRichard Lowe 			if (!IS_EQUAL(depes->names[0]->string_mb,
126010d63b7dSRichard Lowe 				      "VERSION-1.1") ||
126110d63b7dSRichard Lowe 			    !IS_EQUAL(current_make_version->string_mb,
126210d63b7dSRichard Lowe 				      "VERSION-1.0")) {
126310d63b7dSRichard Lowe 				/*
126410d63b7dSRichard Lowe 				 * Version mismatches should cause the
126510d63b7dSRichard Lowe 				 * .make.state file to be skipped.
126610d63b7dSRichard Lowe 				 * This is currently not true - it is read
126710d63b7dSRichard Lowe 				 * anyway.
126810d63b7dSRichard Lowe 				 */
126910d63b7dSRichard Lowe 				warning(gettext("Version mismatch between current version `%s' and `%s'"),
127010d63b7dSRichard Lowe 					current_make_version->string_mb,
127110d63b7dSRichard Lowe 					depes->names[0]->string_mb);
127210d63b7dSRichard Lowe 			}
127310d63b7dSRichard Lowe 		}
127410d63b7dSRichard Lowe 		break;
127510d63b7dSRichard Lowe 
127610d63b7dSRichard Lowe 	case no_parallel_special:
127710d63b7dSRichard Lowe 		if(svr4)
127810d63b7dSRichard Lowe 		  break;
127910d63b7dSRichard Lowe 		/* Set the no_parallel bit for all the targets on */
128010d63b7dSRichard Lowe 		/* the dependency list */
128110d63b7dSRichard Lowe 		if (depes->used == 0) {
128210d63b7dSRichard Lowe 			/* only those explicitly made parallel */
128310d63b7dSRichard Lowe 			only_parallel = true;
128410d63b7dSRichard Lowe 			all_parallel = false;
128510d63b7dSRichard Lowe 		}
128610d63b7dSRichard Lowe 		for (; depes != NULL; depes = depes->next) {
128710d63b7dSRichard Lowe 			for (n = 0; n < depes->used; n++) {
128810d63b7dSRichard Lowe 				if (trace_reader) {
128910d63b7dSRichard Lowe 					(void) printf("%s:\t%s\n",
129010d63b7dSRichard Lowe 						      no_parallel_name->string_mb,
129110d63b7dSRichard Lowe 						      depes->names[n]->string_mb);
129210d63b7dSRichard Lowe 				}
129310d63b7dSRichard Lowe 				depes->names[n]->no_parallel = true;
129410d63b7dSRichard Lowe 				depes->names[n]->parallel = false;
129510d63b7dSRichard Lowe 			}
129610d63b7dSRichard Lowe 		}
129710d63b7dSRichard Lowe 		break;
129810d63b7dSRichard Lowe 
129910d63b7dSRichard Lowe 	case parallel_special:
130010d63b7dSRichard Lowe 		if(svr4)
130110d63b7dSRichard Lowe 		  break;
130210d63b7dSRichard Lowe 		if (depes->used == 0) {
130310d63b7dSRichard Lowe 			/* everything runs in parallel */
130410d63b7dSRichard Lowe 			all_parallel = true;
130510d63b7dSRichard Lowe 			only_parallel = false;
130610d63b7dSRichard Lowe 		}
130710d63b7dSRichard Lowe 		/* Set the parallel bit for all the targets on */
130810d63b7dSRichard Lowe 		/* the dependency list */
130910d63b7dSRichard Lowe 		for (; depes != NULL; depes = depes->next) {
131010d63b7dSRichard Lowe 			for (n = 0; n < depes->used; n++) {
131110d63b7dSRichard Lowe 				if (trace_reader) {
131210d63b7dSRichard Lowe 					(void) printf("%s:\t%s\n",
131310d63b7dSRichard Lowe 						      parallel_name->string_mb,
131410d63b7dSRichard Lowe 						      depes->names[n]->string_mb);
131510d63b7dSRichard Lowe 				}
131610d63b7dSRichard Lowe 				depes->names[n]->parallel = true;
131710d63b7dSRichard Lowe 				depes->names[n]->no_parallel = false;
131810d63b7dSRichard Lowe 			}
131910d63b7dSRichard Lowe 		}
132010d63b7dSRichard Lowe 		break;
132110d63b7dSRichard Lowe 
132210d63b7dSRichard Lowe 	case localhost_special:
132310d63b7dSRichard Lowe 		if(svr4)
132410d63b7dSRichard Lowe 		  break;
132510d63b7dSRichard Lowe 		/* Set the no_parallel bit for all the targets on */
132610d63b7dSRichard Lowe 		/* the dependency list */
132710d63b7dSRichard Lowe 		if (depes->used == 0) {
132810d63b7dSRichard Lowe 			/* only those explicitly made parallel */
132910d63b7dSRichard Lowe 			only_parallel = true;
133010d63b7dSRichard Lowe 			all_parallel = false;
133110d63b7dSRichard Lowe 		}
133210d63b7dSRichard Lowe 		for (; depes != NULL; depes = depes->next) {
133310d63b7dSRichard Lowe 			for (n = 0; n < depes->used; n++) {
133410d63b7dSRichard Lowe 				if (trace_reader) {
133510d63b7dSRichard Lowe 					(void) printf("%s:\t%s\n",
133610d63b7dSRichard Lowe 						      localhost_name->string_mb,
133710d63b7dSRichard Lowe 						      depes->names[n]->string_mb);
133810d63b7dSRichard Lowe 				}
133910d63b7dSRichard Lowe 				depes->names[n]->no_parallel = true;
134010d63b7dSRichard Lowe 				depes->names[n]->parallel = false;
134110d63b7dSRichard Lowe 				depes->names[n]->localhost = true;
134210d63b7dSRichard Lowe 			}
134310d63b7dSRichard Lowe 		}
134410d63b7dSRichard Lowe 		break;
134510d63b7dSRichard Lowe 
134610d63b7dSRichard Lowe 	case precious_special:
134710d63b7dSRichard Lowe 		if (depes->used == 0) {
134810d63b7dSRichard Lowe 			/* everything is precious      */
134910d63b7dSRichard Lowe 			all_precious = true;
135010d63b7dSRichard Lowe 		} else {
135110d63b7dSRichard Lowe 			all_precious = false;
135210d63b7dSRichard Lowe 		}
135310d63b7dSRichard Lowe 		if(svr4) {
135410d63b7dSRichard Lowe 		  all_precious = true;
135510d63b7dSRichard Lowe 		  break;
135610d63b7dSRichard Lowe 		}
135710d63b7dSRichard Lowe 		/* Set the precious bit for all the targets on */
135810d63b7dSRichard Lowe 		/* the dependency list */
135910d63b7dSRichard Lowe 		for (; depes != NULL; depes = depes->next) {
136010d63b7dSRichard Lowe 			for (n = 0; n < depes->used; n++) {
136110d63b7dSRichard Lowe 				if (trace_reader) {
136210d63b7dSRichard Lowe 					(void) printf("%s:\t%s\n",
136310d63b7dSRichard Lowe 						      precious->string_mb,
136410d63b7dSRichard Lowe 						      depes->names[n]->string_mb);
136510d63b7dSRichard Lowe 				}
136610d63b7dSRichard Lowe 				depes->names[n]->stat.is_precious = true;
136710d63b7dSRichard Lowe 			}
136810d63b7dSRichard Lowe 		}
136910d63b7dSRichard Lowe 		break;
137010d63b7dSRichard Lowe 
137110d63b7dSRichard Lowe 	case sccs_get_special:
137210d63b7dSRichard Lowe 		if (depes->used != 0) {
137310d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependencies for target `%s'"),
137410d63b7dSRichard Lowe 				     target->string_mb);
137510d63b7dSRichard Lowe 		}
137610d63b7dSRichard Lowe 		sccs_get_rule = command;
137710d63b7dSRichard Lowe 		sccs_get_org_rule = command;
137810d63b7dSRichard Lowe 		if (trace_reader) {
137910d63b7dSRichard Lowe 			(void) printf("%s:\n", sccs_get_name->string_mb);
138010d63b7dSRichard Lowe 			print_rule(command);
138110d63b7dSRichard Lowe 		}
138210d63b7dSRichard Lowe 		break;
138310d63b7dSRichard Lowe 
138410d63b7dSRichard Lowe 	case sccs_get_posix_special:
138510d63b7dSRichard Lowe 		if (depes->used != 0) {
138610d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependencies for target `%s'"),
138710d63b7dSRichard Lowe 				     target->string_mb);
138810d63b7dSRichard Lowe 		}
138910d63b7dSRichard Lowe 		sccs_get_posix_rule = command;
139010d63b7dSRichard Lowe 		if (trace_reader) {
139110d63b7dSRichard Lowe 			(void) printf("%s:\n", sccs_get_posix_name->string_mb);
139210d63b7dSRichard Lowe 			print_rule(command);
139310d63b7dSRichard Lowe 		}
139410d63b7dSRichard Lowe 		break;
139510d63b7dSRichard Lowe 
139610d63b7dSRichard Lowe 	case get_posix_special:
139710d63b7dSRichard Lowe 		if (depes->used != 0) {
139810d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependencies for target `%s'"),
139910d63b7dSRichard Lowe 				     target->string_mb);
140010d63b7dSRichard Lowe 		}
140110d63b7dSRichard Lowe 		get_posix_rule = command;
140210d63b7dSRichard Lowe 		if (trace_reader) {
140310d63b7dSRichard Lowe 			(void) printf("%s:\n", get_posix_name->string_mb);
140410d63b7dSRichard Lowe 			print_rule(command);
140510d63b7dSRichard Lowe 		}
140610d63b7dSRichard Lowe 		break;
140710d63b7dSRichard Lowe 
140810d63b7dSRichard Lowe 	case get_special:
140910d63b7dSRichard Lowe 		if(!svr4) {
141010d63b7dSRichard Lowe 		  break;
141110d63b7dSRichard Lowe 		}
141210d63b7dSRichard Lowe 		if (depes->used != 0) {
141310d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependencies for target `%s'"),
141410d63b7dSRichard Lowe 				     target->string_mb);
141510d63b7dSRichard Lowe 		}
141610d63b7dSRichard Lowe 		get_rule = command;
141710d63b7dSRichard Lowe 		sccs_get_rule = command;
141810d63b7dSRichard Lowe 		if (trace_reader) {
141910d63b7dSRichard Lowe 			(void) printf("%s:\n", get_name->string_mb);
142010d63b7dSRichard Lowe 			print_rule(command);
142110d63b7dSRichard Lowe 		}
142210d63b7dSRichard Lowe 		break;
142310d63b7dSRichard Lowe 
142410d63b7dSRichard Lowe 	case silent_special:
142510d63b7dSRichard Lowe 		if ((depes->used != 0) && (!posix)){
142610d63b7dSRichard Lowe 			fatal_reader(gettext("Illegal dependencies for target `%s'"),
142710d63b7dSRichard Lowe 				     target->string_mb);
142810d63b7dSRichard Lowe 		}
142910d63b7dSRichard Lowe 		if (depes->used == 0)
143010d63b7dSRichard Lowe 		{
143110d63b7dSRichard Lowe 		   silent_all = true;
143210d63b7dSRichard Lowe 		}
143310d63b7dSRichard Lowe 		if(svr4) {
143410d63b7dSRichard Lowe 		  silent_all = true;
143510d63b7dSRichard Lowe 		  break;
143610d63b7dSRichard Lowe 		}
143710d63b7dSRichard Lowe 		for (; depes != NULL; depes = depes->next) {
143810d63b7dSRichard Lowe 			for (n = 0; n < depes->used; n++) {
143910d63b7dSRichard Lowe 				depes->names[n]->silent_mode = true;
144010d63b7dSRichard Lowe 			}
144110d63b7dSRichard Lowe 		}
144210d63b7dSRichard Lowe 		if (trace_reader) {
144310d63b7dSRichard Lowe 			(void) printf("%s:\n", silent_name->string_mb);
144410d63b7dSRichard Lowe 		}
144510d63b7dSRichard Lowe 		break;
144610d63b7dSRichard Lowe 
144710d63b7dSRichard Lowe 	case suffixes_special:
144810d63b7dSRichard Lowe 		read_suffixes_list(depes);
144910d63b7dSRichard Lowe 		break;
145010d63b7dSRichard Lowe 
145110d63b7dSRichard Lowe 	default:
145210d63b7dSRichard Lowe 
145310d63b7dSRichard Lowe 		fatal_reader(gettext("Internal error: Unknown special reader"));
145410d63b7dSRichard Lowe 	}
145510d63b7dSRichard Lowe }
145610d63b7dSRichard Lowe 
145710d63b7dSRichard Lowe /*
145810d63b7dSRichard Lowe  *	read_suffixes_list(depes)
145910d63b7dSRichard Lowe  *
146010d63b7dSRichard Lowe  *	Read the special list .SUFFIXES. If it is empty the old list is
146110d63b7dSRichard Lowe  *	cleared. Else the new one is appended. Suffixes with ~ are extracted
146210d63b7dSRichard Lowe  *	and marked.
146310d63b7dSRichard Lowe  *
146410d63b7dSRichard Lowe  *	Parameters:
146510d63b7dSRichard Lowe  *		depes		The list of suffixes
146610d63b7dSRichard Lowe  *
146710d63b7dSRichard Lowe  *	Global variables used:
146810d63b7dSRichard Lowe  *		hashtab		The central hashtable for Names.
146910d63b7dSRichard Lowe  *		suffixes	The list of suffixes, set or appended to
147010d63b7dSRichard Lowe  *		suffixes_name	The Name ".SUFFIXES", used for tracing
147110d63b7dSRichard Lowe  *		trace_reader	Indicates that we should echo stuff we read
147210d63b7dSRichard Lowe  */
147310d63b7dSRichard Lowe static void
read_suffixes_list(Name_vector depes)1474*e7afc443SToomas Soome read_suffixes_list(Name_vector depes)
147510d63b7dSRichard Lowe {
1476*e7afc443SToomas Soome 	int		n;
1477*e7afc443SToomas Soome 	Dependency	dp;
1478*e7afc443SToomas Soome 	Dependency	*insert_dep;
1479*e7afc443SToomas Soome 	Name		np;
148010d63b7dSRichard Lowe 	Name			np2;
1481*e7afc443SToomas Soome 	Boolean	first = true;
148210d63b7dSRichard Lowe 
148310d63b7dSRichard Lowe 	if (depes->used == 0) {
148410d63b7dSRichard Lowe 		/* .SUFFIXES with no dependency list clears the */
148510d63b7dSRichard Lowe 		/* suffixes list */
148610d63b7dSRichard Lowe 		for (Name_set::iterator np = hashtab.begin(), e = hashtab.end(); np != e; np++) {
148710d63b7dSRichard Lowe 				np->with_squiggle =
148810d63b7dSRichard Lowe 				  np->without_squiggle =
148910d63b7dSRichard Lowe 				    false;
149010d63b7dSRichard Lowe 		}
149110d63b7dSRichard Lowe 		suffixes = NULL;
149210d63b7dSRichard Lowe 		if (trace_reader) {
149310d63b7dSRichard Lowe 			(void) printf("%s:\n", suffixes_name->string_mb);
149410d63b7dSRichard Lowe 		}
149510d63b7dSRichard Lowe 		return;
149610d63b7dSRichard Lowe 	}
149710d63b7dSRichard Lowe 	Wstring str;
149810d63b7dSRichard Lowe 	/* Otherwise we append to the list */
149910d63b7dSRichard Lowe 	for (; depes != NULL; depes = depes->next) {
150010d63b7dSRichard Lowe 		for (n = 0; n < depes->used; n++) {
150110d63b7dSRichard Lowe 			np = depes->names[n];
150210d63b7dSRichard Lowe 			/* Find the end of the list and check if the */
150310d63b7dSRichard Lowe 			/* suffix already has been entered */
150410d63b7dSRichard Lowe 			for (insert_dep = &suffixes, dp = *insert_dep;
150510d63b7dSRichard Lowe 			     dp != NULL;
150610d63b7dSRichard Lowe 			     insert_dep = &dp->next, dp = *insert_dep) {
150710d63b7dSRichard Lowe 				if (dp->name == np) {
150810d63b7dSRichard Lowe 					goto duplicate_suffix;
150910d63b7dSRichard Lowe 				}
151010d63b7dSRichard Lowe 			}
151110d63b7dSRichard Lowe 			if (trace_reader) {
151210d63b7dSRichard Lowe 				if (first) {
151310d63b7dSRichard Lowe 					(void) printf("%s:\t",
151410d63b7dSRichard Lowe 						      suffixes_name->string_mb);
151510d63b7dSRichard Lowe 					first = false;
151610d63b7dSRichard Lowe 				}
151710d63b7dSRichard Lowe 				(void) printf("%s ", depes->names[n]->string_mb);
151810d63b7dSRichard Lowe 			}
151910d63b7dSRichard Lowe 		if(!(posix|svr4)) {
152010d63b7dSRichard Lowe 			/* If the suffix is suffixed with "~" we */
152110d63b7dSRichard Lowe 			/* strip that and mark the suffix nameblock */
152210d63b7dSRichard Lowe 			str.init(np);
152310d63b7dSRichard Lowe 			wchar_t * wcb = str.get_string();
152410d63b7dSRichard Lowe 			if (wcb[np->hash.length - 1] ==
152510d63b7dSRichard Lowe 			    (int) tilde_char) {
152610d63b7dSRichard Lowe 				np2 = GETNAME(wcb,
152710d63b7dSRichard Lowe 					      (int)(np->hash.length - 1));
152810d63b7dSRichard Lowe 				np2->with_squiggle = true;
152910d63b7dSRichard Lowe 				if (np2->without_squiggle) {
153010d63b7dSRichard Lowe 					continue;
153110d63b7dSRichard Lowe 				}
153210d63b7dSRichard Lowe 				np = np2;
153310d63b7dSRichard Lowe 			}
153410d63b7dSRichard Lowe 		}
153510d63b7dSRichard Lowe 			np->without_squiggle = true;
153610d63b7dSRichard Lowe 			/* Add the suffix to the list */
153710d63b7dSRichard Lowe 			dp = *insert_dep = ALLOC(Dependency);
153810d63b7dSRichard Lowe 			insert_dep = &dp->next;
153910d63b7dSRichard Lowe 			dp->next = NULL;
154010d63b7dSRichard Lowe 			dp->name = np;
154110d63b7dSRichard Lowe 			dp->built = false;
154210d63b7dSRichard Lowe 		duplicate_suffix:;
154310d63b7dSRichard Lowe 		}
154410d63b7dSRichard Lowe 	}
154510d63b7dSRichard Lowe 	if (trace_reader) {
154610d63b7dSRichard Lowe 		(void) printf("\n");
154710d63b7dSRichard Lowe 	}
154810d63b7dSRichard Lowe }
154910d63b7dSRichard Lowe 
155010d63b7dSRichard Lowe /*
155110d63b7dSRichard Lowe  *	make_relative(to, result)
155210d63b7dSRichard Lowe  *
155310d63b7dSRichard Lowe  *	Given a file name compose a relative path name from it to the
155410d63b7dSRichard Lowe  *	current directory.
155510d63b7dSRichard Lowe  *
155610d63b7dSRichard Lowe  *	Parameters:
155710d63b7dSRichard Lowe  *		to		The path we want to make relative
155810d63b7dSRichard Lowe  *		result		Where to put the resulting relative path
155910d63b7dSRichard Lowe  *
156010d63b7dSRichard Lowe  *	Global variables used:
156110d63b7dSRichard Lowe  */
156210d63b7dSRichard Lowe static void
make_relative(wchar_t * to,wchar_t * result)156310d63b7dSRichard Lowe make_relative(wchar_t *to, wchar_t *result)
156410d63b7dSRichard Lowe {
156510d63b7dSRichard Lowe 	wchar_t			*from;
156610d63b7dSRichard Lowe 	wchar_t			*allocated;
156710d63b7dSRichard Lowe 	wchar_t			*cp;
156810d63b7dSRichard Lowe 	wchar_t			*tocomp;
156910d63b7dSRichard Lowe 	int			ncomps;
157010d63b7dSRichard Lowe 	int			i;
157110d63b7dSRichard Lowe 	int			len;
157210d63b7dSRichard Lowe 
157310d63b7dSRichard Lowe 	/* Check if the path is already relative. */
157410d63b7dSRichard Lowe 	if (to[0] != (int) slash_char) {
157510d63b7dSRichard Lowe 		(void) wcscpy(result, to);
157610d63b7dSRichard Lowe 		return;
157710d63b7dSRichard Lowe 	}
157810d63b7dSRichard Lowe 
157910d63b7dSRichard Lowe 	MBSTOWCS(wcs_buffer, get_current_path());
158010d63b7dSRichard Lowe 	from = allocated = (wchar_t *) wcsdup(wcs_buffer);
158110d63b7dSRichard Lowe 
158210d63b7dSRichard Lowe 	/*
158310d63b7dSRichard Lowe 	 * Find the number of components in the from name.
158410d63b7dSRichard Lowe 	 * ncomp = number of slashes + 1.
158510d63b7dSRichard Lowe 	 */
158610d63b7dSRichard Lowe 	ncomps = 1;
158710d63b7dSRichard Lowe 	for (cp = from; *cp != (int) nul_char; cp++) {
158810d63b7dSRichard Lowe 		if (*cp == (int) slash_char) {
158910d63b7dSRichard Lowe 			ncomps++;
159010d63b7dSRichard Lowe 		}
159110d63b7dSRichard Lowe 	}
159210d63b7dSRichard Lowe 
159310d63b7dSRichard Lowe 	/*
159410d63b7dSRichard Lowe 	 * See how many components match to determine how many "..",
159510d63b7dSRichard Lowe 	 * if any, will be needed.
159610d63b7dSRichard Lowe 	 */
159710d63b7dSRichard Lowe 	result[0] = (int) nul_char;
159810d63b7dSRichard Lowe 	tocomp = to;
159910d63b7dSRichard Lowe 	while ((*from != (int) nul_char) && (*from == *to)) {
160010d63b7dSRichard Lowe 		if (*from == (int) slash_char) {
160110d63b7dSRichard Lowe 			ncomps--;
160210d63b7dSRichard Lowe 			tocomp = &to[1];
160310d63b7dSRichard Lowe 		}
160410d63b7dSRichard Lowe 		from++;
160510d63b7dSRichard Lowe 		to++;
160610d63b7dSRichard Lowe 	}
160710d63b7dSRichard Lowe 
160810d63b7dSRichard Lowe 	/*
160910d63b7dSRichard Lowe 	 * Now for some special cases. Check for exact matches and
161010d63b7dSRichard Lowe 	 * for either name terminating exactly.
161110d63b7dSRichard Lowe 	 */
161210d63b7dSRichard Lowe 	if (*from == (int) nul_char) {
161310d63b7dSRichard Lowe 		if (*to == (int) nul_char) {
161410d63b7dSRichard Lowe 			MBSTOWCS(wcs_buffer, ".");
161510d63b7dSRichard Lowe 			(void) wcscpy(result, wcs_buffer);
161610d63b7dSRichard Lowe 			retmem(allocated);
161710d63b7dSRichard Lowe 			return;
161810d63b7dSRichard Lowe 		}
161910d63b7dSRichard Lowe 		if (*to == (int) slash_char) {
162010d63b7dSRichard Lowe 			ncomps--;
162110d63b7dSRichard Lowe 			tocomp = &to[1];
162210d63b7dSRichard Lowe 		}
162310d63b7dSRichard Lowe 	} else if ((*from == (int) slash_char) && (*to == (int) nul_char)) {
162410d63b7dSRichard Lowe 		ncomps--;
162510d63b7dSRichard Lowe 		tocomp = to;
162610d63b7dSRichard Lowe 	}
162710d63b7dSRichard Lowe 	/* Add on the ".."s. */
162810d63b7dSRichard Lowe 	for (i = 0; i < ncomps; i++) {
162910d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "../");
163010d63b7dSRichard Lowe 		(void) wcscat(result, wcs_buffer);
163110d63b7dSRichard Lowe 	}
163210d63b7dSRichard Lowe 
163310d63b7dSRichard Lowe 	/* Add on the remainder of the to name, if any. */
163410d63b7dSRichard Lowe 	if (*tocomp == (int) nul_char) {
163510d63b7dSRichard Lowe 		len = wcslen(result);
163610d63b7dSRichard Lowe 		result[len - 1] = (int) nul_char;
163710d63b7dSRichard Lowe 	} else {
163810d63b7dSRichard Lowe 		(void) wcscat(result, tocomp);
163910d63b7dSRichard Lowe 	}
164010d63b7dSRichard Lowe 	retmem(allocated);
164110d63b7dSRichard Lowe 	return;
164210d63b7dSRichard Lowe }
164310d63b7dSRichard Lowe 
164410d63b7dSRichard Lowe /*
164510d63b7dSRichard Lowe  *	print_rule(command)
164610d63b7dSRichard Lowe  *
164710d63b7dSRichard Lowe  *	Used when tracing the reading of rules
164810d63b7dSRichard Lowe  *
164910d63b7dSRichard Lowe  *	Parameters:
165010d63b7dSRichard Lowe  *		command		Command to print
165110d63b7dSRichard Lowe  *
165210d63b7dSRichard Lowe  *	Global variables used:
165310d63b7dSRichard Lowe  */
165410d63b7dSRichard Lowe static void
print_rule(Cmd_line command)1655*e7afc443SToomas Soome print_rule(Cmd_line command)
165610d63b7dSRichard Lowe {
165710d63b7dSRichard Lowe 	for (; command != NULL; command = command->next) {
165810d63b7dSRichard Lowe 		(void) printf("\t%s\n", command->command_line->string_mb);
165910d63b7dSRichard Lowe 	}
166010d63b7dSRichard Lowe }
166110d63b7dSRichard Lowe 
166210d63b7dSRichard Lowe /*
166310d63b7dSRichard Lowe  *	enter_conditional(target, name, value, append)
166410d63b7dSRichard Lowe  *
166510d63b7dSRichard Lowe  *	Enter "target := MACRO= value" constructs
166610d63b7dSRichard Lowe  *
166710d63b7dSRichard Lowe  *	Parameters:
166810d63b7dSRichard Lowe  *		target		The target the macro is for
166910d63b7dSRichard Lowe  *		name		The name of the macro
167010d63b7dSRichard Lowe  *		value		The value for the macro
167110d63b7dSRichard Lowe  *		append		Indicates if the assignment is appending or not
167210d63b7dSRichard Lowe  *
167310d63b7dSRichard Lowe  *	Global variables used:
167410d63b7dSRichard Lowe  *		conditionals	A special Name that stores all conditionals
167510d63b7dSRichard Lowe  *				where the target is a % pattern
167610d63b7dSRichard Lowe  *		trace_reader	Indicates that we should echo stuff we read
167710d63b7dSRichard Lowe  */
167810d63b7dSRichard Lowe void
enter_conditional(Name target,Name name,Name value,Boolean append)1679*e7afc443SToomas Soome enter_conditional(Name target, Name name, Name value, Boolean append)
168010d63b7dSRichard Lowe {
1681*e7afc443SToomas Soome 	Property	conditional;
168210d63b7dSRichard Lowe 	static int		sequence;
168310d63b7dSRichard Lowe 	Name			orig_target = target;
168410d63b7dSRichard Lowe 
168510d63b7dSRichard Lowe 	if (name == target_arch) {
168610d63b7dSRichard Lowe 		enter_conditional(target, virtual_root, virtual_root, false);
168710d63b7dSRichard Lowe 	}
168810d63b7dSRichard Lowe 
168910d63b7dSRichard Lowe 	if (target->percent) {
169010d63b7dSRichard Lowe 		target = conditionals;
169110d63b7dSRichard Lowe 	}
1692ae389aa9SAndy Fiddaman 
169310d63b7dSRichard Lowe 	if (name->colon) {
169410d63b7dSRichard Lowe 		sh_transform(&name, &value);
169510d63b7dSRichard Lowe 	}
169610d63b7dSRichard Lowe 
169710d63b7dSRichard Lowe 	/* Count how many conditionals we must activate before building the */
169810d63b7dSRichard Lowe 	/* target */
169910d63b7dSRichard Lowe 	if (target->percent) {
170010d63b7dSRichard Lowe 		target = conditionals;
170110d63b7dSRichard Lowe 	}
170210d63b7dSRichard Lowe 
170310d63b7dSRichard Lowe 	target->conditional_cnt++;
170410d63b7dSRichard Lowe 	maybe_append_prop(name, macro_prop)->body.macro.is_conditional = true;
170510d63b7dSRichard Lowe 	/* Add the property for the target */
170610d63b7dSRichard Lowe 	conditional = append_prop(target, conditional_prop);
170710d63b7dSRichard Lowe 	conditional->body.conditional.target = orig_target;
170810d63b7dSRichard Lowe 	conditional->body.conditional.name = name;
170910d63b7dSRichard Lowe 	conditional->body.conditional.value = value;
171010d63b7dSRichard Lowe 	conditional->body.conditional.sequence = sequence++;
171110d63b7dSRichard Lowe 	conditional->body.conditional.append = append;
171210d63b7dSRichard Lowe 	if (trace_reader) {
171310d63b7dSRichard Lowe 		if (value == NULL) {
171410d63b7dSRichard Lowe 			(void) printf("%s := %s %c=\n",
171510d63b7dSRichard Lowe 				      target->string_mb,
171610d63b7dSRichard Lowe 				      name->string_mb,
171710d63b7dSRichard Lowe 				      append ?
171810d63b7dSRichard Lowe 				      (int) plus_char : (int) space_char);
171910d63b7dSRichard Lowe 		} else {
172010d63b7dSRichard Lowe 			(void) printf("%s := %s %c= %s\n",
172110d63b7dSRichard Lowe 				      target->string_mb,
172210d63b7dSRichard Lowe 				      name->string_mb,
172310d63b7dSRichard Lowe 				      append ?
172410d63b7dSRichard Lowe 				      (int) plus_char : (int) space_char,
172510d63b7dSRichard Lowe 				      value->string_mb);
172610d63b7dSRichard Lowe 		}
172710d63b7dSRichard Lowe 	}
172810d63b7dSRichard Lowe }
172910d63b7dSRichard Lowe 
173010d63b7dSRichard Lowe /*
173110d63b7dSRichard Lowe  *	enter_equal(name, value, append)
173210d63b7dSRichard Lowe  *
173310d63b7dSRichard Lowe  *	Enter "MACRO= value" constructs
173410d63b7dSRichard Lowe  *
173510d63b7dSRichard Lowe  *	Parameters:
173610d63b7dSRichard Lowe  *		name		The name of the macro
173710d63b7dSRichard Lowe  *		value		The value for the macro
173810d63b7dSRichard Lowe  *		append		Indicates if the assignment is appending or not
173910d63b7dSRichard Lowe  *
174010d63b7dSRichard Lowe  *	Global variables used:
174110d63b7dSRichard Lowe  *		trace_reader	Indicates that we should echo stuff we read
174210d63b7dSRichard Lowe  */
174310d63b7dSRichard Lowe void
enter_equal(Name name,Name value,Boolean append)1744*e7afc443SToomas Soome enter_equal(Name name, Name value, Boolean append)
174510d63b7dSRichard Lowe {
174610d63b7dSRichard Lowe 	wchar_t		*string;
174710d63b7dSRichard Lowe 	Name		temp;
174810d63b7dSRichard Lowe 
174910d63b7dSRichard Lowe 	if (name->colon) {
175010d63b7dSRichard Lowe 		sh_transform(&name, &value);
175110d63b7dSRichard Lowe 	}
175210d63b7dSRichard Lowe 	(void) SETVAR(name, value, append);
175310d63b7dSRichard Lowe 
175410d63b7dSRichard Lowe 	/* if we're setting FC, we want to set F77 to the same value. */
175510d63b7dSRichard Lowe 	Wstring nms(name);
175610d63b7dSRichard Lowe 	wchar_t * wcb = nms.get_string();
175710d63b7dSRichard Lowe 	string = wcb;
175810d63b7dSRichard Lowe 	if (string[0]=='F' &&
175910d63b7dSRichard Lowe 	    string[1]=='C' &&
176010d63b7dSRichard Lowe 	    string[2]=='\0') {
176110d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "F77");
176210d63b7dSRichard Lowe 		temp = GETNAME(wcs_buffer, FIND_LENGTH);
176310d63b7dSRichard Lowe 		(void) SETVAR(temp, value, append);
176410d63b7dSRichard Lowe /*
176510d63b7dSRichard Lowe 		fprintf(stderr, gettext("warning: FC is obsolete, use F77 instead\n"));
176610d63b7dSRichard Lowe  */
176710d63b7dSRichard Lowe 	}
176810d63b7dSRichard Lowe 
176910d63b7dSRichard Lowe 	if (trace_reader) {
177010d63b7dSRichard Lowe 		if (value == NULL) {
177110d63b7dSRichard Lowe 			(void) printf("%s %c=\n",
177210d63b7dSRichard Lowe 				      name->string_mb,
177310d63b7dSRichard Lowe 				      append ?
177410d63b7dSRichard Lowe 				      (int) plus_char : (int) space_char);
177510d63b7dSRichard Lowe 		} else {
177610d63b7dSRichard Lowe 			(void) printf("%s %c= %s\n",
177710d63b7dSRichard Lowe 				      name->string_mb,
177810d63b7dSRichard Lowe 				      append ?
177910d63b7dSRichard Lowe 				      (int) plus_char : (int) space_char,
178010d63b7dSRichard Lowe 				      value->string_mb);
178110d63b7dSRichard Lowe 		}
178210d63b7dSRichard Lowe 	}
178310d63b7dSRichard Lowe }
178410d63b7dSRichard Lowe 
178510d63b7dSRichard Lowe /*
178610d63b7dSRichard Lowe  *	sh_transform(name, value)
178710d63b7dSRichard Lowe  *
178810d63b7dSRichard Lowe  *	Parameters:
178910d63b7dSRichard Lowe  *		name	The name of the macro we might transform
179010d63b7dSRichard Lowe  *		value	The value to transform
179110d63b7dSRichard Lowe  *
179210d63b7dSRichard Lowe  */
179310d63b7dSRichard Lowe static void
sh_transform(Name * name,Name * value)179410d63b7dSRichard Lowe sh_transform(Name *name, Name *value)
179510d63b7dSRichard Lowe {
179610d63b7dSRichard Lowe 	/* Check if we need :sh transform */
179710d63b7dSRichard Lowe 	wchar_t		*colon;
179810d63b7dSRichard Lowe 	String_rec	command;
179910d63b7dSRichard Lowe 	String_rec	destination;
180010d63b7dSRichard Lowe 	wchar_t		buffer[1000];
180110d63b7dSRichard Lowe 	wchar_t		buffer1[1000];
180210d63b7dSRichard Lowe 
180310d63b7dSRichard Lowe 	static wchar_t	colon_sh[4];
180410d63b7dSRichard Lowe 	static wchar_t	colon_shell[7];
180510d63b7dSRichard Lowe 
180610d63b7dSRichard Lowe 	if (colon_sh[0] == (int) nul_char) {
180710d63b7dSRichard Lowe 		MBSTOWCS(colon_sh, ":sh");
180810d63b7dSRichard Lowe 		MBSTOWCS(colon_shell, ":shell");
180910d63b7dSRichard Lowe 	}
181010d63b7dSRichard Lowe 	Wstring nms((*name));
181110d63b7dSRichard Lowe 	wchar_t * wcb = nms.get_string();
181210d63b7dSRichard Lowe 
181310d63b7dSRichard Lowe 	colon = (wchar_t *) wcsrchr(wcb, (int) colon_char);
181410d63b7dSRichard Lowe 	if ((colon != NULL) && (IS_WEQUAL(colon, colon_sh) || IS_WEQUAL(colon, colon_shell))) {
181510d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(destination, buffer);
181610d63b7dSRichard Lowe 
181710d63b7dSRichard Lowe 		if(*value == NULL) {
181810d63b7dSRichard Lowe 			buffer[0] = 0;
181910d63b7dSRichard Lowe 		} else {
182010d63b7dSRichard Lowe 			Wstring wcb1((*value));
182110d63b7dSRichard Lowe 			if (IS_WEQUAL(colon, colon_shell)) {
182210d63b7dSRichard Lowe 				INIT_STRING_FROM_STACK(command, buffer1);
182310d63b7dSRichard Lowe 				expand_value(*value, &command, false);
182410d63b7dSRichard Lowe 			} else {
182510d63b7dSRichard Lowe 				command.text.p = wcb1.get_string() + (*value)->hash.length;
182610d63b7dSRichard Lowe 				command.text.end = command.text.p;
182710d63b7dSRichard Lowe 				command.buffer.start = wcb1.get_string();
182810d63b7dSRichard Lowe 				command.buffer.end = command.text.p;
182910d63b7dSRichard Lowe 			}
183010d63b7dSRichard Lowe 			sh_command2string(&command, &destination);
183110d63b7dSRichard Lowe 		}
183210d63b7dSRichard Lowe 
183310d63b7dSRichard Lowe 		(*value) = GETNAME(destination.buffer.start, FIND_LENGTH);
183410d63b7dSRichard Lowe 		*colon = (int) nul_char;
183510d63b7dSRichard Lowe 		(*name) = GETNAME(wcb, FIND_LENGTH);
183610d63b7dSRichard Lowe 		*colon = (int) colon_char;
183710d63b7dSRichard Lowe 	}
183810d63b7dSRichard Lowe }
183910d63b7dSRichard Lowe 
184010d63b7dSRichard Lowe /*
184110d63b7dSRichard Lowe  *	fatal_reader(format, args...)
184210d63b7dSRichard Lowe  *
184310d63b7dSRichard Lowe  *	Parameters:
184410d63b7dSRichard Lowe  *		format		printf style format string
184510d63b7dSRichard Lowe  *		args		arguments to match the format
184610d63b7dSRichard Lowe  *
184710d63b7dSRichard Lowe  *	Global variables used:
184810d63b7dSRichard Lowe  *		file_being_read	Name of the makefile being read
184910d63b7dSRichard Lowe  *		line_number	Line that is being read
185010d63b7dSRichard Lowe  *		report_pwd	Indicates whether current path should be shown
185110d63b7dSRichard Lowe  *		temp_file_name	When reading tempfile we report that name
185210d63b7dSRichard Lowe  */
185310d63b7dSRichard Lowe /*VARARGS*/
185410d63b7dSRichard Lowe void
fatal_reader(char * pattern,...)185510d63b7dSRichard Lowe fatal_reader(char * pattern, ...)
185610d63b7dSRichard Lowe {
185710d63b7dSRichard Lowe 	va_list args;
185810d63b7dSRichard Lowe 	char	message[1000];
185910d63b7dSRichard Lowe 
186010d63b7dSRichard Lowe 	va_start(args, pattern);
186110d63b7dSRichard Lowe 	if (file_being_read != NULL) {
186210d63b7dSRichard Lowe 		WCSTOMBS(mbs_buffer, file_being_read);
186310d63b7dSRichard Lowe 		if (line_number != 0) {
186410d63b7dSRichard Lowe 			(void) sprintf(message,
186510d63b7dSRichard Lowe 				       gettext("%s, line %d: %s"),
186610d63b7dSRichard Lowe 				       mbs_buffer,
186710d63b7dSRichard Lowe 				       line_number,
186810d63b7dSRichard Lowe 				       pattern);
186910d63b7dSRichard Lowe 		} else {
187010d63b7dSRichard Lowe 			(void) sprintf(message,
187110d63b7dSRichard Lowe 				       "%s: %s",
187210d63b7dSRichard Lowe 				       mbs_buffer,
187310d63b7dSRichard Lowe 				       pattern);
187410d63b7dSRichard Lowe 		}
187510d63b7dSRichard Lowe 		pattern = message;
187610d63b7dSRichard Lowe 	}
187710d63b7dSRichard Lowe 
187810d63b7dSRichard Lowe 	(void) fflush(stdout);
187910d63b7dSRichard Lowe 	(void) fprintf(stderr, gettext("%s: Fatal error in reader: "),
188010d63b7dSRichard Lowe 	    getprogname());
188110d63b7dSRichard Lowe 	(void) vfprintf(stderr, pattern, args);
188210d63b7dSRichard Lowe 	(void) fprintf(stderr, "\n");
188310d63b7dSRichard Lowe 	va_end(args);
188410d63b7dSRichard Lowe 
188510d63b7dSRichard Lowe 	if (temp_file_name != NULL) {
188610d63b7dSRichard Lowe 		(void) fprintf(stderr,
188710d63b7dSRichard Lowe 			       gettext("%s: Temp-file %s not removed\n"),
188810d63b7dSRichard Lowe 			       getprogname(),
188910d63b7dSRichard Lowe 			       temp_file_name->string_mb);
189010d63b7dSRichard Lowe 		temp_file_name = NULL;
189110d63b7dSRichard Lowe 	}
189210d63b7dSRichard Lowe 
189310d63b7dSRichard Lowe 	if (report_pwd) {
189410d63b7dSRichard Lowe 		(void) fprintf(stderr,
189510d63b7dSRichard Lowe 			       gettext("Current working directory %s\n"),
189610d63b7dSRichard Lowe 			       get_current_path());
189710d63b7dSRichard Lowe 	}
189810d63b7dSRichard Lowe 	(void) fflush(stderr);
189910d63b7dSRichard Lowe 	exit_status = 1;
190010d63b7dSRichard Lowe 	exit(1);
190110d63b7dSRichard Lowe }
190210d63b7dSRichard Lowe 
1903