xref: /illumos-gate/usr/src/cmd/make/lib/mksh/misc.cc (revision e7afc443)
110d63b7dSRichard Lowe /*
210d63b7dSRichard Lowe  * CDDL HEADER START
310d63b7dSRichard Lowe  *
410d63b7dSRichard Lowe  * The contents of this file are subject to the terms of the
510d63b7dSRichard Lowe  * Common Development and Distribution License (the "License").
610d63b7dSRichard Lowe  * You may not use this file except in compliance with the License.
710d63b7dSRichard Lowe  *
810d63b7dSRichard Lowe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910d63b7dSRichard Lowe  * or http://www.opensolaris.org/os/licensing.
1010d63b7dSRichard Lowe  * See the License for the specific language governing permissions
1110d63b7dSRichard Lowe  * and limitations under the License.
1210d63b7dSRichard Lowe  *
1310d63b7dSRichard Lowe  * When distributing Covered Code, include this CDDL HEADER in each
1410d63b7dSRichard Lowe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510d63b7dSRichard Lowe  * If applicable, add the following below this CDDL HEADER, with the
1610d63b7dSRichard Lowe  * fields enclosed by brackets "[]" replaced with your own identifying
1710d63b7dSRichard Lowe  * information: Portions Copyright [yyyy] [name of copyright owner]
1810d63b7dSRichard Lowe  *
1910d63b7dSRichard Lowe  * CDDL HEADER END
2010d63b7dSRichard Lowe  */
2110d63b7dSRichard Lowe /*
2210d63b7dSRichard Lowe  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
2310d63b7dSRichard Lowe  * Use is subject to license terms.
2410d63b7dSRichard Lowe  */
2510d63b7dSRichard Lowe 
2610d63b7dSRichard Lowe 
2710d63b7dSRichard Lowe /*
2810d63b7dSRichard Lowe  *	misc.cc
2910d63b7dSRichard Lowe  *
3010d63b7dSRichard Lowe  *	This file contains various unclassified routines. Some main groups:
3110d63b7dSRichard Lowe  *		getname
3210d63b7dSRichard Lowe  *		Memory allocation
3310d63b7dSRichard Lowe  *		String handling
3410d63b7dSRichard Lowe  *		Property handling
3510d63b7dSRichard Lowe  *		Error message handling
3610d63b7dSRichard Lowe  *		Make internal state dumping
3710d63b7dSRichard Lowe  *		main routine support
3810d63b7dSRichard Lowe  */
3910d63b7dSRichard Lowe 
4010d63b7dSRichard Lowe /*
4110d63b7dSRichard Lowe  * Included files
4210d63b7dSRichard Lowe  */
4310d63b7dSRichard Lowe #include <bsd/bsd.h>		/* bsd_signal() */
4410d63b7dSRichard Lowe #include <mksh/i18n.h>		/* get_char_semantics_value() */
4510d63b7dSRichard Lowe #include <mksh/misc.h>
4610d63b7dSRichard Lowe #include <stdarg.h>		/* va_list, va_start(), va_end() */
4710d63b7dSRichard Lowe #include <stdlib.h>		/* mbstowcs() */
4810d63b7dSRichard Lowe #include <sys/signal.h>		/* SIG_DFL */
4910d63b7dSRichard Lowe #include <sys/wait.h>		/* wait() */
5010d63b7dSRichard Lowe 
5110d63b7dSRichard Lowe #include <string.h>		/* strerror() */
5210d63b7dSRichard Lowe #include <libintl.h>
5310d63b7dSRichard Lowe 
5410d63b7dSRichard Lowe 
5510d63b7dSRichard Lowe /*
5610d63b7dSRichard Lowe  * Defined macros
5710d63b7dSRichard Lowe  */
5810d63b7dSRichard Lowe 
5910d63b7dSRichard Lowe /*
6010d63b7dSRichard Lowe  * typedefs & structs
6110d63b7dSRichard Lowe  */
6210d63b7dSRichard Lowe 
6310d63b7dSRichard Lowe /*
6410d63b7dSRichard Lowe  * Static variables
6510d63b7dSRichard Lowe  */
6610d63b7dSRichard Lowe extern "C" {
6710d63b7dSRichard Lowe 	void		(*sigivalue)(int) = SIG_DFL;
6810d63b7dSRichard Lowe 	void		(*sigqvalue)(int) = SIG_DFL;
6910d63b7dSRichard Lowe 	void		(*sigtvalue)(int) = SIG_DFL;
7010d63b7dSRichard Lowe 	void		(*sighvalue)(int) = SIG_DFL;
7110d63b7dSRichard Lowe }
7210d63b7dSRichard Lowe 
7310d63b7dSRichard Lowe long	getname_bytes_count = 0;
7410d63b7dSRichard Lowe long	getname_names_count = 0;
7510d63b7dSRichard Lowe long	getname_struct_count = 0;
7610d63b7dSRichard Lowe 
7710d63b7dSRichard Lowe long	freename_bytes_count = 0;
7810d63b7dSRichard Lowe long	freename_names_count = 0;
7910d63b7dSRichard Lowe long	freename_struct_count = 0;
8010d63b7dSRichard Lowe 
8110d63b7dSRichard Lowe long	expandstring_count = 0;
8210d63b7dSRichard Lowe long	getwstring_count = 0;
8310d63b7dSRichard Lowe 
8410d63b7dSRichard Lowe /*
8510d63b7dSRichard Lowe  * File table of contents
8610d63b7dSRichard Lowe  */
87*e7afc443SToomas Soome static void	expand_string(String string, int length);
8810d63b7dSRichard Lowe 
8910d63b7dSRichard Lowe #define	FATAL_ERROR_MSG_SIZE 200
9010d63b7dSRichard Lowe 
9110d63b7dSRichard Lowe /*
9210d63b7dSRichard Lowe  *	getmem(size)
9310d63b7dSRichard Lowe  *
9410d63b7dSRichard Lowe  *	malloc() version that checks the returned value.
9510d63b7dSRichard Lowe  *
9610d63b7dSRichard Lowe  *	Return value:
9710d63b7dSRichard Lowe  *				The memory chunk we allocated
9810d63b7dSRichard Lowe  *
9910d63b7dSRichard Lowe  *	Parameters:
10010d63b7dSRichard Lowe  *		size		The size of the chunk we need
10110d63b7dSRichard Lowe  *
10210d63b7dSRichard Lowe  *	Global variables used:
10310d63b7dSRichard Lowe  */
10410d63b7dSRichard Lowe char *
getmem(size_t size)105356ba08cSToomas Soome getmem(size_t size)
10610d63b7dSRichard Lowe {
107356ba08cSToomas Soome 	char *result = (char *)malloc(size);
10810d63b7dSRichard Lowe 	if (result == NULL) {
109356ba08cSToomas Soome 		(void) fprintf(stderr, "*** Error: malloc(%d) failed: %s\n%s",
110356ba08cSToomas Soome 		    size, strerror(errno),
111356ba08cSToomas Soome 		    gettext("mksh: Fatal error: Out of memory\n"));
11210d63b7dSRichard Lowe 		exit(1);
11310d63b7dSRichard Lowe 	}
114356ba08cSToomas Soome 	return (result);
11510d63b7dSRichard Lowe }
11610d63b7dSRichard Lowe 
11710d63b7dSRichard Lowe /*
11810d63b7dSRichard Lowe  *	retmem(p)
11910d63b7dSRichard Lowe  *
12010d63b7dSRichard Lowe  *	Cover funtion for free() to make it possible to insert advises.
12110d63b7dSRichard Lowe  *
12210d63b7dSRichard Lowe  *	Parameters:
12310d63b7dSRichard Lowe  *		p		The memory block to free
12410d63b7dSRichard Lowe  *
12510d63b7dSRichard Lowe  *	Global variables used:
12610d63b7dSRichard Lowe  */
12710d63b7dSRichard Lowe void
retmem(wchar_t * p)12810d63b7dSRichard Lowe retmem(wchar_t *p)
12910d63b7dSRichard Lowe {
13010d63b7dSRichard Lowe 	(void) free((char *) p);
13110d63b7dSRichard Lowe }
13210d63b7dSRichard Lowe 
13310d63b7dSRichard Lowe void
retmem_mb(caddr_t p)13410d63b7dSRichard Lowe retmem_mb(caddr_t p)
13510d63b7dSRichard Lowe {
13610d63b7dSRichard Lowe 	(void) free(p);
13710d63b7dSRichard Lowe }
13810d63b7dSRichard Lowe 
13910d63b7dSRichard Lowe /*
14010d63b7dSRichard Lowe  *	getname_fn(name, len, dont_enter)
14110d63b7dSRichard Lowe  *
14210d63b7dSRichard Lowe  *	Hash a name string to the corresponding nameblock.
14310d63b7dSRichard Lowe  *
14410d63b7dSRichard Lowe  *	Return value:
14510d63b7dSRichard Lowe  *				The Name block for the string
14610d63b7dSRichard Lowe  *
14710d63b7dSRichard Lowe  *	Parameters:
14810d63b7dSRichard Lowe  *		name		The string we want to internalize
14910d63b7dSRichard Lowe  *		len		The length of that string
15010d63b7dSRichard Lowe  *		dont_enter	Don't enter the name if it does not exist
15110d63b7dSRichard Lowe  *
15210d63b7dSRichard Lowe  *	Global variables used:
15310d63b7dSRichard Lowe  *		funny		The vector of semantic tags for characters
15410d63b7dSRichard Lowe  *		hashtab		The hashtable used for the nametable
15510d63b7dSRichard Lowe  */
15610d63b7dSRichard Lowe Name
getname_fn(wchar_t * name,int len,Boolean dont_enter,Boolean * foundp)157*e7afc443SToomas Soome getname_fn(wchar_t *name, int len, Boolean dont_enter, Boolean * foundp)
15810d63b7dSRichard Lowe {
159*e7afc443SToomas Soome 	int		length;
160*e7afc443SToomas Soome 	wchar_t	*cap = name;
161*e7afc443SToomas Soome 	Name		np;
16210d63b7dSRichard Lowe 	static Name_rec		empty_Name;
16310d63b7dSRichard Lowe 	char			*tmp_mbs_buffer = NULL;
16410d63b7dSRichard Lowe 	char			*mbs_name = mbs_buffer;
16510d63b7dSRichard Lowe 
16610d63b7dSRichard Lowe 	/*
16710d63b7dSRichard Lowe 	 * First figure out how long the string is.
16810d63b7dSRichard Lowe 	 * If the len argument is -1 we count the chars here.
16910d63b7dSRichard Lowe 	 */
17010d63b7dSRichard Lowe 	if (len == FIND_LENGTH) {
17110d63b7dSRichard Lowe 		length = wcslen(name);
17210d63b7dSRichard Lowe 	} else {
17310d63b7dSRichard Lowe 		length = len;
17410d63b7dSRichard Lowe 	}
17510d63b7dSRichard Lowe 
17610d63b7dSRichard Lowe 	Wstring ws;
17710d63b7dSRichard Lowe 	ws.init(name, length);
17810d63b7dSRichard Lowe 	if (length >= MAXPATHLEN) {
17910d63b7dSRichard Lowe 		mbs_name = tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
18010d63b7dSRichard Lowe 	}
18110d63b7dSRichard Lowe 	(void) wcstombs(mbs_name, ws.get_string(), (length * MB_LEN_MAX) + 1);
18210d63b7dSRichard Lowe 
18310d63b7dSRichard Lowe 	/* Look for the string */
18410d63b7dSRichard Lowe 	if (dont_enter || (foundp != 0)) {
18510d63b7dSRichard Lowe 		np = hashtab.lookup(mbs_name);
18610d63b7dSRichard Lowe 		if (foundp != 0) {
18710d63b7dSRichard Lowe 			*foundp = (np != 0) ? true : false;
18810d63b7dSRichard Lowe 		}
18910d63b7dSRichard Lowe 		if ((np != 0) || dont_enter) {
19010d63b7dSRichard Lowe 			if(tmp_mbs_buffer != NULL) {
19110d63b7dSRichard Lowe 				retmem_mb(tmp_mbs_buffer);
19210d63b7dSRichard Lowe 			}
19310d63b7dSRichard Lowe 			return np;
19410d63b7dSRichard Lowe 		} else {
19510d63b7dSRichard Lowe 			np = ALLOC(Name);
19610d63b7dSRichard Lowe 		}
19710d63b7dSRichard Lowe 	} else {
19810d63b7dSRichard Lowe 		Boolean found;
19910d63b7dSRichard Lowe 		np = hashtab.insert(mbs_name, found);
20010d63b7dSRichard Lowe 		if (found) {
20110d63b7dSRichard Lowe 			if(tmp_mbs_buffer != NULL) {
20210d63b7dSRichard Lowe 				retmem_mb(tmp_mbs_buffer);
20310d63b7dSRichard Lowe 			}
20410d63b7dSRichard Lowe 			return np;
20510d63b7dSRichard Lowe 		}
20610d63b7dSRichard Lowe 	}
20710d63b7dSRichard Lowe 	getname_struct_count += sizeof(struct _Name);
20810d63b7dSRichard Lowe 	*np = empty_Name;
20910d63b7dSRichard Lowe 
21010d63b7dSRichard Lowe 	np->string_mb = strdup(mbs_name);
21110d63b7dSRichard Lowe 	if(tmp_mbs_buffer != NULL) {
21210d63b7dSRichard Lowe 		retmem_mb(tmp_mbs_buffer);
21310d63b7dSRichard Lowe 		mbs_name = tmp_mbs_buffer = NULL;
21410d63b7dSRichard Lowe 	}
21510d63b7dSRichard Lowe 	getname_bytes_count += strlen(np->string_mb) + 1;
21610d63b7dSRichard Lowe 	/* Fill in the new Name */
21710d63b7dSRichard Lowe 	np->stat.time = file_no_time;
21810d63b7dSRichard Lowe 	np->hash.length = length;
21910d63b7dSRichard Lowe 	/* Scan the namestring to classify it */
22010d63b7dSRichard Lowe 	for (cap = name, len = 0; --length >= 0;) {
22110d63b7dSRichard Lowe 		len |= get_char_semantics_value(*cap++);
22210d63b7dSRichard Lowe 	}
22310d63b7dSRichard Lowe 	np->dollar = BOOLEAN((len & (int) dollar_sem) != 0);
22410d63b7dSRichard Lowe 	np->meta = BOOLEAN((len & (int) meta_sem) != 0);
22510d63b7dSRichard Lowe 	np->percent = BOOLEAN((len & (int) percent_sem) != 0);
22610d63b7dSRichard Lowe 	np->wildcard = BOOLEAN((len & (int) wildcard_sem) != 0);
22710d63b7dSRichard Lowe 	np->colon = BOOLEAN((len & (int) colon_sem) != 0);
22810d63b7dSRichard Lowe 	np->parenleft = BOOLEAN((len & (int) parenleft_sem) != 0);
22910d63b7dSRichard Lowe 	getname_names_count++;
23010d63b7dSRichard Lowe 	return np;
23110d63b7dSRichard Lowe }
23210d63b7dSRichard Lowe 
23310d63b7dSRichard Lowe void
store_name(Name name)23410d63b7dSRichard Lowe store_name(Name name)
23510d63b7dSRichard Lowe {
23610d63b7dSRichard Lowe 	hashtab.insert(name);
23710d63b7dSRichard Lowe }
23810d63b7dSRichard Lowe 
23910d63b7dSRichard Lowe void
free_name(Name name)24010d63b7dSRichard Lowe free_name(Name name)
24110d63b7dSRichard Lowe {
24210d63b7dSRichard Lowe 	freename_names_count++;
24310d63b7dSRichard Lowe 	freename_struct_count += sizeof(struct _Name);
24410d63b7dSRichard Lowe 	freename_bytes_count += strlen(name->string_mb) + 1;
24510d63b7dSRichard Lowe 	retmem_mb(name->string_mb);
24610d63b7dSRichard Lowe 	for (Property next, p = name->prop; p != NULL; p = next) {
24710d63b7dSRichard Lowe 		next = p->next;
24810d63b7dSRichard Lowe 		free(p);
24910d63b7dSRichard Lowe 	}
25010d63b7dSRichard Lowe 	free(name);
25110d63b7dSRichard Lowe }
25210d63b7dSRichard Lowe 
25310d63b7dSRichard Lowe /*
25410d63b7dSRichard Lowe  *	enable_interrupt(handler)
25510d63b7dSRichard Lowe  *
25610d63b7dSRichard Lowe  *	This routine sets a new interrupt handler for the signals make
25710d63b7dSRichard Lowe  *	wants to deal with.
25810d63b7dSRichard Lowe  *
25910d63b7dSRichard Lowe  *	Parameters:
26010d63b7dSRichard Lowe  *		handler		The function installed as interrupt handler
26110d63b7dSRichard Lowe  *
26210d63b7dSRichard Lowe  *	Static variables used:
26310d63b7dSRichard Lowe  *		sigivalue	The original signal handler
26410d63b7dSRichard Lowe  *		sigqvalue	The original signal handler
26510d63b7dSRichard Lowe  *		sigtvalue	The original signal handler
26610d63b7dSRichard Lowe  *		sighvalue	The original signal handler
26710d63b7dSRichard Lowe  */
26810d63b7dSRichard Lowe void
enable_interrupt(void (* handler)(int))269*e7afc443SToomas Soome enable_interrupt(void (*handler) (int))
27010d63b7dSRichard Lowe {
27110d63b7dSRichard Lowe 	if (sigivalue != SIG_IGN) {
27210d63b7dSRichard Lowe 		(void) bsd_signal(SIGINT, (SIG_PF) handler);
27310d63b7dSRichard Lowe 	}
27410d63b7dSRichard Lowe 	if (sigqvalue != SIG_IGN) {
27510d63b7dSRichard Lowe 		(void) bsd_signal(SIGQUIT, (SIG_PF) handler);
27610d63b7dSRichard Lowe 	}
27710d63b7dSRichard Lowe 	if (sigtvalue != SIG_IGN) {
27810d63b7dSRichard Lowe 		(void) bsd_signal(SIGTERM, (SIG_PF) handler);
27910d63b7dSRichard Lowe 	}
28010d63b7dSRichard Lowe 	if (sighvalue != SIG_IGN) {
28110d63b7dSRichard Lowe 		(void) bsd_signal(SIGHUP, (SIG_PF) handler);
28210d63b7dSRichard Lowe 	}
28310d63b7dSRichard Lowe }
28410d63b7dSRichard Lowe 
28510d63b7dSRichard Lowe /*
28610d63b7dSRichard Lowe  *	setup_char_semantics()
28710d63b7dSRichard Lowe  *
28810d63b7dSRichard Lowe  *	Load the vector char_semantics[] with lexical markers
28910d63b7dSRichard Lowe  *
29010d63b7dSRichard Lowe  *	Parameters:
29110d63b7dSRichard Lowe  *
29210d63b7dSRichard Lowe  *	Global variables used:
29310d63b7dSRichard Lowe  *		char_semantics	The vector of character semantics that we set
29410d63b7dSRichard Lowe  */
29510d63b7dSRichard Lowe void
setup_char_semantics(void)29610d63b7dSRichard Lowe setup_char_semantics(void)
29710d63b7dSRichard Lowe {
29810d63b7dSRichard Lowe 	const char	*s;
29910d63b7dSRichard Lowe 	wchar_t		wc_buffer[1];
30010d63b7dSRichard Lowe 	int		entry;
30110d63b7dSRichard Lowe 
30210d63b7dSRichard Lowe 	if (svr4) {
30310d63b7dSRichard Lowe 		s = "@-";
30410d63b7dSRichard Lowe 	} else {
30510d63b7dSRichard Lowe 		s = "=@-?!+";
30610d63b7dSRichard Lowe 	}
30710d63b7dSRichard Lowe 	for (s; MBTOWC(wc_buffer, s); s++) {
30810d63b7dSRichard Lowe 		entry = get_char_semantics_entry(*wc_buffer);
30910d63b7dSRichard Lowe 		char_semantics[entry] |= (int) command_prefix_sem;
31010d63b7dSRichard Lowe 	}
31110d63b7dSRichard Lowe 	char_semantics[dollar_char_entry] |= (int) dollar_sem;
31210d63b7dSRichard Lowe 	for (s = "#|=^();&<>*?[]:$`'\"\\\n"; MBTOWC(wc_buffer, s); s++) {
31310d63b7dSRichard Lowe 		entry = get_char_semantics_entry(*wc_buffer);
31410d63b7dSRichard Lowe 		char_semantics[entry] |= (int) meta_sem;
31510d63b7dSRichard Lowe 	}
31610d63b7dSRichard Lowe 	char_semantics[percent_char_entry] |= (int) percent_sem;
31710d63b7dSRichard Lowe 	for (s = "@*<%?^"; MBTOWC(wc_buffer, s); s++) {
31810d63b7dSRichard Lowe 		entry = get_char_semantics_entry(*wc_buffer);
31910d63b7dSRichard Lowe 		char_semantics[entry] |= (int) special_macro_sem;
32010d63b7dSRichard Lowe 	}
32110d63b7dSRichard Lowe 	for (s = "?[*"; MBTOWC(wc_buffer, s); s++) {
32210d63b7dSRichard Lowe 		entry = get_char_semantics_entry(*wc_buffer);
32310d63b7dSRichard Lowe 		char_semantics[entry] |= (int) wildcard_sem;
32410d63b7dSRichard Lowe 	}
32510d63b7dSRichard Lowe 	char_semantics[colon_char_entry] |= (int) colon_sem;
32610d63b7dSRichard Lowe 	char_semantics[parenleft_char_entry] |= (int) parenleft_sem;
32710d63b7dSRichard Lowe }
32810d63b7dSRichard Lowe 
32910d63b7dSRichard Lowe /*
33010d63b7dSRichard Lowe  *	errmsg(errnum)
33110d63b7dSRichard Lowe  *
33210d63b7dSRichard Lowe  *	Return the error message for a system call error
33310d63b7dSRichard Lowe  *
33410d63b7dSRichard Lowe  *	Return value:
33510d63b7dSRichard Lowe  *				An error message string
33610d63b7dSRichard Lowe  *
33710d63b7dSRichard Lowe  *	Parameters:
33810d63b7dSRichard Lowe  *		errnum		The number of the error we want to describe
33910d63b7dSRichard Lowe  */
34010d63b7dSRichard Lowe char *
errmsg(int errnum)34110d63b7dSRichard Lowe errmsg(int errnum)
34210d63b7dSRichard Lowe {
343356ba08cSToomas Soome 	char *msg;
344356ba08cSToomas Soome 	char *errbuf;
345356ba08cSToomas Soome 
346356ba08cSToomas Soome 	errno = 0;
347356ba08cSToomas Soome 	msg = strerror(errnum);
348356ba08cSToomas Soome 	if (errno == EINVAL) {
349356ba08cSToomas Soome 		size_t size = 6 + 1 + 11 + 1;
350356ba08cSToomas Soome 		errbuf = getmem(size);
351356ba08cSToomas Soome 		(void) snprintf(errbuf, size, gettext("Error %d"), errnum);
352356ba08cSToomas Soome 		return (errbuf);
35310d63b7dSRichard Lowe 	}
354356ba08cSToomas Soome 	return (msg);
35510d63b7dSRichard Lowe }
35610d63b7dSRichard Lowe 
35710d63b7dSRichard Lowe static char static_buf[MAXPATHLEN*3];
35810d63b7dSRichard Lowe 
35910d63b7dSRichard Lowe /*
36010d63b7dSRichard Lowe  *	fatal_mksh(format, args...)
36110d63b7dSRichard Lowe  *
36210d63b7dSRichard Lowe  *	Print a message and die
36310d63b7dSRichard Lowe  *
36410d63b7dSRichard Lowe  *	Parameters:
36510d63b7dSRichard Lowe  *		format		printf type format string
36610d63b7dSRichard Lowe  *		args		Arguments to match the format
36710d63b7dSRichard Lowe  */
36810d63b7dSRichard Lowe /*VARARGS*/
36910d63b7dSRichard Lowe void
fatal_mksh(const char * message,...)37010d63b7dSRichard Lowe fatal_mksh(const char *message, ...)
37110d63b7dSRichard Lowe {
37210d63b7dSRichard Lowe 	va_list args;
37310d63b7dSRichard Lowe 	char    *buf = static_buf;
37410d63b7dSRichard Lowe 	char	*mksh_fat_err = gettext("mksh: Fatal error: ");
37510d63b7dSRichard Lowe 	char	*cur_wrk_dir = gettext("Current working directory: ");
37610d63b7dSRichard Lowe 	int	mksh_fat_err_len = strlen(mksh_fat_err);
37710d63b7dSRichard Lowe 
37810d63b7dSRichard Lowe 	va_start(args, message);
37910d63b7dSRichard Lowe 	(void) fflush(stdout);
38010d63b7dSRichard Lowe 	(void) strcpy(buf, mksh_fat_err);
38110d63b7dSRichard Lowe 	size_t buf_len = vsnprintf(static_buf + mksh_fat_err_len,
38210d63b7dSRichard Lowe 				   sizeof(static_buf) - mksh_fat_err_len,
38310d63b7dSRichard Lowe 				   message, args)
38410d63b7dSRichard Lowe 			+ mksh_fat_err_len
38510d63b7dSRichard Lowe 			+ strlen(cur_wrk_dir)
38610d63b7dSRichard Lowe 			+ strlen(get_current_path_mksh())
38710d63b7dSRichard Lowe 			+ 3; // "\n\n"
38810d63b7dSRichard Lowe 	va_end(args);
38910d63b7dSRichard Lowe 	if (buf_len >= sizeof(static_buf)) {
39010d63b7dSRichard Lowe 		buf = getmem(buf_len);
39110d63b7dSRichard Lowe 		(void) strcpy(buf, mksh_fat_err);
39210d63b7dSRichard Lowe 		va_start(args, message);
39310d63b7dSRichard Lowe 		(void) vsprintf(buf + mksh_fat_err_len, message, args);
39410d63b7dSRichard Lowe 		va_end(args);
39510d63b7dSRichard Lowe 	}
39610d63b7dSRichard Lowe 	(void) strcat(buf, "\n");
39710d63b7dSRichard Lowe /*
39810d63b7dSRichard Lowe 	if (report_pwd) {
39910d63b7dSRichard Lowe  */
40010d63b7dSRichard Lowe 	if (1) {
40110d63b7dSRichard Lowe 		(void) strcat(buf, cur_wrk_dir);
40210d63b7dSRichard Lowe 		(void) strcat(buf, get_current_path_mksh());
40310d63b7dSRichard Lowe 		(void) strcat(buf, "\n");
40410d63b7dSRichard Lowe 	}
40510d63b7dSRichard Lowe 	(void) fputs(buf, stderr);
40610d63b7dSRichard Lowe 	(void) fflush(stderr);
40710d63b7dSRichard Lowe 	if (buf != static_buf) {
40810d63b7dSRichard Lowe 		retmem_mb(buf);
40910d63b7dSRichard Lowe 	}
41010d63b7dSRichard Lowe 	exit_status = 1;
41110d63b7dSRichard Lowe 	exit(1);
41210d63b7dSRichard Lowe }
41310d63b7dSRichard Lowe 
41410d63b7dSRichard Lowe /*
41510d63b7dSRichard Lowe  *	fatal_reader_mksh(format, args...)
41610d63b7dSRichard Lowe  *
41710d63b7dSRichard Lowe  *	Parameters:
41810d63b7dSRichard Lowe  *		format		printf style format string
41910d63b7dSRichard Lowe  *		args		arguments to match the format
42010d63b7dSRichard Lowe  */
42110d63b7dSRichard Lowe /*VARARGS*/
42210d63b7dSRichard Lowe void
fatal_reader_mksh(const char * pattern,...)42310d63b7dSRichard Lowe fatal_reader_mksh(const char * pattern, ...)
42410d63b7dSRichard Lowe {
42510d63b7dSRichard Lowe 	va_list args;
42610d63b7dSRichard Lowe 	char	message[1000];
42710d63b7dSRichard Lowe 
42810d63b7dSRichard Lowe 	va_start(args, pattern);
42910d63b7dSRichard Lowe /*
43010d63b7dSRichard Lowe 	if (file_being_read != NULL) {
43110d63b7dSRichard Lowe 		WCSTOMBS(mbs_buffer, file_being_read);
43210d63b7dSRichard Lowe 		if (line_number != 0) {
43310d63b7dSRichard Lowe 			(void) sprintf(message,
43410d63b7dSRichard Lowe 				       gettext("%s, line %d: %s"),
43510d63b7dSRichard Lowe 				       mbs_buffer,
43610d63b7dSRichard Lowe 				       line_number,
43710d63b7dSRichard Lowe 				       pattern);
43810d63b7dSRichard Lowe 		} else {
43910d63b7dSRichard Lowe 			(void) sprintf(message,
44010d63b7dSRichard Lowe 				       "%s: %s",
44110d63b7dSRichard Lowe 				       mbs_buffer,
44210d63b7dSRichard Lowe 				       pattern);
44310d63b7dSRichard Lowe 		}
44410d63b7dSRichard Lowe 		pattern = message;
44510d63b7dSRichard Lowe 	}
44610d63b7dSRichard Lowe  */
44710d63b7dSRichard Lowe 
44810d63b7dSRichard Lowe 	(void) fflush(stdout);
44910d63b7dSRichard Lowe 	(void) fprintf(stderr, gettext("mksh: Fatal error in reader: "));
45010d63b7dSRichard Lowe 	(void) vfprintf(stderr, pattern, args);
45110d63b7dSRichard Lowe 	(void) fprintf(stderr, "\n");
45210d63b7dSRichard Lowe 	va_end(args);
45310d63b7dSRichard Lowe 
45410d63b7dSRichard Lowe /*
45510d63b7dSRichard Lowe 	if (temp_file_name != NULL) {
45610d63b7dSRichard Lowe 		(void) fprintf(stderr,
45710d63b7dSRichard Lowe 			       gettext("mksh: Temp-file %s not removed\n"),
45810d63b7dSRichard Lowe 			       temp_file_name->string_mb);
45910d63b7dSRichard Lowe 		temp_file_name = NULL;
46010d63b7dSRichard Lowe 	}
46110d63b7dSRichard Lowe  */
46210d63b7dSRichard Lowe 
46310d63b7dSRichard Lowe /*
46410d63b7dSRichard Lowe 	if (report_pwd) {
46510d63b7dSRichard Lowe  */
46610d63b7dSRichard Lowe 	if (1) {
46710d63b7dSRichard Lowe 		(void) fprintf(stderr,
46810d63b7dSRichard Lowe 			       gettext("Current working directory %s\n"),
46910d63b7dSRichard Lowe 			       get_current_path_mksh());
47010d63b7dSRichard Lowe 	}
47110d63b7dSRichard Lowe 	(void) fflush(stderr);
47210d63b7dSRichard Lowe 	exit_status = 1;
47310d63b7dSRichard Lowe 	exit(1);
47410d63b7dSRichard Lowe }
47510d63b7dSRichard Lowe 
47610d63b7dSRichard Lowe /*
47710d63b7dSRichard Lowe  *	warning_mksh(format, args...)
47810d63b7dSRichard Lowe  *
47910d63b7dSRichard Lowe  *	Print a message and continue.
48010d63b7dSRichard Lowe  *
48110d63b7dSRichard Lowe  *	Parameters:
48210d63b7dSRichard Lowe  *		format		printf type format string
48310d63b7dSRichard Lowe  *		args		Arguments to match the format
48410d63b7dSRichard Lowe  */
48510d63b7dSRichard Lowe /*VARARGS*/
48610d63b7dSRichard Lowe void
warning_mksh(char * message,...)48710d63b7dSRichard Lowe warning_mksh(char * message, ...)
48810d63b7dSRichard Lowe {
48910d63b7dSRichard Lowe 	va_list args;
49010d63b7dSRichard Lowe 
49110d63b7dSRichard Lowe 	va_start(args, message);
49210d63b7dSRichard Lowe 	(void) fflush(stdout);
49310d63b7dSRichard Lowe 	(void) fprintf(stderr, gettext("mksh: Warning: "));
49410d63b7dSRichard Lowe 	(void) vfprintf(stderr, message, args);
49510d63b7dSRichard Lowe 	(void) fprintf(stderr, "\n");
49610d63b7dSRichard Lowe 	va_end(args);
49710d63b7dSRichard Lowe /*
49810d63b7dSRichard Lowe 	if (report_pwd) {
49910d63b7dSRichard Lowe  */
50010d63b7dSRichard Lowe 	if (1) {
50110d63b7dSRichard Lowe 		(void) fprintf(stderr,
50210d63b7dSRichard Lowe 			       gettext("Current working directory %s\n"),
50310d63b7dSRichard Lowe 			       get_current_path_mksh());
50410d63b7dSRichard Lowe 	}
50510d63b7dSRichard Lowe 	(void) fflush(stderr);
50610d63b7dSRichard Lowe }
50710d63b7dSRichard Lowe 
50810d63b7dSRichard Lowe /*
50910d63b7dSRichard Lowe  *	get_current_path_mksh()
51010d63b7dSRichard Lowe  *
51110d63b7dSRichard Lowe  *	Stuff current_path with the current path if it isnt there already.
51210d63b7dSRichard Lowe  *
51310d63b7dSRichard Lowe  *	Parameters:
51410d63b7dSRichard Lowe  *
51510d63b7dSRichard Lowe  *	Global variables used:
51610d63b7dSRichard Lowe  */
51710d63b7dSRichard Lowe char *
get_current_path_mksh(void)51810d63b7dSRichard Lowe get_current_path_mksh(void)
51910d63b7dSRichard Lowe {
52010d63b7dSRichard Lowe 	char			pwd[(MAXPATHLEN * MB_LEN_MAX)];
52110d63b7dSRichard Lowe 	static char		*current_path;
52210d63b7dSRichard Lowe 
52310d63b7dSRichard Lowe 	if (current_path == NULL) {
52410d63b7dSRichard Lowe 		getcwd(pwd, sizeof(pwd));
52510d63b7dSRichard Lowe 		if (pwd[0] == (int) nul_char) {
52610d63b7dSRichard Lowe 			pwd[0] = (int) slash_char;
52710d63b7dSRichard Lowe 			pwd[1] = (int) nul_char;
52810d63b7dSRichard Lowe 		}
52910d63b7dSRichard Lowe 		current_path = strdup(pwd);
53010d63b7dSRichard Lowe 	}
53110d63b7dSRichard Lowe 	return current_path;
53210d63b7dSRichard Lowe }
53310d63b7dSRichard Lowe 
53410d63b7dSRichard Lowe /*
53510d63b7dSRichard Lowe  *	append_prop(target, type)
53610d63b7dSRichard Lowe  *
53710d63b7dSRichard Lowe  *	Create a new property and append it to the property list of a Name.
53810d63b7dSRichard Lowe  *
53910d63b7dSRichard Lowe  *	Return value:
54010d63b7dSRichard Lowe  *				A new property block for the target
54110d63b7dSRichard Lowe  *
54210d63b7dSRichard Lowe  *	Parameters:
54310d63b7dSRichard Lowe  *		target		The target that wants a new property
54410d63b7dSRichard Lowe  *		type		The type of property being requested
54510d63b7dSRichard Lowe  *
54610d63b7dSRichard Lowe  *	Global variables used:
54710d63b7dSRichard Lowe  */
54810d63b7dSRichard Lowe Property
append_prop(Name target,Property_id type)549*e7afc443SToomas Soome append_prop(Name target, Property_id type)
55010d63b7dSRichard Lowe {
551*e7afc443SToomas Soome 	Property	*insert = &target->prop;
552*e7afc443SToomas Soome 	Property	prop = *insert;
553*e7afc443SToomas Soome 	int		size;
55410d63b7dSRichard Lowe 
55510d63b7dSRichard Lowe 	switch (type) {
55610d63b7dSRichard Lowe 	case conditional_prop:
55710d63b7dSRichard Lowe 		size = sizeof (struct Conditional);
55810d63b7dSRichard Lowe 		break;
55910d63b7dSRichard Lowe 	case line_prop:
56010d63b7dSRichard Lowe 		size = sizeof (struct Line);
56110d63b7dSRichard Lowe 		break;
56210d63b7dSRichard Lowe 	case macro_prop:
56310d63b7dSRichard Lowe 		size = sizeof (struct _Macro);
56410d63b7dSRichard Lowe 		break;
56510d63b7dSRichard Lowe 	case makefile_prop:
56610d63b7dSRichard Lowe 		size = sizeof (struct Makefile);
56710d63b7dSRichard Lowe 		break;
56810d63b7dSRichard Lowe 	case member_prop:
56910d63b7dSRichard Lowe 		size = sizeof (struct Member);
57010d63b7dSRichard Lowe 		break;
57110d63b7dSRichard Lowe 	case recursive_prop:
57210d63b7dSRichard Lowe 		size = sizeof (struct Recursive);
57310d63b7dSRichard Lowe 		break;
57410d63b7dSRichard Lowe 	case sccs_prop:
57510d63b7dSRichard Lowe 		size = sizeof (struct Sccs);
57610d63b7dSRichard Lowe 		break;
57710d63b7dSRichard Lowe 	case suffix_prop:
57810d63b7dSRichard Lowe 		size = sizeof (struct Suffix);
57910d63b7dSRichard Lowe 		break;
58010d63b7dSRichard Lowe 	case target_prop:
58110d63b7dSRichard Lowe 		size = sizeof (struct Target);
58210d63b7dSRichard Lowe 		break;
58310d63b7dSRichard Lowe 	case time_prop:
58410d63b7dSRichard Lowe 		size = sizeof (struct STime);
58510d63b7dSRichard Lowe 		break;
58610d63b7dSRichard Lowe 	case vpath_alias_prop:
58710d63b7dSRichard Lowe 		size = sizeof (struct Vpath_alias);
58810d63b7dSRichard Lowe 		break;
58910d63b7dSRichard Lowe 	case long_member_name_prop:
59010d63b7dSRichard Lowe 		size = sizeof (struct Long_member_name);
59110d63b7dSRichard Lowe 		break;
59210d63b7dSRichard Lowe 	case macro_append_prop:
59310d63b7dSRichard Lowe 		size = sizeof (struct _Macro_appendix);
59410d63b7dSRichard Lowe 		break;
59510d63b7dSRichard Lowe 	case env_mem_prop:
59610d63b7dSRichard Lowe 		size = sizeof (struct _Env_mem);
59710d63b7dSRichard Lowe 		break;
59810d63b7dSRichard Lowe 	default:
59910d63b7dSRichard Lowe 		fatal_mksh(gettext("Internal error. Unknown prop type %d"), type);
60010d63b7dSRichard Lowe 	}
60110d63b7dSRichard Lowe 	for (; prop != NULL; insert = &prop->next, prop = *insert);
60210d63b7dSRichard Lowe 	size += PROPERTY_HEAD_SIZE;
60310d63b7dSRichard Lowe 	*insert = prop = (Property) getmem(size);
60410d63b7dSRichard Lowe 	memset((char *) prop, 0, size);
60510d63b7dSRichard Lowe 	prop->type = type;
60610d63b7dSRichard Lowe 	prop->next = NULL;
60710d63b7dSRichard Lowe 	return prop;
60810d63b7dSRichard Lowe }
60910d63b7dSRichard Lowe 
61010d63b7dSRichard Lowe /*
61110d63b7dSRichard Lowe  *	maybe_append_prop(target, type)
61210d63b7dSRichard Lowe  *
61310d63b7dSRichard Lowe  *	Append a property to the Name if none of this type exists
61410d63b7dSRichard Lowe  *	else return the one already there
61510d63b7dSRichard Lowe  *
61610d63b7dSRichard Lowe  *	Return value:
61710d63b7dSRichard Lowe  *				A property of the requested type for the target
61810d63b7dSRichard Lowe  *
61910d63b7dSRichard Lowe  *	Parameters:
62010d63b7dSRichard Lowe  *		target		The target that wants a new property
62110d63b7dSRichard Lowe  *		type		The type of property being requested
62210d63b7dSRichard Lowe  *
62310d63b7dSRichard Lowe  *	Global variables used:
62410d63b7dSRichard Lowe  */
62510d63b7dSRichard Lowe Property
maybe_append_prop(Name target,Property_id type)626*e7afc443SToomas Soome maybe_append_prop(Name target, Property_id type)
62710d63b7dSRichard Lowe {
628*e7afc443SToomas Soome 	Property	prop;
62910d63b7dSRichard Lowe 
63010d63b7dSRichard Lowe 	if ((prop = get_prop(target->prop, type)) != NULL) {
63110d63b7dSRichard Lowe 		return prop;
63210d63b7dSRichard Lowe 	}
63310d63b7dSRichard Lowe 	return append_prop(target, type);
63410d63b7dSRichard Lowe }
63510d63b7dSRichard Lowe 
63610d63b7dSRichard Lowe /*
63710d63b7dSRichard Lowe  *	get_prop(start, type)
63810d63b7dSRichard Lowe  *
63910d63b7dSRichard Lowe  *	Scan the property list of a Name to find the next property
64010d63b7dSRichard Lowe  *	of a given type.
64110d63b7dSRichard Lowe  *
64210d63b7dSRichard Lowe  *	Return value:
64310d63b7dSRichard Lowe  *				The first property of the type, if any left
64410d63b7dSRichard Lowe  *
64510d63b7dSRichard Lowe  *	Parameters:
64610d63b7dSRichard Lowe  *		start		The first property block to check for type
64710d63b7dSRichard Lowe  *		type		The type of property block we need
64810d63b7dSRichard Lowe  *
64910d63b7dSRichard Lowe  *	Global variables used:
65010d63b7dSRichard Lowe  */
65110d63b7dSRichard Lowe Property
get_prop(Property start,Property_id type)652*e7afc443SToomas Soome get_prop(Property start, Property_id type)
65310d63b7dSRichard Lowe {
65410d63b7dSRichard Lowe 	for (; start != NULL; start = start->next) {
65510d63b7dSRichard Lowe 		if (start->type == type) {
65610d63b7dSRichard Lowe 			return start;
65710d63b7dSRichard Lowe 		}
65810d63b7dSRichard Lowe 	}
65910d63b7dSRichard Lowe 	return NULL;
66010d63b7dSRichard Lowe }
66110d63b7dSRichard Lowe 
66210d63b7dSRichard Lowe /*
66310d63b7dSRichard Lowe  *	append_string(from, to, length)
66410d63b7dSRichard Lowe  *
66510d63b7dSRichard Lowe  *	Append a C string to a make string expanding it if nessecary
66610d63b7dSRichard Lowe  *
66710d63b7dSRichard Lowe  *	Parameters:
66810d63b7dSRichard Lowe  *		from		The source (C style) string
66910d63b7dSRichard Lowe  *		to		The destination (make style) string
67010d63b7dSRichard Lowe  *		length		The length of the from string
67110d63b7dSRichard Lowe  *
67210d63b7dSRichard Lowe  *	Global variables used:
67310d63b7dSRichard Lowe  */
67410d63b7dSRichard Lowe void
append_string(wchar_t * from,String to,int length)675*e7afc443SToomas Soome append_string(wchar_t *from, String to, int length)
67610d63b7dSRichard Lowe {
67710d63b7dSRichard Lowe 	if (length == FIND_LENGTH) {
67810d63b7dSRichard Lowe 		length = wcslen(from);
67910d63b7dSRichard Lowe 	}
68010d63b7dSRichard Lowe 	if (to->buffer.start == NULL) {
68110d63b7dSRichard Lowe 		expand_string(to, 32 + length);
68210d63b7dSRichard Lowe 	}
68310d63b7dSRichard Lowe 	if (to->buffer.end - to->text.p <= length) {
68410d63b7dSRichard Lowe 		expand_string(to,
68510d63b7dSRichard Lowe 			      (to->buffer.end - to->buffer.start) * 2 +
68610d63b7dSRichard Lowe 			      length);
68710d63b7dSRichard Lowe 	}
68810d63b7dSRichard Lowe 	if (length > 0) {
68910d63b7dSRichard Lowe 		(void) wcsncpy(to->text.p, from, length);
69010d63b7dSRichard Lowe 		to->text.p += length;
69110d63b7dSRichard Lowe 	}
69210d63b7dSRichard Lowe 	*(to->text.p) = (int) nul_char;
69310d63b7dSRichard Lowe }
69410d63b7dSRichard Lowe 
get_wstring(char * from)69510d63b7dSRichard Lowe wchar_t * get_wstring(char *from) {
69610d63b7dSRichard Lowe 	if(from == NULL) {
69710d63b7dSRichard Lowe 		return NULL;
69810d63b7dSRichard Lowe 	}
69910d63b7dSRichard Lowe 	getwstring_count++;
70010d63b7dSRichard Lowe 	wchar_t * wcbuf = ALLOC_WC(strlen(from) + 1);
70110d63b7dSRichard Lowe 	mbstowcs(wcbuf, from, strlen(from)+1);
70210d63b7dSRichard Lowe 	return wcbuf;
70310d63b7dSRichard Lowe }
70410d63b7dSRichard Lowe 
70510d63b7dSRichard Lowe void
append_string(char * from,String to,int length)706*e7afc443SToomas Soome append_string(char *from, String to, int length)
70710d63b7dSRichard Lowe {
70810d63b7dSRichard Lowe 	if (length == FIND_LENGTH) {
70910d63b7dSRichard Lowe 		length = strlen(from);
71010d63b7dSRichard Lowe 	}
71110d63b7dSRichard Lowe 	if (to->buffer.start == NULL) {
71210d63b7dSRichard Lowe 		expand_string(to, 32 + length);
71310d63b7dSRichard Lowe 	}
71410d63b7dSRichard Lowe 	if (to->buffer.end - to->text.p <= length) {
71510d63b7dSRichard Lowe 		expand_string(to,
71610d63b7dSRichard Lowe 			      (to->buffer.end - to->buffer.start) * 2 +
71710d63b7dSRichard Lowe 			      length);
71810d63b7dSRichard Lowe 	}
71910d63b7dSRichard Lowe 	if (length > 0) {
72010d63b7dSRichard Lowe 		(void) mbstowcs(to->text.p, from, length);
72110d63b7dSRichard Lowe 		to->text.p += length;
72210d63b7dSRichard Lowe 	}
72310d63b7dSRichard Lowe 	*(to->text.p) = (int) nul_char;
72410d63b7dSRichard Lowe }
72510d63b7dSRichard Lowe 
72610d63b7dSRichard Lowe /*
72710d63b7dSRichard Lowe  *	expand_string(string, length)
72810d63b7dSRichard Lowe  *
72910d63b7dSRichard Lowe  *	Allocate more memory for strings that run out of space.
73010d63b7dSRichard Lowe  *
73110d63b7dSRichard Lowe  *	Parameters:
73210d63b7dSRichard Lowe  *		string		The make style string we want to expand
73310d63b7dSRichard Lowe  *		length		The new length we need
73410d63b7dSRichard Lowe  *
73510d63b7dSRichard Lowe  *	Global variables used:
73610d63b7dSRichard Lowe  */
73710d63b7dSRichard Lowe static void
expand_string(String string,int length)738*e7afc443SToomas Soome expand_string(String string, int length)
73910d63b7dSRichard Lowe {
740*e7afc443SToomas Soome 	wchar_t	*p;
74110d63b7dSRichard Lowe 
74210d63b7dSRichard Lowe 	if (string->buffer.start == NULL) {
74310d63b7dSRichard Lowe 		/* For strings that have no memory allocated */
74410d63b7dSRichard Lowe 		string->buffer.start =
74510d63b7dSRichard Lowe 		  string->text.p =
74610d63b7dSRichard Lowe 		    string->text.end =
74710d63b7dSRichard Lowe 		      ALLOC_WC(length);
74810d63b7dSRichard Lowe 		string->buffer.end = string->buffer.start + length;
74910d63b7dSRichard Lowe 		string->text.p[0] = (int) nul_char;
75010d63b7dSRichard Lowe 		string->free_after_use = true;
75110d63b7dSRichard Lowe 		expandstring_count++;
75210d63b7dSRichard Lowe 		return;
75310d63b7dSRichard Lowe 	}
75410d63b7dSRichard Lowe 	if (string->buffer.end - string->buffer.start >= length) {
75510d63b7dSRichard Lowe 		/* If we really don't need more memory. */
75610d63b7dSRichard Lowe 		return;
75710d63b7dSRichard Lowe 	}
75810d63b7dSRichard Lowe 	/*
75910d63b7dSRichard Lowe 	 * Get more memory, copy the string and free the old buffer if
76010d63b7dSRichard Lowe 	 * it is was malloc()'ed.
76110d63b7dSRichard Lowe 	 */
76210d63b7dSRichard Lowe 	expandstring_count++;
76310d63b7dSRichard Lowe 	p = ALLOC_WC(length);
76410d63b7dSRichard Lowe 	(void) wcscpy(p, string->buffer.start);
76510d63b7dSRichard Lowe 	string->text.p = p + (string->text.p - string->buffer.start);
76610d63b7dSRichard Lowe 	string->text.end = p + (string->text.end - string->buffer.start);
76710d63b7dSRichard Lowe 	string->buffer.end = p + length;
76810d63b7dSRichard Lowe 	if (string->free_after_use) {
76910d63b7dSRichard Lowe 		retmem(string->buffer.start);
77010d63b7dSRichard Lowe 	}
77110d63b7dSRichard Lowe 	string->buffer.start = p;
77210d63b7dSRichard Lowe 	string->free_after_use = true;
77310d63b7dSRichard Lowe }
77410d63b7dSRichard Lowe 
77510d63b7dSRichard Lowe /*
77610d63b7dSRichard Lowe  *	append_char(from, to)
77710d63b7dSRichard Lowe  *
77810d63b7dSRichard Lowe  *	Append one char to a make string expanding it if nessecary
77910d63b7dSRichard Lowe  *
78010d63b7dSRichard Lowe  *	Parameters:
78110d63b7dSRichard Lowe  *		from		Single character to append to string
78210d63b7dSRichard Lowe  *		to		The destination (make style) string
78310d63b7dSRichard Lowe  *
78410d63b7dSRichard Lowe  *	Global variables used:
78510d63b7dSRichard Lowe  */
78610d63b7dSRichard Lowe void
append_char(wchar_t from,String to)787*e7afc443SToomas Soome append_char(wchar_t from, String to)
78810d63b7dSRichard Lowe {
78910d63b7dSRichard Lowe 	if (to->buffer.start == NULL) {
79010d63b7dSRichard Lowe 		expand_string(to, 32);
79110d63b7dSRichard Lowe 	}
79210d63b7dSRichard Lowe 	if (to->buffer.end - to->text.p <= 2) {
79310d63b7dSRichard Lowe 		expand_string(to, to->buffer.end - to->buffer.start + 32);
79410d63b7dSRichard Lowe 	}
79510d63b7dSRichard Lowe 	*(to->text.p)++ = from;
79610d63b7dSRichard Lowe 	*(to->text.p) = (int) nul_char;
79710d63b7dSRichard Lowe }
79810d63b7dSRichard Lowe 
79910d63b7dSRichard Lowe /*
80010d63b7dSRichard Lowe  *	handle_interrupt_mksh()
80110d63b7dSRichard Lowe  *
80210d63b7dSRichard Lowe  *	This is where C-C traps are caught.
80310d63b7dSRichard Lowe  */
80410d63b7dSRichard Lowe void
handle_interrupt_mksh(int)80510d63b7dSRichard Lowe handle_interrupt_mksh(int)
80610d63b7dSRichard Lowe {
80710d63b7dSRichard Lowe 	(void) fflush(stdout);
80810d63b7dSRichard Lowe 	/* Make sure the processes running under us terminate first. */
80910d63b7dSRichard Lowe 	if (childPid > 0) {
81010d63b7dSRichard Lowe 		kill(childPid, SIGTERM);
81110d63b7dSRichard Lowe 		childPid = -1;
81210d63b7dSRichard Lowe 	}
81310d63b7dSRichard Lowe 	while (wait((int *) NULL) != -1);
81410d63b7dSRichard Lowe 	exit_status = 2;
81510d63b7dSRichard Lowe 	exit(2);
81610d63b7dSRichard Lowe }
81710d63b7dSRichard Lowe 
81810d63b7dSRichard Lowe /*
81910d63b7dSRichard Lowe  *	setup_interrupt()
82010d63b7dSRichard Lowe  *
82110d63b7dSRichard Lowe  *	This routine saves the original interrupt handler pointers
82210d63b7dSRichard Lowe  *
82310d63b7dSRichard Lowe  *	Parameters:
82410d63b7dSRichard Lowe  *
82510d63b7dSRichard Lowe  *	Static variables used:
82610d63b7dSRichard Lowe  *		sigivalue	The original signal handler
82710d63b7dSRichard Lowe  *		sigqvalue	The original signal handler
82810d63b7dSRichard Lowe  *		sigtvalue	The original signal handler
82910d63b7dSRichard Lowe  *		sighvalue	The original signal handler
83010d63b7dSRichard Lowe  */
83110d63b7dSRichard Lowe void
setup_interrupt(void (* handler)(int))832*e7afc443SToomas Soome setup_interrupt(void (*handler) (int))
83310d63b7dSRichard Lowe {
83410d63b7dSRichard Lowe 	sigivalue = bsd_signal(SIGINT, SIG_IGN);
83510d63b7dSRichard Lowe 	sigqvalue = bsd_signal(SIGQUIT, SIG_IGN);
83610d63b7dSRichard Lowe 	sigtvalue = bsd_signal(SIGTERM, SIG_IGN);
83710d63b7dSRichard Lowe 	sighvalue = bsd_signal(SIGHUP, SIG_IGN);
83810d63b7dSRichard Lowe 	enable_interrupt(handler);
83910d63b7dSRichard Lowe }
84010d63b7dSRichard Lowe 
84110d63b7dSRichard Lowe 
84210d63b7dSRichard Lowe void
mbstowcs_with_check(wchar_t * pwcs,const char * s,size_t n)84310d63b7dSRichard Lowe mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n)
84410d63b7dSRichard Lowe {
84510d63b7dSRichard Lowe 	if(mbstowcs(pwcs, s, n) == -1) {
84610d63b7dSRichard Lowe 		fatal_mksh(gettext("The string `%s' is not valid in current locale"), s);
84710d63b7dSRichard Lowe 	}
84810d63b7dSRichard Lowe }
84910d63b7dSRichard Lowe 
85010d63b7dSRichard Lowe 
85110d63b7dSRichard Lowe 
Wstring()85210d63b7dSRichard Lowe Wstring::Wstring()
85310d63b7dSRichard Lowe {
85410d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(string, string_buf);
85510d63b7dSRichard Lowe }
85610d63b7dSRichard Lowe 
Wstring(struct _Name * name)85710d63b7dSRichard Lowe Wstring::Wstring(struct _Name * name)
85810d63b7dSRichard Lowe {
85910d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(string, string_buf);
86010d63b7dSRichard Lowe 	append_string(name->string_mb, &string, name->hash.length);
86110d63b7dSRichard Lowe }
86210d63b7dSRichard Lowe 
~Wstring()86310d63b7dSRichard Lowe Wstring::~Wstring()
86410d63b7dSRichard Lowe {
86510d63b7dSRichard Lowe 	if(string.free_after_use) {
86610d63b7dSRichard Lowe 		retmem(string.buffer.start);
86710d63b7dSRichard Lowe 	}
86810d63b7dSRichard Lowe }
86910d63b7dSRichard Lowe 
87010d63b7dSRichard Lowe void
init(struct _Name * name)87110d63b7dSRichard Lowe Wstring::init(struct _Name * name)
87210d63b7dSRichard Lowe {
87310d63b7dSRichard Lowe 	if(string.free_after_use) {
87410d63b7dSRichard Lowe 		retmem(string.buffer.start);
87510d63b7dSRichard Lowe 	}
87610d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(string, string_buf);
87710d63b7dSRichard Lowe 	append_string(name->string_mb, &string, name->hash.length);
87810d63b7dSRichard Lowe }
87910d63b7dSRichard Lowe 
88010d63b7dSRichard Lowe void
init(wchar_t * name,unsigned length)88110d63b7dSRichard Lowe Wstring::init(wchar_t * name, unsigned length)
88210d63b7dSRichard Lowe {
88310d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(string, string_buf);
88410d63b7dSRichard Lowe 	append_string(name, &string, length);
88510d63b7dSRichard Lowe 	string.buffer.start[length] = 0;
88610d63b7dSRichard Lowe }
88710d63b7dSRichard Lowe 
88810d63b7dSRichard Lowe Boolean
equaln(wchar_t * str,unsigned length)88910d63b7dSRichard Lowe Wstring::equaln(wchar_t * str, unsigned length)
89010d63b7dSRichard Lowe {
89110d63b7dSRichard Lowe 	return (Boolean)IS_WEQUALN(string.buffer.start, str, length);
89210d63b7dSRichard Lowe }
89310d63b7dSRichard Lowe 
89410d63b7dSRichard Lowe Boolean
equaln(Wstring * str,unsigned length)89510d63b7dSRichard Lowe Wstring::equaln(Wstring * str, unsigned length)
89610d63b7dSRichard Lowe {
89710d63b7dSRichard Lowe 	return (Boolean)IS_WEQUALN(string.buffer.start, str->string.buffer.start, length);
89810d63b7dSRichard Lowe }
89910d63b7dSRichard Lowe 
90010d63b7dSRichard Lowe Boolean
equal(wchar_t * str,unsigned off,unsigned length)90110d63b7dSRichard Lowe Wstring::equal(wchar_t * str, unsigned off, unsigned length)
90210d63b7dSRichard Lowe {
90310d63b7dSRichard Lowe 	return (Boolean)IS_WEQUALN(string.buffer.start + off, str, length);
90410d63b7dSRichard Lowe }
90510d63b7dSRichard Lowe 
90610d63b7dSRichard Lowe Boolean
equal(wchar_t * str,unsigned off)90710d63b7dSRichard Lowe Wstring::equal(wchar_t * str, unsigned off)
90810d63b7dSRichard Lowe {
90910d63b7dSRichard Lowe 	return (Boolean)IS_WEQUAL(string.buffer.start + off, str);
91010d63b7dSRichard Lowe }
91110d63b7dSRichard Lowe 
91210d63b7dSRichard Lowe Boolean
equal(wchar_t * str)91310d63b7dSRichard Lowe Wstring::equal(wchar_t * str)
91410d63b7dSRichard Lowe {
91510d63b7dSRichard Lowe 	return equal(str, 0);
91610d63b7dSRichard Lowe }
91710d63b7dSRichard Lowe 
91810d63b7dSRichard Lowe Boolean
equal(Wstring * str,unsigned off,unsigned length)91910d63b7dSRichard Lowe Wstring::equal(Wstring * str, unsigned off, unsigned length)
92010d63b7dSRichard Lowe {
92110d63b7dSRichard Lowe 	return (Boolean)IS_WEQUALN(string.buffer.start + off, str->string.buffer.start, length);
92210d63b7dSRichard Lowe }
92310d63b7dSRichard Lowe 
92410d63b7dSRichard Lowe Boolean
equal(Wstring * str)92510d63b7dSRichard Lowe Wstring::equal(Wstring * str)
92610d63b7dSRichard Lowe {
92710d63b7dSRichard Lowe 	return equal(str, 0);
92810d63b7dSRichard Lowe }
92910d63b7dSRichard Lowe 
93010d63b7dSRichard Lowe Boolean
equal(Wstring * str,unsigned off)93110d63b7dSRichard Lowe Wstring::equal(Wstring * str, unsigned off)
93210d63b7dSRichard Lowe {
93310d63b7dSRichard Lowe 	return (Boolean)IS_WEQUAL(string.buffer.start + off, str->string.buffer.start);
93410d63b7dSRichard Lowe }
93510d63b7dSRichard Lowe 
93610d63b7dSRichard Lowe void
append_to_str(struct _String * str,unsigned off,unsigned length)93710d63b7dSRichard Lowe Wstring::append_to_str(struct _String * str, unsigned off, unsigned length)
93810d63b7dSRichard Lowe {
93910d63b7dSRichard Lowe 	append_string(string.buffer.start + off, str, length);
94010d63b7dSRichard Lowe }
94110d63b7dSRichard Lowe 
94210d63b7dSRichard Lowe Name
lookup(const char * key)94310d63b7dSRichard Lowe Name_set::lookup(const char *key)
94410d63b7dSRichard Lowe {
94510d63b7dSRichard Lowe 	for (entry *node = root; node != 0;) {
94610d63b7dSRichard Lowe 		int res = strcmp(key, node->name->string_mb);
94710d63b7dSRichard Lowe 		if (res < 0) {
94810d63b7dSRichard Lowe 			node = node->left;
94910d63b7dSRichard Lowe 		} else if (res > 0) {
95010d63b7dSRichard Lowe 			node = node->right;
95110d63b7dSRichard Lowe 		} else {
95210d63b7dSRichard Lowe 			return node->name;
95310d63b7dSRichard Lowe 		}
95410d63b7dSRichard Lowe 	}
95510d63b7dSRichard Lowe 	return 0;
95610d63b7dSRichard Lowe }
95710d63b7dSRichard Lowe 
95810d63b7dSRichard Lowe Name
insert(const char * key,Boolean & found)95910d63b7dSRichard Lowe Name_set::insert(const char *key, Boolean &found)
96010d63b7dSRichard Lowe {
96110d63b7dSRichard Lowe 	Name	name = 0;
96210d63b7dSRichard Lowe 
96310d63b7dSRichard Lowe 	if (root != 0) {
96410d63b7dSRichard Lowe 		for (entry *node = root; name == 0;) {
96510d63b7dSRichard Lowe 			int res = strcmp(key, node->name->string_mb);
96610d63b7dSRichard Lowe 			if (res < 0) {
96710d63b7dSRichard Lowe 				if (node->left != 0) {
96810d63b7dSRichard Lowe 					node = node->left;
96910d63b7dSRichard Lowe 				} else {
97010d63b7dSRichard Lowe 					found = false;
97110d63b7dSRichard Lowe 					name = ALLOC(Name);
97210d63b7dSRichard Lowe 
97310d63b7dSRichard Lowe 					node->left = new entry(name, node);
97410d63b7dSRichard Lowe 					rebalance(node);
97510d63b7dSRichard Lowe 				}
97610d63b7dSRichard Lowe 			} else if (res > 0) {
97710d63b7dSRichard Lowe 				if (node->right != 0) {
97810d63b7dSRichard Lowe 					node = node->right;
97910d63b7dSRichard Lowe 				} else {
98010d63b7dSRichard Lowe 					found = false;
98110d63b7dSRichard Lowe 					name = ALLOC(Name);
98210d63b7dSRichard Lowe 
98310d63b7dSRichard Lowe 					node->right = new entry(name, node);
98410d63b7dSRichard Lowe 					rebalance(node);
98510d63b7dSRichard Lowe 				}
98610d63b7dSRichard Lowe 			} else {
98710d63b7dSRichard Lowe 				found = true;
98810d63b7dSRichard Lowe 				name = node->name;
98910d63b7dSRichard Lowe 			}
99010d63b7dSRichard Lowe 		}
99110d63b7dSRichard Lowe 	} else {
99210d63b7dSRichard Lowe 		found = false;
99310d63b7dSRichard Lowe 		name = ALLOC(Name);
99410d63b7dSRichard Lowe 
99510d63b7dSRichard Lowe 		root = new entry(name, 0);
99610d63b7dSRichard Lowe 	}
99710d63b7dSRichard Lowe 	return name;
99810d63b7dSRichard Lowe }
99910d63b7dSRichard Lowe 
100010d63b7dSRichard Lowe void
insert(Name name)100110d63b7dSRichard Lowe Name_set::insert(Name name) {
100210d63b7dSRichard Lowe 	if (root != 0) {
100310d63b7dSRichard Lowe 		for (entry *node = root;;) {
100410d63b7dSRichard Lowe 			int res = strcmp(name->string_mb, node->name->string_mb);
100510d63b7dSRichard Lowe 			if (res < 0) {
100610d63b7dSRichard Lowe 				if (node->left != 0) {
100710d63b7dSRichard Lowe 					node = node->left;
100810d63b7dSRichard Lowe 				} else {
100910d63b7dSRichard Lowe 					node->left = new entry(name, node);
101010d63b7dSRichard Lowe 					rebalance(node);
101110d63b7dSRichard Lowe 					break;
101210d63b7dSRichard Lowe 				}
101310d63b7dSRichard Lowe 			} else if (res > 0) {
101410d63b7dSRichard Lowe 				if (node->right != 0) {
101510d63b7dSRichard Lowe 					node = node->right;
101610d63b7dSRichard Lowe 				} else {
101710d63b7dSRichard Lowe 					node->right = new entry(name, node);
101810d63b7dSRichard Lowe 					rebalance(node);
101910d63b7dSRichard Lowe 					break;
102010d63b7dSRichard Lowe 				}
102110d63b7dSRichard Lowe 			} else {
102210d63b7dSRichard Lowe 				// should be an error: inserting already existing name
102310d63b7dSRichard Lowe 				break;
102410d63b7dSRichard Lowe 			}
102510d63b7dSRichard Lowe 		}
102610d63b7dSRichard Lowe 	} else {
102710d63b7dSRichard Lowe 		root = new entry(name, 0);
102810d63b7dSRichard Lowe 	}
102910d63b7dSRichard Lowe }
103010d63b7dSRichard Lowe 
103110d63b7dSRichard Lowe void
rebalance(Name_set::entry * node)103210d63b7dSRichard Lowe Name_set::rebalance(Name_set::entry *node) {
103310d63b7dSRichard Lowe 	for (; node != 0; node = node->parent) {
103410d63b7dSRichard Lowe 		entry *right = node->right;
103510d63b7dSRichard Lowe 		entry *left = node->left;
103610d63b7dSRichard Lowe 
103710d63b7dSRichard Lowe 		unsigned rdepth = (right != 0) ? right->depth : 0;
103810d63b7dSRichard Lowe 		unsigned ldepth = (left != 0) ? left->depth : 0;
103910d63b7dSRichard Lowe 
104010d63b7dSRichard Lowe 		if (ldepth > rdepth + 1) {
104110d63b7dSRichard Lowe 			if ((node->left = left->right) != 0) {
104210d63b7dSRichard Lowe 				left->right->parent = node;
104310d63b7dSRichard Lowe 			}
104410d63b7dSRichard Lowe 			if ((left->parent = node->parent) != 0) {
104510d63b7dSRichard Lowe 				if (node == node->parent->right) {
104610d63b7dSRichard Lowe 					node->parent->right = left;
104710d63b7dSRichard Lowe 				} else {
104810d63b7dSRichard Lowe 					node->parent->left = left;
104910d63b7dSRichard Lowe 				}
105010d63b7dSRichard Lowe 			} else {
105110d63b7dSRichard Lowe 				root = left;
105210d63b7dSRichard Lowe 			}
105310d63b7dSRichard Lowe 			left->right = node;
105410d63b7dSRichard Lowe 			node->parent = left;
105510d63b7dSRichard Lowe 
105610d63b7dSRichard Lowe 			node->setup_depth();
105710d63b7dSRichard Lowe 			node = left;
105810d63b7dSRichard Lowe 		} else if (rdepth > ldepth + 1) {
105910d63b7dSRichard Lowe 			if ((node->right = right->left) != 0) {
106010d63b7dSRichard Lowe 				right->left->parent = node;
106110d63b7dSRichard Lowe 			}
106210d63b7dSRichard Lowe 			if ((right->parent = node->parent) != 0) {
106310d63b7dSRichard Lowe 				if (node == node->parent->right) {
106410d63b7dSRichard Lowe 					node->parent->right = right;
106510d63b7dSRichard Lowe 				} else {
106610d63b7dSRichard Lowe 					node->parent->left = right;
106710d63b7dSRichard Lowe 				}
106810d63b7dSRichard Lowe 			} else {
106910d63b7dSRichard Lowe 				root = right;
107010d63b7dSRichard Lowe 			}
107110d63b7dSRichard Lowe 			right->left = node;
107210d63b7dSRichard Lowe 			node->parent = right;
107310d63b7dSRichard Lowe 
107410d63b7dSRichard Lowe 			node->setup_depth();
107510d63b7dSRichard Lowe 			node = right;
107610d63b7dSRichard Lowe 		}
107710d63b7dSRichard Lowe 		node->setup_depth();
107810d63b7dSRichard Lowe 	}
107910d63b7dSRichard Lowe }
108010d63b7dSRichard Lowe 
108110d63b7dSRichard Lowe Name_set::iterator
begin() const108210d63b7dSRichard Lowe Name_set::begin() const {
108310d63b7dSRichard Lowe 	for (entry *node = root; node != 0; node = node->left) {
108410d63b7dSRichard Lowe 		if (node->left == 0) {
108510d63b7dSRichard Lowe 			return iterator(node);
108610d63b7dSRichard Lowe 		}
108710d63b7dSRichard Lowe 	}
108810d63b7dSRichard Lowe 	return iterator();
108910d63b7dSRichard Lowe }
109010d63b7dSRichard Lowe 
109110d63b7dSRichard Lowe Name_set::iterator&
operator ++()109210d63b7dSRichard Lowe Name_set::iterator::operator++() {
109310d63b7dSRichard Lowe 	if (node != 0) {
109410d63b7dSRichard Lowe 		if (node->right != 0) {
109510d63b7dSRichard Lowe 			node = node->right;
109610d63b7dSRichard Lowe 			while (node->left != 0) {
109710d63b7dSRichard Lowe 				node = node->left;
109810d63b7dSRichard Lowe 			}
109910d63b7dSRichard Lowe 		} else {
110010d63b7dSRichard Lowe 			while ((node->parent != 0) && (node->parent->right == node)) {
110110d63b7dSRichard Lowe 				node = node->parent;
110210d63b7dSRichard Lowe 			}
110310d63b7dSRichard Lowe 			node = node->parent;
110410d63b7dSRichard Lowe 		}
110510d63b7dSRichard Lowe 	}
110610d63b7dSRichard Lowe 	return *this;
110710d63b7dSRichard Lowe }
1108