1 /* $RCSfile: infer.c,v $
3 -- last change: $Author: ihi $ $Date: 2007-10-15 15:39:49 $
6 -- Infer how to make a target.
9 -- This file contains the code to infer a recipe, and possibly some new
10 -- prerequisites for a target which dmake does not know how to make, or
11 -- has no explicit recipe.
13 -- The inference fails if no path through the inference graph can be
14 -- found by which we can make the target.
17 -- Dennis Vadura, dvadura@dmake.wticorp.com
20 -- http://dmake.wticorp.com/
23 -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
25 -- This program is NOT free software; you can redistribute it and/or
26 -- modify it under the terms of the Software License Agreement Provided
27 -- in the file <distribution-root>/readme/license.txt.
30 -- Use cvs log to obtain detailed change logs.
35 /* attributes that get transfered from the % start cell to the inferred
38 #define A_TRANSFER (A_EPILOG | A_PRECIOUS | A_SILENT | A_SHELL | A_SETDIR |\
39 A_SEQ | A_LIBRARY | A_IGNORE | A_PROLOG | A_SWAP |\
43 /* Define local static functions */
44 static DFALINKPTR dfa_subset
ANSI((DFALINKPTR
, DFASETPTR
));
45 static void free_dfas
ANSI((DFALINKPTR
));
46 static int count_dots
ANSI((char *));
47 static char * buildname
ANSI((char *, char *, char *));
48 static void free_icells
ANSI((void));
49 static ICELLPTR union_iset
ANSI((ICELLPTR
, ICELLPTR
));
50 static ICELLPTR add_iset
ANSI((ICELLPTR
,ICELLPTR
,CELLPTR
,DFALINKPTR
,
51 CELLPTR
,int,int,char *,char *, int));
52 static ICELLPTR derive_prerequisites
ANSI((ICELLPTR
, ICELLPTR
*));
53 static char * dump_inf_chain
ANSI((ICELLPTR
, int, int));
56 static void _dump_dfa_stack
ANSI((DFALINKPTR
, DFASETPTR
));
57 static void _dump_iset
ANSI(( char *, ICELLPTR
));
62 Infer_recipe( cp
, setdirroot
)/*
63 ================================
64 Perform a breadth-first search of the inference graph and return if
65 possible an inferred set of prerequisites for making the current target. */
69 ICELLPTR nomatch
, match
;
71 DB_ENTER("Infer_recipe");
73 if( cp
->ce_attr
& A_NOINFER
) {DB_VOID_RETURN
;}
75 DB_PRINT("inf", ("Inferring rule for [%s]", cp
->CE_NAME
));
78 nomatch
= add_iset( NIL(ICELL
), NIL(ICELL
), NIL(CELL
), NIL(DFALINK
),
79 setdirroot
, Prep
+count_dots(cp
->CE_NAME
), 0,
80 DmStrDup(cp
->CE_NAME
), NIL(char),
81 cp
->ce_time
!= (time_t)0L);
83 /* Make sure we try whole heartedly to infer at least one suffix */
84 if( nomatch
->ic_dmax
== 0 ) ++nomatch
->ic_dmax
;
86 DB_EXECUTE( "inf", _dump_iset("nomatch",nomatch
); );
88 /* If nomatch is non-empty there was no match with an existing
89 * prerrequisite, try to derive one. */
90 while( nomatch
!= NIL(ICELL
) ) {
91 ICELLPTR new_nomatch
= NIL(ICELL
);
92 ICELLPTR ic
, pmatch
, mmatch
;
95 for( ic
=nomatch
; ic
!= NIL(ICELL
); ic
=ic
->ic_next
) {
98 if( ic
->ic_dir
) ipush
= Push_dir(ic
->ic_dir
, ic
->ic_name
, FALSE
);
99 match
= union_iset(match
, derive_prerequisites(ic
, &new_nomatch
));
100 if( ipush
) Pop_dir(FALSE
);
103 DB_EXECUTE( "inf", _dump_iset("match",match
); );
104 DB_EXECUTE( "inf", _dump_iset("nomatch",new_nomatch
); );
106 /* We have now deduced the two sets MATCH and NOMATCH. MATCH holds the
107 * set of edges that we encountered that matched. If this set is empty
108 * then we can apply transitive closure (if enabled) to the elements of
109 * NOMATCH to see if we can find some other method to make the target.
111 * If MATCH is non-empty, we have found a method for making the target.
112 * It is the shortest method for doing so (ie. uses fewest number of
113 * steps). If MATCH contains more than one element then we have a
114 * possible ambiguity.
116 if( match
== NIL(ICELL
) ) {
117 nomatch
= new_nomatch
;
119 /* Skip the rest and try one level deeper. */
120 if( Transitive
) continue;
125 /* Ok, we have a set of possible matches in MATCH, we should check the
126 * set for ambiguity. If more than one inference path exists of the
127 * same depth, then we may issue an ambiguous inference error message.
129 * The message is suppressed if MATCH contains two elements and one of
130 * them is the empty-prerequisite-rule. In this case we ignore the
131 * ambiguity and take the rule that infers the prerequisite.
133 * Also if there are any chains that rely on a non-existant prerequisite
134 * that may get made because it has a recipe then we prefer any that
135 * rely on existing final prerequisites over those that we have to make.
138 /* Split out those that have to be made from those that end in
139 * prerequisites that already exist. */
140 pmatch
= mmatch
= NIL(ICELL
);
141 for(; match
; match
= ic
) {
142 /* This loop checks all possible matches. */
143 DB_PRINT("inf", ("Target [%s] : prerequisite [%s]",
144 match
->ic_meta
->CE_NAME
, match
->ic_name
));
147 match
->ic_next
= NIL(ICELL
);
149 if( match
->ic_exists
)
150 pmatch
= union_iset(pmatch
, match
);
152 mmatch
= union_iset(mmatch
, match
);
155 /* Prefer %-targets with existing prerequisites. */
161 /* Make sure it is unique. It would be easy to check
162 * match->ic_meta->ce_prq for existence and prefer no prerequisites
163 * over prerequisites that are present, but we are currently not
165 if( match
->ic_next
!= NIL(ICELL
) ) {
168 Warning( "Ambiguous inference chains for target '%s'", cp
->CE_NAME
);
169 for( ic
=match
; ic
; ic
=ic
->ic_next
)
170 (void) dump_inf_chain(ic
, TRUE
, count
++);
171 Warning( "First matching rule is chosen.");
174 /* MATCH now points at the derived prerequisite chain(s). We must now
175 * take cp, and construct the correct graph so that the make may
178 /* The folowing shows only the first element, i.e. the last matching
179 * recipe that was found. */
180 if( Verbose
& V_INFER
) {
181 char *tmp
= dump_inf_chain(match
, TRUE
, FALSE
);
182 printf("%s: Inferring prerequistes and recipes using:\n%s: ... %s\n",
189 /* This loop treats the inferred targets last to first. */
191 CELLPTR infcell
=NIL(CELL
);
193 /* Compute the inferred prerequisite first. */
194 if( match
->ic_name
) {
196 infcell
= Def_cell( match
->ic_name
);
200 infcell
->ce_flag
|= F_TARGET
;
202 if( infcell
!= cp
) {
203 infcell
->ce_flag
|= F_INFER
|F_REMOVE
;
204 DB_PRINT("remove", ("Mark for deletion [%s]",
208 if( !match
->ic_flag
)
209 infcell
->ce_attr
|= A_NOINFER
;
212 /* Add global prerequisites from previous rule if there are any and
215 CELLPTR imeta
= pmatch
->ic_meta
;
218 DB_PRINT("inf", ("%%-target [%s] - infered target [%s]\n",
219 imeta
->CE_NAME
, infcell
->CE_NAME
));
221 infcell
->ce_per
= pmatch
->ic_dfa
->dl_per
;
222 infcell
->ce_attr
|= (imeta
->ce_attr
& A_TRANSFER
);
224 /* The .PHONY mechanism relies on having phony targets not
225 * being STATed and having a zero time stamp. While inferring
226 * the this target it might have been created and stated
227 * therefore these values need to be reset. */
228 if( infcell
->ce_attr
& A_PHONY
){
229 infcell
->ce_time
= 0L;
230 infcell
->ce_flag
&= ~F_STAT
;
233 if( !(infcell
->ce_flag
& F_RULES
) ) {
234 infcell
->ce_flag
|= (imeta
->ce_flag
&(F_SINGLE
|F_GROUP
))|F_RULES
;
235 infcell
->ce_recipe
= imeta
->ce_recipe
;
238 /* Add any conditional macro definitions that may be associated
239 * with the inferred cell. */
240 if (imeta
->ce_cond
!= NIL(STRING
)) {
243 last
= infcell
->ce_cond
;
244 for(sp
=imeta
->ce_cond
; sp
; sp
=sp
->st_next
) {
246 TALLOC(new, 1, STRING
);
247 new->st_string
= DmStrDup(sp
->st_string
);
251 infcell
->ce_cond
= new;
256 pmatch
->ic_dfa
->dl_per
= NIL(char);
258 /* If infcell already had a .SETDIR directory set then modify it
259 * based on whether it was the original cell or some intermediary. */
260 if( imeta
->ce_dir
) {
261 if( infcell
->ce_dir
&& infcell
== cp
) {
262 /* cp->ce_dir was set and we have pushed the directory prior
263 * to calling this routine.
264 * We build a new path by appending imeta->ce_dir to the
265 * current directory of the original cell.
266 * We should therefore pop it and push the new concatenated
267 * directory required by the inference.
268 * This leaks memory as cp->ce_dir is not freed before
269 * setting the new the new infcell->ce_dir value but as
270 * the pointer could be a `A_POOL` member we accept this. */
271 infcell
->ce_dir
= DmStrDup(Build_path(infcell
->ce_dir
,
275 /* Inherit a copy of the .SETDIR value. Use a copy because
276 * the original could have been freed in the meantime
277 * in Make() by the FREE() before _pool_lookup(). This can
278 * also leak if infcell->ce_dir was set before. */
279 infcell
->ce_dir
= DmStrDup(imeta
->ce_dir
);
283 for( lp
=imeta
->ce_indprq
; lp
!= NIL(LINK
); lp
=lp
->cl_next
) {
284 char *name
= lp
->cl_prq
->CE_NAME
;
287 name
= buildname( cp
->CE_NAME
, name
, infcell
->ce_per
);
288 tcp
= Def_cell( name
);
289 tcp
->ce_flag
|= F_REMOVE
;
290 Add_prerequisite( infcell
, tcp
, FALSE
, FALSE
);
292 if( Verbose
& V_INFER
)
293 printf( "%s: Inferred indirect prerequisite [%s]\n",
299 /* Add the previous cell as the prerequisite */
301 (Add_prerequisite(infcell
,prereq
,FALSE
,FALSE
))->cl_flag
|=F_TARGET
;
303 pmatch
= match
; /* Previous member in inference chain ... */
304 prereq
= infcell
; /* is a prerequisite to the next match. */
305 /* ip->ic_parent is the next target in the inference chain to be
306 * build. If it is empty we are done. */
307 match
= match
->ic_parent
;
310 DB_PRINT("inf", ("Terminated due to a match"));
322 derive_prerequisites( ic
, nnmp
)/*
323 ===================================
324 Take a cell and derive a set of prerequisites from the cell. Categorize
325 them into those that MATCH (ie. those that we found in the file system),
326 and those that do not match NOMATCH that we may possibly have a look at
327 later. When we process the next level of the breadth-first search.
329 Once MATCH is non-empty we will stop inserting elements into NOMATCH
330 since we know that either MATCH is successful and unique or it will
331 issue an ambiguity error. We will never go on to look at elements
332 in NOMATCH after wards. */
336 ICELLPTR match
= NIL(ICELL
);
340 DB_ENTER("derive_prerequisites");
342 DB_PRINT("inf", ("for [%s]\n", ic
->ic_name
));
344 /* If none of the inference nodes match then forget about the inference.
345 * The user did not tell us how to make such a target. We also stop the
346 * Inference if the new set of DFA's is a proper subset of a previous
347 * subset and it's PREP counts exceed the value of Prep.
349 dfas
= dfa_subset( Match_dfa(ic
->ic_name
), &ic
->ic_dfastack
);
351 DB_EXECUTE("inf", _dump_dfa_stack(dfas
, &ic
->ic_dfastack
); );
353 /* Ok, we have nothing here to work with so return an empty cell. */
354 if( dfas
== NIL(DFALINK
) ) {
355 DB_PRINT( "mem", ("%s:<- mem %ld",ic
->ic_name
, (long)coreleft()));
356 DB_PRINT( "inf", ("<<< Exit, no dfas, cp = %04x", NIL(CELL
)) );
357 DB_RETURN( NIL(ICELL
) );
360 /* Save the dfas, we are going to use on the stack for this cell. */
361 ic
->ic_dfastack
.df_set
= dfas
;
363 /* Run through the %-meta cells, build the prerequisite cells. For each
364 * %-meta go through it's list of edges and try to use each in turn to
365 * deduce a likely prerequisite. We perform a breadth-first search
366 * matching the first path that results in a unique method for making the
368 for( pdfa
= dfas
; pdfa
!= NIL(DFALINK
); pdfa
= pdfa
->dl_next
) {
373 pmeta
= pdfa
->dl_meta
;
374 DB_PRINT( "inf", ("Using dfa: [%s]", pmeta
->CE_NAME
) );
376 /* If the %-meta is a singleton meta then deal with it differently from
377 * the case when it is a bunch of %-meta's found on the original entries
378 * prerequisite list. */
379 if( pmeta
->ce_flag
& F_MULTI
)
380 edge
= pmeta
->ce_prq
;
383 tl
.cl_next
= NIL(LINK
);
387 /* Now run through the list of prerequisite edge's for the %-meta. */
388 for( ; edge
!= NIL(LINK
); edge
= edge
->cl_next
) {
389 HASHPTR thp
= 0; /* temporary hash table pointer */
390 HASH iprqh
; /* hash cell for new prerequisite */
391 CELL iprq
; /* inferred prerequisite to look for */
392 CELLPTR idirroot
; /* Inferred prerequisite root */
393 CELLPTR nidirroot
; /* Inferred prerequisite root */
394 STRINGPTR ircp
= 0; /* Inferred prerequisites recipe */
395 char *idir
; /* directory to CD to. */
396 int ipush
= 0; /* flag for push on inferred prereq */
397 char *name
= NIL(char); /* prerequisite name */
398 CELLPTR meta
= edge
->cl_prq
;
404 /* Name of the prerequisite, can be empty. */
406 name
= meta
->ce_prq
->cl_prq
->CE_NAME
;
408 DB_PRINT( "inf", ("Trying edge from [%s] to [%s] for [%s]",
409 meta
->CE_NAME
, name
?name
:"(nil)", ic
->ic_name
) );
411 /* Set the temp CELL used for building prerequisite candidates to
412 * all zero so that we don't have to keep initializing all the
415 register char *s
= (char *) &iprq
;
416 register int n
= sizeof(CELL
);
417 while( n
) { *s
++ = '\0'; n
--; }
420 nidirroot
= idirroot
= ic
->ic_setdirroot
;
421 iprq
.ce_name
= &iprqh
;
424 /* Build the prerequisite name from the %-meta prerequisite given
425 * for the %-meta rule. */
426 iprqh
.ht_name
= buildname( ic
->ic_name
, name
, pdfa
->dl_per
);
427 if((dmax_fix
= (count_dots(name
)-count_dots(meta
->CE_NAME
))) < 0)
430 if( !strcmp(ic
->ic_name
, iprqh
.ht_name
) ||
431 (count_dots(iprqh
.ht_name
) > ic
->ic_dmax
+ dmax_fix
) ) {
432 FREE( iprqh
.ht_name
);
436 DB_PRINT( "inf", ("Checking prerequisite [%s]", iprqh
.ht_name
) );
438 /* See if the prerequisite CELL has been previously defined. If
439 * it has, then make a copy of it into iprq, and use it to try
440 * the inference. We make the copy so that we don't modify the
441 * stat of the inferred cell if the inference fails.
443 thp
= Get_name( iprqh
.ht_name
, Defs
, FALSE
);
444 if(thp
!= NIL(HASH
)) {
445 iprq
= *thp
->CP_OWNR
;
446 /* Check if a recipe for this target exists. Targets with F_MULTI
447 * set need each cell checked for existing recipes.
449 if( iprq
.ce_flag
& F_MULTI
) {
450 /* Walk through all cells of this target. */
451 LINKPTR mtcp
= iprq
.ce_prq
;
453 for( ; mtcp
!= NIL(LINK
); mtcp
= mtcp
->cl_next
) {
454 /* If a recipe is found stop searching and set ircp to that result.
455 * ircp is not used but only checked if it is set.
457 if( mtcp
->cl_prq
->ce_recipe
!= NIL(STRING
) ) {
458 ircp
= mtcp
->cl_prq
->ce_recipe
;
464 ircp
= iprq
.ce_recipe
;
470 iprqh
.ht_name
= NIL(char);
473 /* If the %-meta has a .SETDIR set then we change to the new
474 * directory prior to performing the stat of the new prerequisite.
475 * If the change of directory fails then the rule is droped from
476 * further consideration.
479 if( (ipush
= Push_dir(iprq
.ce_dir
, iprqh
.ht_name
, TRUE
)) != 0 ) {
480 nidirroot
= thp
->CP_OWNR
;
484 if( iprqh
.ht_name
) FREE( iprqh
.ht_name
);
492 /* Stat the inferred prerequisite.
495 if( Verbose
& V_INFER
)
496 printf( "%s: Trying prerequisite [%s] for [%s]\n", Pname
,
497 iprqh
.ht_name
, ic
->ic_name
);
499 /* irpq is a temporary target cell, a stat will not be remembered. */
500 if( !(iprq
.ce_flag
& F_STAT
) ) Stat_target(&iprq
, FALSE
, FALSE
);
504 /* If the STAT succeeded or if the prerequisite has a recipe for
505 * making it then it's a match and a candidate for getting infered.
506 * Otherwise it is not a match, and we cannot yet tell if it is
507 * going to be a successful path to follow, so we save it for
508 * later consideration.
510 noinf
= ((Glob_attr
)&A_NOINFER
);
512 noinf
|= ((meta
->ce_prq
->cl_prq
->ce_attr
)&A_NOINFER
);
513 trans
= Transitive
|| !noinf
;
515 /* If no prereq is given treat it as if it is existing. */
516 exists
= (iprq
.ce_time
!= (time_t)0L) || (name
== NIL(char));
518 if( exists
|| (ircp
!= NIL(STRING
)) || !name
) {
519 match
= add_iset( match
, ic
, meta
, pdfa
, idirroot
, ic
->ic_dmax
,
520 trans
, iprq
.ce_name
->ht_name
, idir
, exists
);
521 DB_PRINT("inf",("Added to MATCH %s",iprq
.ce_name
->ht_name
));
523 else if( !noinf
&& match
== NIL(ICELL
) ) {
524 *nnmp
= add_iset( *nnmp
, ic
, meta
, pdfa
, nidirroot
, ic
->ic_dmax
,
525 trans
, iprq
.ce_name
->ht_name
, idir
, exists
);
526 DB_PRINT("inf",("Added to NOMATCH %s",iprq
.ce_name
->ht_name
));
529 /* If we pushed a directory for the inferred prerequisite then
532 if( ipush
) Pop_dir(FALSE
);
533 if( iprqh
.ht_name
) FREE(iprqh
.ht_name
);
542 buildname( tg
, meta
, per
)/*
543 ============================
544 Replace '%' with per in meta. Expand the result and return it. */
545 char *tg
; /* Current target name. */
551 name
= Apply_edit( meta
, "%", per
, FALSE
, FALSE
);
552 /* Handle infered dynamic prerequisites. */
553 if( strchr(name
, '$') ) {
557 /* Set $@ so that a Expand() can use it and remove it afterwards. */
558 /* Is $@ already expanded? FIXME: Remove this check later. */
559 if( *DmStrPbrk( tg
, "${}" ) != '\0' )
560 Fatal("$@ [%s] not fully expanded!", tg
);
561 m_at
= Def_macro( "@", DO_WINPATH(tg
), M_MULTI
|M_EXPANDED
);
562 tmp
= Expand( name
);
564 if( m_at
->ht_value
!= NIL(char) ) {
565 FREE( m_at
->ht_value
);
566 m_at
->ht_value
= NIL(char);
569 /* Free name if Apply_edit() did something. */
570 if( name
!= meta
) FREE( name
);
573 else if( name
== meta
)
574 name
= DmStrDup( name
);
581 dfa_subset( pdfa
, stack
)/*
582 ============================
583 This is the valid DFA subset computation. Whenever a CELL has a Match_dfa
584 subset computed this algorithm is run to see if any of the previously
585 computed sets on the DFA stack are proper subsets of the new set. If they
586 are, then any elements of the matching subset whose Prep counts exceed
587 the allowed maximum given by Prep are removed from the computed DFA set,
588 and hence from consideration, thereby cutting off the cycle in the
591 register DFASETPTR stack
;
593 register DFALINKPTR element
;
596 DB_ENTER( "dfa_subset" );
598 DB_PRINT("inf",("Computing DFA subset, PREP = %d",Prep
));
599 DB_EXECUTE("inf", _dump_dfa_stack(pdfa
, stack
); );
601 for(; pdfa
!= NIL(DFALINK
) && stack
!= NIL(DFASET
); stack
= stack
->df_next
) {
604 for( element
=stack
->df_set
; subset
&& element
!= NIL(DFALINK
);
605 element
=element
->dl_next
) {
606 register DFALINKPTR subel
;
609 subel
!= NIL(DFALINK
) && (subel
->dl_meta
!= element
->dl_meta
);
610 subel
= subel
->dl_next
);
612 DB_PRINT("inf",("Looking for %s, (%s)",element
->dl_meta
->CE_NAME
,
613 (subel
!= NIL(DFALINK
))?"succ":"fail"));
615 if( (subset
= (subel
!= NIL(DFALINK
))) != 0 )
616 element
->dl_member
= subel
;
620 for( element
=stack
->df_set
; element
!= NIL(DFALINK
);
621 element
=element
->dl_next
) {
622 DFALINKPTR mem
= element
->dl_member
;
623 int npr
= element
->dl_prep
+ 1;
632 for( element
= pdfa
; element
!= NIL(DFALINK
); element
= nelement
) {
633 nelement
= element
->dl_next
;
635 if( element
->dl_delete
) {
636 /* A member of the subset has a PREP count equal to PREP, so
637 * it should not be considered further in the inference, hence
638 * we remove it from the doubly linked set list */
639 if( element
== pdfa
)
640 pdfa
= element
->dl_next
;
642 element
->dl_prev
->dl_next
= element
->dl_next
;
644 if( element
->dl_next
!= NIL(DFALINK
) )
645 element
->dl_next
->dl_prev
= element
->dl_prev
;
647 DB_PRINT("inf", ("deleting dfa [%s]", element
->dl_meta
->CE_NAME
));
648 FREE( element
->dl_per
);
660 =====================
661 Free the list of DFA's constructed by Match_dfa, and linked together by
662 LINK cells. FREE the % value as well, as long as it isn't NIL. */
665 register DFALINKPTR tl
;
667 DB_ENTER( "free_dfas" );
669 for( tl
=chain
; tl
!= NIL(DFALINK
); chain
= tl
) {
672 DB_PRINT( "inf", ("Freeing DFA [%s], %% = [%s]", chain
->dl_meta
->CE_NAME
,
675 if( chain
->dl_per
!= NIL(char) ) FREE( chain
->dl_per
);
685 =====================*/
691 for( p
= name
; *p
; p
++ ) if(*p
== '.') i
++;
697 static ICELLPTR _icells
= NIL(ICELL
);
699 static int _icell_cost
= 0;
703 add_iset( iset
, parent
, meta
, dfa
, setdirroot
, dmax
, noinf
, name
, dir
, exists
)
717 DB_ENTER("add_iset");
718 TALLOC(icell
, 1, ICELL
);
720 DB_EXECUTE("inf", _icell_cost
+=(sizeof(ICELL
)+strlen(dir
?dir
:"")+strlen(name
?name
:"")+2););
722 icell
->ic_meta
= meta
;
724 icell
->ic_setdirroot
= setdirroot
;
726 if( parent
) icell
->ic_dfastack
.df_next
= &parent
->ic_dfastack
;
728 icell
->ic_dmax
= dmax
;
729 icell
->ic_dir
= DmStrDup(dir
);
730 icell
->ic_name
= DmStrDup(name
);
731 icell
->ic_parent
= parent
;
732 icell
->ic_next
= iset
;
733 icell
->ic_flag
= noinf
;
734 icell
->ic_exists
= exists
;
736 icell
->ic_link
= _icells
;
746 register ICELLPTR ic
;
748 DB_ENTER("free_icells");
750 for( ; _icells
; _icells
= ic
) {
751 ic
= _icells
->ic_link
;
753 free_dfas(_icells
->ic_dfastack
.df_set
);
754 if( _icells
->ic_dir
) FREE(_icells
->ic_dir
);
755 if( _icells
->ic_name
) FREE(_icells
->ic_name
);
759 DB_PRINT("inf",("Used %d memory for icells",_icell_cost
));
760 DB_EXECUTE("inf", _icell_cost
=0; );
767 union_iset( iset
, uset
)
771 register ICELLPTR ic
;
773 if( iset
== NIL(ICELL
) ) return(uset
);
775 for( ic
=iset
; ic
->ic_next
!= NIL(ICELL
); ic
=ic
->ic_next
);
783 dump_inf_chain( ip
, flag
, print
)/*
784 ===================================
785 Return string with infered prerequisites.
786 flag == TRUE adds the top of the chain.
787 print == TRUE prints to screen with number "print" and returns NULL. */
794 if( ip
== NIL(ICELL
) ) return(NIL(char));
796 /* ip->ic_parent is the target to be build after ip. */
797 tmp
= dump_inf_chain(ip
->ic_parent
, FALSE
, FALSE
);
800 tmp
= DmStrJoin(tmp
, "(", -1, TRUE
);
801 tmp
= DmStrJoin(tmp
, ip
->ic_meta
->CE_NAME
, -1, TRUE
);
803 if( ip
->ic_dir
&& !*ip
->ic_dir
) {
804 tmp
= DmStrJoin(tmp
, "[", -1, TRUE
);
805 if( strncmp(Makedir
,ip
->ic_dir
, strlen(Makedir
)) )
806 tmp
= DmStrJoin(tmp
, ip
->ic_dir
, -1, TRUE
);
808 tmp
= DmStrJoin(tmp
, ip
->ic_dir
+strlen(Makedir
)+1, -1, TRUE
);
809 tmp
= DmStrJoin(tmp
, "]", -1, TRUE
);
811 tmp
= DmStrJoin(tmp
, (ip
->ic_name
)?") -->":")", -1, TRUE
);
814 if( ip
->ic_name
) tmp
= DmStrApp( tmp
, ip
->ic_name
);
816 if( flag
&& ip
->ic_meta
->ce_prq
) {
817 tmp
= DmStrJoin(tmp
, "(", -1, TRUE
);
818 tmp
= DmStrJoin(tmp
, ip
->ic_meta
->ce_prq
->cl_prq
->CE_NAME
, -1, TRUE
);
819 tmp
= DmStrJoin(tmp
, ")", -1, TRUE
);
823 fprintf( stderr
, "%s: %2d. %s\n", Pname
, print
, tmp
);
834 _dump_dfa_stack(dfas
, dfa_stack
)
838 register DFALINKPTR pdfa
;
839 char *tmp
= NIL(char);
842 for( pdfa
= dfas
; pdfa
!= NIL(DFALINK
); pdfa
= pdfa
->dl_next
)
843 tmp
= DmStrApp( tmp
, pdfa
->dl_meta
->CE_NAME
);
845 tmp
= DmStrApp( tmp
, ":: {" );
846 for( ds
= dfa_stack
; ds
!= NIL(DFASET
); ds
= ds
->df_next
) {
847 tmp
= DmStrApp( tmp
, "[" );
848 for( pdfa
= ds
->df_set
; pdfa
!= NIL(DFALINK
); pdfa
= pdfa
->dl_next
)
849 tmp
= DmStrApp( tmp
, pdfa
->dl_meta
->CE_NAME
);
850 tmp
= DmStrApp( tmp
, "]" );
852 tmp
= DmStrApp( tmp
, "}" );
854 printf( "DFA set and stack contents:\n%s\n", tmp
);
860 _dump_iset( name
, iset
)
866 printf( "**** ISET for %s\n", name
);
867 for( ; iset
!= NIL(ICELL
); iset
= iset
->ic_next
){
868 printf( "cell %d\n", cell
++ );
870 printf( "edge: %s --> %s\n", iset
->ic_meta
->CE_NAME
,
871 iset
->ic_meta
->ce_prq
?
872 iset
->ic_meta
->ce_prq
->cl_prq
->CE_NAME
:
875 printf( "edge: (nil)\n" );
878 printf( "dfa: %s\n", iset
->ic_dfa
->dl_meta
->CE_NAME
);
880 printf( "dfa: (nil)\n" );
882 printf( "sdr: %p\n", iset
->ic_setdirroot
);
883 _dump_dfa_stack(iset
->ic_dfastack
.df_set
, &iset
->ic_dfastack
);
885 printf( "dmax: %d\n", iset
->ic_dmax
);
886 printf( "name: %s\n", iset
->ic_name
);
887 printf( "dir: %s\n", iset
->ic_dir
?iset
->ic_dir
:"(nil)" );
889 printf( "parent: " );
890 if( iset
->ic_parent
)
891 if( iset
->ic_parent
->ic_meta
)
892 printf( "%s --> %s\n",
893 iset
->ic_parent
->ic_meta
->CE_NAME
,
894 iset
->ic_parent
->ic_meta
->ce_prq
?
895 iset
->ic_parent
->ic_meta
->ce_prq
->cl_prq
->CE_NAME
:
902 printf( "==================================\n" );