1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1984-2013 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *               Glenn Fowler <glenn.s.fowler@gmail.com>                *
18 *                                                                      *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22  * Glenn Fowler
23  * AT&T Research
24  *
25  * make common definitions
26  */
27 
28 #include <ast.h>
29 #include <ls.h>
30 #include <ctype.h>
31 #include <dirent.h>
32 #include <fs3d.h>
33 #include <glob.h>
34 #include <hash.h>
35 #include <swap.h>
36 #include <namval.h>
37 #include <error.h>
38 #include <coshell.h>
39 #include <times.h>
40 #include <tok.h>
41 #include <setjmp.h>
42 #include <sfdisc.h>
43 #include <tmx.h>
44 
45 #if DEBUG
46 #define debug(x)	do if (error_info.trace < 0) { error x; } while (0)
47 #define	PANIC		(ERROR_PANIC|ERROR_SOURCE|ERROR_SYSTEM),__FILE__,__LINE__
48 #else
49 #define debug(x)
50 #define	PANIC		ERROR_PANIC
51 #endif
52 
53 #define COMMENT		'#'		/* make comment char		*/
54 #define MARK_CONTEXT	'\002'		/* context mark -- not in input!*/
55 #define MARK_QUOTE	'\003'		/* quote mark -- not in input!	*/
56 #define SALT		'#'		/* preprocessor control char	*/
57 #define VIEWOFFSET	'0'		/* char offset for view==0	*/
58 
59 #if _WINIX
60 #define FILE_SPACE	'\001'		/* file name space		*/
61 #else
62 #define FILE_SPACE	'?'		/* file name space		*/
63 #endif
64 
65 #define ATTRNAME	'.'		/* prefix to name an attribute	*/
66 #define ATTRSET		'+'		/* prefix to set an attribute	*/
67 #define ATTRCLEAR	'-'		/* prefix to clear an attribute	*/
68 
69 #define CMDTRACE	(-6)		/* coshell trace debug level	*/
70 #define EXPTRACE	(-5)		/* explanation trace debug lev	*/
71 
72 #define EXPLAIN		(state.user&&(state.explain||error_info.trace<=EXPTRACE))
73 
74 #undef	atoi
75 #undef	atol
76 #undef	bind
77 #undef	clrbit		/* netbsd has one in <sys/param.h> */
78 #undef	optinit
79 #undef	setbit		/* netbsd has one in <sys/param.h> */
80 
81 #define bind		bindrule /* avoids possible socket clash */
82 #define canon(x)	((state.context&&iscontextp(x,&state.tmppchar))?state.tmppchar:(state.mam.statix?mamcanon(x):pathcanon(x,0,0)))
83 #define clrbit(v,b)	((v)&=~(1L<<(b)))
84 #define getar(name)	((Dir_t*)hashget(table.ar,(name)))
85 #define getbound(name)	((char*)hashget(table.bound,(name)))
86 #define getdir(id)	((Dir_t*)hashget(table.dir,(char*)(id)))
87 #define getfile(name)	((File_t*)hashget(table.file,(name)))
88 #define getold(name)	((char*)hashget(table.oldvalue,(name)))
89 #define getreg(name)	((int*)hashget(table.regress,(name)))
90 #define getrule(name)	((Rule_t*)hashget(table.rule,(name)))
91 #define getvar(name)	((Var_t*)hashget(table.var,(name)))
92 #define message(x)	do if (error_info.trace < 0) { error x; } while (0)
93 #define notfile(r)	(((r)->property&(P_attribute|P_functional|P_make|P_operator|P_state|P_use|P_virtual))||((r)->dynamic&D_scope)||(r)->semaphore||((r)->property&P_dontcare)&&((r)->dynamic&D_bound)&&!(r)->time)
94 #define oldname(r)	do{if(getbound(r->uname))putbound(0,0);if(r->dynamic&D_alias)r->dynamic&=~D_alias;else putrule(r->name,0);r->name=r->uname;r->uname=0;}while(0)
95 #define putbound(n,d)	hashput(table.bound,(char*)(n),(char*)(d))
96 #define putar(name,d)	hashput(table.ar,(name),(char*)(d))
97 #define putdir(id,d)	hashput(table.dir,(char*)(id),(char*)(d))
98 #define putfile(name,f)	hashput(table.file,(char*)(name),(char*)(f))
99 #define putold(name,v)	hashput(table.oldvalue,(char*)(name),(char*)(v))
100 #define putptr(f,p)	(internal.ptr=(char*)(p),sfwrite(f,&internal.ptr,sizeof(internal.ptr)))
101 #define putreg(name,r)	hashput(table.regress,(char*)(name),(char*)(r))
102 #define putrule(name,r)	hashput(table.rule,(char*)(name),(char*)(r))
103 #define putvar(name,v)	hashput(table.var,(char*)(name),(char*)(v))
104 #define reason(x)	do if(EXPLAIN)explain x;while(0)
105 #define ropen(f,m)	((f)==internal.openfile?(internal.openfile=0,internal.openfd):open(f,m))
106 #define rsfopen(f)	((f)==internal.openfile?(internal.openfile=0,sfnew(NiL,NiL,SF_UNBOUND,internal.openfd,SF_READ)):sfopen(NiL,f,"re"))
107 #define setbit(v,b)	((v)|=(1L<<(b)))
108 #define shquote		shellquote /* netbsd has one in <stdlib.h>! */
109 #define statetimeq	timestateq /* avoids statetime symbol truncation clash */
110 #define timefix(t)      t-=(t<state.tolerance)?t:state.tolerance
111 #define trap()		(state.caught?handle():0)
112 #define tstbit(v,b)	((v)&(1L<<(b)))
113 #define unviewname(s)	(*(s)='(')
114 #define viewable(r)	((r->property&P_state)&&*r->name=='(')
115 #define viewname(s,v)	(*(s)=VIEWOFFSET+(v))
116 #define zero(x)		memzero(&(x),sizeof(x))
117 
118 #define isaltstate(s)	(nametype(s,NiL)&(NAME_altstate))
119 #define iscontext(s)	(nametype(s,NiL)&(NAME_context))
120 #define iscontextp(s,p)	(nametype(s,p)&(NAME_context))
121 #define isdynamic(s)	(nametype(s,NiL)&(NAME_dynamic|NAME_glob))
122 #define isglob(s)	(nametype(s,NiL)&(NAME_glob))
123 #define isintvar(s)	(nametype(s,NiL)&(NAME_intvar))
124 #define isstate(s)	(nametype(s,NiL)&(NAME_staterule|NAME_altstate|NAME_statevar))
125 #define isstatevar(s)	(nametype(s,NiL)&(NAME_statevar))
126 
127 #define freelist(x)	do{if(x){(x)->rule=(Rule_t*)internal.freelists;internal.freelists=(char*)(x);}}while(0)
128 #define freerule(r)	do{zero(*r);*((char**)r)=internal.freerules;internal.freerules=(char*)(r);}while(0)
129 #define freevar(v)	do{(v)->property&=(V_free|V_import);*((char**)v)=internal.freevars;internal.freevars=(char*)(v);}while(0)
130 
131 #define newlist(x)	do{if(x=(List_t*)internal.freelists){if(x->next){x=x->next;*((char**)internal.freelists)=(char*)x->next;}else internal.freelists=(char*)x->rule;}else x=(List_t*)newchunk(&internal.freelists,sizeof(List_t));}while(0)
132 #define newrule(r)	do{if(r=(Rule_t*)internal.freerules){internal.freerules=(*((char**)r));zero(*r);}else r=(Rule_t*)newchunk(&internal.freerules,sizeof(Rule_t));}while(0)
133 #define newvar(v)	do{if(v=(Var_t*)internal.freevars){internal.freevars=(*((char**)v));}else v=(Var_t*)newchunk(&internal.freevars,sizeof(Var_t));}while(0)
134 
135 #if CHAR_MIN < 0
136 #define ctable		(ctypes-(CHAR_MIN)+1)
137 #else
138 #define ctable		(ctypes)
139 #endif
140 
141 #define istype(c,t)	(ctable[c]&(t))
142 #define settype(c,t)	(ctable[c]|=(t))
143 #define unsettype(c,t)	(ctable[c]&=~(t))
144 
145 #define NOTYET		0	/* don't know what to do yet		*/
146 #define UPDATE		1	/* rule in process of being updated	*/
147 #define MAKING		2	/* executing update action		*/
148 #define TOUCH		3	/* archive member to be touched		*/
149 #define EXISTS		4	/* rule already exists in desired state	*/
150 #define IGNORE		5	/* rule make failed but ignore errors	*/
151 #define FAILED		6	/* rule make failed			*/
152 #define OLDRULE		7	/* makefile compiler old rule mark	*/
153 
154 #define RECOMPILE	1	/* recompile make object		*/
155 #define COMPILED	2	/* make object compiled (if necessary)	*/
156 #define SAVED		3	/* make state saved			*/
157 
158 #define DELETE	NiL		/* delete path component in edit()	*/
159 #define KEEP	((char*)1)	/* keep path component in edit()	*/
160 
161 #define NOTIME	TMX_NOTIME	/* not checked time			*/
162 #define OLDTIME	((Time_t)(1))	/* oldest valid time			*/
163 #define CURTIME	TMX_NOW		/* high resolution current time		*/
164 #define CURSECS	((Seconds_t)time(NiL)) /* seconds resolution time	*/
165 
166 /*
167  * VAR and RULE must not change -- the rest must be in sequence
168  */
169 
170 #define VAR		0	/* state var from var in staterule()	*/
171 #define CONSISTENT	VAR	/* consistency check bits		*/
172 #define RULE		1	/* state rule in staterule()		*/
173 #define PREREQS		2	/* alternate prereqs in staterule()	*/
174 #define STATERULES	2	/* last staterule() index		*/
175 
176 #define MINVALUE	32	/* minimum variable value length	*/
177 #define MAXJOBS		128	/* maximum number concurrent jobs	*/
178 #define MAXNAME		1024	/* maximum file pathname length		*/
179 #define PCTGARBAGE	10	/* maximum state garbage percentage	*/
180 
181 #define MAXVIEW		(sizeof(Flags_t)*CHAR_BIT) /* max view index	*/
182 
183 #if BINDINDEX
184 #define MAXBIND		UCHAR_MAX/* maximum bind index			*/
185 #endif
186 
187 #define A_clear		(1<<0)	/* assertion() .CLEAR			*/
188 #define A_copy		(1<<1)	/* assertion() .COPY			*/
189 #define A_delete	(1<<2)	/* assertion() .DELETE			*/
190 #define A_group		(1<<3)	/* assertion() metarule (...) grouping	*/
191 #define A_insert	(1<<4)	/* assertion() .INSERT			*/
192 #define A_metarule	(1<<5)	/* assertion() pattern metarule 	*/
193 #define A_negate	(1<<6)	/* assertion() -attribute		*/
194 #define A_nooptions	(1<<7)	/* assertion() no more option prereqs	*/
195 #define A_norhs		(1<<8)	/* assertion() empty rhs		*/
196 #define A_null		(1<<9)	/* assertion() .NULL			*/
197 #define A_scan		(1<<10)	/* assertion() .SCAN			*/
198 #define A_scope		(1<<11)	/* assertion() metarule scope prereqs	*/
199 #define A_special	(1<<12)	/* assertion() .SPECIAL			*/
200 #define A_target	(1<<13)	/* assertion() set P_target		*/
201 
202 #define C_ID1		(1<<0)	/* istype() first identifier char	*/
203 #define C_ID2		(1<<1)	/* istype() remaining id chars		*/
204 #define C_MATCH		(1<<2)	/* istype() shell pattern match chars	*/
205 #define C_OPTVAL	(1<<3)	/* istype() option value separator	*/
206 #define C_SEP		(1<<4)	/* istype() token separator		*/
207 #define C_TERMINAL	(1<<5)	/* istype() terminal chars		*/
208 #define C_VARIABLE1	(1<<6)	/* istype() first variable name char	*/
209 #define C_VARIABLE2	(1<<7)	/* istype() remaining variable chars	*/
210 
211 #define C_VARPOS1	(1<<8)	/* istype() var superimposed code 1	*/
212 #define C_VARPOS2	(1<<9)	/* istype() var superimposed code 2	*/
213 #define C_VARPOS3	(1<<10)	/* istype() var superimposed code 3	*/
214 #define C_VARPOS4	(1<<11)	/* istype() var superimposed code 4	*/
215 #define C_VARPOS5	(1<<12)	/* istype() var superimposed code 5	*/
216 #define C_VARPOS6	(1<<13)	/* istype() var superimposed code 6	*/
217 #define C_VARPOS7	(1<<14)	/* istype() var superimposed code 7	*/
218 #define C_VARPOS8	(1L<<15)/* istype() var superimposed code 8	*/
219 
220 #define NAME_altstate	0x001	/* altername state rule name		*/
221 #define NAME_assignment	0x002	/* assignment				*/
222 #define NAME_context	0x004	/* context string			*/
223 #define NAME_dynamic	0x008	/* requires dynamic expand()		*/
224 #define NAME_glob	0x010	/* requires dynamic glob()		*/
225 #define NAME_identifier	0x020	/* identifier name			*/
226 #define NAME_intvar	0x040	/* internal variable name		*/
227 #define NAME_option	0x080	/* option				*/
228 #define NAME_path	0x100	/* path name				*/
229 #define NAME_staterule	0x200	/* state rule name			*/
230 #define NAME_statevar	0x400	/* state variable name			*/
231 #define NAME_variable	0x800	/* variable name			*/
232 
233 #define ARG_ASSIGN	(1<<0)	/* command line assignment arg flag	*/
234 #define ARG_SCRIPT	(1<<1)	/* command line script arg flag		*/
235 #define ARG_TARGET	(1<<2)	/* command line target arg flag		*/
236 
237 #define BIND_DOT	(1<<0)	/* bindfile in .			*/
238 #define BIND_FORCE	(1<<1)	/* force bindfile current time		*/
239 #define BIND_MAKEFILE	(1<<2)	/* bindfile using makefile dirs		*/
240 #define BIND_RULE	(1<<3)	/* force bindfile makerule		*/
241 
242 #define MERGE_ALL	(1<<0)	/* merge everything			*/
243 #define MERGE_ASSOC	(1<<1)	/* pattern association merge		*/
244 #define MERGE_ATTR	(1<<2)	/* merge just attributes		*/
245 #define MERGE_BOUND	(1<<3)	/* MERGE_ALL but no bind		*/
246 #define MERGE_FORCE	(1<<4)	/* override attributes			*/
247 #define MERGE_SCANNED	(1<<5)	/* MERGE_ALL but no entries|scanned	*/
248 
249 #define COMP_BASE	(1<<0)	/* base rules prereq			*/
250 #define COMP_DONTCARE	(1<<1)	/* optional include prereq		*/
251 #define COMP_FILE	(1<<2)	/* -f prereq				*/
252 #define COMP_GLOBAL	(1<<3)	/* -g prereq				*/
253 #define COMP_INCLUDE	(1<<4)	/* include prereq			*/
254 #define COMP_OPTIONS	(1<<5)	/* -[DIU]* prereq			*/
255 #define COMP_RULES	(1<<6)	/* from explicit rules statement	*/
256 #define COMP_NSEC	(1<<7)	/* next prereq nsec			*/
257 
258 #define PREREQ_APPEND	1	/* addprereq append			*/
259 #define PREREQ_DELETE	2	/* addprereq delete			*/
260 #define PREREQ_INSERT	3	/* addprereq insert			*/
261 #define PREREQ_LENGTH	4	/* addprereq insert by length		*/
262 
263 #define SCAN_IGNORE	1	/* .SCAN.IGNORE scan index		*/
264 #define SCAN_NULL	2	/* .SCAN.NULL scan index		*/
265 #define SCAN_STATE	3	/* .SCAN.STATE scan index		*/
266 #define SCAN_USER	8	/* first user defined scan index	*/
267 #define SCAN_MAX	UCHAR_MAX/* max scan index			*/
268 
269 #define CO_ALWAYS	(CO_USER<<0)	/* always exec			*/
270 #define CO_DATAFILE	(CO_USER<<1)	/* job output to state.tmpdata	*/
271 #define CO_ERRORS	(CO_USER<<2)	/* job had errors		*/
272 #define CO_FOREGROUND	(CO_USER<<3)	/* wait for completion		*/
273 #define CO_KEEPGOING	(CO_USER<<4)	/* keep going on job error	*/
274 #define CO_LOCALSTACK	(CO_USER<<5)	/* stack local vars for action	*/
275 #define CO_PRIMARY	(CO_USER<<6)	/* primary prereq added		*/
276 #define CO_SEMAPHORES	(CO_USER<<7)	/* release semaphores		*/
277 #define CO_URGENT	(CO_USER<<8)	/* enter job at top of queue	*/
278 
279 /*
280  * rule.property flags
281  */
282 
283 #define P_accept	(1<<0)		/* ignore state conflicts	*/
284 #define P_after		(1<<1)		/* make after parent update	*/
285 #define P_always	(1<<2)		/* execute even if !state.exec	*/
286 #define P_archive	(1<<3)		/* rule bound to archive file	*/
287 #define P_attribute	(1<<4)		/* rule is an attribute		*/
288 #define P_before	(1<<5)		/* make before parent update	*/
289 #define P_command	(1<<6)		/* command target -- no pattern	*/
290 #define P_dontcare	(1<<7)		/* don't care if rule made	*/
291 #define P_force		(1<<8)		/* target is always out of date	*/
292 #define P_foreground	(1<<9)		/* run action in foreground	*/
293 #define P_functional	(1<<10)		/* associated w/functional var	*/
294 #define P_ignore	(1<<11)		/* parent to ignore this prereq	*/
295 #define P_immediate	(1<<12)		/* rule needs immediate action	*/
296 #define P_implicit	(1<<13)		/* force implicit prereq checks	*/
297 #define P_internal	(1<<14)		/* don't compile unless prereq	*/
298 #define P_joint		(1L<<15)	/* pseudo for joint targets	*/
299 #define P_make		(1L<<16)	/* make (not shell) action	*/
300 #define P_metarule	(1L<<17)	/* metarule			*/
301 #define P_multiple	(1L<<18)	/* multi prereq occurrences OK	*/
302 
303 #define P_local		(1L<<19)	/* local affinity		*/
304 
305 #define P_operator	(1L<<20)	/* rule is an operator		*/
306 #define P_parameter	(1L<<21)	/* rule bound to parameter file	*/
307 #define P_readonly	(1L<<22)	/* no user modifications	*/
308 #define P_repeat	(1L<<23)	/* make even if already made	*/
309 #define P_state		(1L<<24)	/* state atom			*/
310 #define P_staterule	(1L<<25)	/* staterule			*/
311 #define P_statevar	(1L<<26)	/* statevar			*/
312 #define P_target	(1L<<27)	/* rule is an explicit target	*/
313 #define P_terminal	(1L<<28)	/* terminal target or metarule	*/
314 #define P_use		(1L<<29)	/* rule is a .USE script	*/
315 #define P_virtual	(1L<<30)	/* target is not a file		*/
316 
317 #define P_read		(1L<<31)	/* read action output		*/
318 
319 #define P_failure	(P_after|P_before)	/* conjoined		*/
320 
321 /*
322  * rule.dynamic flags
323  */
324 
325 #define D_alias		(1<<0)		/* more than one unbound name	*/
326 #define D_aliaschanged	(1<<1)		/* alias changed		*/
327 #define D_bound		(1<<2)		/* rule has been bound		*/
328 #define D_built		(1<<3)		/* triggered action built target*/
329 #define D_cached	(1<<4)		/* post assertion info cached	*/
330 #define D_compiled	(1<<5)		/* rule has been compiled	*/
331 #define D_dynamic	(1<<6)		/* must do dynamic expansion	*/
332 #define D_entries	(1<<7)		/* scanned rule has entries	*/
333 #define D_garbage	(1<<8)		/* state file GC mark		*/
334 #define D_hasafter	(1<<9)		/* rule has after prereqs	*/
335 #define D_hasbefore	(1<<10)		/* rule has before prereqs	*/
336 
337 #define D_membertoo	(1<<11)		/* D_member was also set	*/
338 #define D_hassemaphore	(1<<12)		/* has rule.semaphore prereq	*/
339 #define D_same		(1<<13)		/* target unchanged by action	*/
340 
341 #define D_lower		(1<<14)		/* state from lower view	*/
342 
343 #define D_source	(1L<<15)	/* .SOURCE directory		*/
344 
345 #define D_member	(1L<<16)	/* rule bound to archive member	*/
346 
347 #define D_global	(1L<<17)	/* global view if view==0	*/
348 
349 #define D_regular	(1L<<18)	/* rule bound to regular file	*/
350 #define D_scanned	(1L<<19)	/* has been scanned		*/
351 #define D_select0	(1L<<20)	/* $(...) select bit 0		*/
352 #define D_select1	(1L<<21)	/* $(...) select bit 1		*/
353 #define D_triggered	(1L<<22)	/* rule action triggered	*/
354 
355 #define D_index		(1L<<23)	/* load time index consistency	*/
356 
357 #define D_bindindex	(1L<<24)	/* bind index table entry	*/
358 
359 #define D_intermediate	(1L<<25)	/* intermediate pretend target	*/
360 
361 #define D_hasscope	(1L<<26)	/* has D_scope prereqs		*/
362 #define D_scope		(1L<<27)	/* scoped var assignment	*/
363 
364 #define D_hasmake	(1L<<28)	/* rule has .MAKE after prereqs	*/
365 
366 #define D_context	(1L<<29)	/* ref may be diff dir context	*/
367 
368 #define D_lowres	(1L<<30)	/* low resolution time		*/
369 
370 #define D_CLEAROBJECT	(~(D_bindindex|D_built|D_compiled|D_context|D_dynamic|D_index|D_lower|D_lowres|D_scope))
371 
372 #define M_bind		(1<<0)		/* bind recursion mark		*/
373 #define M_compile	(1<<1)		/* compilation mark		*/
374 #define M_directory	(1<<2)		/* bind directory mark		*/
375 #define M_generate	(1<<3)		/* prereq generation mark	*/
376 #define M_mark		(1<<4)		/* temporary mark		*/
377 #define M_metarule	(1<<5)		/* metarule closure mark	*/
378 #define M_scan		(1<<6)		/* scan recursion mark		*/
379 #define M_waiting	(1<<7)		/* waiting to complete mark	*/
380 
381 /*
382  * var.property flags
383  */
384 
385 #define V_compiled	(1<<0)		/* variable has been compiled	*/
386 #define V_frozen	(1<<1)		/* frozen in make object file	*/
387 #define V_functional	(1<<2)		/* make rule name before access	*/
388 #define V_import	(1<<3)		/* imported from environment	*/
389 #define V_local_D	(1<<4)		/* :T=D: localview reference	*/
390 #define V_oldvalue	(1<<5)		/* compile old value		*/
391 #define V_readonly	(1<<6)		/* only dynamic modifications	*/
392 #define V_retain	(1<<7)		/* retain value in state file	*/
393 #define V_scan		(1<<8)		/* scan for implicit state var	*/
394 
395 #define V_local_E	(1<<9)		/* :T=E: localview reference	*/
396 
397 #define V_auxiliary	(1<<10)		/* auxiliary &= assignment	*/
398 #define V_append	(1<<11)		/* cmd line += property or op	*/
399 #define V_free		(1<<12)		/* value may be freed		*/
400 #define V_builtin	(1<<13)		/* builtin V_functional		*/
401 #define V_scope		(1<<14)		/* scoped value			*/
402 
403 #define V_restored	(1L<<15)	/* retained value stored	*/
404 
405 #define V_CLEARSTATE	(V_free|V_restored)
406 #define V_CLEAROBJECT	(~(V_auxiliary|V_builtin|V_functional|V_import|V_retain|V_scan|V_scope))
407 
408 /*
409  * getval() flags
410  */
411 
412 #define VAL_AUXILIARY	(1<<0)		/* auxilliary value		*/
413 #define VAL_BRACE	(1<<1)		/* { }				*/
414 #define VAL_FILE	(1<<2)		/* !notfile(r)			*/
415 #define VAL_PRIMARY	(1<<3)		/* primary value		*/
416 #define VAL_UNBOUND	(1<<4)		/* unbound name			*/
417 
418 /*
419  * dumpjob() flags
420  */
421 
422 #define JOB_blocked	1		/* blocked jobs with prereqs	*/
423 #define JOB_status	2		/* job status list		*/
424 
425 typedef struct dirent Dirent_t;
426 typedef struct stat Stat_t;
427 
428 struct File_s; typedef struct File_s File_t;
429 struct Frame_s; typedef struct Frame_s Frame_t;
430 struct List_s; typedef struct List_s List_t;
431 struct Rule_s; typedef struct Rule_s Rule_t;
432 
433 typedef uint32_t Flags_t;		/* flag bit vector		*/
434 typedef uint32_t Seconds_t;		/* seconds resolution time	*/
435 
436 typedef struct Fileid_s			/* unique file id		*/
437 {
438 	long		dev;		/* device number		*/
439 	long		ino;		/* inode number			*/
440 } Fileid_t;
441 
442 typedef struct Dir_s			/* scanned directory entry	*/
443 {
444 	char*		name;		/* directory name		*/
445 	Time_t		time;		/* modify time			*/
446 	unsigned char	archive;	/* directory is an archive	*/
447 	unsigned char	directory;	/* directory is a real directory*/
448 	unsigned char	ignorecase;	/* pox on dirs that ignore case	*/
449 	unsigned char	truncate;	/* names truncated to this	*/
450 } Dir_t;
451 
452 struct File_s				/* file table entry		*/
453 {
454 	File_t*		next;		/* next in list			*/
455 	Dir_t*		dir;		/* directory containing file	*/
456 	Time_t		time;		/* modify time			*/
457 };
458 
459 struct Frame_s				/* active target frame		*/
460 {
461 	Frame_t*	parent;		/* parent frame			*/
462 	Frame_t*	previous;	/* previous active frame	*/
463 	Rule_t*		target;		/* target in frame		*/
464 	List_t*		prereqs;	/* original prereqs		*/
465 	char*		action;		/* original action		*/
466 	char*		original;	/* original bound name		*/
467 	char*		primary;	/* metarule primary prereq name	*/
468 	char*		stem;		/* metarule stem		*/
469 	Flags_t		flags;		/* make() flags			*/
470 
471 	struct
472 	{
473 	char*		name;		/* original target name		*/
474 	Frame_t*	frame;		/* original target frame	*/
475 	Time_t		time;		/* original target time		*/
476 	}		context;	/* context push/pop		*/
477 };
478 
479 /*
480  * statevar data, staterule sync time and unbound rule name -- shared in rule.u1
481  */
482 
483 #define event		u1.u_event
484 #define statedata	u1.u_data
485 #define uname		u1.u_uname
486 #define unbound(r)	((r)->uname?(r)->uname:(r)->name)
487 
488 struct Rule_s				/* rule				*/
489 {
490 	char*		name;		/* rule name			*/
491 	Frame_t*	active;		/* active target frame		*/
492 
493 	union
494 	{
495 	char*		u_uname;	/* unbound name			*/
496 	char*		u_data;		/* state value			*/
497 	Time_t		u_event;	/* state rule event time	*/
498 	}		u1;
499 
500 	List_t*		prereqs;	/* prerequisites		*/
501 	char*		action;		/* update action		*/
502 	Time_t		time;		/* modify time			*/
503 
504 	Flags_t		attribute;	/* external named attributes	*/
505 	Flags_t		dynamic;	/* dynamic properties		*/
506 	Flags_t		property;	/* stable properties		*/
507 
508 	unsigned char	scan;		/* file scan strategy index	*/
509 	unsigned char	semaphore;	/* semaphore + count		*/
510 	unsigned char	status;		/* disposition			*/
511 	unsigned char	view;		/* view bind index		*/
512 
513 	unsigned char	mark;		/* M_* marks			*/
514 	unsigned char	preview;	/* min prereq view		*/
515 	unsigned short	must;		/* cancel if == 0		*/
516 
517 	unsigned long	complink;	/* compilation link		*/
518 	Flags_t		checked[STATERULES+1];	/* view state check	*/
519 
520 #if BINDINDEX
521 	unsigned char	source;		/* source bind index		*/
522 #endif
523 };
524 
525 typedef struct Internal_s		/* internal rule and list info	*/
526 {
527 	/*
528 	 * read/write rule attributes
529 	 */
530 
531 	Rule_t*		accept;		/* .ACCEPT rule pointer		*/
532 	Rule_t*		after;		/* .AFTER rule pointer		*/
533 	Rule_t*		alarm;		/* .ALARM rule pointer		*/
534 	Rule_t*		always;		/* .ALWAYS rule pointer		*/
535 	Rule_t*		archive;	/* .ARCHIVE rule pointer	*/
536 	Rule_t*		attribute;	/* .ATTRIBUTE rule pointer	*/
537 	Rule_t*		before;		/* .BEFORE rule pointer		*/
538 	Rule_t*		command;	/* .COMMAND rule pointer	*/
539 	Rule_t*		dontcare;	/* .DONTCARE rule pointer	*/
540 	Rule_t*		force;		/* .FORCE rule pointer		*/
541 	Rule_t*		foreground;	/* .FOREGROUND rule pointer	*/
542 	Rule_t*		functional;	/* .FUNCTIONAL rule pointer	*/
543 	Rule_t*		freeze;		/* .FREEZE rule pointer		*/
544 	Rule_t*		ignore;		/* .IGNORE rule pointer		*/
545 	Rule_t*		immediate;	/* .IMMEDIATE rule pointer	*/
546 	Rule_t*		implicit;	/* .IMPLICIT rule pointer	*/
547 	Rule_t*		insert;		/* .INSERT rule pointer		*/
548 	Rule_t*		joint;		/* .JOINT rule pointer		*/
549 	Rule_t*		local;		/* .LOCAL rule pointer		*/
550 	Rule_t*		make;		/* .MAKE rule pointer		*/
551 	Rule_t*		making;		/* .MAKING rule pointer		*/
552 	Rule_t*		multiple;	/* .MULTIPLE rule pointer	*/
553 	Rule_t*		op;		/* .OPERATOR rule pointer	*/
554 	Rule_t*		parameter;	/* .PARAMETER rule pointer	*/
555 	Rule_t*		read;		/* .READ rule pointer		*/
556 	Rule_t*		readonly;	/* .READONLY rule pointer	*/
557 	Rule_t*		regular;	/* .REGULAR rule pointer	*/
558 	Rule_t*		repeat;		/* .REPEAT rule pointer		*/
559 	Rule_t*		run;		/* .RUN rule pointer		*/
560 	Rule_t*		semaphore;	/* .SEMAPHORE rule pointer	*/
561 	Rule_t*		source;		/* .SOURCE rule pointer		*/
562 	Rule_t*		state;		/* .STATE rule pointer		*/
563 	Rule_t*		sync;		/* .SYNC rule pointer		*/
564 	Rule_t*		terminal;	/* .TERMINAL rule pointer	*/
565 	Rule_t*		use;		/* .USE rule pointer		*/
566 	Rule_t*		virt;		/* .VIRTUAL rule pointer	*/
567 	Rule_t*		wait;		/* .WAIT rule pointer		*/
568 
569 	/*
570 	 * readonly rule attributes
571 	 */
572 
573 	Rule_t*		active;		/* .ACTIVE rule pointer		*/
574 	Rule_t*		bound;		/* .BOUND rule pointer		*/
575 	Rule_t*		built;		/* .BUILT rule pointer		*/
576 	Rule_t*		entries;	/* .ENTRIES rule pointer	*/
577 	Rule_t*		exists;		/* .EXISTS rule pointer		*/
578 	Rule_t*		failed;		/* .FAILED rule pointer		*/
579 	Rule_t*		file;		/* .FILE rule pointer		*/
580 	Rule_t*		global;		/* .GLOBAL rule pointer		*/
581 	Rule_t*		member;		/* .MEMBER rule pointer		*/
582 	Rule_t*		notyet;		/* .NOTYET rule pointer		*/
583 	Rule_t*		scanned;	/* .SCANNED rule pointer	*/
584 	Rule_t*		staterule;	/* .STATERULE rule pointer	*/
585 	Rule_t*		statevar;	/* .STATEVAR rule pointer	*/
586 	Rule_t*		target;		/* .TARGET rule pointer		*/
587 	Rule_t*		triggered;	/* .TRIGGERED rule pointer	*/
588 
589 	/*
590 	 * special rules and names
591 	 */
592 
593 	Rule_t*		args;		/* .ARGS rule pointer		*/
594 	Rule_t*		bind;		/* .BIND rule pointer		*/
595 	Rule_t*		clear;		/* .CLEAR rule pointer		*/
596 	Rule_t*		copy;		/* .COPY rule pointer		*/
597 	Rule_t*		delete;		/* .DELETE rule pointer		*/
598 	Rule_t*		dot;		/* . rule pointer		*/
599 	Rule_t*		empty;		/* "" rule pointer		*/
600 	Rule_t*		error;		/* error intercept rule pointer	*/
601 	Rule_t*		exports;	/* .EXPORT rule pointer		*/
602 	Rule_t*		globalfiles;	/* .GLOBALFILES rule pointer	*/
603 	Rule_t*		include;	/* .INCLUDE rule pointer	*/
604 	Rule_t*		internal;	/* .INTERNAL rule pointer	*/
605 	Rule_t*		main;		/* .MAIN rule pointer		*/
606 	Rule_t*		makefiles;	/* .MAKEFILES rule pointer	*/
607 	Rule_t*		metarule;	/* .METARULE rule pointer	*/
608 	Rule_t*		null;		/* .NULL rule pointer		*/
609 	Rule_t*		preprocess;	/* .PREPROCESS rule pointer	*/
610 	Rule_t*		query;		/* .QUERY rule pointer		*/
611 	Rule_t*		rebind;		/* .REBIND rule pointer		*/
612 	Rule_t*		reset;		/* .RESET rule pointer		*/
613 	Rule_t*		retain;		/* .RETAIN rule pointer		*/
614 	Rule_t*		scan;		/* .SCAN rule pointer		*/
615 	Rule_t*		script;		/* .SCRIPT rule pointer		*/
616 	Rule_t*		serialize;	/* - rule pointer		*/
617 	Rule_t*		special;	/* .SPECIAL rule pointer	*/
618 	Rule_t*		tmplist;	/* .TMPLIST rule pointer	*/
619 	Rule_t*		unbind;		/* .UNBIND rule pointer		*/
620 	Rule_t*		view;		/* .VIEW rule pointer		*/
621 
622 	/*
623 	 * pattern association rules
624 	 */
625 
626 	Rule_t*		append_p;	/* .APPEND. rule pointer	*/
627 	Rule_t*		assert_p;	/* .ASSERT. rule pointer	*/
628 	Rule_t*		assign_p;	/* .ASSIGN. rule pointer	*/
629 	Rule_t*		attribute_p;	/* .ATTRIBUTE. rule pointer	*/
630 	Rule_t*		bind_p;		/* .BIND. rule pointer		*/
631 	Rule_t*		dontcare_p;	/* .DONTCARE. rule pointer	*/
632 	Rule_t*		insert_p;	/* .INSERT. rule pointer	*/
633 	Rule_t*		require_p;	/* .REQUIRE. rule pointer	*/
634 	Rule_t*		source_p;	/* .SOURCE. rule pointer	*/
635 
636 	/*
637 	 * miscellaneous internal info
638 	 */
639 
640 	Sfio_t*		met;		/* metarule expansion buffer	*/
641 	Sfio_t*		nam;		/* name generation buffer	*/
642 	Sfio_t*		tmp;		/* very temporary work buffer	*/
643 	Sfio_t*		val;		/* initial getval return buffer	*/
644 	Sfio_t*		wrk;		/* very temporary work buffer	*/
645 
646 	char*		freelists;	/* free lists list		*/
647 	char*		freerules;	/* free rules list		*/
648 	char*		freevars;	/* free variables list		*/
649 
650 	char*		issource;	/* internal.source* match pat	*/
651 	char*		openfile;	/* bind()-scan() optimization	*/
652 	char*		pwd;		/* PWD value			*/
653 	char*		ptr;		/* temporary for sfstrptr()	*/
654 
655 	int		openfd;		/* bind()-scan() optimization	*/
656 	int		pwdlen;		/* strlen(internal.pwd)		*/
657 } Internal_t;
658 
659 typedef struct External_s		/* external engine name info	*/
660 {
661 	/*
662 	 * names of variables defined by engine, init, or environment
663 	 */
664 
665 	char*		args;		/* candidate args file name(s)	*/
666 	char*		convert;	/* makefile converter patterns	*/
667 	char*		file;		/* main input makefile name	*/
668 	char*		files;		/* candidate makefile name(s)	*/
669 	char*		import;		/* explicit env override vars	*/
670 	char*		lib;		/* related file lib directory	*/
671 	char*		make;		/* program path name		*/
672 	char*		nproc;		/* # jobs for compatibility	*/
673 	char*		old;		/* old program path name	*/
674 	char*		pwd;		/* pwd name			*/
675 	char*		rules;		/* candidate rules file name(s)	*/
676 	char*		skip;		/* order directory skip pattern	*/
677 	char*		version;	/* engine version stamp		*/
678 	char*		viewdot;	/* . view dir list		*/
679 	char*		viewnode;	/* view node dir list		*/
680 
681 	/*
682 	 * infrequently used engine interface names
683 	 */
684 
685 	char*		compdone;	/* made after makefile compiled	*/
686 	char*		compinit;	/* made before makefile compiled*/
687 	char*		done;		/* made just before exit	*/
688 	char*		init;		/* made before first user target*/
689 	char*		interrupt;	/* made on first interrupt	*/
690 	char*		jobdone;	/* made when each job done	*/
691 	char*		makedone;	/* made after done		*/
692 	char*		makeinit;	/* made after before init	*/
693 	char*		makeprompt;	/* made just before each prompt	*/
694 	char*		makerun;	/* made just before each job	*/
695 	char*		mamname;	/* external mam atom name	*/
696 	char*		mamaction;	/* external mam action		*/
697 	char*		order;		/* :W=[OPR]: favorites		*/
698 
699 	/*
700 	 * related file suffixes
701 	 */
702 
703 	char*		lock;		/* make lock file suffix	*/
704 	char*		object;		/* make object file suffix	*/
705 	char*		source;		/* make source file suffix	*/
706 	char*		state;		/* make state file suffix	*/
707 	char*		tmp;		/* make temporary file suffix	*/
708 } External_t;
709 
710 typedef struct Tables_s			/* hash table pointers		*/
711 {
712 	Hash_table_t*	ar;		/* archives dir info by name	*/
713 	Hash_table_t*	bound;		/* directory of bound file	*/
714 	Hash_table_t*	dir;		/* directories and archives	*/
715 	Hash_table_t*	file;		/* files from scanned dirs	*/
716 	Hash_table_t*	oldvalue;	/* old variable values		*/
717 	Hash_table_t*	regress;	/* regression path maps		*/
718 	Hash_table_t*	rule;		/* rule names			*/
719 	Hash_table_t*	var;		/* variable names		*/
720 } Tables_t;
721 
722 #define BIND_EXISTS	(1<<0)		/* statefile loaded		*/
723 #define BIND_LOADED	(1<<1)		/* statefile loaded		*/
724 
725 typedef struct Binding_s		/* binding info			*/
726 {
727 #if BINDINDEX
728 	Rule_t*		path;		/* path name component		*/
729 #else
730 	char*		path;		/* path name component		*/
731 #endif
732 	char*		root;		/* path root			*/
733 	short		pathlen;	/* path length			*/
734 	short		rootlen;	/* root length			*/
735 	unsigned char	flags;		/* BIND_* flags			*/
736 	unsigned char	map;		/* external index map		*/
737 } Binding_t;
738 
739 typedef struct Label_s			/* resume label			*/
740 {
741 	jmp_buf		label;
742 } Label_t;
743 
744 typedef struct Mam_s			/* mam state			*/
745 {
746 	Sfdisc_t	disc;		/* output discipline -- first!	*/
747 
748 	int		hold;		/* output hold nest level	*/
749 	int		level;		/* next error() message level	*/
750 	int		parent;		/* mam parent label		*/
751 	int		rootlen;	/* strlen(state.mam.root)	*/
752 
753 	char*		label;		/* instruction label		*/
754 	char*		options;	/* option string		*/
755 	char*		root;		/* names relative to this root	*/
756 	char*		type;		/* mam type name		*/
757 
758 	Sfio_t*		out;		/* output stream pointer	*/
759 
760 	unsigned char	dynamic;	/* dynamic mam			*/
761 	unsigned char	regress;	/* regression mam		*/
762 	unsigned char	statix;		/* static mam			*/
763 
764 	unsigned char	dontcare;	/* emit dontcare rules too	*/
765 	unsigned char	port;		/* emit porting hints		*/
766 } Mam_t;
767 
768 typedef struct State_s			/* program state		*/
769 {
770 	unsigned char	accept;		/* accept all existing targets	*/
771 	unsigned char	alias;		/* enable directory aliasing	*/
772 	unsigned char	base;		/* compile base|global rules	*/
773 	unsigned char	caught;		/* a signal was caught		*/
774 	unsigned char	compile;	/* make object compile state	*/
775 	unsigned char	compileonly;	/* only compile (force)		*/
776 	unsigned char	compatibility;	/* disable compatibility msgs	*/
777 	unsigned char	cross;		/* don't run gen'd executables	*/
778 	unsigned char	exec;		/* execute shell actions	*/
779 	unsigned char	expandall;	/* expanding $(...)		*/
780 	unsigned char	expandview;	/* expand paths if fsview!=0	*/
781 	unsigned char	explain;	/* explain reason for actions	*/
782 	unsigned char	explicitrules;	/* explicit rules statement	*/
783 	unsigned char	finish;		/* in finish()			*/
784 	unsigned char	force;		/* force target updates		*/
785 	unsigned char	forceread;	/* force makefiles to be read	*/
786 	unsigned char	forcescan;	/* force implicit prereq scan	*/
787 	unsigned char	fsview;		/* file system handles views	*/
788 	unsigned char	fullscan;	/* scan for impl state prereqs	*/
789 	unsigned char	global;		/* reading global rules		*/
790 	unsigned char	ignore;		/* ignore sh action errors	*/
791 	unsigned char	ignorelock;	/* ignore state lock		*/
792 	unsigned char	import;		/* import var def precedence	*/
793 	unsigned char	init;		/* engine initialization	*/
794 	unsigned char	intermediate;	/* force intermediate targets	*/
795 	unsigned char	interpreter;	/* in interpreter main loop	*/
796 	unsigned char	keepgoing;	/* continue w/ sibling prereqs	*/
797 	unsigned char	list;		/* list readable definitions	*/
798 	unsigned char	localview;	/* automatics to local view	*/
799 #if BINDINDEX
800 	unsigned char	logical;	/* emit logical pathnames	*/
801 #endif
802 	unsigned char	never;		/* really - don't exec anything	*/
803 	unsigned char	op;		/* currently parsing operator	*/
804 	unsigned char	override;	/* override explicit rules	*/
805 	unsigned char	pushed;		/* --global state		*/
806 	unsigned char	push_global;	/* --global state		*/
807 	unsigned char	push_user;	/* --global state		*/
808 	unsigned char	preprocess;	/* preprocess all makefiles	*/
809 	unsigned char	reading;	/* currently reading makefile	*/
810 	unsigned char	readonly;	/* current vars|opts readonly	*/
811 	unsigned char	ruledump;	/* dump rule information	*/
812 	unsigned char	savestate;	/* must save state variables	*/
813 	unsigned char	scan;		/* scan|check implicit prereqs	*/
814 	unsigned char	serialize;	/* serialize concurrent output	*/
815 	unsigned char	silent;		/* run silently			*/
816 	unsigned char	strictview;	/* strict views			*/
817 	unsigned char	targetcontext;	/* expand in target dir context	*/
818 	unsigned char	touch;		/* touch out of date targets	*/
819 	unsigned char	user;		/* user activities started	*/
820 	unsigned char	val;		/* internal.val in use		*/
821 	unsigned char	vardump;	/* dump variable information	*/
822 	unsigned char	virtualdot;	/* fsview . is virtual		*/
823 	unsigned char	waiting;	/* waiting for job completion	*/
824 	unsigned char	warn;		/* enable source file warnings	*/
825 
826 	int		argc;		/* global argc			*/
827 	int		believe;	/* believe state from this level*/
828 	int		errors;		/* keepgoing error count	*/
829 	int		interrupt;	/* interrupt causing exit	*/
830 	int		jobs;		/* sh action concurrency level	*/
831 	int		pid;		/* make pid			*/
832 	int		readstate;	/* state files to this view ok	*/
833 	int		reread;		/* input makefile reread count	*/
834 	int		stateview;	/* state file view index	*/
835 	int		tabstops;	/* tab stops for makefile parse	*/
836 	int		targetview;	/* most recent active targ view	*/
837 	int		tolerance;	/* time comparison tolerance	*/
838 	int		unwind;		/* make() dontcare unwind level	*/
839 
840 	Flags_t		questionable;	/* questionable code enable bits*/
841 	Flags_t		test;		/* test code enable bits	*/
842 
843 	Time_t		start;		/* start time of this make	*/
844 
845 	char*		corrupt;	/* corrupt state file action	*/
846 	char*		errorid;	/* error message id		*/
847 	char*		hold;		/* hold error trap		*/
848 	char*		loading;	/* loading this object file	*/
849 	char*		makefile;	/* first makefile name		*/
850 	char*		objectfile;	/* make object file name	*/
851 	char*		regress;	/* output for regression test	*/
852 	char*		rules;		/* base rules base name		*/
853 	char*		statefile;	/* state variable file name	*/
854 	char*		targetprefix;	/* target prefix dir separator	*/
855 	char*		tmppchar;	/* macro char* temporary	*/
856 	char*		tmpfile;	/* temporary file name		*/
857 	char*		writeobject;	/* 0:nowrite or object file def	*/
858 	char*		writestate;	/* 0:nowrite or state file def	*/
859 
860 	int*		argf;		/* global argv ARG_* flags	*/
861 
862 	char**		argv;		/* global argv			*/
863 
864 	Dir_t*		archive;	/* .SCAN archive		*/
865 
866 	Sfio_t*		context;	/* localview() target context	*/
867 
868 	Frame_t*	frame;		/* current target frame		*/
869 
870 #if BINDINDEX
871 	Binding_t	source[MAXBIND+1];/* source bind table		*/
872 	int		maxsource;	/* max source bind index	*/
873 #endif
874 	Binding_t	view[MAXVIEW+1];/* view bind table		*/
875 	unsigned int	maxview;	/* max view bind index		*/
876 
877 	int (*compnew)(const char*, char*, void*); /* new compile rule	*/
878 	void*		comparg;	/* compnew handle		*/
879 
880 	Label_t		resume;		/* if interpreter!=0		*/
881 
882 	Mam_t		mam;		/* mam state			*/
883 
884 	Coshell_t*	coshell;	/* coshell handle		*/
885 
886 	Sfio_t*		io[11];		/* print/read streams		*/
887 } State_t;
888 
889 typedef struct Var_s			/* variable			*/
890 {
891 	char*		name;		/* name				*/
892 	char*		value;		/* value			*/
893 	Flags_t		property;	/* static and dynamic		*/
894 	size_t		length;		/* maximum length of value	*/
895 	char*		(*builtin)(char**);	/* builtin function	*/
896 } Var_t;
897 
898 struct List_s				/* rule cons cell		*/
899 {
900 	List_t*		next;		/* next in list			*/
901 	Rule_t*		rule;		/* list item			*/
902 };
903 
904 /*
905  * make globals
906  */
907 
908 extern External_t	external;	/* external engine names	*/
909 extern Internal_t	internal;	/* internal rule and list info	*/
910 extern State_t		state;		/* engine state			*/
911 extern Tables_t		table;		/* hash table pointers		*/
912 
913 extern char		null[];		/* null string			*/
914 extern char		tmpname[];	/* temporary name buffer	*/
915 
916 extern short		ctypes[];	/* internal character types	*/
917 
918 extern char*		idname;		/* interface id name		*/
919 extern char*		initdynamic;	/* dynamic initialization	*/
920 extern char*		initstatic;	/* static initialization	*/
921 extern char*		version;	/* program version stamp	*/
922 
923 /*
924  * make routines
925  */
926 
927 extern File_t*		addfile(Dir_t*, char*, Time_t);
928 extern void		addprereq(Rule_t*, Rule_t*, int);
929 extern List_t*		append(List_t*, List_t*);
930 extern int		apply(Rule_t*, char*, char*, char*, Flags_t);
931 extern void		argcount(void);
932 extern void		arscan(Rule_t*);
933 extern void		artouch(char*, char*);
934 extern char*		arupdate(char*);
935 extern Rule_t*		associate(Rule_t*, Rule_t*, char*, List_t**);
936 extern Var_t*		auxiliary(char*, int);
937 extern Rule_t*		bind(Rule_t*);
938 extern void		bindattribute(Rule_t*);
939 extern Rule_t*		bindfile(Rule_t*, char*, int);
940 extern Rule_t*		bindstate(Rule_t*, char*);
941 extern int		block(int);
942 extern void		candidates(void);
943 extern char*		call(Rule_t*, char*);
944 extern Rule_t*		catrule(char*, char*, char*, int);
945 extern char*		colonlist(Sfio_t*, char*, int, int);
946 extern void		compile(char*, char*);
947 extern int		complete(Rule_t*, List_t*, Time_t*, Flags_t);
948 extern void		compref(Rule_t*, int);
949 extern List_t*		cons(Rule_t*, List_t*);
950 extern void		dirscan(Rule_t*);
951 extern void		drop(void);
952 extern void		dump(Sfio_t*, int);
953 extern void		dumpaction(Sfio_t*, const char*, char*, const char*);
954 extern void		dumpjobs(int, int);
955 extern void		dumpregress(Sfio_t*, const char*, const char*, char*);
956 extern void		dumprule(Sfio_t*, Rule_t*);
957 extern void		dumpvar(Sfio_t*, Var_t*);
958 extern void		dynamic(Rule_t*);
959 extern void		edit(Sfio_t*, char*, char*, char*, char*);
960 extern void		expand(Sfio_t*, char*);
961 extern void		explain(int, ...);
962 extern long		expr(Sfio_t*, char*);
963 extern Sfio_t*		fapply(Rule_t*, char*, char*, char*, Flags_t);
964 extern void		finish(int);
965 extern int		forcescan(const char*, char* v, void*);
966 extern char*		getarg(char**, int*);
967 extern void		getop(Sfio_t*, char*, int);
968 extern char*		getval(char*, int);
969 extern char**		globv(glob_t*, char*);
970 extern int		handle(void);
971 extern int		hasattribute(Rule_t*, Rule_t*, Rule_t*);
972 extern int		hasafter(Rule_t*, Flags_t);
973 extern void		immediate(Rule_t*);
974 extern void		initcode(void);
975 extern void		inithash(void);
976 extern void		initrule(void);
977 extern void		initscan(int);
978 extern void		inittrap(void);
979 extern void		initview(void);
980 extern void		initwakeup(int);
981 extern void		interpreter(char*);
982 extern int		isoption(const char*);
983 extern int		nametype(const char*, char**);
984 extern List_t*		joint(Rule_t*);
985 extern List_t*		listcopy(List_t*);
986 extern void		listops(Sfio_t*, int);
987 extern int		load(Sfio_t*, const char*, int, int);
988 extern int		loadable(Sfio_t*, Rule_t*, int);
989 extern void		localvar(Sfio_t*, Var_t*, char*, int);
990 extern char*		localview(Rule_t*);
991 extern void		lockstate(int);
992 extern int		make(Rule_t*, Time_t*, char*, Flags_t);
993 extern int		makeafter(Rule_t*, Flags_t);
994 extern int		makebefore(Rule_t*);
995 extern Rule_t*		makerule(char*);
996 extern void		maketop(Rule_t*, int, char*);
997 extern char*		mamcanon(char*);
998 extern ssize_t		mamerror(int, const void*, size_t);
999 extern char*		mamname(Rule_t*);
1000 extern void		mampop(Sfio_t*, Rule_t*, Flags_t);
1001 extern int		mampush(Sfio_t*, Rule_t*, Flags_t);
1002 extern Sfio_t*		mamout(Rule_t*);
1003 extern char*		maprule(char*, Rule_t*);
1004 extern void		merge(Rule_t*, Rule_t*, int);
1005 extern void		mergestate(Rule_t*, Rule_t*);
1006 extern void		metaclose(Rule_t*, Rule_t*, int);
1007 extern void		metaexpand(Sfio_t*, char*, char*);
1008 extern Rule_t*		metaget(Rule_t*, Frame_t*, char*, Rule_t**);
1009 extern Rule_t*		metainfo(int, char*, char*, int);
1010 extern int		metamatch(char*, char*, char*);
1011 extern Rule_t*		metarule(char*, char*, int);
1012 extern void		negate(Rule_t*, Rule_t*);
1013 extern void*		newchunk(char**, size_t);
1014 extern void		newfile(Rule_t*, char*, Time_t);
1015 extern char*		objectfile(void);
1016 extern void		parentage(Sfio_t*, Rule_t*, char*);
1017 extern int		parse(Sfio_t*, char*, char*, Sfio_t*);
1018 extern char*		parsefile(void);
1019 extern char*		pathname(char*, Rule_t*);
1020 extern void		poplocal(void*);
1021 extern int		prereqchange(Rule_t*, List_t*, Rule_t*, List_t*);
1022 extern void		punt(int);
1023 extern void*		pushlocal(void);
1024 extern void		readcheck(void);
1025 extern void		readclear(void);
1026 extern void		readenv(void);
1027 extern int		readfile(char*, int, char*);
1028 extern void		readstate(void);
1029 extern void		rebind(Rule_t*, int);
1030 extern void		remdup(List_t*);
1031 extern void		remtmp(int);
1032 extern int		resolve(char*, int, int);
1033 extern int		rstat(char*, Stat_t*, int);
1034 extern void		rules(char*);
1035 extern Rule_t*		rulestate(Rule_t*, int);
1036 extern void		savestate(void);
1037 extern List_t*		scan(Rule_t*, Time_t*);
1038 extern int		scanargs(int, char**, int*);
1039 extern int		set(char*, int, Sfio_t*);
1040 extern Var_t*		setvar(char*, char*, int);
1041 extern void		shquote(Sfio_t*, char*);
1042 extern Rule_t*		source(Rule_t*);
1043 extern int		special(Rule_t*);
1044 extern char*		statefile(void);
1045 extern Rule_t*		staterule(int, Rule_t*, char*, int);
1046 extern Time_t		statetime(Rule_t*, int);
1047 extern int		statetimeq(Rule_t*, Rule_t*);
1048 extern int		strprintf(Sfio_t*, const char*, char*, int, int);
1049 extern void		terminate(void);
1050 extern char*		timefmt(const char*, Time_t);
1051 extern Time_t		timenum(const char*, char**);
1052 extern char*		timestr(Time_t);
1053 extern void		trigger(Rule_t*, Rule_t*, char*, Flags_t);
1054 extern int		unbind(const char*, char*, void*);
1055 extern Dir_t*		unique(Rule_t*);
1056 extern void		unparse(int);
1057 extern Var_t*		varstate(Rule_t*, int);
1058 extern void		wakeup(Seconds_t, List_t*);
1059