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