1#ifndef _MKSH_DEFS_H
2#define _MKSH_DEFS_H
3/*
4 * CDDL HEADER START
5 *
6 * The contents of this file are subject to the terms of the
7 * Common Development and Distribution License (the "License").
8 * You may not use this file except in compliance with the License.
9 *
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23/*
24 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#include <limits.h>		/* MB_LEN_MAX */
29#include <stdio.h>
30#include <stdlib.h>		/* wchar_t */
31#include <string.h>		/* strcmp() */
32#include <sys/param.h>		/* MAXPATHLEN */
33#include <sys/types.h>		/* time_t, caddr_t */
34#include <vroot/vroot.h>	/* pathpt */
35#include <sys/time.h>		/* timestruc_t */
36#include <errno.h>		/* errno */
37
38#include <wctype.h>
39
40/*
41 * A type and some utilities for boolean values
42 */
43
44#define	false	BOOLEAN_false
45#define	true	BOOLEAN_true
46
47typedef enum {
48	false =		0,
49	true =		1,
50	failed =	0,
51	succeeded =	1
52} Boolean;
53#define BOOLEAN(expr)		((expr) ? true : false)
54
55/*
56 * Some random constants (in an enum so dbx knows their values)
57 */
58enum {
59	update_delay = 30,		/* time between rstat checks */
60	ar_member_name_len = 1024,
61	hashsize = 2048			/* size of hash table */
62};
63
64
65/*
66 * Symbols that defines all the different char constants make uses
67 */
68enum {
69	ampersand_char =	'&',
70	asterisk_char =		'*',
71	at_char =		'@',
72	backquote_char =	'`',
73	backslash_char =	'\\',
74	bar_char =		'|',
75	braceleft_char =	'{',
76	braceright_char =	'}',
77	bracketleft_char =	'[',
78	bracketright_char =	']',
79	colon_char =		':',
80	comma_char =		',',
81	dollar_char =		'$',
82	doublequote_char =	'"',
83	equal_char =		'=',
84	exclam_char =		'!',
85	greater_char =		'>',
86	hat_char =		'^',
87	hyphen_char =		'-',
88	less_char =		'<',
89	newline_char =		'\n',
90	nul_char =		'\0',
91	numbersign_char =	'#',
92	parenleft_char =	'(',
93	parenright_char =	')',
94	percent_char =		'%',
95	period_char =		'.',
96	plus_char =		'+',
97	question_char =		'?',
98	quote_char =		'\'',
99	semicolon_char =	';',
100	slash_char =		'/',
101	space_char =		' ',
102	tab_char =		'\t',
103	tilde_char =		'~'
104};
105
106/*
107 * For make i18n. Codeset independent.
108 * Setup character semantics by identifying all the special characters
109 * of make, and assigning each an entry in the char_semantics[] vector.
110 */
111enum {
112	ampersand_char_entry = 0,	/*  0 */
113	asterisk_char_entry,		/*  1 */
114	at_char_entry,			/*  2 */
115	backquote_char_entry,		/*  3 */
116	backslash_char_entry,		/*  4 */
117	bar_char_entry,			/*  5 */
118	bracketleft_char_entry,		/*  6 */
119	bracketright_char_entry,	/*  7 */
120	colon_char_entry,		/*  8 */
121	dollar_char_entry,		/*  9 */
122	doublequote_char_entry,		/* 10 */
123	equal_char_entry,		/* 11 */
124	exclam_char_entry,		/* 12 */
125	greater_char_entry,		/* 13 */
126	hat_char_entry,			/* 14 */
127	hyphen_char_entry,		/* 15 */
128	less_char_entry,		/* 16 */
129	newline_char_entry,		/* 17 */
130	numbersign_char_entry,		/* 18 */
131	parenleft_char_entry,		/* 19 */
132	parenright_char_entry,		/* 20 */
133	percent_char_entry,		/* 21 */
134	plus_char_entry,		/* 22 */
135	question_char_entry,		/* 23 */
136	quote_char_entry,		/* 24 */
137	semicolon_char_entry,		/* 25 */
138	no_semantics_entry		/* 26 */
139};
140
141/*
142 * CHAR_SEMANTICS_ENTRIES should be the number of entries above.
143 * The last entry in char_semantics[] should be blank.
144 */
145#define CHAR_SEMANTICS_ENTRIES	27
146/*
147#define CHAR_SEMANTICS_STRING	"&*@`\\|[]:$=!>-\n#()%+?;^<'\""
148 */
149
150/*
151 * Some utility macros
152 */
153#define ALLOC(x)		((struct _##x *)getmem(sizeof (struct _##x)))
154#define ALLOC_WC(x)		((wchar_t *)getmem((x) * SIZEOFWCHAR_T))
155#define FIND_LENGTH		-1
156#define GETNAME(a,b)		getname_fn((a), (b), false)
157#define IS_EQUAL(a,b)		(!strcmp((a), (b)))
158#define IS_EQUALN(a,b,n)	(!strncmp((a), (b), (n)))
159#define IS_WEQUAL(a,b)		(!wcscmp((a), (b)))
160#define IS_WEQUALN(a,b,n)	(!wcsncmp((a), (b), (n)))
161#define MBLEN(a)		mblen((a), MB_LEN_MAX)
162#define MBSTOWCS(a,b)		(void) mbstowcs_with_check((a), (b), MAXPATHLEN)
163#define	MBTOWC(a,b)		mbtowc((a), (b), MB_LEN_MAX)
164#define	SIZEOFWCHAR_T		(sizeof (wchar_t))
165#define VSIZEOF(v)		(sizeof (v) / sizeof ((v)[0]))
166#define WCSTOMBS(a,b)		(void) wcstombs((a), (b), (MAXPATHLEN * MB_LEN_MAX))
167#define WCTOMB(a,b)		(void) wctomb((a), (b))
168#define	HASH(v, c)		(v = (v)*31 + (unsigned int)(c))
169
170extern void mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n);
171
172/*
173 * Bits stored in funny vector to classify chars
174 */
175enum {
176	dollar_sem =		0001,
177	meta_sem =		0002,
178	percent_sem =		0004,
179	wildcard_sem =		0010,
180	command_prefix_sem =	0020,
181	special_macro_sem =	0040,
182	colon_sem =		0100,
183	parenleft_sem =		0200
184};
185
186/*
187 * Type returned from doname class functions
188 */
189typedef enum {
190	build_dont_know = 0,
191	build_failed,
192	build_ok,
193	build_in_progress,
194	build_running,		/* PARALLEL & DISTRIBUTED */
195	build_pending,		/* PARALLEL & DISTRIBUTED */
196	build_serial,		/* PARALLEL & DISTRIBUTED */
197	build_subtree		/* PARALLEL & DISTRIBUTED */
198} Doname;
199
200/*
201 * The String struct defines a string with the following layout
202 *	"xxxxxxxxxxxxxxxCxxxxxxxxxxxxxxx________"
203 *	^		^		^		^
204 *	|		|		|		|
205 *	buffer.start	text.p		text.end	buffer.end
206 *	text.p points to the next char to read/write.
207 */
208struct _String {
209	struct Text {
210		wchar_t		*p;	/* Read/Write pointer */
211		wchar_t		*end;	/* Read limit pointer */
212	}		text;
213	struct Physical_buffer {
214		wchar_t		*start;	/* Points to start of buffer */
215		wchar_t		*end;	/* End of physical buffer */
216	}		buffer;
217	Boolean		free_after_use:1;
218};
219
220#define STRING_BUFFER_LENGTH	1024
221#define INIT_STRING_FROM_STACK(str, buf) { \
222			str.buffer.start = (buf); \
223			str.text.p = (buf); \
224			str.text.end = NULL; \
225			str.buffer.end = (buf) \
226                          + (sizeof (buf)/SIZEOFWCHAR_T); \
227			str.free_after_use = false; \
228		  }
229
230#define APPEND_NAME(np, dest, len)	append_string((np)->string_mb, (dest), (len));
231
232class Wstring {
233	public:
234		struct _String	string;
235		wchar_t		string_buf[STRING_BUFFER_LENGTH];
236
237	public:
238		Wstring();
239		Wstring(struct _Name * name);
240		~Wstring();
241
242		void init(struct _Name * name);
243		void init(wchar_t * name, unsigned length);
244		unsigned length() {
245			return wcslen(string.buffer.start);
246		};
247		void append_to_str(struct _String * str, unsigned off, unsigned length);
248
249		wchar_t * get_string() {
250			return string.buffer.start;
251		};
252
253		wchar_t * get_string(unsigned off) {
254			return string.buffer.start + off;
255		};
256
257		Boolean equaln(wchar_t * str, unsigned length);
258		Boolean equal(wchar_t * str);
259		Boolean equal(wchar_t * str, unsigned off);
260		Boolean equal(wchar_t * str, unsigned off, unsigned length);
261
262		Boolean equaln(Wstring * str, unsigned length);
263		Boolean equal(Wstring * str);
264		Boolean equal(Wstring * str, unsigned off);
265		Boolean equal(Wstring * str, unsigned off, unsigned length);
266};
267
268
269/*
270 * Used for storing the $? list and also for the "target + target:"
271 * construct.
272 */
273struct _Chain {
274	struct _Chain		*next;
275	struct _Name		*name;
276	struct _Percent	*percent_member;
277};
278
279/*
280 * Stores one command line for a rule
281 */
282struct _Cmd_line {
283	struct _Cmd_line	*next;
284	struct _Name		*command_line;
285	Boolean			make_refd:1;	/* $(MAKE) referenced? */
286	/*
287	 * Remember any command line prefixes given
288	 */
289	Boolean			ignore_command_dependency:1;	/* `?' */
290	Boolean			assign:1;			/* `=' */
291	Boolean			ignore_error:1;			/* `-' */
292	Boolean			silent:1;			/* `@' */
293	Boolean			always_exec:1;			/* `+' */
294};
295
296/*
297 * Linked list of targets/files
298 */
299struct _Dependency {
300	struct _Dependency	*next;
301	struct _Name		*name;
302	Boolean			automatic:1;
303	Boolean			stale:1;
304	Boolean			built:1;
305};
306
307/*
308 * The specials are markers for targets that the reader should special case
309 */
310typedef enum {
311	no_special,
312	built_last_make_run_special,
313	default_special,
314	get_posix_special,
315	get_special,
316	ignore_special,
317	keep_state_file_special,
318	keep_state_special,
319	make_version_special,
320	no_parallel_special,
321	parallel_special,
322	posix_special,
323	precious_special,
324	sccs_get_posix_special,
325	sccs_get_special,
326	silent_special,
327	suffixes_special,
328	svr4_special,
329	localhost_special
330} Special;
331
332typedef enum {
333	no_colon,
334	one_colon,
335	two_colon,
336	equal_seen,
337	conditional_seen,
338	none_seen
339} Separator;
340
341/*
342 * Magic values for the timestamp stored with each name object
343 */
344
345
346extern const timestruc_t file_no_time;
347extern const timestruc_t file_doesnt_exist;
348extern const timestruc_t file_is_dir;
349extern const timestruc_t file_min_time;
350extern const timestruc_t file_max_time;
351
352/*
353 * Each Name has a list of properties
354 * The properties are used to store information that only
355 * a subset of the Names need
356 */
357typedef enum {
358	no_prop,
359	conditional_prop,
360	line_prop,
361	macro_prop,
362	makefile_prop,
363	member_prop,
364	recursive_prop,
365	sccs_prop,
366	suffix_prop,
367	target_prop,
368	time_prop,
369	vpath_alias_prop,
370	long_member_name_prop,
371	macro_append_prop,
372	env_mem_prop
373} Property_id;
374
375typedef enum {
376	no_daemon = 0,
377	chain_daemon
378} Daemon;
379
380struct _Env_mem {
381	char		*value;
382};
383
384struct _Macro_appendix {
385	struct _Name		*value;
386	struct _Name		*value_to_append;
387};
388
389struct _Macro {
390	/*
391	* For "ABC = xyz" constructs
392	* Name "ABC" get one macro prop
393	*/
394	struct _Name		*value;
395	Boolean			exported:1;
396	Boolean			read_only:1;
397	/*
398	* This macro is defined conditionally
399	*/
400	Boolean			is_conditional:1;
401	/*
402	* The list for $? is stored as a structured list that
403	* is translated into a string iff it is referenced.
404	* This is why  some macro values need a daemon.
405	*/
406	Daemon			daemon:2;
407};
408
409struct _Macro_list {
410	struct _Macro_list	*next;
411	char			*macro_name;
412	char			*value;
413};
414
415enum sccs_stat {
416	DONT_KNOW_SCCS = 0,
417	NO_SCCS,
418	HAS_SCCS
419};
420
421struct _Name {
422	struct _Property	*prop;		/* List of properties */
423	char			*string_mb;     /* Multi-byte name string */
424	struct {
425		unsigned int		length;
426	}                       hash;
427	struct {
428		timestruc_t		time;		/* Modification */
429		int			stat_errno;	/* error from "stat" */
430		off_t			size;		/* Of file */
431		mode_t			mode;		/* Of file */
432		Boolean			is_file:1;
433		Boolean			is_dir:1;
434		Boolean			is_sym_link:1;
435		Boolean			is_precious:1;
436		enum sccs_stat		has_sccs:2;
437	}                       stat;
438	/*
439	 * Count instances of :: definitions for this target
440	 */
441	short			colon_splits;
442	/*
443	 * We only clear the automatic depes once per target per report
444	 */
445	short			temp_file_number;
446	/*
447	 * Count how many conditional macros this target has defined
448	 */
449	short			conditional_cnt;
450	/*
451	 * A conditional macro was used when building this target
452	 */
453	Boolean			depends_on_conditional:1;
454	/*
455	 * Pointer to list of conditional macros which were used to build
456	 * this target
457	 */
458	struct _Macro_list	*conditional_macro_list;
459	Boolean			has_member_depe:1;
460	Boolean			is_member:1;
461	/*
462	 * This target is a directory that has been read
463	 */
464	Boolean			has_read_dir:1;
465	/*
466	 * This name is a macro that is now being expanded
467	 */
468	Boolean			being_expanded:1;
469	/*
470	 * This name is a magic name that the reader must know about
471	 */
472	Special			special_reader:5;
473	Doname			state:3;
474	Separator		colons:3;
475	Boolean			has_depe_list_expanded:1;
476	Boolean			suffix_scan_done:1;
477	Boolean			has_complained:1;	/* For sccs */
478	/*
479	 * This target has been built during this make run
480	 */
481	Boolean			ran_command:1;
482	Boolean			with_squiggle:1;	/* for .SUFFIXES */
483	Boolean			without_squiggle:1;	/* for .SUFFIXES */
484	Boolean			has_read_suffixes:1;	/* Suffix list cached*/
485	Boolean			has_suffixes:1;
486	Boolean			has_target_prop:1;
487	Boolean			has_vpath_alias_prop:1;
488	Boolean			dependency_printed:1;	/* For dump_make_state() */
489	Boolean			dollar:1;		/* In namestring */
490	Boolean			meta:1;			/* In namestring */
491	Boolean			percent:1;		/* In namestring */
492	Boolean			wildcard:1;		/* In namestring */
493        Boolean                 has_parent:1;
494        Boolean                 is_target:1;
495	Boolean			has_built:1;
496	Boolean			colon:1;		/* In namestring */
497	Boolean			parenleft:1;		/* In namestring */
498	Boolean			has_recursive_dependency:1;
499	Boolean			has_regular_dependency:1;
500	Boolean			is_double_colon:1;
501	Boolean			is_double_colon_parent:1;
502	Boolean			has_long_member_name:1;
503	/*
504	 * allowed to run in parallel
505	 */
506	Boolean			parallel:1;
507	/*
508	 * not allowed to run in parallel
509	 */
510	Boolean			no_parallel:1;
511	/*
512	 * used in dependency_conflict
513	 */
514	Boolean			checking_subtree:1;
515	Boolean			added_pattern_conditionals:1;
516	/*
517	 * rechecking target for possible rebuild
518	 */
519	Boolean			rechecking_target:1;
520	/*
521	 * build this target in silent mode
522	 */
523	Boolean			silent_mode:1;
524	/*
525	 * build this target in ignore error mode
526	 */
527	Boolean			ignore_error_mode:1;
528	Boolean			dont_activate_cond_values:1;
529	/*
530	 * allowed to run serially on local host
531	 */
532	Boolean			localhost:1;
533};
534
535/*
536 * Stores the % matched default rules
537 */
538struct _Percent {
539	struct _Percent	*next;
540	struct _Name		**patterns;
541	struct _Name		*name;
542	struct _Percent		*dependencies;
543	struct _Cmd_line	*command_template;
544	struct _Chain		*target_group;
545	int			patterns_total;
546	Boolean			being_expanded;
547};
548
549struct Conditional {
550	/*
551	 * For "foo := ABC [+]= xyz" constructs
552	 * Name "foo" gets one conditional prop
553	 */
554	struct _Name		*target;
555	struct _Name		*name;
556	struct _Name		*value;
557	int			sequence;
558	Boolean			append:1;
559};
560
561struct Line {
562	/*
563	 * For "target : dependencies" constructs
564	 * Name "target" gets one line prop
565	 */
566	struct _Cmd_line	*command_template;
567	struct _Cmd_line	*command_used;
568	struct _Dependency	*dependencies;
569	timestruc_t		dependency_time;
570	struct _Chain		*target_group;
571	Boolean			is_out_of_date:1;
572	Boolean			sccs_command:1;
573	Boolean			command_template_redefined:1;
574	Boolean			dont_rebuild_command_used:1;
575	/*
576	 * Values for the dynamic macros
577	 */
578	struct _Name		*target;
579	struct _Name		*star;
580	struct _Name		*less;
581	struct _Name		*percent;
582	struct _Chain		*query;
583};
584
585struct Makefile {
586	/*
587	 * Names that reference makefiles gets one prop
588	 */
589	wchar_t			*contents;
590	off_t			size;
591};
592
593struct Member {
594	/*
595	 * For "lib(member)" and "lib((entry))" constructs
596	 * Name "lib(member)" gets one member prop
597	 * Name "lib((entry))" gets one member prop
598	 * The member field is filled in when the prop is refd
599	 */
600	struct _Name		*library;
601	struct _Name		*entry;
602	struct _Name		*member;
603};
604
605struct Recursive {
606	/*
607	 * For "target: .RECURSIVE dir makefiles" constructs
608	 * Used to keep track of recursive calls to make
609	 * Name "target" gets one recursive prop
610	 */
611	struct _Name		*directory;
612	struct _Name		*target;
613	struct _Dependency	*makefiles;
614	Boolean			has_built;
615	Boolean			in_depinfo;
616};
617
618struct Sccs {
619	/*
620	 * Each file that has a SCCS s. file gets one prop
621	 */
622	struct _Name		*file;
623};
624
625struct Suffix {
626	/*
627	 * Cached list of suffixes that can build this target
628	 * suffix is built from .SUFFIXES
629	 */
630	struct _Name		*suffix;
631	struct _Cmd_line	*command_template;
632};
633
634struct Target {
635	/*
636	 * For "target:: dependencies" constructs
637	 * The "::" construct is handled by converting it to
638	 * "foo: 1@foo" + "1@foo: dependecies"
639	 * "1@foo" gets one target prop
640	 * This target prop cause $@ to be bound to "foo"
641	 * not "1@foo" when the rule is evaluated
642	 */
643	struct _Name		*target;
644};
645
646struct STime {
647	/*
648	 * Save the original time for :: targets
649	 */
650	timestruc_t			time;
651};
652
653struct Vpath_alias {
654	/*
655	 * If a file was found using the VPATH it gets
656	 * a vpath_alias prop
657	 */
658	struct _Name		*alias;
659};
660
661struct Long_member_name {
662	/*
663	 * Targets with a truncated member name carries
664	 * the full lib(member) name for the state file
665	 */
666	struct _Name		*member_name;
667};
668
669union Body {
670	struct _Macro		macro;
671	struct Conditional	conditional;
672	struct Line		line;
673	struct Makefile		makefile;
674	struct Member		member;
675	struct Recursive	recursive;
676	struct Sccs		sccs;
677	struct Suffix		suffix;
678	struct Target		target;
679	struct STime		time;
680	struct Vpath_alias	vpath_alias;
681	struct Long_member_name	long_member_name;
682	struct _Macro_appendix	macro_appendix;
683	struct _Env_mem		env_mem;
684};
685
686#define PROPERTY_HEAD_SIZE (sizeof (struct _Property)-sizeof (union Body))
687struct _Property {
688	struct _Property	*next;
689	Property_id		type:4;
690	union Body		body;
691};
692
693/* Structure for dynamic "ascii" arrays */
694struct ASCII_Dyn_Array {
695	char			*start;
696	size_t			size;
697};
698
699struct _Envvar {
700	struct _Name		*name;
701	struct _Name		*value;
702	struct _Envvar		*next;
703	char			*env_string;
704	Boolean			already_put:1;
705};
706
707/*
708 * Macros for the reader
709 */
710#define GOTO_STATE(new_state) { \
711				  SET_STATE(new_state); \
712				    goto enter_state; \
713			      }
714#define SET_STATE(new_state) state = (new_state)
715
716#define UNCACHE_SOURCE()	if (source != NULL) { \
717					source->string.text.p = source_p; \
718				  }
719#define CACHE_SOURCE(comp)	if (source != NULL) { \
720					source_p = source->string.text.p - \
721					  (comp); \
722					source_end = source->string.text.end; \
723				  }
724#define GET_NEXT_BLOCK_NOCHK(source)	{ UNCACHE_SOURCE(); \
725				 source = get_next_block_fn(source); \
726				 CACHE_SOURCE(0) \
727			   }
728#define GET_NEXT_BLOCK(source)	{ GET_NEXT_BLOCK_NOCHK(source); \
729				 if (source != NULL && source->error_converting) { \
730				 	GOTO_STATE(illegal_bytes_state); \
731				 } \
732			   }
733#define GET_CHAR()		((source == NULL) || \
734				(source_p >= source_end) ? 0 : *source_p)
735
736struct _Source {
737	struct _String		string;
738	struct _Source		*previous;
739	off_t			bytes_left_in_file;
740	short			fd;
741	Boolean			already_expanded:1;
742	Boolean			error_converting:1;
743	char			*inp_buf;
744	char			*inp_buf_end;
745	char			*inp_buf_ptr;
746};
747
748typedef enum {
749	reading_nothing,
750	reading_makefile,
751	reading_statefile,
752	rereading_statefile,
753	reading_cpp_file
754} Makefile_type;
755
756/*
757 * Typedefs for all structs
758 */
759typedef struct _Chain		*Chain, Chain_rec;
760typedef struct _Envvar		*Envvar, Envvar_rec;
761typedef struct _Macro_list	*Macro_list, Macro_list_rec;
762typedef struct _Name		*Name, Name_rec;
763typedef struct _Property	*Property, Property_rec;
764typedef struct _Source		*Source, Source_rec;
765typedef struct _String		*String, String_rec;
766
767/*
768 * name records hash table.
769 */
770struct Name_set {
771private:
772	// single node in a tree
773	struct entry {
774		entry(Name name_, entry *parent_) :
775			name(name_),
776			parent(parent_),
777			left(0),
778			right(0),
779			depth(1)
780		{}
781
782		Name		name;
783
784		entry		*parent;
785		entry		*left;
786		entry		*right;
787		unsigned	depth;
788
789		void setup_depth() {
790			unsigned rdepth = (right != 0) ? right->depth : 0;
791			unsigned ldepth = (left != 0) ? left->depth : 0;
792			depth = 1 + ((ldepth > rdepth) ? ldepth : rdepth);
793		}
794	};
795
796public:
797	// make iterator a friend of Name_set to have access to struct entry
798	struct iterator;
799	friend struct Name_set::iterator;
800
801	// iterator over tree nodes
802	struct iterator {
803	public:
804		// constructors
805		iterator() : node(0) {}
806		iterator(entry *node_) : node(node_) {}
807		iterator(const iterator&) = default;
808
809		// dereference operator
810		Name operator->() const { return node->name; }
811
812		// conversion operator
813		operator Name() { return node->name; }
814
815		// assignment operator
816		iterator& operator=(const iterator &o) { node = o.node; return *this; }
817
818		// equality/inequality operators
819		int operator==(const iterator &o) const { return (node == o.node); }
820		int operator!=(const iterator &o) const { return (node != o.node); }
821
822		// pre/post increment operators
823		iterator& operator++();
824		iterator  operator++(int) { iterator it = *this; ++*this; return it; }
825
826	private:
827		// the node iterator points to
828		entry *node;
829	};
830
831public:
832	// constructor
833	Name_set() : root(0) {}
834
835	// lookup, insert and remove operations
836	Name lookup(const char *key);
837	Name insert(const char *key, Boolean &found);
838	void insert(Name name);
839
840	// begin/end iterators
841	iterator begin() const;
842	iterator end() const { return iterator(); }
843
844private:
845	// rebalance given node
846	void	rebalance(entry *node);
847
848private:
849	// tree root
850	entry	*root;
851};
852
853/*
854 *	extern declarations for all global variables.
855 *	The actual declarations are in globals.cc
856 */
857extern char		char_semantics[];
858extern wchar_t		char_semantics_char[];
859extern Macro_list	cond_macro_list;
860extern Boolean		conditional_macro_used;
861extern Boolean		do_not_exec_rule;		/* `-n' */
862extern Boolean		dollarget_seen;
863extern Boolean		dollarless_flag;
864extern Name		dollarless_value;
865extern char		**environ;
866extern Envvar		envvar;
867extern int		exit_status;
868extern wchar_t		*file_being_read;
869/* Variable gnu_style=true if env. var. SUN_MAKE_COMPAT_MODE=GNU (RFE 4866328) */
870extern Boolean		gnu_style;
871extern Name_set		hashtab;
872extern Name		host_arch;
873extern Name		host_mach;
874extern int		line_number;
875extern char		*make_state_lockfile;
876extern Boolean		make_word_mentioned;
877extern Makefile_type	makefile_type;
878extern char		mbs_buffer[];
879extern Name		path_name;
880extern Boolean		posix;
881extern Name		query;
882extern Boolean		query_mentioned;
883extern Name		hat;
884extern Boolean		reading_environment;
885extern Name		shell_name;
886extern Boolean		svr4;
887extern Name		target_arch;
888extern Name		target_mach;
889extern Boolean		tilde_rule;
890extern wchar_t		wcs_buffer[];
891extern Boolean		working_on_targets;
892extern Name		virtual_root;
893extern Boolean		vpath_defined;
894extern Name		vpath_name;
895extern Boolean		make_state_locked;
896extern Boolean		out_err_same;
897extern pid_t		childPid;
898
899/*
900 * RFE 1257407: make does not use fine granularity time info available from stat.
901 * High resolution time comparison.
902 */
903
904inline int
905operator==(const timestruc_t &t1, const timestruc_t &t2) {
906	return ((t1.tv_sec == t2.tv_sec) && (t1.tv_nsec == t2.tv_nsec));
907}
908
909inline int
910operator!=(const timestruc_t &t1, const timestruc_t &t2) {
911	return ((t1.tv_sec != t2.tv_sec) || (t1.tv_nsec != t2.tv_nsec));
912}
913
914inline int
915operator>(const timestruc_t &t1, const timestruc_t &t2) {
916	if (t1.tv_sec == t2.tv_sec) {
917		return (t1.tv_nsec > t2.tv_nsec);
918	}
919	return (t1.tv_sec > t2.tv_sec);
920}
921
922inline int
923operator>=(const timestruc_t &t1, const timestruc_t &t2) {
924	if (t1.tv_sec == t2.tv_sec) {
925		return (t1.tv_nsec >= t2.tv_nsec);
926	}
927	return (t1.tv_sec > t2.tv_sec);
928}
929
930inline int
931operator<(const timestruc_t &t1, const timestruc_t &t2) {
932	if (t1.tv_sec == t2.tv_sec) {
933		return (t1.tv_nsec < t2.tv_nsec);
934	}
935	return (t1.tv_sec < t2.tv_sec);
936}
937
938inline int
939operator<=(const timestruc_t &t1, const timestruc_t &t2) {
940	if (t1.tv_sec == t2.tv_sec) {
941		return (t1.tv_nsec <= t2.tv_nsec);
942	}
943	return (t1.tv_sec < t2.tv_sec);
944}
945
946#endif
947