]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/make.c
2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * Copyright 2001-2004 David Abrahams.
9 * Distributed under the Boost Software License, Version 1.0.
10 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
14 * make.c - bring a target up to date, once rules are in place.
16 * This modules controls the execution of rules to bring a target and its
17 * dependencies up to date. It is invoked after the targets, rules, et. al.
18 * described in rules.h are created by the interpreting jam files.
20 * This file contains the main make() entry point and the first pass make0().
21 * The second pass, make1(), which actually does the command execution, is in
25 * make() - make a target, given its name
28 * make0() - bind and scan everything to make a TARGET
29 * make0sort() - reorder TARGETS chain by their time (newest to oldest)
36 #ifdef OPT_HEADER_CACHE_EXT
45 #include "timestamp.h"
53 # define max(a,b) ((a)>(b)?(a):(b))
56 static TARGETS
* make0sort( TARGETS
* c
);
58 #ifdef OPT_GRAPH_DEBUG_EXT
59 static void dependGraphOutput( TARGET
* t
, int depth
);
62 static char const * target_fate
[] =
64 "init", /* T_FATE_INIT */
65 "making", /* T_FATE_MAKING */
66 "stable", /* T_FATE_STABLE */
67 "newer", /* T_FATE_NEWER */
68 "temp", /* T_FATE_ISTMP */
69 "touched", /* T_FATE_TOUCHED */
70 "rebuild", /* T_FATE_REBUILD */
71 "missing", /* T_FATE_MISSING */
72 "needtmp", /* T_FATE_NEEDTMP */
73 "old", /* T_FATE_OUTDATED */
74 "update", /* T_FATE_UPDATE */
75 "nofind", /* T_FATE_CANTFIND */
76 "nomake" /* T_FATE_CANTMAKE */
79 static char const * target_bind
[] =
87 #define spaces(x) ( ((const char *)" ") + ( x > 20 ? 0 : 20-x ) )
91 * make() - make a target, given its name.
94 int make( LIST
* targets
, int anyhow
)
97 int status
= 0; /* 1 if anything fails */
99 #ifdef OPT_HEADER_CACHE_EXT
103 memset( (char *)counts
, 0, sizeof( *counts
) );
105 /* Make sure that the tables are set up correctly.
109 /* First bind all targets with LOCATE_TARGET setting. This is needed to
110 * correctly handle dependencies to generated headers.
112 bind_explicitly_located_targets();
116 PROFILE_ENTER( MAKE_MAKE0
);
117 for ( iter
= list_begin( targets
), end
= list_end( targets
); iter
!= end
; iter
= list_next( iter
) )
119 TARGET
* t
= bindtarget( list_item( iter
) );
120 if ( t
->fate
== T_FATE_INIT
)
121 make0( t
, 0, 0, counts
, anyhow
, 0 );
123 PROFILE_EXIT( MAKE_MAKE0
);
126 #ifdef OPT_GRAPH_DEBUG_EXT
130 for ( iter
= list_begin( targets
), end
= list_end( targets
); iter
!= end
; iter
= list_next( iter
) )
131 dependGraphOutput( bindtarget( list_item( iter
) ), 0 );
137 if ( counts
->targets
)
138 out_printf( "...found %d target%s...\n", counts
->targets
,
139 counts
->targets
> 1 ? "s" : "" );
141 out_printf( "...using %d temp target%s...\n", counts
->temp
,
142 counts
->temp
> 1 ? "s" : "" );
143 if ( counts
->updating
)
144 out_printf( "...updating %d target%s...\n", counts
->updating
,
145 counts
->updating
> 1 ? "s" : "" );
146 if ( counts
->cantfind
)
147 out_printf( "...can't find %d target%s...\n", counts
->cantfind
,
148 counts
->cantfind
> 1 ? "s" : "" );
149 if ( counts
->cantmake
)
150 out_printf( "...can't make %d target%s...\n", counts
->cantmake
,
151 counts
->cantmake
> 1 ? "s" : "" );
154 status
= counts
->cantfind
|| counts
->cantmake
;
157 PROFILE_ENTER( MAKE_MAKE1
);
158 status
|= make1( targets
);
159 PROFILE_EXIT( MAKE_MAKE1
);
166 /* Force any dependants of t that have already at least begun being visited by
167 * make0() to be updated.
170 static void force_rebuilds( TARGET
* t
);
172 static void update_dependants( TARGET
* t
)
176 for ( q
= t
->dependants
; q
; q
= q
->next
)
178 TARGET
* p
= q
->target
;
179 char fate0
= p
->fate
;
181 /* If we have already at least begun visiting it and we are not already
182 * rebuilding it for other reasons.
184 if ( ( fate0
!= T_FATE_INIT
) && ( fate0
< T_FATE_BUILD
) )
186 p
->fate
= T_FATE_UPDATE
;
190 out_printf( "fate change %s from %s to %s (as dependant of %s)\n",
191 object_str( p
->name
), target_fate
[ (int) fate0
], target_fate
[ (int) p
->fate
], object_str( t
->name
) );
194 /* If we are done visiting it, go back and make sure its dependants
197 if ( fate0
> T_FATE_MAKING
)
198 update_dependants( p
);
201 /* Make sure that rebuilds can be chained. */
207 * Make sure that all of t's rebuilds get rebuilt.
210 static void force_rebuilds( TARGET
* t
)
213 for ( d
= t
->rebuilds
; d
; d
= d
->next
)
215 TARGET
* r
= d
->target
;
217 /* If it is not already being rebuilt for other reasons. */
218 if ( r
->fate
< T_FATE_BUILD
)
221 out_printf( "fate change %s from %s to %s (by rebuild)\n",
222 object_str( r
->name
), target_fate
[ (int) r
->fate
], target_fate
[ T_FATE_REBUILD
] );
224 /* Force rebuild it. */
225 r
->fate
= T_FATE_REBUILD
;
227 /* And make sure its dependants are updated too. */
228 update_dependants( r
);
234 int make0rescan( TARGET
* t
, TARGET
* rescanning
)
239 /* Check whether we have already found a cycle. */
240 if ( target_scc( t
) == rescanning
)
243 /* If we have already visited this node, ignore it. */
244 if ( t
->rescanning
== rescanning
)
247 /* If t is already updated, ignore it. */
248 if ( t
->scc_root
== NULL
&& t
->progress
> T_MAKE_ACTIVE
)
251 t
->rescanning
= rescanning
;
252 for ( c
= t
->depends
; c
; c
= c
->next
)
254 TARGET
* dependency
= c
->target
;
255 /* Always start at the root of each new strongly connected component. */
256 if ( target_scc( dependency
) != target_scc( t
) )
257 dependency
= target_scc( dependency
);
258 result
|= make0rescan( dependency
, rescanning
);
260 /* Make sure that we pick up the new include node. */
261 if ( c
->target
->includes
== rescanning
)
264 if ( result
&& t
->scc_root
== NULL
)
266 t
->scc_root
= rescanning
;
267 rescanning
->depends
= targetentry( rescanning
->depends
, t
);
274 * make0() - bind and scan everything to make a TARGET.
276 * Recursively binds a target, searches for #included headers, calls itself on
277 * those headers and any dependencies.
283 TARGET
* p
, /* parent */
284 int depth
, /* for display purposes */
285 COUNTS
* counts
, /* for reporting */
288 ) /* forcibly touch all (real) targets */
292 TARGET
* located_target
= 0;
297 char const * flag
= "";
300 #ifdef OPT_GRAPH_DEBUG_EXT
305 if ( DEBUG_MAKEPROG
)
306 out_printf( "make\t--\t%s%s\n", spaces( depth
), object_str( t
->name
) );
309 * Step 1: Initialize.
312 if ( DEBUG_MAKEPROG
)
313 out_printf( "make\t--\t%s%s\n", spaces( depth
), object_str( t
->name
) );
315 t
->fate
= T_FATE_MAKING
;
319 * Step 2: Under the influence of "on target" variables, bind the target and
320 * search for headers.
323 /* Step 2a: Set "on target" variables. */
324 s
= copysettings( t
->settings
);
325 pushsettings( root_module(), s
);
327 /* Step 2b: Find and timestamp the target file (if it is a file). */
328 if ( ( t
->binding
== T_BIND_UNBOUND
) && !( t
->flags
& T_FLAG_NOTFILE
) )
330 OBJECT
* another_target
;
331 object_free( t
->boundname
);
332 t
->boundname
= search( t
->name
, &t
->time
, &another_target
,
333 t
->flags
& T_FLAG_ISFILE
);
334 /* If it was detected that this target refers to an already existing and
335 * bound target, we add a dependency so that every target depending on
336 * us will depend on that other target as well.
338 if ( another_target
)
339 located_target
= bindtarget( another_target
);
341 t
->binding
= timestamp_empty( &t
->time
)
346 /* INTERNAL, NOTFILE header nodes have the time of their parents. */
347 if ( p
&& ( t
->flags
& T_FLAG_INTERNAL
) )
350 /* If temp file does not exist but parent does, use parent. */
351 if ( p
&& ( t
->flags
& T_FLAG_TEMP
) &&
352 ( t
->binding
== T_BIND_MISSING
) &&
353 ( p
->binding
!= T_BIND_MISSING
) )
355 t
->binding
= T_BIND_PARENTS
;
361 LIST
* var
= var_get( root_module(), constant_JAM_SEMAPHORE
);
362 if ( !list_empty( var
) )
364 TARGET
* const semaphore
= bindtarget( list_front( var
) );
365 semaphore
->progress
= T_MAKE_SEMAPHORE
;
366 t
->semaphore
= semaphore
;
371 /* Step 2c: If its a file, search for headers. */
372 if ( t
->binding
== T_BIND_EXISTS
)
375 /* Step 2d: reset "on target" variables. */
376 popsettings( root_module(), s
);
380 * Pause for a little progress reporting.
385 if ( !object_equal( t
->name
, t
->boundname
) )
386 out_printf( "bind\t--\t%s%s: %s\n", spaces( depth
),
387 object_str( t
->name
), object_str( t
->boundname
) );
389 switch ( t
->binding
)
394 out_printf( "time\t--\t%s%s: %s\n", spaces( depth
),
395 object_str( t
->name
), target_bind
[ (int)t
->binding
] );
399 out_printf( "time\t--\t%s%s: %s\n", spaces( depth
),
400 object_str( t
->name
), timestamp_str( &t
->time
) );
406 * Step 3: Recursively make0() dependencies & headers.
409 /* Step 3a: Recursively make0() dependencies. */
410 for ( c
= t
->depends
; c
; c
= c
->next
)
412 int const internal
= t
->flags
& T_FLAG_INTERNAL
;
414 /* Warn about circular deps, except for includes, which include each
417 if ( c
->target
->fate
== T_FATE_INIT
)
418 make0( c
->target
, ptime
, depth
+ 1, counts
, anyhow
, rescanning
);
419 else if ( c
->target
->fate
== T_FATE_MAKING
&& !internal
)
420 out_printf( "warning: %s depends on itself\n", object_str(
422 else if ( c
->target
->fate
!= T_FATE_MAKING
&& rescanning
)
423 make0rescan( c
->target
, rescanning
);
424 if ( rescanning
&& c
->target
->includes
&& c
->target
->includes
->fate
!=
426 make0rescan( target_scc( c
->target
->includes
), rescanning
);
429 if ( located_target
)
431 if ( located_target
->fate
== T_FATE_INIT
)
432 make0( located_target
, ptime
, depth
+ 1, counts
, anyhow
, rescanning
434 else if ( located_target
->fate
!= T_FATE_MAKING
&& rescanning
)
435 make0rescan( located_target
, rescanning
);
438 /* Step 3b: Recursively make0() internal includes node. */
440 make0( t
->includes
, p
, depth
+ 1, counts
, anyhow
, rescanning
);
442 /* Step 3c: Add dependencies' includes to our direct dependencies. */
445 for ( c
= t
->depends
; c
; c
= c
->next
)
446 if ( c
->target
->includes
)
447 incs
= targetentry( incs
, c
->target
->includes
);
448 t
->depends
= targetchain( t
->depends
, incs
);
451 if ( located_target
)
452 t
->depends
= targetentry( t
->depends
, located_target
);
454 /* Step 3d: Detect cycles. */
456 int cycle_depth
= depth
;
457 for ( c
= t
->depends
; c
; c
= c
->next
)
459 TARGET
* scc_root
= target_scc( c
->target
);
460 if ( scc_root
->fate
== T_FATE_MAKING
&&
461 ( !scc_root
->includes
||
462 scc_root
->includes
->fate
!= T_FATE_MAKING
) )
464 if ( scc_root
->depth
< cycle_depth
)
466 cycle_depth
= scc_root
->depth
;
467 t
->scc_root
= scc_root
;
474 * Step 4: Compute time & fate.
477 /* Step 4a: Pick up dependencies' time and fate. */
478 timestamp_clear( &last
);
479 timestamp_clear( &leaf
);
480 fate
= T_FATE_STABLE
;
481 for ( c
= t
->depends
; c
; c
= c
->next
)
483 /* If we are in a different strongly connected component, pull
484 * timestamps from the root.
486 if ( c
->target
->scc_root
)
488 TARGET
* const scc_root
= target_scc( c
->target
);
489 if ( scc_root
!= t
->scc_root
)
491 timestamp_max( &c
->target
->leaf
, &c
->target
->leaf
,
493 timestamp_max( &c
->target
->time
, &c
->target
->time
,
495 c
->target
->fate
= max( c
->target
->fate
, scc_root
->fate
);
499 /* If LEAVES has been applied, we only heed the timestamps of the leaf
502 timestamp_max( &leaf
, &leaf
, &c
->target
->leaf
);
503 if ( t
->flags
& T_FLAG_LEAVES
)
505 timestamp_copy( &last
, &leaf
);
508 timestamp_max( &last
, &last
, &c
->target
->time
);
509 fate
= max( fate
, c
->target
->fate
);
511 #ifdef OPT_GRAPH_DEBUG_EXT
513 if ( fate
< c
->target
->fate
)
514 out_printf( "fate change %s from %s to %s by dependency %s\n",
515 object_str( t
->name
), target_fate
[ (int)fate
],
516 target_fate
[ (int)c
->target
->fate
], object_str(
521 /* Step 4b: Pick up included headers time. */
524 * If a header is newer than a temp source that includes it, the temp source
525 * will need building.
528 timestamp_copy( &hlast
, &t
->includes
->time
);
530 timestamp_clear( &hlast
);
532 /* Step 4c: handle NOUPDATE oddity.
534 * If a NOUPDATE file exists, mark it as having eternally old dependencies.
535 * Do not inherit our fate from our dependencies. Decide fate based only on
536 * other flags and our binding (done later).
538 if ( t
->flags
& T_FLAG_NOUPDATE
)
540 #ifdef OPT_GRAPH_DEBUG_EXT
542 if ( fate
!= T_FATE_STABLE
)
543 out_printf( "fate change %s back to stable, NOUPDATE.\n",
544 object_str( t
->name
) );
547 timestamp_clear( &last
);
548 timestamp_clear( &t
->time
);
550 /* Do not inherit our fate from our dependencies. Decide fate based only
551 * upon other flags and our binding (done later).
553 fate
= T_FATE_STABLE
;
556 /* Step 4d: Determine fate: rebuild target or what? */
560 If can not find or make child, can not make target.
561 If children changed, make target.
562 If target missing, make it.
563 If children newer, make target.
564 If temp's children newer than parent, make temp.
565 If temp's headers newer than parent, make temp.
566 If deliberately touched, make it.
567 If up-to-date temp file present, use it.
568 If target newer than non-notfile parent, mark target newer.
571 Note this block runs from least to most stable: as we make it further
572 down the list, the target's fate gets more stable.
575 #ifdef OPT_GRAPH_DEBUG_EXT
580 if ( fate
>= T_FATE_BROKEN
)
582 fate
= T_FATE_CANTMAKE
;
584 else if ( fate
>= T_FATE_SPOIL
)
586 fate
= T_FATE_UPDATE
;
588 else if ( t
->binding
== T_BIND_MISSING
)
590 fate
= T_FATE_MISSING
;
592 else if ( t
->binding
== T_BIND_EXISTS
&& timestamp_cmp( &last
, &t
->time
) >
595 #ifdef OPT_GRAPH_DEBUG_EXT
598 fate
= T_FATE_OUTDATED
;
600 else if ( t
->binding
== T_BIND_PARENTS
&& timestamp_cmp( &last
, &p
->time
) >
603 #ifdef OPT_GRAPH_DEBUG_EXT
606 fate
= T_FATE_NEEDTMP
;
608 else if ( t
->binding
== T_BIND_PARENTS
&& timestamp_cmp( &hlast
, &p
->time
)
611 fate
= T_FATE_NEEDTMP
;
613 else if ( t
->flags
& T_FLAG_TOUCHED
)
615 fate
= T_FATE_TOUCHED
;
617 else if ( anyhow
&& !( t
->flags
& T_FLAG_NOUPDATE
) )
619 fate
= T_FATE_TOUCHED
;
621 else if ( t
->binding
== T_BIND_EXISTS
&& ( t
->flags
& T_FLAG_TEMP
) )
625 else if ( t
->binding
== T_BIND_EXISTS
&& p
&& p
->binding
!= T_BIND_UNBOUND
626 && timestamp_cmp( &t
->time
, &p
->time
) > 0 )
628 #ifdef OPT_GRAPH_DEBUG_EXT
635 fate
= T_FATE_STABLE
;
637 #ifdef OPT_GRAPH_DEBUG_EXT
638 if ( DEBUG_FATE
&& ( fate
!= savedFate
) )
640 if ( savedFate
== T_FATE_STABLE
)
641 out_printf( "fate change %s set to %s%s\n", object_str( t
->name
),
642 target_fate
[ fate
], oldTimeStamp
? " (by timestamp)" : "" );
644 out_printf( "fate change %s from %s to %s%s\n", object_str( t
->name
),
645 target_fate
[ savedFate
], target_fate
[ fate
], oldTimeStamp
?
646 " (by timestamp)" : "" );
650 /* Step 4e: Handle missing files. */
651 /* If it is missing and there are no actions to create it, boom. */
652 /* If we can not make a target we do not care about it, okay. */
653 /* We could insist that there are updating actions for all missing */
654 /* files, but if they have dependencies we just pretend it is a NOTFILE. */
656 if ( ( fate
== T_FATE_MISSING
) && !t
->actions
&& !t
->depends
)
658 if ( t
->flags
& T_FLAG_NOCARE
)
660 #ifdef OPT_GRAPH_DEBUG_EXT
662 out_printf( "fate change %s to STABLE from %s, "
663 "no actions, no dependencies and do not care\n",
664 object_str( t
->name
), target_fate
[ fate
] );
666 fate
= T_FATE_STABLE
;
670 out_printf( "don't know how to make %s\n", object_str( t
->name
) );
671 fate
= T_FATE_CANTFIND
;
675 /* Step 4f: Propagate dependencies' time & fate. */
676 /* Set leaf time to be our time only if this is a leaf. */
678 timestamp_max( &t
->time
, &t
->time
, &last
);
679 timestamp_copy( &t
->leaf
, timestamp_empty( &leaf
) ? &t
->time
: &leaf
);
680 /* This target's fate may have been updated by virtue of following some
681 * target's rebuilds list, so only allow it to be increased to the fate we
682 * have calculated. Otherwise, grab its new fate.
684 if ( fate
> t
->fate
)
690 * Step 4g: If this target needs to be built, make0 all targets
691 * that are updated by the same actions used to update this target.
692 * These have already been marked as REBUILDS, and make1 has
693 * special handling for them. We just need to make sure that
696 if ( ( fate
>= T_FATE_BUILD
) && ( fate
< T_FATE_BROKEN
) )
700 for ( a
= t
->actions
; a
; a
= a
->next
)
702 for ( c
= a
->action
->targets
; c
; c
= c
->next
)
704 if ( c
->target
->fate
== T_FATE_INIT
)
706 make0( c
->target
, ptime
, depth
+ 1, counts
, anyhow
, rescanning
);
712 /* Step 4h: If this target needs to be built, force rebuild everything in
715 if ( ( fate
>= T_FATE_BUILD
) && ( fate
< T_FATE_BROKEN
) )
719 * Step 5: Sort dependencies by their update time.
722 if ( globs
.newestfirst
)
723 t
->depends
= make0sort( t
->depends
);
726 * Step 6: A little harmless tabulating for tracing purposes.
729 /* Do not count or report interal includes nodes. */
730 if ( t
->flags
& T_FLAG_INTERNAL
)
735 #ifdef OPT_IMPROVED_PATIENCE_EXT
738 if ( !( ++counts
->targets
% 1000 ) && DEBUG_MAKE
)
740 out_printf( "...patience...\n" );
745 if ( fate
== T_FATE_ISTMP
)
747 else if ( fate
== T_FATE_CANTFIND
)
749 else if ( ( fate
== T_FATE_CANTMAKE
) && t
->actions
)
751 else if ( ( fate
>= T_FATE_BUILD
) && ( fate
< T_FATE_BROKEN
) &&
756 if ( !( t
->flags
& T_FLAG_NOTFILE
) && ( fate
>= T_FATE_SPOIL
) )
758 else if ( t
->binding
== T_BIND_EXISTS
&& p
&& timestamp_cmp( &t
->time
,
762 if ( DEBUG_MAKEPROG
)
763 out_printf( "made%s\t%s\t%s%s\n", flag
, target_fate
[ (int)t
->fate
],
764 spaces( depth
), object_str( t
->name
) );
768 #ifdef OPT_GRAPH_DEBUG_EXT
770 static char const * target_name( TARGET
* t
)
772 static char buf
[ 1000 ];
773 if ( t
->flags
& T_FLAG_INTERNAL
)
775 sprintf( buf
, "%s (internal node)", object_str( t
->name
) );
778 return object_str( t
->name
);
783 * dependGraphOutput() - output the DG after make0 has run.
786 static void dependGraphOutput( TARGET
* t
, int depth
)
790 if ( ( t
->flags
& T_FLAG_VISITED
) || !t
->name
|| !t
->boundname
)
793 t
->flags
|= T_FLAG_VISITED
;
799 case T_FATE_OUTDATED
:
801 out_printf( "->%s%2d Name: %s\n", spaces( depth
), depth
, target_name( t
805 out_printf( " %s%2d Name: %s\n", spaces( depth
), depth
, target_name( t
810 if ( !object_equal( t
->name
, t
->boundname
) )
811 out_printf( " %s Loc: %s\n", spaces( depth
), object_str( t
->boundname
)
817 out_printf( " %s : Stable\n", spaces( depth
) );
820 out_printf( " %s : Newer\n", spaces( depth
) );
823 out_printf( " %s : Up to date temp file\n", spaces( depth
) );
826 out_printf( " %s : Temporary file, to be updated\n", spaces( depth
)
830 out_printf( " %s : Been touched, updating it\n", spaces( depth
) );
833 out_printf( " %s : Missing, creating it\n", spaces( depth
) );
835 case T_FATE_OUTDATED
:
836 out_printf( " %s : Outdated, updating it\n", spaces( depth
) );
839 out_printf( " %s : Rebuild, updating it\n", spaces( depth
) );
842 out_printf( " %s : Updating it\n", spaces( depth
) );
844 case T_FATE_CANTFIND
:
845 out_printf( " %s : Can not find it\n", spaces( depth
) );
847 case T_FATE_CANTMAKE
:
848 out_printf( " %s : Can make it\n", spaces( depth
) );
852 if ( t
->flags
& ~T_FLAG_VISITED
)
854 out_printf( " %s : ", spaces( depth
) );
855 if ( t
->flags
& T_FLAG_TEMP
) out_printf( "TEMPORARY " );
856 if ( t
->flags
& T_FLAG_NOCARE
) out_printf( "NOCARE " );
857 if ( t
->flags
& T_FLAG_NOTFILE
) out_printf( "NOTFILE " );
858 if ( t
->flags
& T_FLAG_TOUCHED
) out_printf( "TOUCHED " );
859 if ( t
->flags
& T_FLAG_LEAVES
) out_printf( "LEAVES " );
860 if ( t
->flags
& T_FLAG_NOUPDATE
) out_printf( "NOUPDATE " );
864 for ( c
= t
->depends
; c
; c
= c
->next
)
866 out_printf( " %s : Depends on %s (%s)", spaces( depth
),
867 target_name( c
->target
), target_fate
[ (int)c
->target
->fate
] );
868 if ( !timestamp_cmp( &c
->target
->time
, &t
->time
) )
869 out_printf( " (max time)");
873 for ( c
= t
->depends
; c
; c
= c
->next
)
874 dependGraphOutput( c
->target
, depth
+ 1 );
880 * make0sort() - reorder TARGETS chain by their time (newest to oldest).
882 * We walk chain, taking each item and inserting it on the sorted result, with
883 * newest items at the front. This involves updating each of the TARGETS'
884 * c->next and c->tail. Note that we make c->tail a valid prev pointer for every
885 * entry. Normally, it is only valid at the head, where prev == tail. Note also
886 * that while tail is a loop, next ends at the end of the chain.
889 static TARGETS
* make0sort( TARGETS
* chain
)
891 PROFILE_ENTER( MAKE_MAKE0SORT
);
893 TARGETS
* result
= 0;
895 /* Walk the current target list. */
899 TARGETS
* s
= result
;
903 /* Find point s in result for c. */
904 while ( s
&& timestamp_cmp( &s
->target
->time
, &c
->target
->time
) > 0 )
907 /* Insert c in front of s (might be 0). */
908 c
->next
= s
; /* good even if s = 0 */
909 if ( result
== s
) result
= c
; /* new head of chain? */
910 if ( !s
) s
= result
; /* wrap to ensure a next */
911 if ( result
!= c
) s
->tail
->next
= c
; /* not head? be prev's next */
912 c
->tail
= s
->tail
; /* take on next's prev */
913 s
->tail
= c
; /* make next's prev us */
916 PROFILE_EXIT( MAKE_MAKE0SORT
);
921 static LIST
* targets_to_update_
= L0
;
924 void mark_target_for_updating( OBJECT
* target
)
926 targets_to_update_
= list_push_back( targets_to_update_
, object_copy(
931 LIST
* targets_to_update()
933 return targets_to_update_
;
937 void clear_targets_to_update()
939 list_free( targets_to_update_
);
940 targets_to_update_
= L0
;