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