4 -- Infer how to make a target.
7 -- This file contains the code to infer a recipe, and possibly some new
8 -- prerequisites for a target which dmake does not know how to make, or
9 -- has no explicit recipe.
11 -- The inference fails if no path through the inference graph can be
12 -- found by which we can make the target.
15 -- Dennis Vadura, dvadura@dmake.wticorp.com
18 -- http://dmake.wticorp.com/
21 -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
23 -- This program is NOT free software; you can redistribute it and/or
24 -- modify it under the terms of the Software License Agreement Provided
25 -- in the file <distribution-root>/readme/license.txt.
28 -- Use cvs log to obtain detailed change logs.
33 /* attributes that get transfered from the % start cell to the inferred
36 #define A_TRANSFER (A_EPILOG | A_PRECIOUS | A_SILENT | A_SHELL | A_SETDIR |\
37 A_SEQ | A_LIBRARY | A_IGNORE | A_PROLOG | A_SWAP |\
41 /* Define local static functions */
42 static DFALINKPTR dfa_subset
ANSI((DFALINKPTR
, DFASETPTR
));
43 static void free_dfas
ANSI((DFALINKPTR
));
44 static int count_dots
ANSI((char *));
45 static char * buildname
ANSI((char *, char *, char *));
46 static void free_icells
ANSI((void));
47 static ICELLPTR union_iset
ANSI((ICELLPTR
, ICELLPTR
));
48 static ICELLPTR add_iset
ANSI((ICELLPTR
,ICELLPTR
,CELLPTR
,DFALINKPTR
,
49 CELLPTR
,int,int,char *,char *, int));
50 static ICELLPTR derive_prerequisites
ANSI((ICELLPTR
, ICELLPTR
*));
51 static char * dump_inf_chain
ANSI((ICELLPTR
, int, int));
54 static void _dump_dfa_stack
ANSI((DFALINKPTR
, DFASETPTR
));
55 static void _dump_iset
ANSI(( char *, ICELLPTR
));
60 Infer_recipe( cp
, setdirroot
)/*
61 ================================
62 Perform a breadth-first search of the inference graph and return if
63 possible an inferred set of prerequisites for making the current target. */
67 ICELLPTR nomatch
, match
;
69 DB_ENTER("Infer_recipe");
71 if( cp
->ce_attr
& A_NOINFER
) {DB_VOID_RETURN
;}
73 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 tmp
= DmStrDup(cp
->CE_NAME
), NIL(char),
81 cp
->ce_time
!= (time_t)0L);
85 /* Make sure we try whole heartedly to infer at least one suffix */
86 if( nomatch
->ic_dmax
== 0 ) ++nomatch
->ic_dmax
;
88 DB_EXECUTE( "inf", _dump_iset("nomatch",nomatch
); );
90 /* If nomatch is non-empty there was no match with an existing
91 * prerrequisite, try to derive one. */
92 while( nomatch
!= NIL(ICELL
) ) {
93 ICELLPTR new_nomatch
= NIL(ICELL
);
94 ICELLPTR ic
, pmatch
, mmatch
;
97 for( ic
=nomatch
; ic
!= NIL(ICELL
); ic
=ic
->ic_next
) {
100 if( ic
->ic_dir
) ipush
= Push_dir(ic
->ic_dir
, ic
->ic_name
, FALSE
);
101 match
= union_iset(match
, derive_prerequisites(ic
, &new_nomatch
));
102 if( ipush
) Pop_dir(FALSE
);
105 DB_EXECUTE( "inf", _dump_iset("match",match
); );
106 DB_EXECUTE( "inf", _dump_iset("nomatch",new_nomatch
); );
108 /* We have now deduced the two sets MATCH and NOMATCH. MATCH holds the
109 * set of edges that we encountered that matched. If this set is empty
110 * then we can apply transitive closure (if enabled) to the elements of
111 * NOMATCH to see if we can find some other method to make the target.
113 * If MATCH is non-empty, we have found a method for making the target.
114 * It is the shortest method for doing so (ie. uses fewest number of
115 * steps). If MATCH contains more than one element then we have a
116 * possible ambiguity.
118 if( match
== NIL(ICELL
) ) {
119 nomatch
= new_nomatch
;
121 /* Skip the rest and try one level deeper. */
122 if( Transitive
) continue;
127 /* Ok, we have a set of possible matches in MATCH, we should check the
128 * set for ambiguity. If more than one inference path exists of the
129 * same depth, then we may issue an ambiguous inference error message.
131 * The message is suppressed if MATCH contains two elements and one of
132 * them is the empty-prerequisite-rule. In this case we ignore the
133 * ambiguity and take the rule that infers the prerequisite.
135 * Also if there are any chains that rely on a non-existant prerequisite
136 * that may get made because it has a recipe then we prefer any that
137 * rely on existing final prerequisites over those that we have to make.
140 /* Split out those that have to be made from those that end in
141 * prerequisites that already exist. */
142 pmatch
= mmatch
= NIL(ICELL
);
143 for(; match
; match
= ic
) {
144 /* This loop checks all possible matches. */
145 DB_PRINT("inf", ("Target [%s] : prerequisite [%s]",
146 match
->ic_meta
->CE_NAME
, match
->ic_name
));
149 match
->ic_next
= NIL(ICELL
);
151 if( match
->ic_exists
)
152 pmatch
= union_iset(pmatch
, match
);
154 mmatch
= union_iset(mmatch
, match
);
157 /* Prefer %-targets with existing prerequisites. */
163 /* Make sure it is unique. It would be easy to check
164 * match->ic_meta->ce_prq for existence and prefer no prerequisites
165 * over prerequisites that are present, but we are currently not
167 if( match
->ic_next
!= NIL(ICELL
) ) {
170 Warning( "Ambiguous inference chains for target '%s'", cp
->CE_NAME
);
171 for( ic
=match
; ic
; ic
=ic
->ic_next
)
172 (void) dump_inf_chain(ic
, TRUE
, count
++);
173 Warning( "First matching rule is chosen.");
176 /* MATCH now points at the derived prerequisite chain(s). We must now
177 * take cp, and construct the correct graph so that the make may
180 /* The folowing shows only the first element, i.e. the last matching
181 * recipe that was found. */
182 if( Verbose
& V_INFER
) {
183 char *tmp
= dump_inf_chain(match
, TRUE
, FALSE
);
184 printf("%s: Inferring prerequistes and recipes using:\n%s: ... %s\n",
192 /* This loop treats the inferred targets last to first. */
194 CELLPTR infcell
=NIL(CELL
);
196 /* Compute the inferred prerequisite first. */
197 if( match
->ic_name
) {
199 infcell
= Def_cell( match
->ic_name
);
203 infcell
->ce_flag
|= F_TARGET
;
205 if( infcell
!= cp
) {
206 infcell
->ce_flag
|= F_INFER
|F_REMOVE
;
207 DB_PRINT("remove", ("Mark for deletion [%s]",
211 if( !match
->ic_flag
)
212 infcell
->ce_attr
|= A_NOINFER
;
215 /* Add global prerequisites from previous rule if there are any and
218 CELLPTR imeta
= pmatch
->ic_meta
;
221 DB_PRINT("inf", ("%%-target [%s] - infered target [%s]\n",
222 imeta
->CE_NAME
, infcell
->CE_NAME
));
224 infcell
->ce_per
= pmatch
->ic_dfa
->dl_per
;
225 infcell
->ce_attr
|= (imeta
->ce_attr
& A_TRANSFER
);
227 /* The .PHONY mechanism relies on having phony targets not
228 * being STATed and having a zero time stamp. While inferring
229 * the this target it might have been created and stated
230 * therefore these values need to be reset. */
231 if( infcell
->ce_attr
& A_PHONY
){
232 infcell
->ce_time
= 0L;
233 infcell
->ce_flag
&= ~F_STAT
;
236 if( !(infcell
->ce_flag
& F_RULES
) ) {
237 infcell
->ce_flag
|= (imeta
->ce_flag
&(F_SINGLE
|F_GROUP
))|F_RULES
;
238 infcell
->ce_recipe
= imeta
->ce_recipe
;
241 /* Add any conditional macro definitions that may be associated
242 * with the inferred cell. */
243 if (imeta
->ce_cond
!= NIL(STRING
)) {
246 last
= infcell
->ce_cond
;
247 for(sp
=imeta
->ce_cond
; sp
; sp
=sp
->st_next
) {
249 TALLOC(new, 1, STRING
);
250 new->st_string
= DmStrDup(sp
->st_string
);
254 infcell
->ce_cond
= new;
259 pmatch
->ic_dfa
->dl_per
= NIL(char);
261 /* If infcell already had a .SETDIR directory set then modify it
262 * based on whether it was the original cell or some intermediary. */
263 if( imeta
->ce_dir
) {
264 if( infcell
->ce_dir
&& infcell
== cp
) {
265 /* cp->ce_dir was set and we have pushed the directory prior
266 * to calling this routine.
267 * We build a new path by appending imeta->ce_dir to the
268 * current directory of the original cell.
269 * We should therefore pop it and push the new concatenated
270 * directory required by the inference.
271 * This leaks memory as cp->ce_dir is not freed before
272 * setting the new the new infcell->ce_dir value but as
273 * the pointer could be a `A_POOL` member we accept this. */
274 infcell
->ce_dir
= DmStrDup(Build_path(infcell
->ce_dir
,
278 /* Inherit a copy of the .SETDIR value. Use a copy because
279 * the original could have been freed in the meantime
280 * in Make() by the FREE() before _pool_lookup(). This can
281 * also leak if infcell->ce_dir was set before. */
282 infcell
->ce_dir
= DmStrDup(imeta
->ce_dir
);
286 for( lp
=imeta
->ce_indprq
; lp
!= NIL(LINK
); lp
=lp
->cl_next
) {
287 char *name
= lp
->cl_prq
->CE_NAME
;
290 name
= buildname( cp
->CE_NAME
, name
, infcell
->ce_per
);
291 tcp
= Def_cell( name
);
292 tcp
->ce_flag
|= F_REMOVE
;
293 Add_prerequisite( infcell
, tcp
, FALSE
, FALSE
);
295 if( Verbose
& V_INFER
)
296 printf( "%s: Inferred indirect prerequisite [%s]\n",
302 /* Add the previous cell as the prerequisite */
304 (Add_prerequisite(infcell
,prereq
,FALSE
,FALSE
))->cl_flag
|=F_TARGET
;
306 pmatch
= match
; /* Previous member in inference chain ... */
307 prereq
= infcell
; /* is a prerequisite to the next match. */
308 /* ip->ic_parent is the next target in the inference chain to be
309 * build. If it is empty we are done. */
310 match
= match
->ic_parent
;
313 DB_PRINT("inf", ("Terminated due to a match"));
325 derive_prerequisites( ic
, nnmp
)/*
326 ===================================
327 Take a cell and derive a set of prerequisites from the cell. Categorize
328 them into those that MATCH (ie. those that we found in the file system),
329 and those that do not match NOMATCH that we may possibly have a look at
330 later. When we process the next level of the breadth-first search.
332 Once MATCH is non-empty we will stop inserting elements into NOMATCH
333 since we know that either MATCH is successful and unique or it will
334 issue an ambiguity error. We will never go on to look at elements
335 in NOMATCH after wards. */
339 ICELLPTR match
= NIL(ICELL
);
343 DB_ENTER("derive_prerequisites");
345 DB_PRINT("inf", ("for [%s]\n", ic
->ic_name
));
347 /* If none of the inference nodes match then forget about the inference.
348 * The user did not tell us how to make such a target. We also stop the
349 * Inference if the new set of DFA's is a proper subset of a previous
350 * subset and it's PREP counts exceed the value of Prep.
352 dfas
= dfa_subset( Match_dfa(ic
->ic_name
), &ic
->ic_dfastack
);
354 DB_EXECUTE("inf", _dump_dfa_stack(dfas
, &ic
->ic_dfastack
); );
356 /* Ok, we have nothing here to work with so return an empty cell. */
357 if( dfas
== NIL(DFALINK
) ) {
358 DB_PRINT( "mem", ("%s:<- mem %ld",ic
->ic_name
, (long)coreleft()));
359 DB_PRINT( "inf", ("<<< Exit, no dfas, cp = %04x", NIL(CELL
)) );
360 DB_RETURN( NIL(ICELL
) );
363 /* Save the dfas, we are going to use on the stack for this cell. */
364 ic
->ic_dfastack
.df_set
= dfas
;
366 /* Run through the %-meta cells, build the prerequisite cells. For each
367 * %-meta go through it's list of edges and try to use each in turn to
368 * deduce a likely prerequisite. We perform a breadth-first search
369 * matching the first path that results in a unique method for making the
371 for( pdfa
= dfas
; pdfa
!= NIL(DFALINK
); pdfa
= pdfa
->dl_next
) {
376 pmeta
= pdfa
->dl_meta
;
377 DB_PRINT( "inf", ("Using dfa: [%s]", pmeta
->CE_NAME
) );
379 /* If the %-meta is a singleton meta then deal with it differently from
380 * the case when it is a bunch of %-meta's found on the original entries
381 * prerequisite list. */
382 if( pmeta
->ce_flag
& F_MULTI
)
383 edge
= pmeta
->ce_prq
;
386 tl
.cl_next
= NIL(LINK
);
390 /* Now run through the list of prerequisite edge's for the %-meta. */
391 for( ; edge
!= NIL(LINK
); edge
= edge
->cl_next
) {
392 HASHPTR thp
= 0; /* temporary hash table pointer */
393 HASH iprqh
; /* hash cell for new prerequisite */
394 CELL iprq
; /* inferred prerequisite to look for */
395 CELLPTR idirroot
; /* Inferred prerequisite root */
396 CELLPTR nidirroot
; /* Inferred prerequisite root */
397 STRINGPTR ircp
= 0; /* Inferred prerequisites recipe */
398 char *idir
; /* directory to CD to. */
399 int ipush
= 0; /* flag for push on inferred prereq */
400 char *name
= NIL(char); /* prerequisite name */
401 CELLPTR meta
= edge
->cl_prq
;
406 /* Name of the prerequisite, can be empty. */
408 name
= meta
->ce_prq
->cl_prq
->CE_NAME
;
410 DB_PRINT( "inf", ("Trying edge from [%s] to [%s] for [%s]",
411 meta
->CE_NAME
, name
?name
:"(nil)", ic
->ic_name
) );
413 /* Set the temp CELL used for building prerequisite candidates to
414 * all zero so that we don't have to keep initializing all the
417 register char *s
= (char *) &iprq
;
418 register int n
= sizeof(CELL
);
419 while( n
) { *s
++ = '\0'; n
--; }
422 nidirroot
= idirroot
= ic
->ic_setdirroot
;
423 iprq
.ce_name
= &iprqh
;
426 /* Build the prerequisite name from the %-meta prerequisite given
427 * for the %-meta rule. */
429 iprqh
.ht_name
= buildname( ic
->ic_name
, name
, pdfa
->dl_per
);
430 if((dmax_fix
= (count_dots(name
)-count_dots(meta
->CE_NAME
))) < 0)
433 if( !strcmp(ic
->ic_name
, iprqh
.ht_name
) ||
434 (count_dots(iprqh
.ht_name
) > ic
->ic_dmax
+ dmax_fix
) ) {
435 FREE( iprqh
.ht_name
);
439 DB_PRINT( "inf", ("Checking prerequisite [%s]", iprqh
.ht_name
) );
441 /* See if the prerequisite CELL has been previously defined. If
442 * it has, then make a copy of it into iprq, and use it to try
443 * the inference. We make the copy so that we don't modify the
444 * stat of the inferred cell if the inference fails.
446 thp
= Get_name( iprqh
.ht_name
, Defs
, FALSE
);
447 if(thp
!= NIL(HASH
)) {
448 iprq
= *thp
->CP_OWNR
;
449 /* Check if a recipe for this target exists. Targets with F_MULTI
450 * set need each cell checked for existing recipes.
452 if( iprq
.ce_flag
& F_MULTI
) {
453 /* Walk through all cells of this target. */
454 LINKPTR mtcp
= iprq
.ce_prq
;
456 for( ; mtcp
!= NIL(LINK
); mtcp
= mtcp
->cl_next
) {
457 /* If a recipe is found stop searching and set ircp to that result.
458 * ircp is not used but only checked if it is set.
460 if( mtcp
->cl_prq
->ce_recipe
!= NIL(STRING
) ) {
461 ircp
= mtcp
->cl_prq
->ce_recipe
;
467 ircp
= iprq
.ce_recipe
;
473 iprqh
.ht_name
= NIL(char);
476 /* If the %-meta has a .SETDIR set then we change to the new
477 * directory prior to performing the stat of the new prerequisite.
478 * If the change of directory fails then the rule is droped from
479 * further consideration.
482 if( (ipush
= Push_dir(iprq
.ce_dir
, iprqh
.ht_name
, TRUE
)) != 0 ) {
483 nidirroot
= thp
->CP_OWNR
;
487 if( iprqh
.ht_name
) FREE( iprqh
.ht_name
);
495 /* Stat the inferred prerequisite.
498 if( Verbose
& V_INFER
)
499 printf( "%s: Trying prerequisite [%s] for [%s]\n", Pname
,
500 iprqh
.ht_name
, ic
->ic_name
);
502 /* irpq is a temporary target cell, a stat will not be remembered. */
503 if( !(iprq
.ce_flag
& F_STAT
) ) Stat_target(&iprq
, FALSE
, FALSE
);
507 /* If the STAT succeeded or if the prerequisite has a recipe for
508 * making it then it's a match and a candidate for getting infered.
509 * Otherwise it is not a match, and we cannot yet tell if it is
510 * going to be a successful path to follow, so we save it for
511 * later consideration.
513 noinf
= ((Glob_attr
)&A_NOINFER
);
515 noinf
|= ((meta
->ce_prq
->cl_prq
->ce_attr
)&A_NOINFER
);
516 trans
= Transitive
|| !noinf
;
518 /* If no prereq is given treat it as if it is existing. */
519 exists
= (iprq
.ce_time
!= (time_t)0L) || (name
== NIL(char));
521 if( exists
|| (ircp
!= NIL(STRING
)) || !name
) {
522 match
= add_iset( match
, ic
, meta
, pdfa
, idirroot
, ic
->ic_dmax
,
523 trans
, iprq
.ce_name
->ht_name
, idir
, exists
);
524 DB_PRINT("inf",("Added to MATCH %s",iprq
.ce_name
->ht_name
));
526 else if( !noinf
&& match
== NIL(ICELL
) ) {
527 *nnmp
= add_iset( *nnmp
, ic
, meta
, pdfa
, nidirroot
, ic
->ic_dmax
,
528 trans
, iprq
.ce_name
->ht_name
, idir
, exists
);
529 DB_PRINT("inf",("Added to NOMATCH %s",iprq
.ce_name
->ht_name
));
532 /* If we pushed a directory for the inferred prerequisite then
535 if( ipush
) Pop_dir(FALSE
);
536 if( iprqh
.ht_name
) FREE(iprqh
.ht_name
);
545 buildname( tg
, meta
, per
)/*
546 ============================
547 Replace '%' with per in meta. Expand the result and return it. */
548 char *tg
; /* Current target name. */
554 name
= Apply_edit( meta
, "%", per
, FALSE
, FALSE
);
555 /* Handle infered dynamic prerequisites. */
556 if( strchr(name
, '$') ) {
560 /* Set $@ so that a Expand() can use it and remove it afterwards. */
561 /* Is $@ already expanded? FIXME: Remove this check later. */
562 if( *DmStrPbrk( tg
, "${}" ) != '\0' )
563 Fatal("$@ [%s] not fully expanded!", tg
);
564 m_at
= Def_macro( "@", DO_WINPATH(tg
), M_MULTI
|M_EXPANDED
);
565 tmp
= Expand( name
);
567 if( m_at
->ht_value
!= NIL(char) ) {
568 FREE( m_at
->ht_value
);
569 m_at
->ht_value
= NIL(char);
572 /* Free name if Apply_edit() did something. */
573 if( name
!= meta
) FREE( name
);
576 else if( name
== meta
)
577 name
= DmStrDup( name
);
584 dfa_subset( pdfa
, stack
)/*
585 ============================
586 This is the valid DFA subset computation. Whenever a CELL has a Match_dfa
587 subset computed this algorithm is run to see if any of the previously
588 computed sets on the DFA stack are proper subsets of the new set. If they
589 are, then any elements of the matching subset whose Prep counts exceed
590 the allowed maximum given by Prep are removed from the computed DFA set,
591 and hence from consideration, thereby cutting off the cycle in the
594 register DFASETPTR stack
;
596 register DFALINKPTR element
;
599 DB_ENTER( "dfa_subset" );
601 DB_PRINT("inf",("Computing DFA subset, PREP = %d",Prep
));
602 DB_EXECUTE("inf", _dump_dfa_stack(pdfa
, stack
); );
604 for(; pdfa
!= NIL(DFALINK
) && stack
!= NIL(DFASET
); stack
= stack
->df_next
) {
607 for( element
=stack
->df_set
; subset
&& element
!= NIL(DFALINK
);
608 element
=element
->dl_next
) {
609 register DFALINKPTR subel
;
612 subel
!= NIL(DFALINK
) && (subel
->dl_meta
!= element
->dl_meta
);
613 subel
= subel
->dl_next
);
615 DB_PRINT("inf",("Looking for %s, (%s)",element
->dl_meta
->CE_NAME
,
616 (subel
!= NIL(DFALINK
))?"succ":"fail"));
618 if( (subset
= (subel
!= NIL(DFALINK
))) != 0 )
619 element
->dl_member
= subel
;
623 for( element
=stack
->df_set
; element
!= NIL(DFALINK
);
624 element
=element
->dl_next
) {
625 DFALINKPTR mem
= element
->dl_member
;
626 int npr
= element
->dl_prep
+ 1;
635 for( element
= pdfa
; element
!= NIL(DFALINK
); element
= nelement
) {
636 nelement
= element
->dl_next
;
638 if( element
->dl_delete
) {
639 /* A member of the subset has a PREP count equal to PREP, so
640 * it should not be considered further in the inference, hence
641 * we remove it from the doubly linked set list */
642 if( element
== pdfa
)
643 pdfa
= element
->dl_next
;
645 element
->dl_prev
->dl_next
= element
->dl_next
;
647 if( element
->dl_next
!= NIL(DFALINK
) )
648 element
->dl_next
->dl_prev
= element
->dl_prev
;
650 DB_PRINT("inf", ("deleting dfa [%s]", element
->dl_meta
->CE_NAME
));
651 FREE( element
->dl_per
);
663 =====================
664 Free the list of DFA's constructed by Match_dfa, and linked together by
665 LINK cells. FREE the % value as well, as long as it isn't NIL. */
668 register DFALINKPTR tl
;
670 DB_ENTER( "free_dfas" );
672 for( tl
=chain
; tl
!= NIL(DFALINK
); chain
= tl
) {
675 DB_PRINT( "inf", ("Freeing DFA [%s], %% = [%s]", chain
->dl_meta
->CE_NAME
,
678 if( chain
->dl_per
!= NIL(char) ) FREE( chain
->dl_per
);
688 =====================*/
694 for( p
= name
; *p
; p
++ ) if(*p
== '.') i
++;
700 static ICELLPTR _icells
= NIL(ICELL
);
702 static int _icell_cost
= 0;
706 add_iset( iset
, parent
, meta
, dfa
, setdirroot
, dmax
, noinf
, name
, dir
, exists
)
720 DB_ENTER("add_iset");
721 TALLOC(icell
, 1, ICELL
);
723 DB_EXECUTE("inf", _icell_cost
+=(sizeof(ICELL
)+strlen(dir
?dir
:"")+strlen(name
?name
:"")+2););
725 icell
->ic_meta
= meta
;
727 icell
->ic_setdirroot
= setdirroot
;
729 if( parent
) icell
->ic_dfastack
.df_next
= &parent
->ic_dfastack
;
731 icell
->ic_dmax
= dmax
;
732 icell
->ic_dir
= DmStrDup(dir
);
733 icell
->ic_name
= DmStrDup(name
);
734 icell
->ic_parent
= parent
;
735 icell
->ic_next
= iset
;
736 icell
->ic_flag
= noinf
;
737 icell
->ic_exists
= exists
;
739 icell
->ic_link
= _icells
;
749 register ICELLPTR ic
;
751 DB_ENTER("free_icells");
753 for( ; _icells
; _icells
= ic
) {
754 ic
= _icells
->ic_link
;
756 free_dfas(_icells
->ic_dfastack
.df_set
);
757 if( _icells
->ic_dir
) FREE(_icells
->ic_dir
);
758 if( _icells
->ic_name
) FREE(_icells
->ic_name
);
762 DB_PRINT("inf",("Used %d memory for icells",_icell_cost
));
763 DB_EXECUTE("inf", _icell_cost
=0; );
770 union_iset( iset
, uset
)
774 register ICELLPTR ic
;
776 if( iset
== NIL(ICELL
) ) return(uset
);
778 for( ic
=iset
; ic
->ic_next
!= NIL(ICELL
); ic
=ic
->ic_next
);
786 dump_inf_chain( ip
, flag
, print
)/*
787 ===================================
788 Return string with infered prerequisites.
789 flag == TRUE adds the top of the chain.
790 print == TRUE prints to screen with number "print" and returns NULL. */
797 if( ip
== NIL(ICELL
) ) return(NIL(char));
799 /* ip->ic_parent is the target to be build after ip. */
800 tmp
= dump_inf_chain(ip
->ic_parent
, FALSE
, FALSE
);
803 tmp
= DmStrJoin(tmp
, "(", -1, TRUE
);
804 tmp
= DmStrJoin(tmp
, ip
->ic_meta
->CE_NAME
, -1, TRUE
);
806 if( ip
->ic_dir
&& !*ip
->ic_dir
) {
807 tmp
= DmStrJoin(tmp
, "[", -1, TRUE
);
808 if( strncmp(Makedir
,ip
->ic_dir
, strlen(Makedir
)) )
809 tmp
= DmStrJoin(tmp
, ip
->ic_dir
, -1, TRUE
);
811 tmp
= DmStrJoin(tmp
, ip
->ic_dir
+strlen(Makedir
)+1, -1, TRUE
);
812 tmp
= DmStrJoin(tmp
, "]", -1, TRUE
);
814 tmp
= DmStrJoin(tmp
, (ip
->ic_name
)?") -->":")", -1, TRUE
);
817 if( ip
->ic_name
) tmp
= DmStrApp( tmp
, ip
->ic_name
);
819 if( flag
&& ip
->ic_meta
->ce_prq
) {
820 tmp
= DmStrJoin(tmp
, "(", -1, TRUE
);
821 tmp
= DmStrJoin(tmp
, ip
->ic_meta
->ce_prq
->cl_prq
->CE_NAME
, -1, TRUE
);
822 tmp
= DmStrJoin(tmp
, ")", -1, TRUE
);
826 fprintf( stderr
, "%s: %2d. %s\n", Pname
, print
, tmp
);
837 _dump_dfa_stack(dfas
, dfa_stack
)
841 register DFALINKPTR pdfa
;
842 char *tmp
= NIL(char);
845 for( pdfa
= dfas
; pdfa
!= NIL(DFALINK
); pdfa
= pdfa
->dl_next
)
846 tmp
= DmStrApp( tmp
, pdfa
->dl_meta
->CE_NAME
);
848 tmp
= DmStrApp( tmp
, ":: {" );
849 for( ds
= dfa_stack
; ds
!= NIL(DFASET
); ds
= ds
->df_next
) {
850 tmp
= DmStrApp( tmp
, "[" );
851 for( pdfa
= ds
->df_set
; pdfa
!= NIL(DFALINK
); pdfa
= pdfa
->dl_next
)
852 tmp
= DmStrApp( tmp
, pdfa
->dl_meta
->CE_NAME
);
853 tmp
= DmStrApp( tmp
, "]" );
855 tmp
= DmStrApp( tmp
, "}" );
857 printf( "DFA set and stack contents:\n%s\n", tmp
);
863 _dump_iset( name
, iset
)
869 printf( "**** ISET for %s\n", name
);
870 for( ; iset
!= NIL(ICELL
); iset
= iset
->ic_next
){
871 printf( "cell %d\n", cell
++ );
873 printf( "edge: %s --> %s\n", iset
->ic_meta
->CE_NAME
,
874 iset
->ic_meta
->ce_prq
?
875 iset
->ic_meta
->ce_prq
->cl_prq
->CE_NAME
:
878 printf( "edge: (nil)\n" );
881 printf( "dfa: %s\n", iset
->ic_dfa
->dl_meta
->CE_NAME
);
883 printf( "dfa: (nil)\n" );
885 printf( "sdr: %p\n", iset
->ic_setdirroot
);
886 _dump_dfa_stack(iset
->ic_dfastack
.df_set
, &iset
->ic_dfastack
);
888 printf( "dmax: %d\n", iset
->ic_dmax
);
889 printf( "name: %s\n", iset
->ic_name
);
890 printf( "dir: %s\n", iset
->ic_dir
?iset
->ic_dir
:"(nil)" );
892 printf( "parent: " );
893 if( iset
->ic_parent
)
894 if( iset
->ic_parent
->ic_meta
)
895 printf( "%s --> %s\n",
896 iset
->ic_parent
->ic_meta
->CE_NAME
,
897 iset
->ic_parent
->ic_meta
->ce_prq
?
898 iset
->ic_parent
->ic_meta
->ce_prq
->cl_prq
->CE_NAME
:
905 printf( "==================================\n" );