xref: /illumos-gate/usr/src/cmd/make/lib/mksh/misc.cc (revision 10d63b7d)
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 2004 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  *	misc.cc
29*10d63b7dSRichard Lowe  *
30*10d63b7dSRichard Lowe  *	This file contains various unclassified routines. Some main groups:
31*10d63b7dSRichard Lowe  *		getname
32*10d63b7dSRichard Lowe  *		Memory allocation
33*10d63b7dSRichard Lowe  *		String handling
34*10d63b7dSRichard Lowe  *		Property handling
35*10d63b7dSRichard Lowe  *		Error message handling
36*10d63b7dSRichard Lowe  *		Make internal state dumping
37*10d63b7dSRichard Lowe  *		main routine support
38*10d63b7dSRichard Lowe  */
39*10d63b7dSRichard Lowe 
40*10d63b7dSRichard Lowe /*
41*10d63b7dSRichard Lowe  * Included files
42*10d63b7dSRichard Lowe  */
43*10d63b7dSRichard Lowe #include <bsd/bsd.h>		/* bsd_signal() */
44*10d63b7dSRichard Lowe #include <mksh/i18n.h>		/* get_char_semantics_value() */
45*10d63b7dSRichard Lowe #include <mksh/misc.h>
46*10d63b7dSRichard Lowe #include <stdarg.h>		/* va_list, va_start(), va_end() */
47*10d63b7dSRichard Lowe #include <stdlib.h>		/* mbstowcs() */
48*10d63b7dSRichard Lowe #include <sys/signal.h>		/* SIG_DFL */
49*10d63b7dSRichard Lowe #include <sys/wait.h>		/* wait() */
50*10d63b7dSRichard Lowe 
51*10d63b7dSRichard Lowe #include <string.h>		/* strerror() */
52*10d63b7dSRichard Lowe #include <libintl.h>
53*10d63b7dSRichard Lowe 
54*10d63b7dSRichard Lowe 
55*10d63b7dSRichard Lowe /*
56*10d63b7dSRichard Lowe  * Defined macros
57*10d63b7dSRichard Lowe  */
58*10d63b7dSRichard Lowe 
59*10d63b7dSRichard Lowe /*
60*10d63b7dSRichard Lowe  * typedefs & structs
61*10d63b7dSRichard Lowe  */
62*10d63b7dSRichard Lowe 
63*10d63b7dSRichard Lowe /*
64*10d63b7dSRichard Lowe  * Static variables
65*10d63b7dSRichard Lowe  */
66*10d63b7dSRichard Lowe extern "C" {
67*10d63b7dSRichard Lowe 	void		(*sigivalue)(int) = SIG_DFL;
68*10d63b7dSRichard Lowe 	void		(*sigqvalue)(int) = SIG_DFL;
69*10d63b7dSRichard Lowe 	void		(*sigtvalue)(int) = SIG_DFL;
70*10d63b7dSRichard Lowe 	void		(*sighvalue)(int) = SIG_DFL;
71*10d63b7dSRichard Lowe }
72*10d63b7dSRichard Lowe 
73*10d63b7dSRichard Lowe long	getname_bytes_count = 0;
74*10d63b7dSRichard Lowe long	getname_names_count = 0;
75*10d63b7dSRichard Lowe long	getname_struct_count = 0;
76*10d63b7dSRichard Lowe 
77*10d63b7dSRichard Lowe long	freename_bytes_count = 0;
78*10d63b7dSRichard Lowe long	freename_names_count = 0;
79*10d63b7dSRichard Lowe long	freename_struct_count = 0;
80*10d63b7dSRichard Lowe 
81*10d63b7dSRichard Lowe long	expandstring_count = 0;
82*10d63b7dSRichard Lowe long	getwstring_count = 0;
83*10d63b7dSRichard Lowe 
84*10d63b7dSRichard Lowe /*
85*10d63b7dSRichard Lowe  * File table of contents
86*10d63b7dSRichard Lowe  */
87*10d63b7dSRichard Lowe static void	expand_string(register String string, register int length);
88*10d63b7dSRichard Lowe 
89*10d63b7dSRichard Lowe #define	FATAL_ERROR_MSG_SIZE 200
90*10d63b7dSRichard Lowe 
91*10d63b7dSRichard Lowe /*
92*10d63b7dSRichard Lowe  *	getmem(size)
93*10d63b7dSRichard Lowe  *
94*10d63b7dSRichard Lowe  *	malloc() version that checks the returned value.
95*10d63b7dSRichard Lowe  *
96*10d63b7dSRichard Lowe  *	Return value:
97*10d63b7dSRichard Lowe  *				The memory chunk we allocated
98*10d63b7dSRichard Lowe  *
99*10d63b7dSRichard Lowe  *	Parameters:
100*10d63b7dSRichard Lowe  *		size		The size of the chunk we need
101*10d63b7dSRichard Lowe  *
102*10d63b7dSRichard Lowe  *	Global variables used:
103*10d63b7dSRichard Lowe  */
104*10d63b7dSRichard Lowe char *
105*10d63b7dSRichard Lowe getmem(register int size)
106*10d63b7dSRichard Lowe {
107*10d63b7dSRichard Lowe 	register char          *result = (char *) malloc((unsigned) size);
108*10d63b7dSRichard Lowe 	if (result == NULL) {
109*10d63b7dSRichard Lowe 		char buf[FATAL_ERROR_MSG_SIZE];
110*10d63b7dSRichard Lowe 		sprintf(buf, "*** Error: malloc(%d) failed: %s\n", size, strerror(errno));
111*10d63b7dSRichard Lowe 		strcat(buf, gettext("mksh: Fatal error: Out of memory\n"));
112*10d63b7dSRichard Lowe 		fputs(buf, stderr);
113*10d63b7dSRichard Lowe 		exit_status = 1;
114*10d63b7dSRichard Lowe 		exit(1);
115*10d63b7dSRichard Lowe 	}
116*10d63b7dSRichard Lowe 	return result;
117*10d63b7dSRichard Lowe }
118*10d63b7dSRichard Lowe 
119*10d63b7dSRichard Lowe /*
120*10d63b7dSRichard Lowe  *	retmem(p)
121*10d63b7dSRichard Lowe  *
122*10d63b7dSRichard Lowe  *	Cover funtion for free() to make it possible to insert advises.
123*10d63b7dSRichard Lowe  *
124*10d63b7dSRichard Lowe  *	Parameters:
125*10d63b7dSRichard Lowe  *		p		The memory block to free
126*10d63b7dSRichard Lowe  *
127*10d63b7dSRichard Lowe  *	Global variables used:
128*10d63b7dSRichard Lowe  */
129*10d63b7dSRichard Lowe void
130*10d63b7dSRichard Lowe retmem(wchar_t *p)
131*10d63b7dSRichard Lowe {
132*10d63b7dSRichard Lowe 	(void) free((char *) p);
133*10d63b7dSRichard Lowe }
134*10d63b7dSRichard Lowe 
135*10d63b7dSRichard Lowe void
136*10d63b7dSRichard Lowe retmem_mb(caddr_t p)
137*10d63b7dSRichard Lowe {
138*10d63b7dSRichard Lowe 	(void) free(p);
139*10d63b7dSRichard Lowe }
140*10d63b7dSRichard Lowe 
141*10d63b7dSRichard Lowe /*
142*10d63b7dSRichard Lowe  *	getname_fn(name, len, dont_enter)
143*10d63b7dSRichard Lowe  *
144*10d63b7dSRichard Lowe  *	Hash a name string to the corresponding nameblock.
145*10d63b7dSRichard Lowe  *
146*10d63b7dSRichard Lowe  *	Return value:
147*10d63b7dSRichard Lowe  *				The Name block for the string
148*10d63b7dSRichard Lowe  *
149*10d63b7dSRichard Lowe  *	Parameters:
150*10d63b7dSRichard Lowe  *		name		The string we want to internalize
151*10d63b7dSRichard Lowe  *		len		The length of that string
152*10d63b7dSRichard Lowe  *		dont_enter	Don't enter the name if it does not exist
153*10d63b7dSRichard Lowe  *
154*10d63b7dSRichard Lowe  *	Global variables used:
155*10d63b7dSRichard Lowe  *		funny		The vector of semantic tags for characters
156*10d63b7dSRichard Lowe  *		hashtab		The hashtable used for the nametable
157*10d63b7dSRichard Lowe  */
158*10d63b7dSRichard Lowe Name
159*10d63b7dSRichard Lowe getname_fn(wchar_t *name, register int len, register Boolean dont_enter, register Boolean * foundp)
160*10d63b7dSRichard Lowe {
161*10d63b7dSRichard Lowe 	register int		length;
162*10d63b7dSRichard Lowe 	register wchar_t	*cap = name;
163*10d63b7dSRichard Lowe 	register Name		np;
164*10d63b7dSRichard Lowe 	static Name_rec		empty_Name;
165*10d63b7dSRichard Lowe 	char			*tmp_mbs_buffer = NULL;
166*10d63b7dSRichard Lowe 	char			*mbs_name = mbs_buffer;
167*10d63b7dSRichard Lowe 
168*10d63b7dSRichard Lowe 	/*
169*10d63b7dSRichard Lowe 	 * First figure out how long the string is.
170*10d63b7dSRichard Lowe 	 * If the len argument is -1 we count the chars here.
171*10d63b7dSRichard Lowe 	 */
172*10d63b7dSRichard Lowe 	if (len == FIND_LENGTH) {
173*10d63b7dSRichard Lowe 		length = wcslen(name);
174*10d63b7dSRichard Lowe 	} else {
175*10d63b7dSRichard Lowe 		length = len;
176*10d63b7dSRichard Lowe 	}
177*10d63b7dSRichard Lowe 
178*10d63b7dSRichard Lowe 	Wstring ws;
179*10d63b7dSRichard Lowe 	ws.init(name, length);
180*10d63b7dSRichard Lowe 	if (length >= MAXPATHLEN) {
181*10d63b7dSRichard Lowe 		mbs_name = tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
182*10d63b7dSRichard Lowe 	}
183*10d63b7dSRichard Lowe 	(void) wcstombs(mbs_name, ws.get_string(), (length * MB_LEN_MAX) + 1);
184*10d63b7dSRichard Lowe 
185*10d63b7dSRichard Lowe 	/* Look for the string */
186*10d63b7dSRichard Lowe 	if (dont_enter || (foundp != 0)) {
187*10d63b7dSRichard Lowe 		np = hashtab.lookup(mbs_name);
188*10d63b7dSRichard Lowe 		if (foundp != 0) {
189*10d63b7dSRichard Lowe 			*foundp = (np != 0) ? true : false;
190*10d63b7dSRichard Lowe 		}
191*10d63b7dSRichard Lowe 		if ((np != 0) || dont_enter) {
192*10d63b7dSRichard Lowe 			if(tmp_mbs_buffer != NULL) {
193*10d63b7dSRichard Lowe 				retmem_mb(tmp_mbs_buffer);
194*10d63b7dSRichard Lowe 			}
195*10d63b7dSRichard Lowe 			return np;
196*10d63b7dSRichard Lowe 		} else {
197*10d63b7dSRichard Lowe 			np = ALLOC(Name);
198*10d63b7dSRichard Lowe 		}
199*10d63b7dSRichard Lowe 	} else {
200*10d63b7dSRichard Lowe 		Boolean found;
201*10d63b7dSRichard Lowe 		np = hashtab.insert(mbs_name, found);
202*10d63b7dSRichard Lowe 		if (found) {
203*10d63b7dSRichard Lowe 			if(tmp_mbs_buffer != NULL) {
204*10d63b7dSRichard Lowe 				retmem_mb(tmp_mbs_buffer);
205*10d63b7dSRichard Lowe 			}
206*10d63b7dSRichard Lowe 			return np;
207*10d63b7dSRichard Lowe 		}
208*10d63b7dSRichard Lowe 	}
209*10d63b7dSRichard Lowe 	getname_struct_count += sizeof(struct _Name);
210*10d63b7dSRichard Lowe 	*np = empty_Name;
211*10d63b7dSRichard Lowe 
212*10d63b7dSRichard Lowe 	np->string_mb = strdup(mbs_name);
213*10d63b7dSRichard Lowe 	if(tmp_mbs_buffer != NULL) {
214*10d63b7dSRichard Lowe 		retmem_mb(tmp_mbs_buffer);
215*10d63b7dSRichard Lowe 		mbs_name = tmp_mbs_buffer = NULL;
216*10d63b7dSRichard Lowe 	}
217*10d63b7dSRichard Lowe 	getname_bytes_count += strlen(np->string_mb) + 1;
218*10d63b7dSRichard Lowe 	/* Fill in the new Name */
219*10d63b7dSRichard Lowe 	np->stat.time = file_no_time;
220*10d63b7dSRichard Lowe 	np->hash.length = length;
221*10d63b7dSRichard Lowe 	/* Scan the namestring to classify it */
222*10d63b7dSRichard Lowe 	for (cap = name, len = 0; --length >= 0;) {
223*10d63b7dSRichard Lowe 		len |= get_char_semantics_value(*cap++);
224*10d63b7dSRichard Lowe 	}
225*10d63b7dSRichard Lowe 	np->dollar = BOOLEAN((len & (int) dollar_sem) != 0);
226*10d63b7dSRichard Lowe 	np->meta = BOOLEAN((len & (int) meta_sem) != 0);
227*10d63b7dSRichard Lowe 	np->percent = BOOLEAN((len & (int) percent_sem) != 0);
228*10d63b7dSRichard Lowe 	np->wildcard = BOOLEAN((len & (int) wildcard_sem) != 0);
229*10d63b7dSRichard Lowe 	np->colon = BOOLEAN((len & (int) colon_sem) != 0);
230*10d63b7dSRichard Lowe 	np->parenleft = BOOLEAN((len & (int) parenleft_sem) != 0);
231*10d63b7dSRichard Lowe 	getname_names_count++;
232*10d63b7dSRichard Lowe 	return np;
233*10d63b7dSRichard Lowe }
234*10d63b7dSRichard Lowe 
235*10d63b7dSRichard Lowe void
236*10d63b7dSRichard Lowe store_name(Name name)
237*10d63b7dSRichard Lowe {
238*10d63b7dSRichard Lowe 	hashtab.insert(name);
239*10d63b7dSRichard Lowe }
240*10d63b7dSRichard Lowe 
241*10d63b7dSRichard Lowe void
242*10d63b7dSRichard Lowe free_name(Name name)
243*10d63b7dSRichard Lowe {
244*10d63b7dSRichard Lowe 	freename_names_count++;
245*10d63b7dSRichard Lowe 	freename_struct_count += sizeof(struct _Name);
246*10d63b7dSRichard Lowe 	freename_bytes_count += strlen(name->string_mb) + 1;
247*10d63b7dSRichard Lowe 	retmem_mb(name->string_mb);
248*10d63b7dSRichard Lowe 	for (Property next, p = name->prop; p != NULL; p = next) {
249*10d63b7dSRichard Lowe 		next = p->next;
250*10d63b7dSRichard Lowe 		free(p);
251*10d63b7dSRichard Lowe 	}
252*10d63b7dSRichard Lowe 	free(name);
253*10d63b7dSRichard Lowe }
254*10d63b7dSRichard Lowe 
255*10d63b7dSRichard Lowe /*
256*10d63b7dSRichard Lowe  *	enable_interrupt(handler)
257*10d63b7dSRichard Lowe  *
258*10d63b7dSRichard Lowe  *	This routine sets a new interrupt handler for the signals make
259*10d63b7dSRichard Lowe  *	wants to deal with.
260*10d63b7dSRichard Lowe  *
261*10d63b7dSRichard Lowe  *	Parameters:
262*10d63b7dSRichard Lowe  *		handler		The function installed as interrupt handler
263*10d63b7dSRichard Lowe  *
264*10d63b7dSRichard Lowe  *	Static variables used:
265*10d63b7dSRichard Lowe  *		sigivalue	The original signal handler
266*10d63b7dSRichard Lowe  *		sigqvalue	The original signal handler
267*10d63b7dSRichard Lowe  *		sigtvalue	The original signal handler
268*10d63b7dSRichard Lowe  *		sighvalue	The original signal handler
269*10d63b7dSRichard Lowe  */
270*10d63b7dSRichard Lowe void
271*10d63b7dSRichard Lowe enable_interrupt(register void (*handler) (int))
272*10d63b7dSRichard Lowe {
273*10d63b7dSRichard Lowe 	if (sigivalue != SIG_IGN) {
274*10d63b7dSRichard Lowe 		(void) bsd_signal(SIGINT, (SIG_PF) handler);
275*10d63b7dSRichard Lowe 	}
276*10d63b7dSRichard Lowe 	if (sigqvalue != SIG_IGN) {
277*10d63b7dSRichard Lowe 		(void) bsd_signal(SIGQUIT, (SIG_PF) handler);
278*10d63b7dSRichard Lowe 	}
279*10d63b7dSRichard Lowe 	if (sigtvalue != SIG_IGN) {
280*10d63b7dSRichard Lowe 		(void) bsd_signal(SIGTERM, (SIG_PF) handler);
281*10d63b7dSRichard Lowe 	}
282*10d63b7dSRichard Lowe 	if (sighvalue != SIG_IGN) {
283*10d63b7dSRichard Lowe 		(void) bsd_signal(SIGHUP, (SIG_PF) handler);
284*10d63b7dSRichard Lowe 	}
285*10d63b7dSRichard Lowe }
286*10d63b7dSRichard Lowe 
287*10d63b7dSRichard Lowe /*
288*10d63b7dSRichard Lowe  *	setup_char_semantics()
289*10d63b7dSRichard Lowe  *
290*10d63b7dSRichard Lowe  *	Load the vector char_semantics[] with lexical markers
291*10d63b7dSRichard Lowe  *
292*10d63b7dSRichard Lowe  *	Parameters:
293*10d63b7dSRichard Lowe  *
294*10d63b7dSRichard Lowe  *	Global variables used:
295*10d63b7dSRichard Lowe  *		char_semantics	The vector of character semantics that we set
296*10d63b7dSRichard Lowe  */
297*10d63b7dSRichard Lowe void
298*10d63b7dSRichard Lowe setup_char_semantics(void)
299*10d63b7dSRichard Lowe {
300*10d63b7dSRichard Lowe 	const char	*s;
301*10d63b7dSRichard Lowe 	wchar_t		wc_buffer[1];
302*10d63b7dSRichard Lowe 	int		entry;
303*10d63b7dSRichard Lowe 
304*10d63b7dSRichard Lowe 	if (svr4) {
305*10d63b7dSRichard Lowe 		s = "@-";
306*10d63b7dSRichard Lowe 	} else {
307*10d63b7dSRichard Lowe 		s = "=@-?!+";
308*10d63b7dSRichard Lowe 	}
309*10d63b7dSRichard Lowe 	for (s; MBTOWC(wc_buffer, s); s++) {
310*10d63b7dSRichard Lowe 		entry = get_char_semantics_entry(*wc_buffer);
311*10d63b7dSRichard Lowe 		char_semantics[entry] |= (int) command_prefix_sem;
312*10d63b7dSRichard Lowe 	}
313*10d63b7dSRichard Lowe 	char_semantics[dollar_char_entry] |= (int) dollar_sem;
314*10d63b7dSRichard Lowe 	for (s = "#|=^();&<>*?[]:$`'\"\\\n"; MBTOWC(wc_buffer, s); s++) {
315*10d63b7dSRichard Lowe 		entry = get_char_semantics_entry(*wc_buffer);
316*10d63b7dSRichard Lowe 		char_semantics[entry] |= (int) meta_sem;
317*10d63b7dSRichard Lowe 	}
318*10d63b7dSRichard Lowe 	char_semantics[percent_char_entry] |= (int) percent_sem;
319*10d63b7dSRichard Lowe 	for (s = "@*<%?^"; MBTOWC(wc_buffer, s); s++) {
320*10d63b7dSRichard Lowe 		entry = get_char_semantics_entry(*wc_buffer);
321*10d63b7dSRichard Lowe 		char_semantics[entry] |= (int) special_macro_sem;
322*10d63b7dSRichard Lowe 	}
323*10d63b7dSRichard Lowe 	for (s = "?[*"; MBTOWC(wc_buffer, s); s++) {
324*10d63b7dSRichard Lowe 		entry = get_char_semantics_entry(*wc_buffer);
325*10d63b7dSRichard Lowe 		char_semantics[entry] |= (int) wildcard_sem;
326*10d63b7dSRichard Lowe 	}
327*10d63b7dSRichard Lowe 	char_semantics[colon_char_entry] |= (int) colon_sem;
328*10d63b7dSRichard Lowe 	char_semantics[parenleft_char_entry] |= (int) parenleft_sem;
329*10d63b7dSRichard Lowe }
330*10d63b7dSRichard Lowe 
331*10d63b7dSRichard Lowe /*
332*10d63b7dSRichard Lowe  *	errmsg(errnum)
333*10d63b7dSRichard Lowe  *
334*10d63b7dSRichard Lowe  *	Return the error message for a system call error
335*10d63b7dSRichard Lowe  *
336*10d63b7dSRichard Lowe  *	Return value:
337*10d63b7dSRichard Lowe  *				An error message string
338*10d63b7dSRichard Lowe  *
339*10d63b7dSRichard Lowe  *	Parameters:
340*10d63b7dSRichard Lowe  *		errnum		The number of the error we want to describe
341*10d63b7dSRichard Lowe  *
342*10d63b7dSRichard Lowe  *	Global variables used:
343*10d63b7dSRichard Lowe  *		sys_errlist	A vector of error messages
344*10d63b7dSRichard Lowe  *		sys_nerr	The size of sys_errlist
345*10d63b7dSRichard Lowe  */
346*10d63b7dSRichard Lowe char *
347*10d63b7dSRichard Lowe errmsg(int errnum)
348*10d63b7dSRichard Lowe {
349*10d63b7dSRichard Lowe 
350*10d63b7dSRichard Lowe 	extern int		sys_nerr;
351*10d63b7dSRichard Lowe 	char			*errbuf;
352*10d63b7dSRichard Lowe 
353*10d63b7dSRichard Lowe 	if ((errnum < 0) || (errnum > sys_nerr)) {
354*10d63b7dSRichard Lowe 		errbuf = getmem(6+1+11+1);
355*10d63b7dSRichard Lowe 		(void) sprintf(errbuf, gettext("Error %d"), errnum);
356*10d63b7dSRichard Lowe 		return errbuf;
357*10d63b7dSRichard Lowe 	} else {
358*10d63b7dSRichard Lowe 		return strerror(errnum);
359*10d63b7dSRichard Lowe 
360*10d63b7dSRichard Lowe 	}
361*10d63b7dSRichard Lowe }
362*10d63b7dSRichard Lowe 
363*10d63b7dSRichard Lowe static char static_buf[MAXPATHLEN*3];
364*10d63b7dSRichard Lowe 
365*10d63b7dSRichard Lowe /*
366*10d63b7dSRichard Lowe  *	fatal_mksh(format, args...)
367*10d63b7dSRichard Lowe  *
368*10d63b7dSRichard Lowe  *	Print a message and die
369*10d63b7dSRichard Lowe  *
370*10d63b7dSRichard Lowe  *	Parameters:
371*10d63b7dSRichard Lowe  *		format		printf type format string
372*10d63b7dSRichard Lowe  *		args		Arguments to match the format
373*10d63b7dSRichard Lowe  */
374*10d63b7dSRichard Lowe /*VARARGS*/
375*10d63b7dSRichard Lowe void
376*10d63b7dSRichard Lowe fatal_mksh(const char *message, ...)
377*10d63b7dSRichard Lowe {
378*10d63b7dSRichard Lowe 	va_list args;
379*10d63b7dSRichard Lowe 	char    *buf = static_buf;
380*10d63b7dSRichard Lowe 	char	*mksh_fat_err = gettext("mksh: Fatal error: ");
381*10d63b7dSRichard Lowe 	char	*cur_wrk_dir = gettext("Current working directory: ");
382*10d63b7dSRichard Lowe 	int	mksh_fat_err_len = strlen(mksh_fat_err);
383*10d63b7dSRichard Lowe 
384*10d63b7dSRichard Lowe 	va_start(args, message);
385*10d63b7dSRichard Lowe 	(void) fflush(stdout);
386*10d63b7dSRichard Lowe 	(void) strcpy(buf, mksh_fat_err);
387*10d63b7dSRichard Lowe 	size_t buf_len = vsnprintf(static_buf + mksh_fat_err_len,
388*10d63b7dSRichard Lowe 				   sizeof(static_buf) - mksh_fat_err_len,
389*10d63b7dSRichard Lowe 				   message, args)
390*10d63b7dSRichard Lowe 			+ mksh_fat_err_len
391*10d63b7dSRichard Lowe 			+ strlen(cur_wrk_dir)
392*10d63b7dSRichard Lowe 			+ strlen(get_current_path_mksh())
393*10d63b7dSRichard Lowe 			+ 3; // "\n\n"
394*10d63b7dSRichard Lowe 	va_end(args);
395*10d63b7dSRichard Lowe 	if (buf_len >= sizeof(static_buf)) {
396*10d63b7dSRichard Lowe 		buf = getmem(buf_len);
397*10d63b7dSRichard Lowe 		(void) strcpy(buf, mksh_fat_err);
398*10d63b7dSRichard Lowe 		va_start(args, message);
399*10d63b7dSRichard Lowe 		(void) vsprintf(buf + mksh_fat_err_len, message, args);
400*10d63b7dSRichard Lowe 		va_end(args);
401*10d63b7dSRichard Lowe 	}
402*10d63b7dSRichard Lowe 	(void) strcat(buf, "\n");
403*10d63b7dSRichard Lowe /*
404*10d63b7dSRichard Lowe 	if (report_pwd) {
405*10d63b7dSRichard Lowe  */
406*10d63b7dSRichard Lowe 	if (1) {
407*10d63b7dSRichard Lowe 		(void) strcat(buf, cur_wrk_dir);
408*10d63b7dSRichard Lowe 		(void) strcat(buf, get_current_path_mksh());
409*10d63b7dSRichard Lowe 		(void) strcat(buf, "\n");
410*10d63b7dSRichard Lowe 	}
411*10d63b7dSRichard Lowe 	(void) fputs(buf, stderr);
412*10d63b7dSRichard Lowe 	(void) fflush(stderr);
413*10d63b7dSRichard Lowe 	if (buf != static_buf) {
414*10d63b7dSRichard Lowe 		retmem_mb(buf);
415*10d63b7dSRichard Lowe 	}
416*10d63b7dSRichard Lowe 	exit_status = 1;
417*10d63b7dSRichard Lowe 	exit(1);
418*10d63b7dSRichard Lowe }
419*10d63b7dSRichard Lowe 
420*10d63b7dSRichard Lowe /*
421*10d63b7dSRichard Lowe  *	fatal_reader_mksh(format, args...)
422*10d63b7dSRichard Lowe  *
423*10d63b7dSRichard Lowe  *	Parameters:
424*10d63b7dSRichard Lowe  *		format		printf style format string
425*10d63b7dSRichard Lowe  *		args		arguments to match the format
426*10d63b7dSRichard Lowe  */
427*10d63b7dSRichard Lowe /*VARARGS*/
428*10d63b7dSRichard Lowe void
429*10d63b7dSRichard Lowe fatal_reader_mksh(const char * pattern, ...)
430*10d63b7dSRichard Lowe {
431*10d63b7dSRichard Lowe 	va_list args;
432*10d63b7dSRichard Lowe 	char	message[1000];
433*10d63b7dSRichard Lowe 
434*10d63b7dSRichard Lowe 	va_start(args, pattern);
435*10d63b7dSRichard Lowe /*
436*10d63b7dSRichard Lowe 	if (file_being_read != NULL) {
437*10d63b7dSRichard Lowe 		WCSTOMBS(mbs_buffer, file_being_read);
438*10d63b7dSRichard Lowe 		if (line_number != 0) {
439*10d63b7dSRichard Lowe 			(void) sprintf(message,
440*10d63b7dSRichard Lowe 				       gettext("%s, line %d: %s"),
441*10d63b7dSRichard Lowe 				       mbs_buffer,
442*10d63b7dSRichard Lowe 				       line_number,
443*10d63b7dSRichard Lowe 				       pattern);
444*10d63b7dSRichard Lowe 		} else {
445*10d63b7dSRichard Lowe 			(void) sprintf(message,
446*10d63b7dSRichard Lowe 				       "%s: %s",
447*10d63b7dSRichard Lowe 				       mbs_buffer,
448*10d63b7dSRichard Lowe 				       pattern);
449*10d63b7dSRichard Lowe 		}
450*10d63b7dSRichard Lowe 		pattern = message;
451*10d63b7dSRichard Lowe 	}
452*10d63b7dSRichard Lowe  */
453*10d63b7dSRichard Lowe 
454*10d63b7dSRichard Lowe 	(void) fflush(stdout);
455*10d63b7dSRichard Lowe 	(void) fprintf(stderr, gettext("mksh: Fatal error in reader: "));
456*10d63b7dSRichard Lowe 	(void) vfprintf(stderr, pattern, args);
457*10d63b7dSRichard Lowe 	(void) fprintf(stderr, "\n");
458*10d63b7dSRichard Lowe 	va_end(args);
459*10d63b7dSRichard Lowe 
460*10d63b7dSRichard Lowe /*
461*10d63b7dSRichard Lowe 	if (temp_file_name != NULL) {
462*10d63b7dSRichard Lowe 		(void) fprintf(stderr,
463*10d63b7dSRichard Lowe 			       gettext("mksh: Temp-file %s not removed\n"),
464*10d63b7dSRichard Lowe 			       temp_file_name->string_mb);
465*10d63b7dSRichard Lowe 		temp_file_name = NULL;
466*10d63b7dSRichard Lowe 	}
467*10d63b7dSRichard Lowe  */
468*10d63b7dSRichard Lowe 
469*10d63b7dSRichard Lowe /*
470*10d63b7dSRichard Lowe 	if (report_pwd) {
471*10d63b7dSRichard Lowe  */
472*10d63b7dSRichard Lowe 	if (1) {
473*10d63b7dSRichard Lowe 		(void) fprintf(stderr,
474*10d63b7dSRichard Lowe 			       gettext("Current working directory %s\n"),
475*10d63b7dSRichard Lowe 			       get_current_path_mksh());
476*10d63b7dSRichard Lowe 	}
477*10d63b7dSRichard Lowe 	(void) fflush(stderr);
478*10d63b7dSRichard Lowe 	exit_status = 1;
479*10d63b7dSRichard Lowe 	exit(1);
480*10d63b7dSRichard Lowe }
481*10d63b7dSRichard Lowe 
482*10d63b7dSRichard Lowe /*
483*10d63b7dSRichard Lowe  *	warning_mksh(format, args...)
484*10d63b7dSRichard Lowe  *
485*10d63b7dSRichard Lowe  *	Print a message and continue.
486*10d63b7dSRichard Lowe  *
487*10d63b7dSRichard Lowe  *	Parameters:
488*10d63b7dSRichard Lowe  *		format		printf type format string
489*10d63b7dSRichard Lowe  *		args		Arguments to match the format
490*10d63b7dSRichard Lowe  */
491*10d63b7dSRichard Lowe /*VARARGS*/
492*10d63b7dSRichard Lowe void
493*10d63b7dSRichard Lowe warning_mksh(char * message, ...)
494*10d63b7dSRichard Lowe {
495*10d63b7dSRichard Lowe 	va_list args;
496*10d63b7dSRichard Lowe 
497*10d63b7dSRichard Lowe 	va_start(args, message);
498*10d63b7dSRichard Lowe 	(void) fflush(stdout);
499*10d63b7dSRichard Lowe 	(void) fprintf(stderr, gettext("mksh: Warning: "));
500*10d63b7dSRichard Lowe 	(void) vfprintf(stderr, message, args);
501*10d63b7dSRichard Lowe 	(void) fprintf(stderr, "\n");
502*10d63b7dSRichard Lowe 	va_end(args);
503*10d63b7dSRichard Lowe /*
504*10d63b7dSRichard Lowe 	if (report_pwd) {
505*10d63b7dSRichard Lowe  */
506*10d63b7dSRichard Lowe 	if (1) {
507*10d63b7dSRichard Lowe 		(void) fprintf(stderr,
508*10d63b7dSRichard Lowe 			       gettext("Current working directory %s\n"),
509*10d63b7dSRichard Lowe 			       get_current_path_mksh());
510*10d63b7dSRichard Lowe 	}
511*10d63b7dSRichard Lowe 	(void) fflush(stderr);
512*10d63b7dSRichard Lowe }
513*10d63b7dSRichard Lowe 
514*10d63b7dSRichard Lowe /*
515*10d63b7dSRichard Lowe  *	get_current_path_mksh()
516*10d63b7dSRichard Lowe  *
517*10d63b7dSRichard Lowe  *	Stuff current_path with the current path if it isnt there already.
518*10d63b7dSRichard Lowe  *
519*10d63b7dSRichard Lowe  *	Parameters:
520*10d63b7dSRichard Lowe  *
521*10d63b7dSRichard Lowe  *	Global variables used:
522*10d63b7dSRichard Lowe  */
523*10d63b7dSRichard Lowe char *
524*10d63b7dSRichard Lowe get_current_path_mksh(void)
525*10d63b7dSRichard Lowe {
526*10d63b7dSRichard Lowe 	char			pwd[(MAXPATHLEN * MB_LEN_MAX)];
527*10d63b7dSRichard Lowe 	static char		*current_path;
528*10d63b7dSRichard Lowe 
529*10d63b7dSRichard Lowe 	if (current_path == NULL) {
530*10d63b7dSRichard Lowe 		getcwd(pwd, sizeof(pwd));
531*10d63b7dSRichard Lowe 		if (pwd[0] == (int) nul_char) {
532*10d63b7dSRichard Lowe 			pwd[0] = (int) slash_char;
533*10d63b7dSRichard Lowe 			pwd[1] = (int) nul_char;
534*10d63b7dSRichard Lowe 		}
535*10d63b7dSRichard Lowe 		current_path = strdup(pwd);
536*10d63b7dSRichard Lowe 	}
537*10d63b7dSRichard Lowe 	return current_path;
538*10d63b7dSRichard Lowe }
539*10d63b7dSRichard Lowe 
540*10d63b7dSRichard Lowe /*
541*10d63b7dSRichard Lowe  *	append_prop(target, type)
542*10d63b7dSRichard Lowe  *
543*10d63b7dSRichard Lowe  *	Create a new property and append it to the property list of a Name.
544*10d63b7dSRichard Lowe  *
545*10d63b7dSRichard Lowe  *	Return value:
546*10d63b7dSRichard Lowe  *				A new property block for the target
547*10d63b7dSRichard Lowe  *
548*10d63b7dSRichard Lowe  *	Parameters:
549*10d63b7dSRichard Lowe  *		target		The target that wants a new property
550*10d63b7dSRichard Lowe  *		type		The type of property being requested
551*10d63b7dSRichard Lowe  *
552*10d63b7dSRichard Lowe  *	Global variables used:
553*10d63b7dSRichard Lowe  */
554*10d63b7dSRichard Lowe Property
555*10d63b7dSRichard Lowe append_prop(register Name target, register Property_id type)
556*10d63b7dSRichard Lowe {
557*10d63b7dSRichard Lowe 	register Property	*insert = &target->prop;
558*10d63b7dSRichard Lowe 	register Property	prop = *insert;
559*10d63b7dSRichard Lowe 	register int		size;
560*10d63b7dSRichard Lowe 
561*10d63b7dSRichard Lowe 	switch (type) {
562*10d63b7dSRichard Lowe 	case conditional_prop:
563*10d63b7dSRichard Lowe 		size = sizeof (struct Conditional);
564*10d63b7dSRichard Lowe 		break;
565*10d63b7dSRichard Lowe 	case line_prop:
566*10d63b7dSRichard Lowe 		size = sizeof (struct Line);
567*10d63b7dSRichard Lowe 		break;
568*10d63b7dSRichard Lowe 	case macro_prop:
569*10d63b7dSRichard Lowe 		size = sizeof (struct _Macro);
570*10d63b7dSRichard Lowe 		break;
571*10d63b7dSRichard Lowe 	case makefile_prop:
572*10d63b7dSRichard Lowe 		size = sizeof (struct Makefile);
573*10d63b7dSRichard Lowe 		break;
574*10d63b7dSRichard Lowe 	case member_prop:
575*10d63b7dSRichard Lowe 		size = sizeof (struct Member);
576*10d63b7dSRichard Lowe 		break;
577*10d63b7dSRichard Lowe 	case recursive_prop:
578*10d63b7dSRichard Lowe 		size = sizeof (struct Recursive);
579*10d63b7dSRichard Lowe 		break;
580*10d63b7dSRichard Lowe 	case sccs_prop:
581*10d63b7dSRichard Lowe 		size = sizeof (struct Sccs);
582*10d63b7dSRichard Lowe 		break;
583*10d63b7dSRichard Lowe 	case suffix_prop:
584*10d63b7dSRichard Lowe 		size = sizeof (struct Suffix);
585*10d63b7dSRichard Lowe 		break;
586*10d63b7dSRichard Lowe 	case target_prop:
587*10d63b7dSRichard Lowe 		size = sizeof (struct Target);
588*10d63b7dSRichard Lowe 		break;
589*10d63b7dSRichard Lowe 	case time_prop:
590*10d63b7dSRichard Lowe 		size = sizeof (struct STime);
591*10d63b7dSRichard Lowe 		break;
592*10d63b7dSRichard Lowe 	case vpath_alias_prop:
593*10d63b7dSRichard Lowe 		size = sizeof (struct Vpath_alias);
594*10d63b7dSRichard Lowe 		break;
595*10d63b7dSRichard Lowe 	case long_member_name_prop:
596*10d63b7dSRichard Lowe 		size = sizeof (struct Long_member_name);
597*10d63b7dSRichard Lowe 		break;
598*10d63b7dSRichard Lowe 	case macro_append_prop:
599*10d63b7dSRichard Lowe 		size = sizeof (struct _Macro_appendix);
600*10d63b7dSRichard Lowe 		break;
601*10d63b7dSRichard Lowe 	case env_mem_prop:
602*10d63b7dSRichard Lowe 		size = sizeof (struct _Env_mem);
603*10d63b7dSRichard Lowe 		break;
604*10d63b7dSRichard Lowe 	default:
605*10d63b7dSRichard Lowe 		fatal_mksh(gettext("Internal error. Unknown prop type %d"), type);
606*10d63b7dSRichard Lowe 	}
607*10d63b7dSRichard Lowe 	for (; prop != NULL; insert = &prop->next, prop = *insert);
608*10d63b7dSRichard Lowe 	size += PROPERTY_HEAD_SIZE;
609*10d63b7dSRichard Lowe 	*insert = prop = (Property) getmem(size);
610*10d63b7dSRichard Lowe 	memset((char *) prop, 0, size);
611*10d63b7dSRichard Lowe 	prop->type = type;
612*10d63b7dSRichard Lowe 	prop->next = NULL;
613*10d63b7dSRichard Lowe 	return prop;
614*10d63b7dSRichard Lowe }
615*10d63b7dSRichard Lowe 
616*10d63b7dSRichard Lowe /*
617*10d63b7dSRichard Lowe  *	maybe_append_prop(target, type)
618*10d63b7dSRichard Lowe  *
619*10d63b7dSRichard Lowe  *	Append a property to the Name if none of this type exists
620*10d63b7dSRichard Lowe  *	else return the one already there
621*10d63b7dSRichard Lowe  *
622*10d63b7dSRichard Lowe  *	Return value:
623*10d63b7dSRichard Lowe  *				A property of the requested type for the target
624*10d63b7dSRichard Lowe  *
625*10d63b7dSRichard Lowe  *	Parameters:
626*10d63b7dSRichard Lowe  *		target		The target that wants a new property
627*10d63b7dSRichard Lowe  *		type		The type of property being requested
628*10d63b7dSRichard Lowe  *
629*10d63b7dSRichard Lowe  *	Global variables used:
630*10d63b7dSRichard Lowe  */
631*10d63b7dSRichard Lowe Property
632*10d63b7dSRichard Lowe maybe_append_prop(register Name target, register Property_id type)
633*10d63b7dSRichard Lowe {
634*10d63b7dSRichard Lowe 	register Property	prop;
635*10d63b7dSRichard Lowe 
636*10d63b7dSRichard Lowe 	if ((prop = get_prop(target->prop, type)) != NULL) {
637*10d63b7dSRichard Lowe 		return prop;
638*10d63b7dSRichard Lowe 	}
639*10d63b7dSRichard Lowe 	return append_prop(target, type);
640*10d63b7dSRichard Lowe }
641*10d63b7dSRichard Lowe 
642*10d63b7dSRichard Lowe /*
643*10d63b7dSRichard Lowe  *	get_prop(start, type)
644*10d63b7dSRichard Lowe  *
645*10d63b7dSRichard Lowe  *	Scan the property list of a Name to find the next property
646*10d63b7dSRichard Lowe  *	of a given type.
647*10d63b7dSRichard Lowe  *
648*10d63b7dSRichard Lowe  *	Return value:
649*10d63b7dSRichard Lowe  *				The first property of the type, if any left
650*10d63b7dSRichard Lowe  *
651*10d63b7dSRichard Lowe  *	Parameters:
652*10d63b7dSRichard Lowe  *		start		The first property block to check for type
653*10d63b7dSRichard Lowe  *		type		The type of property block we need
654*10d63b7dSRichard Lowe  *
655*10d63b7dSRichard Lowe  *	Global variables used:
656*10d63b7dSRichard Lowe  */
657*10d63b7dSRichard Lowe Property
658*10d63b7dSRichard Lowe get_prop(register Property start, register Property_id type)
659*10d63b7dSRichard Lowe {
660*10d63b7dSRichard Lowe 	for (; start != NULL; start = start->next) {
661*10d63b7dSRichard Lowe 		if (start->type == type) {
662*10d63b7dSRichard Lowe 			return start;
663*10d63b7dSRichard Lowe 		}
664*10d63b7dSRichard Lowe 	}
665*10d63b7dSRichard Lowe 	return NULL;
666*10d63b7dSRichard Lowe }
667*10d63b7dSRichard Lowe 
668*10d63b7dSRichard Lowe /*
669*10d63b7dSRichard Lowe  *	append_string(from, to, length)
670*10d63b7dSRichard Lowe  *
671*10d63b7dSRichard Lowe  *	Append a C string to a make string expanding it if nessecary
672*10d63b7dSRichard Lowe  *
673*10d63b7dSRichard Lowe  *	Parameters:
674*10d63b7dSRichard Lowe  *		from		The source (C style) string
675*10d63b7dSRichard Lowe  *		to		The destination (make style) string
676*10d63b7dSRichard Lowe  *		length		The length of the from string
677*10d63b7dSRichard Lowe  *
678*10d63b7dSRichard Lowe  *	Global variables used:
679*10d63b7dSRichard Lowe  */
680*10d63b7dSRichard Lowe void
681*10d63b7dSRichard Lowe append_string(register wchar_t *from, register String to, register int length)
682*10d63b7dSRichard Lowe {
683*10d63b7dSRichard Lowe 	if (length == FIND_LENGTH) {
684*10d63b7dSRichard Lowe 		length = wcslen(from);
685*10d63b7dSRichard Lowe 	}
686*10d63b7dSRichard Lowe 	if (to->buffer.start == NULL) {
687*10d63b7dSRichard Lowe 		expand_string(to, 32 + length);
688*10d63b7dSRichard Lowe 	}
689*10d63b7dSRichard Lowe 	if (to->buffer.end - to->text.p <= length) {
690*10d63b7dSRichard Lowe 		expand_string(to,
691*10d63b7dSRichard Lowe 			      (to->buffer.end - to->buffer.start) * 2 +
692*10d63b7dSRichard Lowe 			      length);
693*10d63b7dSRichard Lowe 	}
694*10d63b7dSRichard Lowe 	if (length > 0) {
695*10d63b7dSRichard Lowe 		(void) wcsncpy(to->text.p, from, length);
696*10d63b7dSRichard Lowe 		to->text.p += length;
697*10d63b7dSRichard Lowe 	}
698*10d63b7dSRichard Lowe 	*(to->text.p) = (int) nul_char;
699*10d63b7dSRichard Lowe }
700*10d63b7dSRichard Lowe 
701*10d63b7dSRichard Lowe wchar_t * get_wstring(char *from) {
702*10d63b7dSRichard Lowe 	if(from == NULL) {
703*10d63b7dSRichard Lowe 		return NULL;
704*10d63b7dSRichard Lowe 	}
705*10d63b7dSRichard Lowe 	getwstring_count++;
706*10d63b7dSRichard Lowe 	wchar_t * wcbuf = ALLOC_WC(strlen(from) + 1);
707*10d63b7dSRichard Lowe 	mbstowcs(wcbuf, from, strlen(from)+1);
708*10d63b7dSRichard Lowe 	return wcbuf;
709*10d63b7dSRichard Lowe }
710*10d63b7dSRichard Lowe 
711*10d63b7dSRichard Lowe void
712*10d63b7dSRichard Lowe append_string(register char *from, register String to, register int length)
713*10d63b7dSRichard Lowe {
714*10d63b7dSRichard Lowe 	if (length == FIND_LENGTH) {
715*10d63b7dSRichard Lowe 		length = strlen(from);
716*10d63b7dSRichard Lowe 	}
717*10d63b7dSRichard Lowe 	if (to->buffer.start == NULL) {
718*10d63b7dSRichard Lowe 		expand_string(to, 32 + length);
719*10d63b7dSRichard Lowe 	}
720*10d63b7dSRichard Lowe 	if (to->buffer.end - to->text.p <= length) {
721*10d63b7dSRichard Lowe 		expand_string(to,
722*10d63b7dSRichard Lowe 			      (to->buffer.end - to->buffer.start) * 2 +
723*10d63b7dSRichard Lowe 			      length);
724*10d63b7dSRichard Lowe 	}
725*10d63b7dSRichard Lowe 	if (length > 0) {
726*10d63b7dSRichard Lowe 		(void) mbstowcs(to->text.p, from, length);
727*10d63b7dSRichard Lowe 		to->text.p += length;
728*10d63b7dSRichard Lowe 	}
729*10d63b7dSRichard Lowe 	*(to->text.p) = (int) nul_char;
730*10d63b7dSRichard Lowe }
731*10d63b7dSRichard Lowe 
732*10d63b7dSRichard Lowe /*
733*10d63b7dSRichard Lowe  *	expand_string(string, length)
734*10d63b7dSRichard Lowe  *
735*10d63b7dSRichard Lowe  *	Allocate more memory for strings that run out of space.
736*10d63b7dSRichard Lowe  *
737*10d63b7dSRichard Lowe  *	Parameters:
738*10d63b7dSRichard Lowe  *		string		The make style string we want to expand
739*10d63b7dSRichard Lowe  *		length		The new length we need
740*10d63b7dSRichard Lowe  *
741*10d63b7dSRichard Lowe  *	Global variables used:
742*10d63b7dSRichard Lowe  */
743*10d63b7dSRichard Lowe static void
744*10d63b7dSRichard Lowe expand_string(register String string, register int length)
745*10d63b7dSRichard Lowe {
746*10d63b7dSRichard Lowe 	register wchar_t	*p;
747*10d63b7dSRichard Lowe 
748*10d63b7dSRichard Lowe 	if (string->buffer.start == NULL) {
749*10d63b7dSRichard Lowe 		/* For strings that have no memory allocated */
750*10d63b7dSRichard Lowe 		string->buffer.start =
751*10d63b7dSRichard Lowe 		  string->text.p =
752*10d63b7dSRichard Lowe 		    string->text.end =
753*10d63b7dSRichard Lowe 		      ALLOC_WC(length);
754*10d63b7dSRichard Lowe 		string->buffer.end = string->buffer.start + length;
755*10d63b7dSRichard Lowe 		string->text.p[0] = (int) nul_char;
756*10d63b7dSRichard Lowe 		string->free_after_use = true;
757*10d63b7dSRichard Lowe 		expandstring_count++;
758*10d63b7dSRichard Lowe 		return;
759*10d63b7dSRichard Lowe 	}
760*10d63b7dSRichard Lowe 	if (string->buffer.end - string->buffer.start >= length) {
761*10d63b7dSRichard Lowe 		/* If we really don't need more memory. */
762*10d63b7dSRichard Lowe 		return;
763*10d63b7dSRichard Lowe 	}
764*10d63b7dSRichard Lowe 	/*
765*10d63b7dSRichard Lowe 	 * Get more memory, copy the string and free the old buffer if
766*10d63b7dSRichard Lowe 	 * it is was malloc()'ed.
767*10d63b7dSRichard Lowe 	 */
768*10d63b7dSRichard Lowe 	expandstring_count++;
769*10d63b7dSRichard Lowe 	p = ALLOC_WC(length);
770*10d63b7dSRichard Lowe 	(void) wcscpy(p, string->buffer.start);
771*10d63b7dSRichard Lowe 	string->text.p = p + (string->text.p - string->buffer.start);
772*10d63b7dSRichard Lowe 	string->text.end = p + (string->text.end - string->buffer.start);
773*10d63b7dSRichard Lowe 	string->buffer.end = p + length;
774*10d63b7dSRichard Lowe 	if (string->free_after_use) {
775*10d63b7dSRichard Lowe 		retmem(string->buffer.start);
776*10d63b7dSRichard Lowe 	}
777*10d63b7dSRichard Lowe 	string->buffer.start = p;
778*10d63b7dSRichard Lowe 	string->free_after_use = true;
779*10d63b7dSRichard Lowe }
780*10d63b7dSRichard Lowe 
781*10d63b7dSRichard Lowe /*
782*10d63b7dSRichard Lowe  *	append_char(from, to)
783*10d63b7dSRichard Lowe  *
784*10d63b7dSRichard Lowe  *	Append one char to a make string expanding it if nessecary
785*10d63b7dSRichard Lowe  *
786*10d63b7dSRichard Lowe  *	Parameters:
787*10d63b7dSRichard Lowe  *		from		Single character to append to string
788*10d63b7dSRichard Lowe  *		to		The destination (make style) string
789*10d63b7dSRichard Lowe  *
790*10d63b7dSRichard Lowe  *	Global variables used:
791*10d63b7dSRichard Lowe  */
792*10d63b7dSRichard Lowe void
793*10d63b7dSRichard Lowe append_char(wchar_t from, register String to)
794*10d63b7dSRichard Lowe {
795*10d63b7dSRichard Lowe 	if (to->buffer.start == NULL) {
796*10d63b7dSRichard Lowe 		expand_string(to, 32);
797*10d63b7dSRichard Lowe 	}
798*10d63b7dSRichard Lowe 	if (to->buffer.end - to->text.p <= 2) {
799*10d63b7dSRichard Lowe 		expand_string(to, to->buffer.end - to->buffer.start + 32);
800*10d63b7dSRichard Lowe 	}
801*10d63b7dSRichard Lowe 	*(to->text.p)++ = from;
802*10d63b7dSRichard Lowe 	*(to->text.p) = (int) nul_char;
803*10d63b7dSRichard Lowe }
804*10d63b7dSRichard Lowe 
805*10d63b7dSRichard Lowe /*
806*10d63b7dSRichard Lowe  *	handle_interrupt_mksh()
807*10d63b7dSRichard Lowe  *
808*10d63b7dSRichard Lowe  *	This is where C-C traps are caught.
809*10d63b7dSRichard Lowe  */
810*10d63b7dSRichard Lowe void
811*10d63b7dSRichard Lowe handle_interrupt_mksh(int)
812*10d63b7dSRichard Lowe {
813*10d63b7dSRichard Lowe 	(void) fflush(stdout);
814*10d63b7dSRichard Lowe 	/* Make sure the processes running under us terminate first. */
815*10d63b7dSRichard Lowe 	if (childPid > 0) {
816*10d63b7dSRichard Lowe 		kill(childPid, SIGTERM);
817*10d63b7dSRichard Lowe 		childPid = -1;
818*10d63b7dSRichard Lowe 	}
819*10d63b7dSRichard Lowe 	while (wait((int *) NULL) != -1);
820*10d63b7dSRichard Lowe 	exit_status = 2;
821*10d63b7dSRichard Lowe 	exit(2);
822*10d63b7dSRichard Lowe }
823*10d63b7dSRichard Lowe 
824*10d63b7dSRichard Lowe /*
825*10d63b7dSRichard Lowe  *	setup_interrupt()
826*10d63b7dSRichard Lowe  *
827*10d63b7dSRichard Lowe  *	This routine saves the original interrupt handler pointers
828*10d63b7dSRichard Lowe  *
829*10d63b7dSRichard Lowe  *	Parameters:
830*10d63b7dSRichard Lowe  *
831*10d63b7dSRichard Lowe  *	Static variables used:
832*10d63b7dSRichard Lowe  *		sigivalue	The original signal handler
833*10d63b7dSRichard Lowe  *		sigqvalue	The original signal handler
834*10d63b7dSRichard Lowe  *		sigtvalue	The original signal handler
835*10d63b7dSRichard Lowe  *		sighvalue	The original signal handler
836*10d63b7dSRichard Lowe  */
837*10d63b7dSRichard Lowe void
838*10d63b7dSRichard Lowe setup_interrupt(register void (*handler) (int))
839*10d63b7dSRichard Lowe {
840*10d63b7dSRichard Lowe 	sigivalue = bsd_signal(SIGINT, SIG_IGN);
841*10d63b7dSRichard Lowe 	sigqvalue = bsd_signal(SIGQUIT, SIG_IGN);
842*10d63b7dSRichard Lowe 	sigtvalue = bsd_signal(SIGTERM, SIG_IGN);
843*10d63b7dSRichard Lowe 	sighvalue = bsd_signal(SIGHUP, SIG_IGN);
844*10d63b7dSRichard Lowe 	enable_interrupt(handler);
845*10d63b7dSRichard Lowe }
846*10d63b7dSRichard Lowe 
847*10d63b7dSRichard Lowe 
848*10d63b7dSRichard Lowe void
849*10d63b7dSRichard Lowe mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n)
850*10d63b7dSRichard Lowe {
851*10d63b7dSRichard Lowe 	if(mbstowcs(pwcs, s, n) == -1) {
852*10d63b7dSRichard Lowe 		fatal_mksh(gettext("The string `%s' is not valid in current locale"), s);
853*10d63b7dSRichard Lowe 	}
854*10d63b7dSRichard Lowe }
855*10d63b7dSRichard Lowe 
856*10d63b7dSRichard Lowe 
857*10d63b7dSRichard Lowe 
858*10d63b7dSRichard Lowe Wstring::Wstring()
859*10d63b7dSRichard Lowe {
860*10d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(string, string_buf);
861*10d63b7dSRichard Lowe }
862*10d63b7dSRichard Lowe 
863*10d63b7dSRichard Lowe Wstring::Wstring(struct _Name * name)
864*10d63b7dSRichard Lowe {
865*10d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(string, string_buf);
866*10d63b7dSRichard Lowe 	append_string(name->string_mb, &string, name->hash.length);
867*10d63b7dSRichard Lowe }
868*10d63b7dSRichard Lowe 
869*10d63b7dSRichard Lowe Wstring::~Wstring()
870*10d63b7dSRichard Lowe {
871*10d63b7dSRichard Lowe 	if(string.free_after_use) {
872*10d63b7dSRichard Lowe 		retmem(string.buffer.start);
873*10d63b7dSRichard Lowe 	}
874*10d63b7dSRichard Lowe }
875*10d63b7dSRichard Lowe 
876*10d63b7dSRichard Lowe void
877*10d63b7dSRichard Lowe Wstring::init(struct _Name * name)
878*10d63b7dSRichard Lowe {
879*10d63b7dSRichard Lowe 	if(string.free_after_use) {
880*10d63b7dSRichard Lowe 		retmem(string.buffer.start);
881*10d63b7dSRichard Lowe 	}
882*10d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(string, string_buf);
883*10d63b7dSRichard Lowe 	append_string(name->string_mb, &string, name->hash.length);
884*10d63b7dSRichard Lowe }
885*10d63b7dSRichard Lowe 
886*10d63b7dSRichard Lowe void
887*10d63b7dSRichard Lowe Wstring::init(wchar_t * name, unsigned length)
888*10d63b7dSRichard Lowe {
889*10d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(string, string_buf);
890*10d63b7dSRichard Lowe 	append_string(name, &string, length);
891*10d63b7dSRichard Lowe 	string.buffer.start[length] = 0;
892*10d63b7dSRichard Lowe }
893*10d63b7dSRichard Lowe 
894*10d63b7dSRichard Lowe Boolean
895*10d63b7dSRichard Lowe Wstring::equaln(wchar_t * str, unsigned length)
896*10d63b7dSRichard Lowe {
897*10d63b7dSRichard Lowe 	return (Boolean)IS_WEQUALN(string.buffer.start, str, length);
898*10d63b7dSRichard Lowe }
899*10d63b7dSRichard Lowe 
900*10d63b7dSRichard Lowe Boolean
901*10d63b7dSRichard Lowe Wstring::equaln(Wstring * str, unsigned length)
902*10d63b7dSRichard Lowe {
903*10d63b7dSRichard Lowe 	return (Boolean)IS_WEQUALN(string.buffer.start, str->string.buffer.start, length);
904*10d63b7dSRichard Lowe }
905*10d63b7dSRichard Lowe 
906*10d63b7dSRichard Lowe Boolean
907*10d63b7dSRichard Lowe Wstring::equal(wchar_t * str, unsigned off, unsigned length)
908*10d63b7dSRichard Lowe {
909*10d63b7dSRichard Lowe 	return (Boolean)IS_WEQUALN(string.buffer.start + off, str, length);
910*10d63b7dSRichard Lowe }
911*10d63b7dSRichard Lowe 
912*10d63b7dSRichard Lowe Boolean
913*10d63b7dSRichard Lowe Wstring::equal(wchar_t * str, unsigned off)
914*10d63b7dSRichard Lowe {
915*10d63b7dSRichard Lowe 	return (Boolean)IS_WEQUAL(string.buffer.start + off, str);
916*10d63b7dSRichard Lowe }
917*10d63b7dSRichard Lowe 
918*10d63b7dSRichard Lowe Boolean
919*10d63b7dSRichard Lowe Wstring::equal(wchar_t * str)
920*10d63b7dSRichard Lowe {
921*10d63b7dSRichard Lowe 	return equal(str, 0);
922*10d63b7dSRichard Lowe }
923*10d63b7dSRichard Lowe 
924*10d63b7dSRichard Lowe Boolean
925*10d63b7dSRichard Lowe Wstring::equal(Wstring * str, unsigned off, unsigned length)
926*10d63b7dSRichard Lowe {
927*10d63b7dSRichard Lowe 	return (Boolean)IS_WEQUALN(string.buffer.start + off, str->string.buffer.start, length);
928*10d63b7dSRichard Lowe }
929*10d63b7dSRichard Lowe 
930*10d63b7dSRichard Lowe Boolean
931*10d63b7dSRichard Lowe Wstring::equal(Wstring * str)
932*10d63b7dSRichard Lowe {
933*10d63b7dSRichard Lowe 	return equal(str, 0);
934*10d63b7dSRichard Lowe }
935*10d63b7dSRichard Lowe 
936*10d63b7dSRichard Lowe Boolean
937*10d63b7dSRichard Lowe Wstring::equal(Wstring * str, unsigned off)
938*10d63b7dSRichard Lowe {
939*10d63b7dSRichard Lowe 	return (Boolean)IS_WEQUAL(string.buffer.start + off, str->string.buffer.start);
940*10d63b7dSRichard Lowe }
941*10d63b7dSRichard Lowe 
942*10d63b7dSRichard Lowe void
943*10d63b7dSRichard Lowe Wstring::append_to_str(struct _String * str, unsigned off, unsigned length)
944*10d63b7dSRichard Lowe {
945*10d63b7dSRichard Lowe 	append_string(string.buffer.start + off, str, length);
946*10d63b7dSRichard Lowe }
947*10d63b7dSRichard Lowe 
948*10d63b7dSRichard Lowe Name
949*10d63b7dSRichard Lowe Name_set::lookup(const char *key)
950*10d63b7dSRichard Lowe {
951*10d63b7dSRichard Lowe 	for (entry *node = root; node != 0;) {
952*10d63b7dSRichard Lowe 		int res = strcmp(key, node->name->string_mb);
953*10d63b7dSRichard Lowe 		if (res < 0) {
954*10d63b7dSRichard Lowe 			node = node->left;
955*10d63b7dSRichard Lowe 		} else if (res > 0) {
956*10d63b7dSRichard Lowe 			node = node->right;
957*10d63b7dSRichard Lowe 		} else {
958*10d63b7dSRichard Lowe 			return node->name;
959*10d63b7dSRichard Lowe 		}
960*10d63b7dSRichard Lowe 	}
961*10d63b7dSRichard Lowe 	return 0;
962*10d63b7dSRichard Lowe }
963*10d63b7dSRichard Lowe 
964*10d63b7dSRichard Lowe Name
965*10d63b7dSRichard Lowe Name_set::insert(const char *key, Boolean &found)
966*10d63b7dSRichard Lowe {
967*10d63b7dSRichard Lowe 	Name	name = 0;
968*10d63b7dSRichard Lowe 
969*10d63b7dSRichard Lowe 	if (root != 0) {
970*10d63b7dSRichard Lowe 		for (entry *node = root; name == 0;) {
971*10d63b7dSRichard Lowe 			int res = strcmp(key, node->name->string_mb);
972*10d63b7dSRichard Lowe 			if (res < 0) {
973*10d63b7dSRichard Lowe 				if (node->left != 0) {
974*10d63b7dSRichard Lowe 					node = node->left;
975*10d63b7dSRichard Lowe 				} else {
976*10d63b7dSRichard Lowe 					found = false;
977*10d63b7dSRichard Lowe 					name = ALLOC(Name);
978*10d63b7dSRichard Lowe 
979*10d63b7dSRichard Lowe 					node->left = new entry(name, node);
980*10d63b7dSRichard Lowe 					rebalance(node);
981*10d63b7dSRichard Lowe 				}
982*10d63b7dSRichard Lowe 			} else if (res > 0) {
983*10d63b7dSRichard Lowe 				if (node->right != 0) {
984*10d63b7dSRichard Lowe 					node = node->right;
985*10d63b7dSRichard Lowe 				} else {
986*10d63b7dSRichard Lowe 					found = false;
987*10d63b7dSRichard Lowe 					name = ALLOC(Name);
988*10d63b7dSRichard Lowe 
989*10d63b7dSRichard Lowe 					node->right = new entry(name, node);
990*10d63b7dSRichard Lowe 					rebalance(node);
991*10d63b7dSRichard Lowe 				}
992*10d63b7dSRichard Lowe 			} else {
993*10d63b7dSRichard Lowe 				found = true;
994*10d63b7dSRichard Lowe 				name = node->name;
995*10d63b7dSRichard Lowe 			}
996*10d63b7dSRichard Lowe 		}
997*10d63b7dSRichard Lowe 	} else {
998*10d63b7dSRichard Lowe 		found = false;
999*10d63b7dSRichard Lowe 		name = ALLOC(Name);
1000*10d63b7dSRichard Lowe 
1001*10d63b7dSRichard Lowe 		root = new entry(name, 0);
1002*10d63b7dSRichard Lowe 	}
1003*10d63b7dSRichard Lowe 	return name;
1004*10d63b7dSRichard Lowe }
1005*10d63b7dSRichard Lowe 
1006*10d63b7dSRichard Lowe void
1007*10d63b7dSRichard Lowe Name_set::insert(Name name) {
1008*10d63b7dSRichard Lowe 	if (root != 0) {
1009*10d63b7dSRichard Lowe 		for (entry *node = root;;) {
1010*10d63b7dSRichard Lowe 			int res = strcmp(name->string_mb, node->name->string_mb);
1011*10d63b7dSRichard Lowe 			if (res < 0) {
1012*10d63b7dSRichard Lowe 				if (node->left != 0) {
1013*10d63b7dSRichard Lowe 					node = node->left;
1014*10d63b7dSRichard Lowe 				} else {
1015*10d63b7dSRichard Lowe 					node->left = new entry(name, node);
1016*10d63b7dSRichard Lowe 					rebalance(node);
1017*10d63b7dSRichard Lowe 					break;
1018*10d63b7dSRichard Lowe 				}
1019*10d63b7dSRichard Lowe 			} else if (res > 0) {
1020*10d63b7dSRichard Lowe 				if (node->right != 0) {
1021*10d63b7dSRichard Lowe 					node = node->right;
1022*10d63b7dSRichard Lowe 				} else {
1023*10d63b7dSRichard Lowe 					node->right = new entry(name, node);
1024*10d63b7dSRichard Lowe 					rebalance(node);
1025*10d63b7dSRichard Lowe 					break;
1026*10d63b7dSRichard Lowe 				}
1027*10d63b7dSRichard Lowe 			} else {
1028*10d63b7dSRichard Lowe 				// should be an error: inserting already existing name
1029*10d63b7dSRichard Lowe 				break;
1030*10d63b7dSRichard Lowe 			}
1031*10d63b7dSRichard Lowe 		}
1032*10d63b7dSRichard Lowe 	} else {
1033*10d63b7dSRichard Lowe 		root = new entry(name, 0);
1034*10d63b7dSRichard Lowe 	}
1035*10d63b7dSRichard Lowe }
1036*10d63b7dSRichard Lowe 
1037*10d63b7dSRichard Lowe void
1038*10d63b7dSRichard Lowe Name_set::rebalance(Name_set::entry *node) {
1039*10d63b7dSRichard Lowe 	for (; node != 0; node = node->parent) {
1040*10d63b7dSRichard Lowe 		entry *right = node->right;
1041*10d63b7dSRichard Lowe 		entry *left = node->left;
1042*10d63b7dSRichard Lowe 
1043*10d63b7dSRichard Lowe 		unsigned rdepth = (right != 0) ? right->depth : 0;
1044*10d63b7dSRichard Lowe 		unsigned ldepth = (left != 0) ? left->depth : 0;
1045*10d63b7dSRichard Lowe 
1046*10d63b7dSRichard Lowe 		if (ldepth > rdepth + 1) {
1047*10d63b7dSRichard Lowe 			if ((node->left = left->right) != 0) {
1048*10d63b7dSRichard Lowe 				left->right->parent = node;
1049*10d63b7dSRichard Lowe 			}
1050*10d63b7dSRichard Lowe 			if ((left->parent = node->parent) != 0) {
1051*10d63b7dSRichard Lowe 				if (node == node->parent->right) {
1052*10d63b7dSRichard Lowe 					node->parent->right = left;
1053*10d63b7dSRichard Lowe 				} else {
1054*10d63b7dSRichard Lowe 					node->parent->left = left;
1055*10d63b7dSRichard Lowe 				}
1056*10d63b7dSRichard Lowe 			} else {
1057*10d63b7dSRichard Lowe 				root = left;
1058*10d63b7dSRichard Lowe 			}
1059*10d63b7dSRichard Lowe 			left->right = node;
1060*10d63b7dSRichard Lowe 			node->parent = left;
1061*10d63b7dSRichard Lowe 
1062*10d63b7dSRichard Lowe 			node->setup_depth();
1063*10d63b7dSRichard Lowe 			node = left;
1064*10d63b7dSRichard Lowe 		} else if (rdepth > ldepth + 1) {
1065*10d63b7dSRichard Lowe 			if ((node->right = right->left) != 0) {
1066*10d63b7dSRichard Lowe 				right->left->parent = node;
1067*10d63b7dSRichard Lowe 			}
1068*10d63b7dSRichard Lowe 			if ((right->parent = node->parent) != 0) {
1069*10d63b7dSRichard Lowe 				if (node == node->parent->right) {
1070*10d63b7dSRichard Lowe 					node->parent->right = right;
1071*10d63b7dSRichard Lowe 				} else {
1072*10d63b7dSRichard Lowe 					node->parent->left = right;
1073*10d63b7dSRichard Lowe 				}
1074*10d63b7dSRichard Lowe 			} else {
1075*10d63b7dSRichard Lowe 				root = right;
1076*10d63b7dSRichard Lowe 			}
1077*10d63b7dSRichard Lowe 			right->left = node;
1078*10d63b7dSRichard Lowe 			node->parent = right;
1079*10d63b7dSRichard Lowe 
1080*10d63b7dSRichard Lowe 			node->setup_depth();
1081*10d63b7dSRichard Lowe 			node = right;
1082*10d63b7dSRichard Lowe 		}
1083*10d63b7dSRichard Lowe 		node->setup_depth();
1084*10d63b7dSRichard Lowe 	}
1085*10d63b7dSRichard Lowe }
1086*10d63b7dSRichard Lowe 
1087*10d63b7dSRichard Lowe Name_set::iterator
1088*10d63b7dSRichard Lowe Name_set::begin() const {
1089*10d63b7dSRichard Lowe 	for (entry *node = root; node != 0; node = node->left) {
1090*10d63b7dSRichard Lowe 		if (node->left == 0) {
1091*10d63b7dSRichard Lowe 			return iterator(node);
1092*10d63b7dSRichard Lowe 		}
1093*10d63b7dSRichard Lowe 	}
1094*10d63b7dSRichard Lowe 	return iterator();
1095*10d63b7dSRichard Lowe }
1096*10d63b7dSRichard Lowe 
1097*10d63b7dSRichard Lowe Name_set::iterator&
1098*10d63b7dSRichard Lowe Name_set::iterator::operator++() {
1099*10d63b7dSRichard Lowe 	if (node != 0) {
1100*10d63b7dSRichard Lowe 		if (node->right != 0) {
1101*10d63b7dSRichard Lowe 			node = node->right;
1102*10d63b7dSRichard Lowe 			while (node->left != 0) {
1103*10d63b7dSRichard Lowe 				node = node->left;
1104*10d63b7dSRichard Lowe 			}
1105*10d63b7dSRichard Lowe 		} else {
1106*10d63b7dSRichard Lowe 			while ((node->parent != 0) && (node->parent->right == node)) {
1107*10d63b7dSRichard Lowe 				node = node->parent;
1108*10d63b7dSRichard Lowe 			}
1109*10d63b7dSRichard Lowe 			node = node->parent;
1110*10d63b7dSRichard Lowe 		}
1111*10d63b7dSRichard Lowe 	}
1112*10d63b7dSRichard Lowe 	return *this;
1113*10d63b7dSRichard Lowe }
1114