xref: /titanic_50/usr/src/cmd/make/lib/mksh/macro.cc (revision 10d63b7db37a83b39c7f511cf9426c9d03ea0760)
1*10d63b7dSRichard Lowe /*
2*10d63b7dSRichard Lowe  * CDDL HEADER START
3*10d63b7dSRichard Lowe  *
4*10d63b7dSRichard Lowe  * The contents of this file are subject to the terms of the
5*10d63b7dSRichard Lowe  * Common Development and Distribution License (the "License").
6*10d63b7dSRichard Lowe  * You may not use this file except in compliance with the License.
7*10d63b7dSRichard Lowe  *
8*10d63b7dSRichard Lowe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10d63b7dSRichard Lowe  * or http://www.opensolaris.org/os/licensing.
10*10d63b7dSRichard Lowe  * See the License for the specific language governing permissions
11*10d63b7dSRichard Lowe  * and limitations under the License.
12*10d63b7dSRichard Lowe  *
13*10d63b7dSRichard Lowe  * When distributing Covered Code, include this CDDL HEADER in each
14*10d63b7dSRichard Lowe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10d63b7dSRichard Lowe  * If applicable, add the following below this CDDL HEADER, with the
16*10d63b7dSRichard Lowe  * fields enclosed by brackets "[]" replaced with your own identifying
17*10d63b7dSRichard Lowe  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10d63b7dSRichard Lowe  *
19*10d63b7dSRichard Lowe  * CDDL HEADER END
20*10d63b7dSRichard Lowe  */
21*10d63b7dSRichard Lowe /*
22*10d63b7dSRichard Lowe  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23*10d63b7dSRichard Lowe  * Use is subject to license terms.
24*10d63b7dSRichard Lowe  */
25*10d63b7dSRichard Lowe 
26*10d63b7dSRichard Lowe 
27*10d63b7dSRichard Lowe /*
28*10d63b7dSRichard Lowe  *	macro.cc
29*10d63b7dSRichard Lowe  *
30*10d63b7dSRichard Lowe  *	Handle expansion of make macros
31*10d63b7dSRichard Lowe  */
32*10d63b7dSRichard Lowe 
33*10d63b7dSRichard Lowe /*
34*10d63b7dSRichard Lowe  * Included files
35*10d63b7dSRichard Lowe  */
36*10d63b7dSRichard Lowe #include <mksh/dosys.h>		/* sh_command2string() */
37*10d63b7dSRichard Lowe #include <mksh/i18n.h>		/* get_char_semantics_value() */
38*10d63b7dSRichard Lowe #include <mksh/macro.h>
39*10d63b7dSRichard Lowe #include <mksh/misc.h>		/* retmem() */
40*10d63b7dSRichard Lowe #include <mksh/read.h>		/* get_next_block_fn() */
41*10d63b7dSRichard Lowe 
42*10d63b7dSRichard Lowe #include <libintl.h>
43*10d63b7dSRichard Lowe 
44*10d63b7dSRichard Lowe /*
45*10d63b7dSRichard Lowe  * File table of contents
46*10d63b7dSRichard Lowe  */
47*10d63b7dSRichard Lowe static void	add_macro_to_global_list(Name macro_to_add);
48*10d63b7dSRichard Lowe static void	expand_value_with_daemon(Name, register Property macro, register String destination, Boolean cmd);
49*10d63b7dSRichard Lowe 
50*10d63b7dSRichard Lowe static void	init_arch_macros(void);
51*10d63b7dSRichard Lowe static void	init_mach_macros(void);
52*10d63b7dSRichard Lowe static Boolean	init_arch_done = false;
53*10d63b7dSRichard Lowe static Boolean	init_mach_done = false;
54*10d63b7dSRichard Lowe 
55*10d63b7dSRichard Lowe 
56*10d63b7dSRichard Lowe long env_alloc_num = 0;
57*10d63b7dSRichard Lowe long env_alloc_bytes = 0;
58*10d63b7dSRichard Lowe 
59*10d63b7dSRichard Lowe /*
60*10d63b7dSRichard Lowe  *	getvar(name)
61*10d63b7dSRichard Lowe  *
62*10d63b7dSRichard Lowe  *	Return expanded value of macro.
63*10d63b7dSRichard Lowe  *
64*10d63b7dSRichard Lowe  *	Return value:
65*10d63b7dSRichard Lowe  *				The expanded value of the macro
66*10d63b7dSRichard Lowe  *
67*10d63b7dSRichard Lowe  *	Parameters:
68*10d63b7dSRichard Lowe  *		name		The name of the macro we want the value for
69*10d63b7dSRichard Lowe  *
70*10d63b7dSRichard Lowe  *	Global variables used:
71*10d63b7dSRichard Lowe  */
72*10d63b7dSRichard Lowe Name
getvar(register Name name)73*10d63b7dSRichard Lowe getvar(register Name name)
74*10d63b7dSRichard Lowe {
75*10d63b7dSRichard Lowe 	String_rec		destination;
76*10d63b7dSRichard Lowe 	wchar_t			buffer[STRING_BUFFER_LENGTH];
77*10d63b7dSRichard Lowe 	register Name		result;
78*10d63b7dSRichard Lowe 
79*10d63b7dSRichard Lowe 	if ((name == host_arch) || (name == target_arch)) {
80*10d63b7dSRichard Lowe 		if (!init_arch_done) {
81*10d63b7dSRichard Lowe 			init_arch_done = true;
82*10d63b7dSRichard Lowe 			init_arch_macros();
83*10d63b7dSRichard Lowe 		}
84*10d63b7dSRichard Lowe 	}
85*10d63b7dSRichard Lowe 	if ((name == host_mach) || (name == target_mach)) {
86*10d63b7dSRichard Lowe 		if (!init_mach_done) {
87*10d63b7dSRichard Lowe 			init_mach_done = true;
88*10d63b7dSRichard Lowe 			init_mach_macros();
89*10d63b7dSRichard Lowe 		}
90*10d63b7dSRichard Lowe 	}
91*10d63b7dSRichard Lowe 
92*10d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(destination, buffer);
93*10d63b7dSRichard Lowe 	expand_value(maybe_append_prop(name, macro_prop)->body.macro.value,
94*10d63b7dSRichard Lowe 		     &destination,
95*10d63b7dSRichard Lowe 		     false);
96*10d63b7dSRichard Lowe 	result = GETNAME(destination.buffer.start, FIND_LENGTH);
97*10d63b7dSRichard Lowe 	if (destination.free_after_use) {
98*10d63b7dSRichard Lowe 		retmem(destination.buffer.start);
99*10d63b7dSRichard Lowe 	}
100*10d63b7dSRichard Lowe 	return result;
101*10d63b7dSRichard Lowe }
102*10d63b7dSRichard Lowe 
103*10d63b7dSRichard Lowe /*
104*10d63b7dSRichard Lowe  *	expand_value(value, destination, cmd)
105*10d63b7dSRichard Lowe  *
106*10d63b7dSRichard Lowe  *	Recursively expands all macros in the string value.
107*10d63b7dSRichard Lowe  *	destination is where the expanded value should be appended.
108*10d63b7dSRichard Lowe  *
109*10d63b7dSRichard Lowe  *	Parameters:
110*10d63b7dSRichard Lowe  *		value		The value we are expanding
111*10d63b7dSRichard Lowe  *		destination	Where to deposit the expansion
112*10d63b7dSRichard Lowe  *		cmd		If we are evaluating a command line we
113*10d63b7dSRichard Lowe  *				turn \ quoting off
114*10d63b7dSRichard Lowe  *
115*10d63b7dSRichard Lowe  *	Global variables used:
116*10d63b7dSRichard Lowe  */
117*10d63b7dSRichard Lowe void
expand_value(Name value,register String destination,Boolean cmd)118*10d63b7dSRichard Lowe expand_value(Name value, register String destination, Boolean cmd)
119*10d63b7dSRichard Lowe {
120*10d63b7dSRichard Lowe 	Source_rec		sourceb;
121*10d63b7dSRichard Lowe 	register Source		source = &sourceb;
122*10d63b7dSRichard Lowe 	register wchar_t	*source_p = NULL;
123*10d63b7dSRichard Lowe 	register wchar_t	*source_end = NULL;
124*10d63b7dSRichard Lowe 	wchar_t			*block_start = NULL;
125*10d63b7dSRichard Lowe 	int			quote_seen = 0;
126*10d63b7dSRichard Lowe 
127*10d63b7dSRichard Lowe 	if (value == NULL) {
128*10d63b7dSRichard Lowe 		/*
129*10d63b7dSRichard Lowe 		 * Make sure to get a string allocated even if it
130*10d63b7dSRichard Lowe 		 * will be empty.
131*10d63b7dSRichard Lowe 		 */
132*10d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "");
133*10d63b7dSRichard Lowe 		append_string(wcs_buffer, destination, FIND_LENGTH);
134*10d63b7dSRichard Lowe 		destination->text.end = destination->text.p;
135*10d63b7dSRichard Lowe 		return;
136*10d63b7dSRichard Lowe 	}
137*10d63b7dSRichard Lowe 	if (!value->dollar) {
138*10d63b7dSRichard Lowe 		/*
139*10d63b7dSRichard Lowe 		 * If the value we are expanding does not contain
140*10d63b7dSRichard Lowe 		 * any $, we don't have to parse it.
141*10d63b7dSRichard Lowe 		 */
142*10d63b7dSRichard Lowe 		APPEND_NAME(value,
143*10d63b7dSRichard Lowe 			destination,
144*10d63b7dSRichard Lowe 			(int) value->hash.length
145*10d63b7dSRichard Lowe 		);
146*10d63b7dSRichard Lowe 		destination->text.end = destination->text.p;
147*10d63b7dSRichard Lowe 		return;
148*10d63b7dSRichard Lowe 	}
149*10d63b7dSRichard Lowe 
150*10d63b7dSRichard Lowe 	if (value->being_expanded) {
151*10d63b7dSRichard Lowe 		fatal_reader_mksh(gettext("Loop detected when expanding macro value `%s'"),
152*10d63b7dSRichard Lowe 			     value->string_mb);
153*10d63b7dSRichard Lowe 	}
154*10d63b7dSRichard Lowe 	value->being_expanded = true;
155*10d63b7dSRichard Lowe 	/* Setup the structure we read from */
156*10d63b7dSRichard Lowe 	Wstring vals(value);
157*10d63b7dSRichard Lowe 	sourceb.string.text.p = sourceb.string.buffer.start = wcsdup(vals.get_string());
158*10d63b7dSRichard Lowe 	sourceb.string.free_after_use = true;
159*10d63b7dSRichard Lowe 	sourceb.string.text.end =
160*10d63b7dSRichard Lowe 	  sourceb.string.buffer.end =
161*10d63b7dSRichard Lowe 	    sourceb.string.text.p + value->hash.length;
162*10d63b7dSRichard Lowe 	sourceb.previous = NULL;
163*10d63b7dSRichard Lowe 	sourceb.fd = -1;
164*10d63b7dSRichard Lowe 	sourceb.inp_buf =
165*10d63b7dSRichard Lowe 	  sourceb.inp_buf_ptr =
166*10d63b7dSRichard Lowe 	    sourceb.inp_buf_end = NULL;
167*10d63b7dSRichard Lowe 	sourceb.error_converting = false;
168*10d63b7dSRichard Lowe 	/* Lift some pointers from the struct to local register variables */
169*10d63b7dSRichard Lowe 	CACHE_SOURCE(0);
170*10d63b7dSRichard Lowe /* We parse the string in segments */
171*10d63b7dSRichard Lowe /* We read chars until we find a $, then we append what we have read so far */
172*10d63b7dSRichard Lowe /* (since last $ processing) to the destination. When we find a $ we call */
173*10d63b7dSRichard Lowe /* expand_macro() and let it expand that particular $ reference into dest */
174*10d63b7dSRichard Lowe 	block_start = source_p;
175*10d63b7dSRichard Lowe 	quote_seen = 0;
176*10d63b7dSRichard Lowe 	for (; 1; source_p++) {
177*10d63b7dSRichard Lowe 		switch (GET_CHAR()) {
178*10d63b7dSRichard Lowe 		case backslash_char:
179*10d63b7dSRichard Lowe 			/* Quote $ in macro value */
180*10d63b7dSRichard Lowe 			if (!cmd) {
181*10d63b7dSRichard Lowe 				quote_seen = ~quote_seen;
182*10d63b7dSRichard Lowe 			}
183*10d63b7dSRichard Lowe 			continue;
184*10d63b7dSRichard Lowe 		case dollar_char:
185*10d63b7dSRichard Lowe 			/* Save the plain string we found since */
186*10d63b7dSRichard Lowe 			/* start of string or previous $ */
187*10d63b7dSRichard Lowe 			if (quote_seen) {
188*10d63b7dSRichard Lowe 				append_string(block_start,
189*10d63b7dSRichard Lowe 					      destination,
190*10d63b7dSRichard Lowe 					      source_p - block_start - 1);
191*10d63b7dSRichard Lowe 				block_start = source_p;
192*10d63b7dSRichard Lowe 				break;
193*10d63b7dSRichard Lowe 			}
194*10d63b7dSRichard Lowe 			append_string(block_start,
195*10d63b7dSRichard Lowe 				      destination,
196*10d63b7dSRichard Lowe 				      source_p - block_start);
197*10d63b7dSRichard Lowe 			source->string.text.p = ++source_p;
198*10d63b7dSRichard Lowe 			UNCACHE_SOURCE();
199*10d63b7dSRichard Lowe 			/* Go expand the macro reference */
200*10d63b7dSRichard Lowe 			expand_macro(source, destination, sourceb.string.buffer.start, cmd);
201*10d63b7dSRichard Lowe 			CACHE_SOURCE(1);
202*10d63b7dSRichard Lowe 			block_start = source_p + 1;
203*10d63b7dSRichard Lowe 			break;
204*10d63b7dSRichard Lowe 		case nul_char:
205*10d63b7dSRichard Lowe 			/* The string ran out. Get some more */
206*10d63b7dSRichard Lowe 			append_string(block_start,
207*10d63b7dSRichard Lowe 				      destination,
208*10d63b7dSRichard Lowe 				      source_p - block_start);
209*10d63b7dSRichard Lowe 			GET_NEXT_BLOCK_NOCHK(source);
210*10d63b7dSRichard Lowe 			if (source == NULL) {
211*10d63b7dSRichard Lowe 				destination->text.end = destination->text.p;
212*10d63b7dSRichard Lowe 				value->being_expanded = false;
213*10d63b7dSRichard Lowe 				return;
214*10d63b7dSRichard Lowe 			}
215*10d63b7dSRichard Lowe 			if (source->error_converting) {
216*10d63b7dSRichard Lowe 				fatal_reader_mksh("Internal error: Invalid byte sequence in expand_value()");
217*10d63b7dSRichard Lowe 			}
218*10d63b7dSRichard Lowe 			block_start = source_p;
219*10d63b7dSRichard Lowe 			source_p--;
220*10d63b7dSRichard Lowe 			continue;
221*10d63b7dSRichard Lowe 		}
222*10d63b7dSRichard Lowe 		quote_seen = 0;
223*10d63b7dSRichard Lowe 	}
224*10d63b7dSRichard Lowe 	retmem(sourceb.string.buffer.start);
225*10d63b7dSRichard Lowe }
226*10d63b7dSRichard Lowe 
227*10d63b7dSRichard Lowe /*
228*10d63b7dSRichard Lowe  *	expand_macro(source, destination, current_string, cmd)
229*10d63b7dSRichard Lowe  *
230*10d63b7dSRichard Lowe  *	Should be called with source->string.text.p pointing to
231*10d63b7dSRichard Lowe  *	the first char after the $ that starts a macro reference.
232*10d63b7dSRichard Lowe  *	source->string.text.p is returned pointing to the first char after
233*10d63b7dSRichard Lowe  *	the macro name.
234*10d63b7dSRichard Lowe  *	It will read the macro name, expanding any macros in it,
235*10d63b7dSRichard Lowe  *	and get the value. The value is then expanded.
236*10d63b7dSRichard Lowe  *	destination is a String that is filled in with the expanded macro.
237*10d63b7dSRichard Lowe  *	It may be passed in referencing a buffer to expand the macro into.
238*10d63b7dSRichard Lowe  * 	Note that most expansions are done on demand, e.g. right
239*10d63b7dSRichard Lowe  *	before the command is executed and not while the file is
240*10d63b7dSRichard Lowe  * 	being parsed.
241*10d63b7dSRichard Lowe  *
242*10d63b7dSRichard Lowe  *	Parameters:
243*10d63b7dSRichard Lowe  *		source		The source block that references the string
244*10d63b7dSRichard Lowe  *				to expand
245*10d63b7dSRichard Lowe  *		destination	Where to put the result
246*10d63b7dSRichard Lowe  *		current_string	The string we are expanding, for error msg
247*10d63b7dSRichard Lowe  *		cmd		If we are evaluating a command line we
248*10d63b7dSRichard Lowe  *				turn \ quoting off
249*10d63b7dSRichard Lowe  *
250*10d63b7dSRichard Lowe  *	Global variables used:
251*10d63b7dSRichard Lowe  *		funny		Vector of semantic tags for characters
252*10d63b7dSRichard Lowe  *		is_conditional	Set if a conditional macro is refd
253*10d63b7dSRichard Lowe  *		make_word_mentioned Set if the word "MAKE" is mentioned
254*10d63b7dSRichard Lowe  *		makefile_type	We deliver extra msg when reading makefiles
255*10d63b7dSRichard Lowe  *		query		The Name "?", compared against
256*10d63b7dSRichard Lowe  *		query_mentioned	Set if the word "?" is mentioned
257*10d63b7dSRichard Lowe  */
258*10d63b7dSRichard Lowe void
expand_macro(register Source source,register String destination,wchar_t * current_string,Boolean cmd)259*10d63b7dSRichard Lowe expand_macro(register Source source, register String destination, wchar_t *current_string, Boolean cmd)
260*10d63b7dSRichard Lowe {
261*10d63b7dSRichard Lowe 	static Name		make = (Name)NULL;
262*10d63b7dSRichard Lowe 	static wchar_t		colon_sh[4];
263*10d63b7dSRichard Lowe 	static wchar_t		colon_shell[7];
264*10d63b7dSRichard Lowe 	String_rec		string;
265*10d63b7dSRichard Lowe 	wchar_t			buffer[STRING_BUFFER_LENGTH];
266*10d63b7dSRichard Lowe 	register wchar_t	*source_p = source->string.text.p;
267*10d63b7dSRichard Lowe 	register wchar_t	*source_end = source->string.text.end;
268*10d63b7dSRichard Lowe 	register int		closer = 0;
269*10d63b7dSRichard Lowe 	wchar_t			*block_start = (wchar_t *)NULL;
270*10d63b7dSRichard Lowe 	int			quote_seen = 0;
271*10d63b7dSRichard Lowe 	register int		closer_level = 1;
272*10d63b7dSRichard Lowe 	Name			name = (Name)NULL;
273*10d63b7dSRichard Lowe 	wchar_t			*colon = (wchar_t *)NULL;
274*10d63b7dSRichard Lowe 	wchar_t			*percent = (wchar_t *)NULL;
275*10d63b7dSRichard Lowe 	wchar_t			*eq = (wchar_t *) NULL;
276*10d63b7dSRichard Lowe 	Property		macro = NULL;
277*10d63b7dSRichard Lowe 	wchar_t			*p = (wchar_t*)NULL;
278*10d63b7dSRichard Lowe 	String_rec		extracted;
279*10d63b7dSRichard Lowe 	wchar_t			extracted_string[MAXPATHLEN];
280*10d63b7dSRichard Lowe 	wchar_t			*left_head = NULL;
281*10d63b7dSRichard Lowe 	wchar_t			*left_tail = NULL;
282*10d63b7dSRichard Lowe 	wchar_t			*right_tail = NULL;
283*10d63b7dSRichard Lowe 	int			left_head_len = 0;
284*10d63b7dSRichard Lowe 	int			left_tail_len = 0;
285*10d63b7dSRichard Lowe 	int			tmp_len = 0;
286*10d63b7dSRichard Lowe 	wchar_t			*right_hand[128];
287*10d63b7dSRichard Lowe 	int			i = 0;
288*10d63b7dSRichard Lowe 	enum {
289*10d63b7dSRichard Lowe 		no_extract,
290*10d63b7dSRichard Lowe 		dir_extract,
291*10d63b7dSRichard Lowe 		file_extract
292*10d63b7dSRichard Lowe 	}                       extraction = no_extract;
293*10d63b7dSRichard Lowe 	enum {
294*10d63b7dSRichard Lowe 		no_replace,
295*10d63b7dSRichard Lowe 		suffix_replace,
296*10d63b7dSRichard Lowe 		pattern_replace,
297*10d63b7dSRichard Lowe 		sh_replace
298*10d63b7dSRichard Lowe 	}			replacement = no_replace;
299*10d63b7dSRichard Lowe 
300*10d63b7dSRichard Lowe 	if (make == NULL) {
301*10d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "MAKE");
302*10d63b7dSRichard Lowe 		make = GETNAME(wcs_buffer, FIND_LENGTH);
303*10d63b7dSRichard Lowe 
304*10d63b7dSRichard Lowe 		MBSTOWCS(colon_sh, ":sh");
305*10d63b7dSRichard Lowe 		MBSTOWCS(colon_shell, ":shell");
306*10d63b7dSRichard Lowe 	}
307*10d63b7dSRichard Lowe 
308*10d63b7dSRichard Lowe 	right_hand[0] = NULL;
309*10d63b7dSRichard Lowe 
310*10d63b7dSRichard Lowe 	/* First copy the (macro-expanded) macro name into string. */
311*10d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(string, buffer);
312*10d63b7dSRichard Lowe recheck_first_char:
313*10d63b7dSRichard Lowe 	/* Check the first char of the macro name to figure out what to do. */
314*10d63b7dSRichard Lowe 	switch (GET_CHAR()) {
315*10d63b7dSRichard Lowe 	case nul_char:
316*10d63b7dSRichard Lowe 		GET_NEXT_BLOCK_NOCHK(source);
317*10d63b7dSRichard Lowe 		if (source == NULL) {
318*10d63b7dSRichard Lowe 			WCSTOMBS(mbs_buffer, current_string);
319*10d63b7dSRichard Lowe 			fatal_reader_mksh(gettext("'$' at end of string `%s'"),
320*10d63b7dSRichard Lowe 				     mbs_buffer);
321*10d63b7dSRichard Lowe 		}
322*10d63b7dSRichard Lowe 		if (source->error_converting) {
323*10d63b7dSRichard Lowe 			fatal_reader_mksh("Internal error: Invalid byte sequence in expand_macro()");
324*10d63b7dSRichard Lowe 		}
325*10d63b7dSRichard Lowe 		goto recheck_first_char;
326*10d63b7dSRichard Lowe 	case parenleft_char:
327*10d63b7dSRichard Lowe 		/* Multi char name. */
328*10d63b7dSRichard Lowe 		closer = (int) parenright_char;
329*10d63b7dSRichard Lowe 		break;
330*10d63b7dSRichard Lowe 	case braceleft_char:
331*10d63b7dSRichard Lowe 		/* Multi char name. */
332*10d63b7dSRichard Lowe 		closer = (int) braceright_char;
333*10d63b7dSRichard Lowe 		break;
334*10d63b7dSRichard Lowe 	case newline_char:
335*10d63b7dSRichard Lowe 		fatal_reader_mksh(gettext("'$' at end of line"));
336*10d63b7dSRichard Lowe 	default:
337*10d63b7dSRichard Lowe 		/* Single char macro name. Just suck it up */
338*10d63b7dSRichard Lowe 		append_char(*source_p, &string);
339*10d63b7dSRichard Lowe 		source->string.text.p = source_p + 1;
340*10d63b7dSRichard Lowe 		goto get_macro_value;
341*10d63b7dSRichard Lowe 	}
342*10d63b7dSRichard Lowe 
343*10d63b7dSRichard Lowe 	/* Handle multi-char macro names */
344*10d63b7dSRichard Lowe 	block_start = ++source_p;
345*10d63b7dSRichard Lowe 	quote_seen = 0;
346*10d63b7dSRichard Lowe 	for (; 1; source_p++) {
347*10d63b7dSRichard Lowe 		switch (GET_CHAR()) {
348*10d63b7dSRichard Lowe 		case nul_char:
349*10d63b7dSRichard Lowe 			append_string(block_start,
350*10d63b7dSRichard Lowe 				      &string,
351*10d63b7dSRichard Lowe 				      source_p - block_start);
352*10d63b7dSRichard Lowe 			GET_NEXT_BLOCK_NOCHK(source);
353*10d63b7dSRichard Lowe 			if (source == NULL) {
354*10d63b7dSRichard Lowe 				if (current_string != NULL) {
355*10d63b7dSRichard Lowe 					WCSTOMBS(mbs_buffer, current_string);
356*10d63b7dSRichard Lowe 					fatal_reader_mksh(gettext("Unmatched `%c' in string `%s'"),
357*10d63b7dSRichard Lowe 						     closer ==
358*10d63b7dSRichard Lowe 						     (int) braceright_char ?
359*10d63b7dSRichard Lowe 						     (int) braceleft_char :
360*10d63b7dSRichard Lowe 						     (int) parenleft_char,
361*10d63b7dSRichard Lowe 						     mbs_buffer);
362*10d63b7dSRichard Lowe 				} else {
363*10d63b7dSRichard Lowe 					fatal_reader_mksh(gettext("Premature EOF"));
364*10d63b7dSRichard Lowe 				}
365*10d63b7dSRichard Lowe 			}
366*10d63b7dSRichard Lowe 			if (source->error_converting) {
367*10d63b7dSRichard Lowe 				fatal_reader_mksh("Internal error: Invalid byte sequence in expand_macro()");
368*10d63b7dSRichard Lowe 			}
369*10d63b7dSRichard Lowe 			block_start = source_p;
370*10d63b7dSRichard Lowe 			source_p--;
371*10d63b7dSRichard Lowe 			continue;
372*10d63b7dSRichard Lowe 		case newline_char:
373*10d63b7dSRichard Lowe 			fatal_reader_mksh(gettext("Unmatched `%c' on line"),
374*10d63b7dSRichard Lowe 				     closer == (int) braceright_char ?
375*10d63b7dSRichard Lowe 				     (int) braceleft_char :
376*10d63b7dSRichard Lowe 				     (int) parenleft_char);
377*10d63b7dSRichard Lowe 		case backslash_char:
378*10d63b7dSRichard Lowe 			/* Quote dollar in macro value. */
379*10d63b7dSRichard Lowe 			if (!cmd) {
380*10d63b7dSRichard Lowe 				quote_seen = ~quote_seen;
381*10d63b7dSRichard Lowe 			}
382*10d63b7dSRichard Lowe 			continue;
383*10d63b7dSRichard Lowe 		case dollar_char:
384*10d63b7dSRichard Lowe 			/*
385*10d63b7dSRichard Lowe 			 * Macro names may reference macros.
386*10d63b7dSRichard Lowe 			 * This expands the value of such macros into the
387*10d63b7dSRichard Lowe 			 * macro name string.
388*10d63b7dSRichard Lowe 			 */
389*10d63b7dSRichard Lowe 			if (quote_seen) {
390*10d63b7dSRichard Lowe 				append_string(block_start,
391*10d63b7dSRichard Lowe 					      &string,
392*10d63b7dSRichard Lowe 					      source_p - block_start - 1);
393*10d63b7dSRichard Lowe 				block_start = source_p;
394*10d63b7dSRichard Lowe 				break;
395*10d63b7dSRichard Lowe 			}
396*10d63b7dSRichard Lowe 			append_string(block_start,
397*10d63b7dSRichard Lowe 				      &string,
398*10d63b7dSRichard Lowe 				      source_p - block_start);
399*10d63b7dSRichard Lowe 			source->string.text.p = ++source_p;
400*10d63b7dSRichard Lowe 			UNCACHE_SOURCE();
401*10d63b7dSRichard Lowe 			expand_macro(source, &string, current_string, cmd);
402*10d63b7dSRichard Lowe 			CACHE_SOURCE(0);
403*10d63b7dSRichard Lowe 			block_start = source_p;
404*10d63b7dSRichard Lowe 			source_p--;
405*10d63b7dSRichard Lowe 			break;
406*10d63b7dSRichard Lowe 		case parenleft_char:
407*10d63b7dSRichard Lowe 			/* Allow nested pairs of () in the macro name. */
408*10d63b7dSRichard Lowe 			if (closer == (int) parenright_char) {
409*10d63b7dSRichard Lowe 				closer_level++;
410*10d63b7dSRichard Lowe 			}
411*10d63b7dSRichard Lowe 			break;
412*10d63b7dSRichard Lowe 		case braceleft_char:
413*10d63b7dSRichard Lowe 			/* Allow nested pairs of {} in the macro name. */
414*10d63b7dSRichard Lowe 			if (closer == (int) braceright_char) {
415*10d63b7dSRichard Lowe 				closer_level++;
416*10d63b7dSRichard Lowe 			}
417*10d63b7dSRichard Lowe 			break;
418*10d63b7dSRichard Lowe 		case parenright_char:
419*10d63b7dSRichard Lowe 		case braceright_char:
420*10d63b7dSRichard Lowe 			/*
421*10d63b7dSRichard Lowe 			 * End of the name. Save the string in the macro
422*10d63b7dSRichard Lowe 			 * name string.
423*10d63b7dSRichard Lowe 			 */
424*10d63b7dSRichard Lowe 			if ((*source_p == closer) && (--closer_level <= 0)) {
425*10d63b7dSRichard Lowe 				source->string.text.p = source_p + 1;
426*10d63b7dSRichard Lowe 				append_string(block_start,
427*10d63b7dSRichard Lowe 					      &string,
428*10d63b7dSRichard Lowe 					      source_p - block_start);
429*10d63b7dSRichard Lowe 				goto get_macro_value;
430*10d63b7dSRichard Lowe 			}
431*10d63b7dSRichard Lowe 			break;
432*10d63b7dSRichard Lowe 		}
433*10d63b7dSRichard Lowe 		quote_seen = 0;
434*10d63b7dSRichard Lowe 	}
435*10d63b7dSRichard Lowe 	/*
436*10d63b7dSRichard Lowe 	 * We got the macro name. We now inspect it to see if it
437*10d63b7dSRichard Lowe 	 * specifies any translations of the value.
438*10d63b7dSRichard Lowe 	 */
439*10d63b7dSRichard Lowe get_macro_value:
440*10d63b7dSRichard Lowe 	name = NULL;
441*10d63b7dSRichard Lowe 	/* First check if we have a $(@D) type translation. */
442*10d63b7dSRichard Lowe 	if ((get_char_semantics_value(string.buffer.start[0]) &
443*10d63b7dSRichard Lowe 	     (int) special_macro_sem) &&
444*10d63b7dSRichard Lowe 	    (string.text.p - string.buffer.start >= 2) &&
445*10d63b7dSRichard Lowe 	    ((string.buffer.start[1] == 'D') ||
446*10d63b7dSRichard Lowe 	     (string.buffer.start[1] == 'F'))) {
447*10d63b7dSRichard Lowe 		switch (string.buffer.start[1]) {
448*10d63b7dSRichard Lowe 		case 'D':
449*10d63b7dSRichard Lowe 			extraction = dir_extract;
450*10d63b7dSRichard Lowe 			break;
451*10d63b7dSRichard Lowe 		case 'F':
452*10d63b7dSRichard Lowe 			extraction = file_extract;
453*10d63b7dSRichard Lowe 			break;
454*10d63b7dSRichard Lowe 		default:
455*10d63b7dSRichard Lowe 			WCSTOMBS(mbs_buffer, string.buffer.start);
456*10d63b7dSRichard Lowe 			fatal_reader_mksh(gettext("Illegal macro reference `%s'"),
457*10d63b7dSRichard Lowe 				     mbs_buffer);
458*10d63b7dSRichard Lowe 		}
459*10d63b7dSRichard Lowe 		/* Internalize the macro name using the first char only. */
460*10d63b7dSRichard Lowe 		name = GETNAME(string.buffer.start, 1);
461*10d63b7dSRichard Lowe 		(void) wcscpy(string.buffer.start, string.buffer.start + 2);
462*10d63b7dSRichard Lowe 	}
463*10d63b7dSRichard Lowe 	/* Check for other kinds of translations. */
464*10d63b7dSRichard Lowe 	if ((colon = (wchar_t *) wcschr(string.buffer.start,
465*10d63b7dSRichard Lowe 				       (int) colon_char)) != NULL) {
466*10d63b7dSRichard Lowe 		/*
467*10d63b7dSRichard Lowe 		 * We have a $(FOO:.c=.o) type translation.
468*10d63b7dSRichard Lowe 		 * Get the name of the macro proper.
469*10d63b7dSRichard Lowe 		 */
470*10d63b7dSRichard Lowe 		if (name == NULL) {
471*10d63b7dSRichard Lowe 			name = GETNAME(string.buffer.start,
472*10d63b7dSRichard Lowe 				       colon - string.buffer.start);
473*10d63b7dSRichard Lowe 		}
474*10d63b7dSRichard Lowe 		/* Pickup all the translations. */
475*10d63b7dSRichard Lowe 		if (IS_WEQUAL(colon, colon_sh) || IS_WEQUAL(colon, colon_shell)) {
476*10d63b7dSRichard Lowe 			replacement = sh_replace;
477*10d63b7dSRichard Lowe 		} else if ((svr4) ||
478*10d63b7dSRichard Lowe 		           ((percent = (wchar_t *) wcschr(colon + 1,
479*10d63b7dSRichard Lowe 							 (int) percent_char)) == NULL)) {
480*10d63b7dSRichard Lowe 			while (colon != NULL) {
481*10d63b7dSRichard Lowe 				if ((eq = (wchar_t *) wcschr(colon + 1,
482*10d63b7dSRichard Lowe 							    (int) equal_char)) == NULL) {
483*10d63b7dSRichard Lowe 					fatal_reader_mksh(gettext("= missing from replacement macro reference"));
484*10d63b7dSRichard Lowe 				}
485*10d63b7dSRichard Lowe 				left_tail_len = eq - colon - 1;
486*10d63b7dSRichard Lowe 				if(left_tail) {
487*10d63b7dSRichard Lowe 					retmem(left_tail);
488*10d63b7dSRichard Lowe 				}
489*10d63b7dSRichard Lowe 				left_tail = ALLOC_WC(left_tail_len + 1);
490*10d63b7dSRichard Lowe 				(void) wcsncpy(left_tail,
491*10d63b7dSRichard Lowe 					      colon + 1,
492*10d63b7dSRichard Lowe 					      eq - colon - 1);
493*10d63b7dSRichard Lowe 				left_tail[eq - colon - 1] = (int) nul_char;
494*10d63b7dSRichard Lowe 				replacement = suffix_replace;
495*10d63b7dSRichard Lowe 				if ((colon = (wchar_t *) wcschr(eq + 1,
496*10d63b7dSRichard Lowe 							       (int) colon_char)) != NULL) {
497*10d63b7dSRichard Lowe 					tmp_len = colon - eq;
498*10d63b7dSRichard Lowe 					if(right_tail) {
499*10d63b7dSRichard Lowe 						retmem(right_tail);
500*10d63b7dSRichard Lowe 					}
501*10d63b7dSRichard Lowe 					right_tail = ALLOC_WC(tmp_len);
502*10d63b7dSRichard Lowe 					(void) wcsncpy(right_tail,
503*10d63b7dSRichard Lowe 						      eq + 1,
504*10d63b7dSRichard Lowe 						      colon - eq - 1);
505*10d63b7dSRichard Lowe 					right_tail[colon - eq - 1] =
506*10d63b7dSRichard Lowe 					  (int) nul_char;
507*10d63b7dSRichard Lowe 				} else {
508*10d63b7dSRichard Lowe 					if(right_tail) {
509*10d63b7dSRichard Lowe 						retmem(right_tail);
510*10d63b7dSRichard Lowe 					}
511*10d63b7dSRichard Lowe 					right_tail = ALLOC_WC(wcslen(eq) + 1);
512*10d63b7dSRichard Lowe 					(void) wcscpy(right_tail, eq + 1);
513*10d63b7dSRichard Lowe 				}
514*10d63b7dSRichard Lowe 			}
515*10d63b7dSRichard Lowe 		} else {
516*10d63b7dSRichard Lowe 			if ((eq = (wchar_t *) wcschr(colon + 1,
517*10d63b7dSRichard Lowe 						    (int) equal_char)) == NULL) {
518*10d63b7dSRichard Lowe 				fatal_reader_mksh(gettext("= missing from replacement macro reference"));
519*10d63b7dSRichard Lowe 			}
520*10d63b7dSRichard Lowe 			if ((percent = (wchar_t *) wcschr(colon + 1,
521*10d63b7dSRichard Lowe 							 (int) percent_char)) == NULL) {
522*10d63b7dSRichard Lowe 				fatal_reader_mksh(gettext("%% missing from replacement macro reference"));
523*10d63b7dSRichard Lowe 			}
524*10d63b7dSRichard Lowe 			if (eq < percent) {
525*10d63b7dSRichard Lowe 				fatal_reader_mksh(gettext("%% missing from replacement macro reference"));
526*10d63b7dSRichard Lowe 			}
527*10d63b7dSRichard Lowe 
528*10d63b7dSRichard Lowe 			if (percent > (colon + 1)) {
529*10d63b7dSRichard Lowe 				tmp_len = percent - colon;
530*10d63b7dSRichard Lowe 				if(left_head) {
531*10d63b7dSRichard Lowe 					retmem(left_head);
532*10d63b7dSRichard Lowe 				}
533*10d63b7dSRichard Lowe 				left_head = ALLOC_WC(tmp_len);
534*10d63b7dSRichard Lowe 				(void) wcsncpy(left_head,
535*10d63b7dSRichard Lowe 					      colon + 1,
536*10d63b7dSRichard Lowe 					      percent - colon - 1);
537*10d63b7dSRichard Lowe 				left_head[percent-colon-1] = (int) nul_char;
538*10d63b7dSRichard Lowe 				left_head_len = percent-colon-1;
539*10d63b7dSRichard Lowe 			} else {
540*10d63b7dSRichard Lowe 				left_head = NULL;
541*10d63b7dSRichard Lowe 				left_head_len = 0;
542*10d63b7dSRichard Lowe 			}
543*10d63b7dSRichard Lowe 
544*10d63b7dSRichard Lowe 			if (eq > percent+1) {
545*10d63b7dSRichard Lowe 				tmp_len = eq - percent;
546*10d63b7dSRichard Lowe 				if(left_tail) {
547*10d63b7dSRichard Lowe 					retmem(left_tail);
548*10d63b7dSRichard Lowe 				}
549*10d63b7dSRichard Lowe 				left_tail = ALLOC_WC(tmp_len);
550*10d63b7dSRichard Lowe 				(void) wcsncpy(left_tail,
551*10d63b7dSRichard Lowe 					      percent + 1,
552*10d63b7dSRichard Lowe 					      eq - percent - 1);
553*10d63b7dSRichard Lowe 				left_tail[eq-percent-1] = (int) nul_char;
554*10d63b7dSRichard Lowe 				left_tail_len = eq-percent-1;
555*10d63b7dSRichard Lowe 			} else {
556*10d63b7dSRichard Lowe 				left_tail = NULL;
557*10d63b7dSRichard Lowe 				left_tail_len = 0;
558*10d63b7dSRichard Lowe 			}
559*10d63b7dSRichard Lowe 
560*10d63b7dSRichard Lowe 			if ((percent = (wchar_t *) wcschr(++eq,
561*10d63b7dSRichard Lowe 							 (int) percent_char)) == NULL) {
562*10d63b7dSRichard Lowe 
563*10d63b7dSRichard Lowe 				right_hand[0] = ALLOC_WC(wcslen(eq) + 1);
564*10d63b7dSRichard Lowe 				right_hand[1] = NULL;
565*10d63b7dSRichard Lowe 				(void) wcscpy(right_hand[0], eq);
566*10d63b7dSRichard Lowe 			} else {
567*10d63b7dSRichard Lowe 				i = 0;
568*10d63b7dSRichard Lowe 				do {
569*10d63b7dSRichard Lowe 					right_hand[i] = ALLOC_WC(percent-eq+1);
570*10d63b7dSRichard Lowe 					(void) wcsncpy(right_hand[i],
571*10d63b7dSRichard Lowe 						      eq,
572*10d63b7dSRichard Lowe 						      percent - eq);
573*10d63b7dSRichard Lowe 					right_hand[i][percent-eq] =
574*10d63b7dSRichard Lowe 					  (int) nul_char;
575*10d63b7dSRichard Lowe 					if (i++ >= VSIZEOF(right_hand)) {
576*10d63b7dSRichard Lowe 						fatal_mksh(gettext("Too many %% in pattern"));
577*10d63b7dSRichard Lowe 					}
578*10d63b7dSRichard Lowe 					eq = percent + 1;
579*10d63b7dSRichard Lowe 					if (eq[0] == (int) nul_char) {
580*10d63b7dSRichard Lowe 						MBSTOWCS(wcs_buffer, "");
581*10d63b7dSRichard Lowe 						right_hand[i] = (wchar_t *) wcsdup(wcs_buffer);
582*10d63b7dSRichard Lowe 						i++;
583*10d63b7dSRichard Lowe 						break;
584*10d63b7dSRichard Lowe 					}
585*10d63b7dSRichard Lowe 				} while ((percent = (wchar_t *) wcschr(eq, (int) percent_char)) != NULL);
586*10d63b7dSRichard Lowe 				if (eq[0] != (int) nul_char) {
587*10d63b7dSRichard Lowe 					right_hand[i] = ALLOC_WC(wcslen(eq) + 1);
588*10d63b7dSRichard Lowe 					(void) wcscpy(right_hand[i], eq);
589*10d63b7dSRichard Lowe 					i++;
590*10d63b7dSRichard Lowe 				}
591*10d63b7dSRichard Lowe 				right_hand[i] = NULL;
592*10d63b7dSRichard Lowe 			}
593*10d63b7dSRichard Lowe 			replacement = pattern_replace;
594*10d63b7dSRichard Lowe 		}
595*10d63b7dSRichard Lowe 	}
596*10d63b7dSRichard Lowe 	if (name == NULL) {
597*10d63b7dSRichard Lowe 		/*
598*10d63b7dSRichard Lowe 		 * No translations found.
599*10d63b7dSRichard Lowe 		 * Use the whole string as the macro name.
600*10d63b7dSRichard Lowe 		 */
601*10d63b7dSRichard Lowe 		name = GETNAME(string.buffer.start,
602*10d63b7dSRichard Lowe 			       string.text.p - string.buffer.start);
603*10d63b7dSRichard Lowe 	}
604*10d63b7dSRichard Lowe 	if (string.free_after_use) {
605*10d63b7dSRichard Lowe 		retmem(string.buffer.start);
606*10d63b7dSRichard Lowe 	}
607*10d63b7dSRichard Lowe 	if (name == make) {
608*10d63b7dSRichard Lowe 		make_word_mentioned = true;
609*10d63b7dSRichard Lowe 	}
610*10d63b7dSRichard Lowe 	if (name == query) {
611*10d63b7dSRichard Lowe 		query_mentioned = true;
612*10d63b7dSRichard Lowe 	}
613*10d63b7dSRichard Lowe 	if ((name == host_arch) || (name == target_arch)) {
614*10d63b7dSRichard Lowe 		if (!init_arch_done) {
615*10d63b7dSRichard Lowe 			init_arch_done = true;
616*10d63b7dSRichard Lowe 			init_arch_macros();
617*10d63b7dSRichard Lowe 		}
618*10d63b7dSRichard Lowe 	}
619*10d63b7dSRichard Lowe 	if ((name == host_mach) || (name == target_mach)) {
620*10d63b7dSRichard Lowe 		if (!init_mach_done) {
621*10d63b7dSRichard Lowe 			init_mach_done = true;
622*10d63b7dSRichard Lowe 			init_mach_macros();
623*10d63b7dSRichard Lowe 		}
624*10d63b7dSRichard Lowe 	}
625*10d63b7dSRichard Lowe 	/* Get the macro value. */
626*10d63b7dSRichard Lowe 	macro = get_prop(name->prop, macro_prop);
627*10d63b7dSRichard Lowe 	if ((macro != NULL) && macro->body.macro.is_conditional) {
628*10d63b7dSRichard Lowe 		conditional_macro_used = true;
629*10d63b7dSRichard Lowe 		/*
630*10d63b7dSRichard Lowe 		 * Add this conditional macro to the beginning of the
631*10d63b7dSRichard Lowe 		 * global list.
632*10d63b7dSRichard Lowe 		 */
633*10d63b7dSRichard Lowe 		add_macro_to_global_list(name);
634*10d63b7dSRichard Lowe 		if (makefile_type == reading_makefile) {
635*10d63b7dSRichard Lowe 			warning_mksh(gettext("Conditional macro `%s' referenced in file `%ws', line %d"),
636*10d63b7dSRichard Lowe 					name->string_mb, file_being_read, line_number);
637*10d63b7dSRichard Lowe 		}
638*10d63b7dSRichard Lowe 	}
639*10d63b7dSRichard Lowe 	/* Macro name read and parsed. Expand the value. */
640*10d63b7dSRichard Lowe 	if ((macro == NULL) || (macro->body.macro.value == NULL)) {
641*10d63b7dSRichard Lowe 		/* If the value is empty, we just get out of here. */
642*10d63b7dSRichard Lowe 		goto exit;
643*10d63b7dSRichard Lowe 	}
644*10d63b7dSRichard Lowe 	if (replacement == sh_replace) {
645*10d63b7dSRichard Lowe 		/* If we should do a :sh transform, we expand the command
646*10d63b7dSRichard Lowe 		 * and process it.
647*10d63b7dSRichard Lowe 		 */
648*10d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(string, buffer);
649*10d63b7dSRichard Lowe 		/* Expand the value into a local string buffer and run cmd. */
650*10d63b7dSRichard Lowe 		expand_value_with_daemon(name, macro, &string, cmd);
651*10d63b7dSRichard Lowe 		sh_command2string(&string, destination);
652*10d63b7dSRichard Lowe 	} else if ((replacement != no_replace) || (extraction != no_extract)) {
653*10d63b7dSRichard Lowe 		/*
654*10d63b7dSRichard Lowe 		 * If there were any transforms specified in the macro
655*10d63b7dSRichard Lowe 		 * name, we deal with them here.
656*10d63b7dSRichard Lowe 		 */
657*10d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(string, buffer);
658*10d63b7dSRichard Lowe 		/* Expand the value into a local string buffer. */
659*10d63b7dSRichard Lowe 		expand_value_with_daemon(name, macro, &string, cmd);
660*10d63b7dSRichard Lowe 		/* Scan the expanded string. */
661*10d63b7dSRichard Lowe 		p = string.buffer.start;
662*10d63b7dSRichard Lowe 		while (*p != (int) nul_char) {
663*10d63b7dSRichard Lowe 			wchar_t		chr;
664*10d63b7dSRichard Lowe 
665*10d63b7dSRichard Lowe 			/*
666*10d63b7dSRichard Lowe 			 * First skip over any white space and append
667*10d63b7dSRichard Lowe 			 * that to the destination string.
668*10d63b7dSRichard Lowe 			 */
669*10d63b7dSRichard Lowe 			block_start = p;
670*10d63b7dSRichard Lowe 			while ((*p != (int) nul_char) && iswspace(*p)) {
671*10d63b7dSRichard Lowe 				p++;
672*10d63b7dSRichard Lowe 			}
673*10d63b7dSRichard Lowe 			append_string(block_start,
674*10d63b7dSRichard Lowe 				      destination,
675*10d63b7dSRichard Lowe 				      p - block_start);
676*10d63b7dSRichard Lowe 			/* Then find the end of the next word. */
677*10d63b7dSRichard Lowe 			block_start = p;
678*10d63b7dSRichard Lowe 			while ((*p != (int) nul_char) && !iswspace(*p)) {
679*10d63b7dSRichard Lowe 				p++;
680*10d63b7dSRichard Lowe 			}
681*10d63b7dSRichard Lowe 			/* If we cant find another word we are done */
682*10d63b7dSRichard Lowe 			if (block_start == p) {
683*10d63b7dSRichard Lowe 				break;
684*10d63b7dSRichard Lowe 			}
685*10d63b7dSRichard Lowe 			/* Then apply the transforms to the word */
686*10d63b7dSRichard Lowe 			INIT_STRING_FROM_STACK(extracted, extracted_string);
687*10d63b7dSRichard Lowe 			switch (extraction) {
688*10d63b7dSRichard Lowe 			case dir_extract:
689*10d63b7dSRichard Lowe 				/*
690*10d63b7dSRichard Lowe 				 * $(@D) type transform. Extract the
691*10d63b7dSRichard Lowe 				 * path from the word. Deliver "." if
692*10d63b7dSRichard Lowe 				 * none is found.
693*10d63b7dSRichard Lowe 				 */
694*10d63b7dSRichard Lowe 				if (p != NULL) {
695*10d63b7dSRichard Lowe 					chr = *p;
696*10d63b7dSRichard Lowe 					*p = (int) nul_char;
697*10d63b7dSRichard Lowe 				}
698*10d63b7dSRichard Lowe 				eq = (wchar_t *) wcsrchr(block_start, (int) slash_char);
699*10d63b7dSRichard Lowe 				if (p != NULL) {
700*10d63b7dSRichard Lowe 					*p = chr;
701*10d63b7dSRichard Lowe 				}
702*10d63b7dSRichard Lowe 				if ((eq == NULL) || (eq > p)) {
703*10d63b7dSRichard Lowe 					MBSTOWCS(wcs_buffer, ".");
704*10d63b7dSRichard Lowe 					append_string(wcs_buffer, &extracted, 1);
705*10d63b7dSRichard Lowe 				} else {
706*10d63b7dSRichard Lowe 					append_string(block_start,
707*10d63b7dSRichard Lowe 						      &extracted,
708*10d63b7dSRichard Lowe 						      eq - block_start);
709*10d63b7dSRichard Lowe 				}
710*10d63b7dSRichard Lowe 				break;
711*10d63b7dSRichard Lowe 			case file_extract:
712*10d63b7dSRichard Lowe 				/*
713*10d63b7dSRichard Lowe 				 * $(@F) type transform. Remove the path
714*10d63b7dSRichard Lowe 				 * from the word if any.
715*10d63b7dSRichard Lowe 				 */
716*10d63b7dSRichard Lowe 				if (p != NULL) {
717*10d63b7dSRichard Lowe 					chr = *p;
718*10d63b7dSRichard Lowe 					*p = (int) nul_char;
719*10d63b7dSRichard Lowe 				}
720*10d63b7dSRichard Lowe 				eq = (wchar_t *) wcsrchr(block_start, (int) slash_char);
721*10d63b7dSRichard Lowe 				if (p != NULL) {
722*10d63b7dSRichard Lowe 					*p = chr;
723*10d63b7dSRichard Lowe 				}
724*10d63b7dSRichard Lowe 				if ((eq == NULL) || (eq > p)) {
725*10d63b7dSRichard Lowe 					append_string(block_start,
726*10d63b7dSRichard Lowe 						      &extracted,
727*10d63b7dSRichard Lowe 						      p - block_start);
728*10d63b7dSRichard Lowe 				} else {
729*10d63b7dSRichard Lowe 					append_string(eq + 1,
730*10d63b7dSRichard Lowe 						      &extracted,
731*10d63b7dSRichard Lowe 						      p - eq - 1);
732*10d63b7dSRichard Lowe 				}
733*10d63b7dSRichard Lowe 				break;
734*10d63b7dSRichard Lowe 			case no_extract:
735*10d63b7dSRichard Lowe 				append_string(block_start,
736*10d63b7dSRichard Lowe 					      &extracted,
737*10d63b7dSRichard Lowe 					      p - block_start);
738*10d63b7dSRichard Lowe 				break;
739*10d63b7dSRichard Lowe 			}
740*10d63b7dSRichard Lowe 			switch (replacement) {
741*10d63b7dSRichard Lowe 			case suffix_replace:
742*10d63b7dSRichard Lowe 				/*
743*10d63b7dSRichard Lowe 				 * $(FOO:.o=.c) type transform.
744*10d63b7dSRichard Lowe 				 * Maybe replace the tail of the word.
745*10d63b7dSRichard Lowe 				 */
746*10d63b7dSRichard Lowe 				if (((extracted.text.p -
747*10d63b7dSRichard Lowe 				      extracted.buffer.start) >=
748*10d63b7dSRichard Lowe 				     left_tail_len) &&
749*10d63b7dSRichard Lowe 				    IS_WEQUALN(extracted.text.p - left_tail_len,
750*10d63b7dSRichard Lowe 					      left_tail,
751*10d63b7dSRichard Lowe 					      left_tail_len)) {
752*10d63b7dSRichard Lowe 					append_string(extracted.buffer.start,
753*10d63b7dSRichard Lowe 						      destination,
754*10d63b7dSRichard Lowe 						      (extracted.text.p -
755*10d63b7dSRichard Lowe 						       extracted.buffer.start)
756*10d63b7dSRichard Lowe 						      - left_tail_len);
757*10d63b7dSRichard Lowe 					append_string(right_tail,
758*10d63b7dSRichard Lowe 						      destination,
759*10d63b7dSRichard Lowe 						      FIND_LENGTH);
760*10d63b7dSRichard Lowe 				} else {
761*10d63b7dSRichard Lowe 					append_string(extracted.buffer.start,
762*10d63b7dSRichard Lowe 						      destination,
763*10d63b7dSRichard Lowe 						      FIND_LENGTH);
764*10d63b7dSRichard Lowe 				}
765*10d63b7dSRichard Lowe 				break;
766*10d63b7dSRichard Lowe 			case pattern_replace:
767*10d63b7dSRichard Lowe 				/* $(X:a%b=c%d) type transform. */
768*10d63b7dSRichard Lowe 				if (((extracted.text.p -
769*10d63b7dSRichard Lowe 				      extracted.buffer.start) >=
770*10d63b7dSRichard Lowe 				     left_head_len+left_tail_len) &&
771*10d63b7dSRichard Lowe 				    IS_WEQUALN(left_head,
772*10d63b7dSRichard Lowe 					      extracted.buffer.start,
773*10d63b7dSRichard Lowe 					      left_head_len) &&
774*10d63b7dSRichard Lowe 				    IS_WEQUALN(left_tail,
775*10d63b7dSRichard Lowe 					      extracted.text.p - left_tail_len,
776*10d63b7dSRichard Lowe 					      left_tail_len)) {
777*10d63b7dSRichard Lowe 					i = 0;
778*10d63b7dSRichard Lowe 					while (right_hand[i] != NULL) {
779*10d63b7dSRichard Lowe 						append_string(right_hand[i],
780*10d63b7dSRichard Lowe 							      destination,
781*10d63b7dSRichard Lowe 							      FIND_LENGTH);
782*10d63b7dSRichard Lowe 						i++;
783*10d63b7dSRichard Lowe 						if (right_hand[i] != NULL) {
784*10d63b7dSRichard Lowe 							append_string(extracted.buffer.
785*10d63b7dSRichard Lowe 								      start +
786*10d63b7dSRichard Lowe 								      left_head_len,
787*10d63b7dSRichard Lowe 								      destination,
788*10d63b7dSRichard Lowe 								      (extracted.text.p - extracted.buffer.start)-left_head_len-left_tail_len);
789*10d63b7dSRichard Lowe 						}
790*10d63b7dSRichard Lowe 					}
791*10d63b7dSRichard Lowe 				} else {
792*10d63b7dSRichard Lowe 					append_string(extracted.buffer.start,
793*10d63b7dSRichard Lowe 						      destination,
794*10d63b7dSRichard Lowe 						      FIND_LENGTH);
795*10d63b7dSRichard Lowe 				}
796*10d63b7dSRichard Lowe 				break;
797*10d63b7dSRichard Lowe 			case no_replace:
798*10d63b7dSRichard Lowe 				append_string(extracted.buffer.start,
799*10d63b7dSRichard Lowe 					      destination,
800*10d63b7dSRichard Lowe 					      FIND_LENGTH);
801*10d63b7dSRichard Lowe 				break;
802*10d63b7dSRichard Lowe 			case sh_replace:
803*10d63b7dSRichard Lowe 				break;
804*10d63b7dSRichard Lowe 			    }
805*10d63b7dSRichard Lowe 		}
806*10d63b7dSRichard Lowe 		if (string.free_after_use) {
807*10d63b7dSRichard Lowe 			retmem(string.buffer.start);
808*10d63b7dSRichard Lowe 		}
809*10d63b7dSRichard Lowe 	} else {
810*10d63b7dSRichard Lowe 		/*
811*10d63b7dSRichard Lowe 		 * This is for the case when the macro name did not
812*10d63b7dSRichard Lowe 		 * specify transforms.
813*10d63b7dSRichard Lowe 		 */
814*10d63b7dSRichard Lowe 		if (!strncmp(name->string_mb, "GET", 3)) {
815*10d63b7dSRichard Lowe 			dollarget_seen = true;
816*10d63b7dSRichard Lowe 		}
817*10d63b7dSRichard Lowe 		dollarless_flag = false;
818*10d63b7dSRichard Lowe 		if (!strncmp(name->string_mb, "<", 1) &&
819*10d63b7dSRichard Lowe 		    dollarget_seen) {
820*10d63b7dSRichard Lowe 			dollarless_flag = true;
821*10d63b7dSRichard Lowe 			dollarget_seen = false;
822*10d63b7dSRichard Lowe 		}
823*10d63b7dSRichard Lowe 		expand_value_with_daemon(name, macro, destination, cmd);
824*10d63b7dSRichard Lowe 	}
825*10d63b7dSRichard Lowe exit:
826*10d63b7dSRichard Lowe 	if(left_tail) {
827*10d63b7dSRichard Lowe 		retmem(left_tail);
828*10d63b7dSRichard Lowe 	}
829*10d63b7dSRichard Lowe 	if(right_tail) {
830*10d63b7dSRichard Lowe 		retmem(right_tail);
831*10d63b7dSRichard Lowe 	}
832*10d63b7dSRichard Lowe 	if(left_head) {
833*10d63b7dSRichard Lowe 		retmem(left_head);
834*10d63b7dSRichard Lowe 	}
835*10d63b7dSRichard Lowe 	i = 0;
836*10d63b7dSRichard Lowe 	while (right_hand[i] != NULL) {
837*10d63b7dSRichard Lowe 		retmem(right_hand[i]);
838*10d63b7dSRichard Lowe 		i++;
839*10d63b7dSRichard Lowe 	}
840*10d63b7dSRichard Lowe 	*destination->text.p = (int) nul_char;
841*10d63b7dSRichard Lowe 	destination->text.end = destination->text.p;
842*10d63b7dSRichard Lowe }
843*10d63b7dSRichard Lowe 
844*10d63b7dSRichard Lowe static void
add_macro_to_global_list(Name macro_to_add)845*10d63b7dSRichard Lowe add_macro_to_global_list(Name macro_to_add)
846*10d63b7dSRichard Lowe {
847*10d63b7dSRichard Lowe 	Macro_list	new_macro;
848*10d63b7dSRichard Lowe 	Macro_list	macro_on_list;
849*10d63b7dSRichard Lowe 	char		*name_on_list = (char*)NULL;
850*10d63b7dSRichard Lowe 	char		*name_to_add = macro_to_add->string_mb;
851*10d63b7dSRichard Lowe 	char		*value_on_list = (char*)NULL;
852*10d63b7dSRichard Lowe 	const char	*value_to_add = (char*)NULL;
853*10d63b7dSRichard Lowe 
854*10d63b7dSRichard Lowe 	if (macro_to_add->prop->body.macro.value != NULL) {
855*10d63b7dSRichard Lowe 		value_to_add = macro_to_add->prop->body.macro.value->string_mb;
856*10d63b7dSRichard Lowe 	} else {
857*10d63b7dSRichard Lowe 		value_to_add = "";
858*10d63b7dSRichard Lowe 	}
859*10d63b7dSRichard Lowe 
860*10d63b7dSRichard Lowe 	/*
861*10d63b7dSRichard Lowe 	 * Check if this macro is already on list, if so, do nothing
862*10d63b7dSRichard Lowe 	 */
863*10d63b7dSRichard Lowe 	for (macro_on_list = cond_macro_list;
864*10d63b7dSRichard Lowe 	     macro_on_list != NULL;
865*10d63b7dSRichard Lowe 	     macro_on_list = macro_on_list->next) {
866*10d63b7dSRichard Lowe 
867*10d63b7dSRichard Lowe 		name_on_list = macro_on_list->macro_name;
868*10d63b7dSRichard Lowe 		value_on_list = macro_on_list->value;
869*10d63b7dSRichard Lowe 
870*10d63b7dSRichard Lowe 		if (IS_EQUAL(name_on_list, name_to_add)) {
871*10d63b7dSRichard Lowe 			if (IS_EQUAL(value_on_list, value_to_add)) {
872*10d63b7dSRichard Lowe 				return;
873*10d63b7dSRichard Lowe 			}
874*10d63b7dSRichard Lowe 		}
875*10d63b7dSRichard Lowe 	}
876*10d63b7dSRichard Lowe 	new_macro = (Macro_list) malloc(sizeof(Macro_list_rec));
877*10d63b7dSRichard Lowe 	new_macro->macro_name = strdup(name_to_add);
878*10d63b7dSRichard Lowe 	new_macro->value = strdup(value_to_add);
879*10d63b7dSRichard Lowe 	new_macro->next = cond_macro_list;
880*10d63b7dSRichard Lowe 	cond_macro_list = new_macro;
881*10d63b7dSRichard Lowe }
882*10d63b7dSRichard Lowe 
883*10d63b7dSRichard Lowe /*
884*10d63b7dSRichard Lowe  *	init_arch_macros(void)
885*10d63b7dSRichard Lowe  *
886*10d63b7dSRichard Lowe  *	Set the magic macros TARGET_ARCH, HOST_ARCH,
887*10d63b7dSRichard Lowe  *
888*10d63b7dSRichard Lowe  *	Parameters:
889*10d63b7dSRichard Lowe  *
890*10d63b7dSRichard Lowe  *	Global variables used:
891*10d63b7dSRichard Lowe  * 	                        host_arch   Property for magic macro HOST_ARCH
892*10d63b7dSRichard Lowe  * 	                        target_arch Property for magic macro TARGET_ARCH
893*10d63b7dSRichard Lowe  *
894*10d63b7dSRichard Lowe  *	Return value:
895*10d63b7dSRichard Lowe  *				The function does not return a value, but can
896*10d63b7dSRichard Lowe  *				call fatal() in case of error.
897*10d63b7dSRichard Lowe  */
898*10d63b7dSRichard Lowe static void
init_arch_macros(void)899*10d63b7dSRichard Lowe init_arch_macros(void)
900*10d63b7dSRichard Lowe {
901*10d63b7dSRichard Lowe 	String_rec	result_string;
902*10d63b7dSRichard Lowe 	wchar_t		wc_buf[STRING_BUFFER_LENGTH];
903*10d63b7dSRichard Lowe 	char		mb_buf[STRING_BUFFER_LENGTH];
904*10d63b7dSRichard Lowe 	FILE		*pipe;
905*10d63b7dSRichard Lowe 	Name		value;
906*10d63b7dSRichard Lowe 	int		set_host, set_target;
907*10d63b7dSRichard Lowe 	const char	*mach_command = "/bin/mach";
908*10d63b7dSRichard Lowe 
909*10d63b7dSRichard Lowe 	set_host = (get_prop(host_arch->prop, macro_prop) == NULL);
910*10d63b7dSRichard Lowe 	set_target = (get_prop(target_arch->prop, macro_prop) == NULL);
911*10d63b7dSRichard Lowe 
912*10d63b7dSRichard Lowe 	if (set_host || set_target) {
913*10d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(result_string, wc_buf);
914*10d63b7dSRichard Lowe 		append_char((int) hyphen_char, &result_string);
915*10d63b7dSRichard Lowe 
916*10d63b7dSRichard Lowe 		if ((pipe = popen(mach_command, "r")) == NULL) {
917*10d63b7dSRichard Lowe 			fatal_mksh(gettext("Execute of %s failed"), mach_command);
918*10d63b7dSRichard Lowe 		}
919*10d63b7dSRichard Lowe 		while (fgets(mb_buf, sizeof(mb_buf), pipe) != NULL) {
920*10d63b7dSRichard Lowe 			MBSTOWCS(wcs_buffer, mb_buf);
921*10d63b7dSRichard Lowe 			append_string(wcs_buffer, &result_string, wcslen(wcs_buffer));
922*10d63b7dSRichard Lowe 		}
923*10d63b7dSRichard Lowe 		if (pclose(pipe) != 0) {
924*10d63b7dSRichard Lowe 			fatal_mksh(gettext("Execute of %s failed"), mach_command);
925*10d63b7dSRichard Lowe 		}
926*10d63b7dSRichard Lowe 
927*10d63b7dSRichard Lowe 		value = GETNAME(result_string.buffer.start, wcslen(result_string.buffer.start));
928*10d63b7dSRichard Lowe 
929*10d63b7dSRichard Lowe 		if (set_host) {
930*10d63b7dSRichard Lowe 			(void) setvar_daemon(host_arch, value, false, no_daemon, true, 0);
931*10d63b7dSRichard Lowe 		}
932*10d63b7dSRichard Lowe 		if (set_target) {
933*10d63b7dSRichard Lowe 			(void) setvar_daemon(target_arch, value, false, no_daemon, true, 0);
934*10d63b7dSRichard Lowe 		}
935*10d63b7dSRichard Lowe 	}
936*10d63b7dSRichard Lowe }
937*10d63b7dSRichard Lowe 
938*10d63b7dSRichard Lowe /*
939*10d63b7dSRichard Lowe  *	init_mach_macros(void)
940*10d63b7dSRichard Lowe  *
941*10d63b7dSRichard Lowe  *	Set the magic macros TARGET_MACH, HOST_MACH,
942*10d63b7dSRichard Lowe  *
943*10d63b7dSRichard Lowe  *	Parameters:
944*10d63b7dSRichard Lowe  *
945*10d63b7dSRichard Lowe  *	Global variables used:
946*10d63b7dSRichard Lowe  * 	                        host_mach   Property for magic macro HOST_MACH
947*10d63b7dSRichard Lowe  * 	                        target_mach Property for magic macro TARGET_MACH
948*10d63b7dSRichard Lowe  *
949*10d63b7dSRichard Lowe  *	Return value:
950*10d63b7dSRichard Lowe  *				The function does not return a value, but can
951*10d63b7dSRichard Lowe  *				call fatal() in case of error.
952*10d63b7dSRichard Lowe  */
953*10d63b7dSRichard Lowe static void
init_mach_macros(void)954*10d63b7dSRichard Lowe init_mach_macros(void)
955*10d63b7dSRichard Lowe {
956*10d63b7dSRichard Lowe 	String_rec	result_string;
957*10d63b7dSRichard Lowe 	wchar_t		wc_buf[STRING_BUFFER_LENGTH];
958*10d63b7dSRichard Lowe 	char		mb_buf[STRING_BUFFER_LENGTH];
959*10d63b7dSRichard Lowe 	FILE		*pipe;
960*10d63b7dSRichard Lowe 	Name		value;
961*10d63b7dSRichard Lowe 	int		set_host, set_target;
962*10d63b7dSRichard Lowe 	const char	*arch_command = "/bin/arch";
963*10d63b7dSRichard Lowe 
964*10d63b7dSRichard Lowe 	set_host = (get_prop(host_mach->prop, macro_prop) == NULL);
965*10d63b7dSRichard Lowe 	set_target = (get_prop(target_mach->prop, macro_prop) == NULL);
966*10d63b7dSRichard Lowe 
967*10d63b7dSRichard Lowe 	if (set_host || set_target) {
968*10d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(result_string, wc_buf);
969*10d63b7dSRichard Lowe 		append_char((int) hyphen_char, &result_string);
970*10d63b7dSRichard Lowe 
971*10d63b7dSRichard Lowe 		if ((pipe = popen(arch_command, "r")) == NULL) {
972*10d63b7dSRichard Lowe 			fatal_mksh(gettext("Execute of %s failed"), arch_command);
973*10d63b7dSRichard Lowe 		}
974*10d63b7dSRichard Lowe 		while (fgets(mb_buf, sizeof(mb_buf), pipe) != NULL) {
975*10d63b7dSRichard Lowe 			MBSTOWCS(wcs_buffer, mb_buf);
976*10d63b7dSRichard Lowe 			append_string(wcs_buffer, &result_string, wcslen(wcs_buffer));
977*10d63b7dSRichard Lowe 		}
978*10d63b7dSRichard Lowe 		if (pclose(pipe) != 0) {
979*10d63b7dSRichard Lowe 			fatal_mksh(gettext("Execute of %s failed"), arch_command);
980*10d63b7dSRichard Lowe 		}
981*10d63b7dSRichard Lowe 
982*10d63b7dSRichard Lowe 		value = GETNAME(result_string.buffer.start, wcslen(result_string.buffer.start));
983*10d63b7dSRichard Lowe 
984*10d63b7dSRichard Lowe 		if (set_host) {
985*10d63b7dSRichard Lowe 			(void) setvar_daemon(host_mach, value, false, no_daemon, true, 0);
986*10d63b7dSRichard Lowe 		}
987*10d63b7dSRichard Lowe 		if (set_target) {
988*10d63b7dSRichard Lowe 			(void) setvar_daemon(target_mach, value, false, no_daemon, true, 0);
989*10d63b7dSRichard Lowe 		}
990*10d63b7dSRichard Lowe 	}
991*10d63b7dSRichard Lowe }
992*10d63b7dSRichard Lowe 
993*10d63b7dSRichard Lowe /*
994*10d63b7dSRichard Lowe  *	expand_value_with_daemon(name, macro, destination, cmd)
995*10d63b7dSRichard Lowe  *
996*10d63b7dSRichard Lowe  *	Checks for daemons and then maybe calls expand_value().
997*10d63b7dSRichard Lowe  *
998*10d63b7dSRichard Lowe  *	Parameters:
999*10d63b7dSRichard Lowe  *              name            Name of the macro  (Added by the NSE)
1000*10d63b7dSRichard Lowe  *		macro		The property block with the value to expand
1001*10d63b7dSRichard Lowe  *		destination	Where the result should be deposited
1002*10d63b7dSRichard Lowe  *		cmd		If we are evaluating a command line we
1003*10d63b7dSRichard Lowe  *				turn \ quoting off
1004*10d63b7dSRichard Lowe  *
1005*10d63b7dSRichard Lowe  *	Global variables used:
1006*10d63b7dSRichard Lowe  */
1007*10d63b7dSRichard Lowe static void
expand_value_with_daemon(Name,register Property macro,register String destination,Boolean cmd)1008*10d63b7dSRichard Lowe expand_value_with_daemon(Name, register Property macro, register String destination, Boolean cmd)
1009*10d63b7dSRichard Lowe {
1010*10d63b7dSRichard Lowe 	register Chain		chain;
1011*10d63b7dSRichard Lowe 
1012*10d63b7dSRichard Lowe 
1013*10d63b7dSRichard Lowe 	switch (macro->body.macro.daemon) {
1014*10d63b7dSRichard Lowe 	case no_daemon:
1015*10d63b7dSRichard Lowe 		if (!svr4 && !posix) {
1016*10d63b7dSRichard Lowe 			expand_value(macro->body.macro.value, destination, cmd);
1017*10d63b7dSRichard Lowe 		} else {
1018*10d63b7dSRichard Lowe 			if (dollarless_flag && tilde_rule) {
1019*10d63b7dSRichard Lowe 				expand_value(dollarless_value, destination, cmd);
1020*10d63b7dSRichard Lowe 				dollarless_flag = false;
1021*10d63b7dSRichard Lowe 				tilde_rule = false;
1022*10d63b7dSRichard Lowe 			} else {
1023*10d63b7dSRichard Lowe 				expand_value(macro->body.macro.value, destination, cmd);
1024*10d63b7dSRichard Lowe 			}
1025*10d63b7dSRichard Lowe 		}
1026*10d63b7dSRichard Lowe 		return;
1027*10d63b7dSRichard Lowe 	case chain_daemon:
1028*10d63b7dSRichard Lowe 		/* If this is a $? value we call the daemon to translate the */
1029*10d63b7dSRichard Lowe 		/* list of names to a string */
1030*10d63b7dSRichard Lowe 		for (chain = (Chain) macro->body.macro.value;
1031*10d63b7dSRichard Lowe 		     chain != NULL;
1032*10d63b7dSRichard Lowe 		     chain = chain->next) {
1033*10d63b7dSRichard Lowe 			APPEND_NAME(chain->name,
1034*10d63b7dSRichard Lowe 				      destination,
1035*10d63b7dSRichard Lowe 				      (int) chain->name->hash.length);
1036*10d63b7dSRichard Lowe 			if (chain->next != NULL) {
1037*10d63b7dSRichard Lowe 				append_char((int) space_char, destination);
1038*10d63b7dSRichard Lowe 			}
1039*10d63b7dSRichard Lowe 		}
1040*10d63b7dSRichard Lowe 		return;
1041*10d63b7dSRichard Lowe 	}
1042*10d63b7dSRichard Lowe }
1043*10d63b7dSRichard Lowe 
1044*10d63b7dSRichard Lowe /*
1045*10d63b7dSRichard Lowe  * We use a permanent buffer to reset SUNPRO_DEPENDENCIES value.
1046*10d63b7dSRichard Lowe  */
1047*10d63b7dSRichard Lowe char	*sunpro_dependencies_buf = NULL;
1048*10d63b7dSRichard Lowe char	*sunpro_dependencies_oldbuf = NULL;
1049*10d63b7dSRichard Lowe int	sunpro_dependencies_buf_size = 0;
1050*10d63b7dSRichard Lowe 
1051*10d63b7dSRichard Lowe /*
1052*10d63b7dSRichard Lowe  *	setvar_daemon(name, value, append, daemon, strip_trailing_spaces)
1053*10d63b7dSRichard Lowe  *
1054*10d63b7dSRichard Lowe  *	Set a macro value, possibly supplying a daemon to be used
1055*10d63b7dSRichard Lowe  *	when referencing the value.
1056*10d63b7dSRichard Lowe  *
1057*10d63b7dSRichard Lowe  *	Return value:
1058*10d63b7dSRichard Lowe  *				The property block with the new value
1059*10d63b7dSRichard Lowe  *
1060*10d63b7dSRichard Lowe  *	Parameters:
1061*10d63b7dSRichard Lowe  *		name		Name of the macro to set
1062*10d63b7dSRichard Lowe  *		value		The value to set
1063*10d63b7dSRichard Lowe  *		append		Should we reset or append to the current value?
1064*10d63b7dSRichard Lowe  *		daemon		Special treatment when reading the value
1065*10d63b7dSRichard Lowe  *		strip_trailing_spaces from the end of value->string
1066*10d63b7dSRichard Lowe  *		debug_level	Indicates how much tracing we should do
1067*10d63b7dSRichard Lowe  *
1068*10d63b7dSRichard Lowe  *	Global variables used:
1069*10d63b7dSRichard Lowe  *		makefile_type	Used to check if we should enforce read only
1070*10d63b7dSRichard Lowe  *		path_name	The Name "PATH", compared against
1071*10d63b7dSRichard Lowe  *		virtual_root	The Name "VIRTUAL_ROOT", compared against
1072*10d63b7dSRichard Lowe  *		vpath_defined	Set if the macro VPATH is set
1073*10d63b7dSRichard Lowe  *		vpath_name	The Name "VPATH", compared against
1074*10d63b7dSRichard Lowe  *		envvar		A list of environment vars with $ in value
1075*10d63b7dSRichard Lowe  */
1076*10d63b7dSRichard Lowe Property
setvar_daemon(register Name name,register Name value,Boolean append,Daemon daemon,Boolean strip_trailing_spaces,short debug_level)1077*10d63b7dSRichard Lowe setvar_daemon(register Name name, register Name value, Boolean append, Daemon daemon, Boolean strip_trailing_spaces, short debug_level)
1078*10d63b7dSRichard Lowe {
1079*10d63b7dSRichard Lowe 	register Property	macro = maybe_append_prop(name, macro_prop);
1080*10d63b7dSRichard Lowe 	register Property	macro_apx = get_prop(name->prop, macro_append_prop);
1081*10d63b7dSRichard Lowe 	int			length = 0;
1082*10d63b7dSRichard Lowe 	String_rec		destination;
1083*10d63b7dSRichard Lowe 	wchar_t			buffer[STRING_BUFFER_LENGTH];
1084*10d63b7dSRichard Lowe 	register Chain		chain;
1085*10d63b7dSRichard Lowe 	Name			val;
1086*10d63b7dSRichard Lowe 	wchar_t			*val_string = (wchar_t*)NULL;
1087*10d63b7dSRichard Lowe 	Wstring			wcb;
1088*10d63b7dSRichard Lowe 
1089*10d63b7dSRichard Lowe 
1090*10d63b7dSRichard Lowe 	if ((makefile_type != reading_nothing) &&
1091*10d63b7dSRichard Lowe 	    macro->body.macro.read_only) {
1092*10d63b7dSRichard Lowe 		return macro;
1093*10d63b7dSRichard Lowe 	}
1094*10d63b7dSRichard Lowe 	/* Strip spaces from the end of the value */
1095*10d63b7dSRichard Lowe 	if (daemon == no_daemon) {
1096*10d63b7dSRichard Lowe 		if(value != NULL) {
1097*10d63b7dSRichard Lowe 			wcb.init(value);
1098*10d63b7dSRichard Lowe 			length = wcb.length();
1099*10d63b7dSRichard Lowe 			val_string = wcb.get_string();
1100*10d63b7dSRichard Lowe 		}
1101*10d63b7dSRichard Lowe 		if ((length > 0) && iswspace(val_string[length-1])) {
1102*10d63b7dSRichard Lowe 			INIT_STRING_FROM_STACK(destination, buffer);
1103*10d63b7dSRichard Lowe 			buffer[0] = 0;
1104*10d63b7dSRichard Lowe 			append_string(val_string, &destination, length);
1105*10d63b7dSRichard Lowe 			if (strip_trailing_spaces) {
1106*10d63b7dSRichard Lowe 				while ((length > 0) &&
1107*10d63b7dSRichard Lowe 				       iswspace(destination.buffer.start[length-1])) {
1108*10d63b7dSRichard Lowe 					destination.buffer.start[--length] = 0;
1109*10d63b7dSRichard Lowe 				}
1110*10d63b7dSRichard Lowe 			}
1111*10d63b7dSRichard Lowe 			value = GETNAME(destination.buffer.start, FIND_LENGTH);
1112*10d63b7dSRichard Lowe 		}
1113*10d63b7dSRichard Lowe 	}
1114*10d63b7dSRichard Lowe 
1115*10d63b7dSRichard Lowe 	if(macro_apx != NULL) {
1116*10d63b7dSRichard Lowe 		val = macro_apx->body.macro_appendix.value;
1117*10d63b7dSRichard Lowe 	} else {
1118*10d63b7dSRichard Lowe 		val = macro->body.macro.value;
1119*10d63b7dSRichard Lowe 	}
1120*10d63b7dSRichard Lowe 
1121*10d63b7dSRichard Lowe 	if (append) {
1122*10d63b7dSRichard Lowe 		/*
1123*10d63b7dSRichard Lowe 		 * If we are appending, we just tack the new value after
1124*10d63b7dSRichard Lowe 		 * the old one with a space in between.
1125*10d63b7dSRichard Lowe 		 */
1126*10d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(destination, buffer);
1127*10d63b7dSRichard Lowe 		buffer[0] = 0;
1128*10d63b7dSRichard Lowe 		if ((macro != NULL) && (val != NULL)) {
1129*10d63b7dSRichard Lowe 			APPEND_NAME(val,
1130*10d63b7dSRichard Lowe 				      &destination,
1131*10d63b7dSRichard Lowe 				      (int) val->hash.length);
1132*10d63b7dSRichard Lowe 			if (value != NULL) {
1133*10d63b7dSRichard Lowe 				wcb.init(value);
1134*10d63b7dSRichard Lowe 				if(wcb.length() > 0) {
1135*10d63b7dSRichard Lowe 					MBTOWC(wcs_buffer, " ");
1136*10d63b7dSRichard Lowe 					append_char(wcs_buffer[0], &destination);
1137*10d63b7dSRichard Lowe 				}
1138*10d63b7dSRichard Lowe 			}
1139*10d63b7dSRichard Lowe 		}
1140*10d63b7dSRichard Lowe 		if (value != NULL) {
1141*10d63b7dSRichard Lowe 			APPEND_NAME(value,
1142*10d63b7dSRichard Lowe 				      &destination,
1143*10d63b7dSRichard Lowe 				      (int) value->hash.length);
1144*10d63b7dSRichard Lowe 		}
1145*10d63b7dSRichard Lowe 		value = GETNAME(destination.buffer.start, FIND_LENGTH);
1146*10d63b7dSRichard Lowe 		wcb.init(value);
1147*10d63b7dSRichard Lowe 		if (destination.free_after_use) {
1148*10d63b7dSRichard Lowe 			retmem(destination.buffer.start);
1149*10d63b7dSRichard Lowe 		}
1150*10d63b7dSRichard Lowe 	}
1151*10d63b7dSRichard Lowe 
1152*10d63b7dSRichard Lowe 	/* Debugging trace */
1153*10d63b7dSRichard Lowe 	if (debug_level > 1) {
1154*10d63b7dSRichard Lowe 		if (value != NULL) {
1155*10d63b7dSRichard Lowe 			switch (daemon) {
1156*10d63b7dSRichard Lowe 			case chain_daemon:
1157*10d63b7dSRichard Lowe 				(void) printf("%s =", name->string_mb);
1158*10d63b7dSRichard Lowe 				for (chain = (Chain) value;
1159*10d63b7dSRichard Lowe 				     chain != NULL;
1160*10d63b7dSRichard Lowe 				     chain = chain->next) {
1161*10d63b7dSRichard Lowe 					(void) printf(" %s", chain->name->string_mb);
1162*10d63b7dSRichard Lowe 				}
1163*10d63b7dSRichard Lowe 				(void) printf("\n");
1164*10d63b7dSRichard Lowe 				break;
1165*10d63b7dSRichard Lowe 			case no_daemon:
1166*10d63b7dSRichard Lowe 				(void) printf("%s= %s\n",
1167*10d63b7dSRichard Lowe 					      name->string_mb,
1168*10d63b7dSRichard Lowe 					      value->string_mb);
1169*10d63b7dSRichard Lowe 				break;
1170*10d63b7dSRichard Lowe 			}
1171*10d63b7dSRichard Lowe 		} else {
1172*10d63b7dSRichard Lowe 			(void) printf("%s =\n", name->string_mb);
1173*10d63b7dSRichard Lowe 		}
1174*10d63b7dSRichard Lowe 	}
1175*10d63b7dSRichard Lowe 	/* Set the new values in the macro property block */
1176*10d63b7dSRichard Lowe /**/
1177*10d63b7dSRichard Lowe 	if(macro_apx != NULL) {
1178*10d63b7dSRichard Lowe 		macro_apx->body.macro_appendix.value = value;
1179*10d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(destination, buffer);
1180*10d63b7dSRichard Lowe 		buffer[0] = 0;
1181*10d63b7dSRichard Lowe 		if (value != NULL) {
1182*10d63b7dSRichard Lowe 			APPEND_NAME(value,
1183*10d63b7dSRichard Lowe 				      &destination,
1184*10d63b7dSRichard Lowe 				      (int) value->hash.length);
1185*10d63b7dSRichard Lowe 			if (macro_apx->body.macro_appendix.value_to_append != NULL) {
1186*10d63b7dSRichard Lowe 				MBTOWC(wcs_buffer, " ");
1187*10d63b7dSRichard Lowe 				append_char(wcs_buffer[0], &destination);
1188*10d63b7dSRichard Lowe 			}
1189*10d63b7dSRichard Lowe 		}
1190*10d63b7dSRichard Lowe 		if (macro_apx->body.macro_appendix.value_to_append != NULL) {
1191*10d63b7dSRichard Lowe 			APPEND_NAME(macro_apx->body.macro_appendix.value_to_append,
1192*10d63b7dSRichard Lowe 				      &destination,
1193*10d63b7dSRichard Lowe 				      (int) macro_apx->body.macro_appendix.value_to_append->hash.length);
1194*10d63b7dSRichard Lowe 		}
1195*10d63b7dSRichard Lowe 		value = GETNAME(destination.buffer.start, FIND_LENGTH);
1196*10d63b7dSRichard Lowe 		if (destination.free_after_use) {
1197*10d63b7dSRichard Lowe 			retmem(destination.buffer.start);
1198*10d63b7dSRichard Lowe 		}
1199*10d63b7dSRichard Lowe 	}
1200*10d63b7dSRichard Lowe /**/
1201*10d63b7dSRichard Lowe 	macro->body.macro.value = value;
1202*10d63b7dSRichard Lowe 	macro->body.macro.daemon = daemon;
1203*10d63b7dSRichard Lowe 	/*
1204*10d63b7dSRichard Lowe 	 * If the user changes the VIRTUAL_ROOT, we need to flush
1205*10d63b7dSRichard Lowe 	 * the vroot package cache.
1206*10d63b7dSRichard Lowe 	 */
1207*10d63b7dSRichard Lowe 	if (name == path_name) {
1208*10d63b7dSRichard Lowe 		flush_path_cache();
1209*10d63b7dSRichard Lowe 	}
1210*10d63b7dSRichard Lowe 	if (name == virtual_root) {
1211*10d63b7dSRichard Lowe 		flush_vroot_cache();
1212*10d63b7dSRichard Lowe 	}
1213*10d63b7dSRichard Lowe 	/* If this sets the VPATH we remember that */
1214*10d63b7dSRichard Lowe 	if ((name == vpath_name) &&
1215*10d63b7dSRichard Lowe 	    (value != NULL) &&
1216*10d63b7dSRichard Lowe 	    (value->hash.length > 0)) {
1217*10d63b7dSRichard Lowe 		vpath_defined = true;
1218*10d63b7dSRichard Lowe 	}
1219*10d63b7dSRichard Lowe 	/*
1220*10d63b7dSRichard Lowe 	 * For environment variables we also set the
1221*10d63b7dSRichard Lowe 	 * environment value each time.
1222*10d63b7dSRichard Lowe 	 */
1223*10d63b7dSRichard Lowe 	if (macro->body.macro.exported) {
1224*10d63b7dSRichard Lowe 		static char	*env;
1225*10d63b7dSRichard Lowe 
1226*10d63b7dSRichard Lowe 		if (!reading_environment && (value != NULL)) {
1227*10d63b7dSRichard Lowe 			Envvar	p;
1228*10d63b7dSRichard Lowe 
1229*10d63b7dSRichard Lowe 			for (p = envvar; p != NULL; p = p->next) {
1230*10d63b7dSRichard Lowe 				if (p->name == name) {
1231*10d63b7dSRichard Lowe 					p->value = value;
1232*10d63b7dSRichard Lowe 					p->already_put = false;
1233*10d63b7dSRichard Lowe 					goto found_it;
1234*10d63b7dSRichard Lowe 				}
1235*10d63b7dSRichard Lowe 			}
1236*10d63b7dSRichard Lowe 			p = ALLOC(Envvar);
1237*10d63b7dSRichard Lowe 			p->name = name;
1238*10d63b7dSRichard Lowe 			p->value = value;
1239*10d63b7dSRichard Lowe 			p->next = envvar;
1240*10d63b7dSRichard Lowe 			p->env_string = NULL;
1241*10d63b7dSRichard Lowe 			p->already_put = false;
1242*10d63b7dSRichard Lowe 			envvar = p;
1243*10d63b7dSRichard Lowe found_it:;
1244*10d63b7dSRichard Lowe 		} if (reading_environment || (value == NULL) || !value->dollar) {
1245*10d63b7dSRichard Lowe 			length = 2 + strlen(name->string_mb);
1246*10d63b7dSRichard Lowe 			if (value != NULL) {
1247*10d63b7dSRichard Lowe 				length += strlen(value->string_mb);
1248*10d63b7dSRichard Lowe 			}
1249*10d63b7dSRichard Lowe 			Property env_prop = maybe_append_prop(name, env_mem_prop);
1250*10d63b7dSRichard Lowe 			/*
1251*10d63b7dSRichard Lowe 			 * We use a permanent buffer to reset SUNPRO_DEPENDENCIES value.
1252*10d63b7dSRichard Lowe 			 */
1253*10d63b7dSRichard Lowe 			if (!strncmp(name->string_mb, "SUNPRO_DEPENDENCIES", 19)) {
1254*10d63b7dSRichard Lowe 				if (length >= sunpro_dependencies_buf_size) {
1255*10d63b7dSRichard Lowe 					sunpro_dependencies_buf_size=length*2;
1256*10d63b7dSRichard Lowe 					if (sunpro_dependencies_buf_size < 4096)
1257*10d63b7dSRichard Lowe 						sunpro_dependencies_buf_size = 4096; // Default minimum size
1258*10d63b7dSRichard Lowe 					if (sunpro_dependencies_buf)
1259*10d63b7dSRichard Lowe 						sunpro_dependencies_oldbuf = sunpro_dependencies_buf;
1260*10d63b7dSRichard Lowe 					sunpro_dependencies_buf=getmem(sunpro_dependencies_buf_size);
1261*10d63b7dSRichard Lowe 				}
1262*10d63b7dSRichard Lowe 				env = sunpro_dependencies_buf;
1263*10d63b7dSRichard Lowe 			} else {
1264*10d63b7dSRichard Lowe 				env = getmem(length);
1265*10d63b7dSRichard Lowe 			}
1266*10d63b7dSRichard Lowe 			env_alloc_num++;
1267*10d63b7dSRichard Lowe 			env_alloc_bytes += length;
1268*10d63b7dSRichard Lowe 			(void) sprintf(env,
1269*10d63b7dSRichard Lowe 				       "%s=%s",
1270*10d63b7dSRichard Lowe 				       name->string_mb,
1271*10d63b7dSRichard Lowe 				       value == NULL ?
1272*10d63b7dSRichard Lowe 			                 "" : value->string_mb);
1273*10d63b7dSRichard Lowe 			(void) putenv(env);
1274*10d63b7dSRichard Lowe 			env_prop->body.env_mem.value = env;
1275*10d63b7dSRichard Lowe 			if (sunpro_dependencies_oldbuf) {
1276*10d63b7dSRichard Lowe 				/* Return old buffer */
1277*10d63b7dSRichard Lowe 				retmem_mb(sunpro_dependencies_oldbuf);
1278*10d63b7dSRichard Lowe 				sunpro_dependencies_oldbuf = NULL;
1279*10d63b7dSRichard Lowe 			}
1280*10d63b7dSRichard Lowe 		}
1281*10d63b7dSRichard Lowe 	}
1282*10d63b7dSRichard Lowe 	if (name == target_arch) {
1283*10d63b7dSRichard Lowe 		Name		ha = getvar(host_arch);
1284*10d63b7dSRichard Lowe 		Name		ta = getvar(target_arch);
1285*10d63b7dSRichard Lowe 		Name		vr = getvar(virtual_root);
1286*10d63b7dSRichard Lowe 		int		length;
1287*10d63b7dSRichard Lowe 		wchar_t		*new_value;
1288*10d63b7dSRichard Lowe 		wchar_t		*old_vr;
1289*10d63b7dSRichard Lowe 		Boolean		new_value_allocated = false;
1290*10d63b7dSRichard Lowe 
1291*10d63b7dSRichard Lowe 		Wstring		ha_str(ha);
1292*10d63b7dSRichard Lowe 		Wstring		ta_str(ta);
1293*10d63b7dSRichard Lowe 		Wstring		vr_str(vr);
1294*10d63b7dSRichard Lowe 
1295*10d63b7dSRichard Lowe 		wchar_t * wcb_ha = ha_str.get_string();
1296*10d63b7dSRichard Lowe 		wchar_t * wcb_ta = ta_str.get_string();
1297*10d63b7dSRichard Lowe 		wchar_t * wcb_vr = vr_str.get_string();
1298*10d63b7dSRichard Lowe 
1299*10d63b7dSRichard Lowe 		length = 32 +
1300*10d63b7dSRichard Lowe 		  wcslen(wcb_ha) +
1301*10d63b7dSRichard Lowe 		    wcslen(wcb_ta) +
1302*10d63b7dSRichard Lowe 		      wcslen(wcb_vr);
1303*10d63b7dSRichard Lowe 		old_vr = wcb_vr;
1304*10d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "/usr/arch/");
1305*10d63b7dSRichard Lowe 		if (IS_WEQUALN(old_vr,
1306*10d63b7dSRichard Lowe 			       wcs_buffer,
1307*10d63b7dSRichard Lowe 			       wcslen(wcs_buffer))) {
1308*10d63b7dSRichard Lowe 			old_vr = (wchar_t *) wcschr(old_vr, (int) colon_char) + 1;
1309*10d63b7dSRichard Lowe 		}
1310*10d63b7dSRichard Lowe 		if ( (ha == ta) || (wcslen(wcb_ta) == 0) ) {
1311*10d63b7dSRichard Lowe 			new_value = old_vr;
1312*10d63b7dSRichard Lowe 		} else {
1313*10d63b7dSRichard Lowe 			new_value = ALLOC_WC(length);
1314*10d63b7dSRichard Lowe 			new_value_allocated = true;
1315*10d63b7dSRichard Lowe 			WCSTOMBS(mbs_buffer, old_vr);
1316*10d63b7dSRichard Lowe 			(void) swprintf(new_value, length * SIZEOFWCHAR_T,
1317*10d63b7dSRichard Lowe 				        L"/usr/arch/%s/%s:%s",
1318*10d63b7dSRichard Lowe 				        ha->string_mb + 1,
1319*10d63b7dSRichard Lowe 				        ta->string_mb + 1,
1320*10d63b7dSRichard Lowe 				        mbs_buffer);
1321*10d63b7dSRichard Lowe 		}
1322*10d63b7dSRichard Lowe 		if (new_value[0] != 0) {
1323*10d63b7dSRichard Lowe 			(void) setvar_daemon(virtual_root,
1324*10d63b7dSRichard Lowe 					     GETNAME(new_value, FIND_LENGTH),
1325*10d63b7dSRichard Lowe 					     false,
1326*10d63b7dSRichard Lowe 					     no_daemon,
1327*10d63b7dSRichard Lowe 					     true,
1328*10d63b7dSRichard Lowe 					     debug_level);
1329*10d63b7dSRichard Lowe 		}
1330*10d63b7dSRichard Lowe 		if (new_value_allocated) {
1331*10d63b7dSRichard Lowe 			retmem(new_value);
1332*10d63b7dSRichard Lowe 		}
1333*10d63b7dSRichard Lowe 	}
1334*10d63b7dSRichard Lowe 	return macro;
1335*10d63b7dSRichard Lowe }
1336