xref: /illumos-gate/usr/src/cmd/make/include/mksh/defs.h (revision 50d96771)
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 
47 typedef 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  */
58 enum {
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  */
68 enum {
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  */
111 enum {
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 
170 extern 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  */
175 enum {
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  */
189 typedef 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  */
208 struct _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 
232 class 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);
length()244 		unsigned length() {
245 			return wcslen(string.buffer.start);
246 		};
247 		void append_to_str(struct _String * str, unsigned off, unsigned length);
248 
get_string()249 		wchar_t * get_string() {
250 			return string.buffer.start;
251 		};
252 
get_string(unsigned off)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  */
273 struct _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  */
282 struct _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  */
299 struct _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  */
310 typedef 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 
332 typedef 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 
346 extern const timestruc_t file_no_time;
347 extern const timestruc_t file_doesnt_exist;
348 extern const timestruc_t file_is_dir;
349 extern const timestruc_t file_min_time;
350 extern 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  */
357 typedef 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 
375 typedef enum {
376 	no_daemon = 0,
377 	chain_daemon
378 } Daemon;
379 
380 struct _Env_mem {
381 	char		*value;
382 };
383 
384 struct _Macro_appendix {
385 	struct _Name		*value;
386 	struct _Name		*value_to_append;
387 };
388 
389 struct _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 
409 struct _Macro_list {
410 	struct _Macro_list	*next;
411 	char			*macro_name;
412 	char			*value;
413 };
414 
415 enum sccs_stat {
416 	DONT_KNOW_SCCS = 0,
417 	NO_SCCS,
418 	HAS_SCCS
419 };
420 
421 struct _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  */
538 struct _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 
549 struct 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 
561 struct 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 
585 struct Makefile {
586 	/*
587 	 * Names that reference makefiles gets one prop
588 	 */
589 	wchar_t			*contents;
590 	off_t			size;
591 };
592 
593 struct 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 
605 struct 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 
618 struct Sccs {
619 	/*
620 	 * Each file that has a SCCS s. file gets one prop
621 	 */
622 	struct _Name		*file;
623 };
624 
625 struct 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 
634 struct 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 
646 struct STime {
647 	/*
648 	 * Save the original time for :: targets
649 	 */
650 	timestruc_t			time;
651 };
652 
653 struct 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 
661 struct 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 
669 union 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))
687 struct _Property {
688 	struct _Property	*next;
689 	Property_id		type:4;
690 	union Body		body;
691 };
692 
693 /* Structure for dynamic "ascii" arrays */
694 struct ASCII_Dyn_Array {
695 	char			*start;
696 	size_t			size;
697 };
698 
699 struct _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 
736 struct _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 
748 typedef 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  */
759 typedef struct _Chain		*Chain, Chain_rec;
760 typedef struct _Envvar		*Envvar, Envvar_rec;
761 typedef struct _Macro_list	*Macro_list, Macro_list_rec;
762 typedef struct _Name		*Name, Name_rec;
763 typedef struct _Property	*Property, Property_rec;
764 typedef struct _Source		*Source, Source_rec;
765 typedef struct _String		*String, String_rec;
766 
767 /*
768  * name records hash table.
769  */
770 struct Name_set {
771 private:
772 	// single node in a tree
773 	struct entry {
entryName_set::entry774 		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 
setup_depthName_set::entry789 		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 
796 public:
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
iteratorName_set::iterator805 		iterator() : node(0) {}
iteratorName_set::iterator806 		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
NameName_set::iterator813 		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 
831 public:
832 	// constructor
Name_setName_set833 	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;
endName_set842 	iterator end() const { return iterator(); }
843 
844 private:
845 	// rebalance given node
846 	void	rebalance(entry *node);
847 
848 private:
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  */
857 extern char		char_semantics[];
858 extern wchar_t		char_semantics_char[];
859 extern Macro_list	cond_macro_list;
860 extern Boolean		conditional_macro_used;
861 extern Boolean		do_not_exec_rule;		/* `-n' */
862 extern Boolean		dollarget_seen;
863 extern Boolean		dollarless_flag;
864 extern Name		dollarless_value;
865 extern char		**environ;
866 extern Envvar		envvar;
867 extern int		exit_status;
868 extern wchar_t		*file_being_read;
869 /* Variable gnu_style=true if env. var. SUN_MAKE_COMPAT_MODE=GNU (RFE 4866328) */
870 extern Boolean		gnu_style;
871 extern Name_set		hashtab;
872 extern Name		host_arch;
873 extern Name		host_mach;
874 extern int		line_number;
875 extern char		*make_state_lockfile;
876 extern Boolean		make_word_mentioned;
877 extern Makefile_type	makefile_type;
878 extern char		mbs_buffer[];
879 extern Name		path_name;
880 extern Boolean		posix;
881 extern Name		query;
882 extern Boolean		query_mentioned;
883 extern Name		hat;
884 extern Boolean		reading_environment;
885 extern Name		shell_name;
886 extern Boolean		svr4;
887 extern Name		target_arch;
888 extern Name		target_mach;
889 extern Boolean		tilde_rule;
890 extern wchar_t		wcs_buffer[];
891 extern Boolean		working_on_targets;
892 extern Name		virtual_root;
893 extern Boolean		vpath_defined;
894 extern Name		vpath_name;
895 extern Boolean		make_state_locked;
896 extern Boolean		out_err_same;
897 extern 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 
904 inline int
905 operator==(const timestruc_t &t1, const timestruc_t &t2) {
906 	return ((t1.tv_sec == t2.tv_sec) && (t1.tv_nsec == t2.tv_nsec));
907 }
908 
909 inline int
910 operator!=(const timestruc_t &t1, const timestruc_t &t2) {
911 	return ((t1.tv_sec != t2.tv_sec) || (t1.tv_nsec != t2.tv_nsec));
912 }
913 
914 inline int
915 operator>(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 
922 inline int
923 operator>=(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 
930 inline int
931 operator<(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 
938 inline int
939 operator<=(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