The Machine Perception Toolbox

[Introduction]- [News]- [Download]- [Screenshots]- [Manual (pdf)]- [Forums]- [API Reference]- [Repository ]

 

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

make.c

Go to the documentation of this file.
00001 /*
00002  * Copyright 1993, 1995 Christopher Seiwald.
00003  *
00004  * This file is part of Jam - see jam.c for Copyright information.
00005  */
00006 
00007 /*  This file is ALSO:
00008  *  (C) Copyright David Abrahams 2001. Permission to copy, use,
00009  *  modify, sell and distribute this software is granted provided this
00010  *  copyright notice appears in all copies. This software is provided
00011  *  "as is" without express or implied warranty, and with no claim as
00012  *  to its suitability for any purpose.
00013  */
00014 
00015 /*
00016  * make.c - bring a target up to date, once rules are in place
00017  *
00018  * This modules controls the execution of rules to bring a target and
00019  * its dependencies up to date.  It is invoked after the targets, rules,
00020  * et. al. described in rules.h are created by the interpreting of the
00021  * jam files.
00022  *
00023  * This file contains the main make() entry point and the first pass
00024  * make0().  The second pass, make1(), which actually does the command
00025  * execution, is in make1.c.
00026  *
00027  * External routines:
00028  *      make() - make a target, given its name
00029  *
00030  * Internal routines:
00031  *      make0() - bind and scan everything to make a TARGET
00032  *      make0sort() - reorder TARGETS chain by their time (newest to oldest)
00033  *
00034  * 12/26/93 (seiwald) - allow NOTIME targets to be expanded via $(<), $(>)
00035  * 01/04/94 (seiwald) - print all targets, bounded, when tracing commands
00036  * 04/08/94 (seiwald) - progress report now reflects only targets with actions
00037  * 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
00038  * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
00039  * 12/20/94 (seiwald) - make0() headers after determining fate of target, so 
00040  *                      that headers aren't seen as dependents on themselves.
00041  * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets.
00042  * 02/02/95 (seiwald) - propagate leaf source time for new LEAVES rule.
00043  * 02/14/95 (seiwald) - NOUPDATE rule means don't update existing target.
00044  * 08/22/95 (seiwald) - NOUPDATE targets immune to anyhow (-a) flag.
00045  * 09/06/00 (seiwald) - NOCARE affects targets with sources/actions.
00046  * 03/02/01 (seiwald) - reverse NOCARE change.
00047  * 03/14/02 (seiwald) - TEMPORARY targets no longer take on parents age
00048  * 03/16/02 (seiwald) - support for -g (reorder builds by source time)
00049  */
00050 
00051 # include "jam.h"
00052 
00053 # include "lists.h"
00054 # include "parse.h"
00055 # include "variable.h"
00056 # include "rules.h"
00057 
00058 #ifdef OPT_HEADER_CACHE_EXT
00059 # include "hcache.h"
00060 #endif
00061 
00062 # include "search.h"
00063 # include "newstr.h"
00064 # include "make.h"
00065 # include "headers.h"
00066 # include "command.h"
00067 # include <assert.h>
00068 
00069 # ifndef max
00070 # define max( a,b ) ((a)>(b)?(a):(b))
00071 # endif
00072 
00073 static TARGETS *make0sort( TARGETS *c );
00074 
00075 #ifdef OPT_GRAPH_DEBUG_EXT
00076 static void dependGraphOutput( TARGET *t, int depth );
00077 #endif
00078 
00079 static const char *target_fate[] = 
00080 {
00081         "init",         /* T_FATE_INIT */
00082         "making",       /* T_FATE_MAKING */
00083         "stable",       /* T_FATE_STABLE */
00084         "newer",        /* T_FATE_NEWER */
00085         "temp",         /* T_FATE_ISTMP */
00086         "touched",      /* T_FATE_TOUCHED */
00087         "missing",      /* T_FATE_MISSING */
00088         "needtmp",      /* T_FATE_NEEDTMP */
00089         "old",          /* T_FATE_OUTDATED */
00090         "update",       /* T_FATE_UPDATE */
00091         "nofind",       /* T_FATE_CANTFIND */
00092         "nomake"        /* T_FATE_CANTMAKE */
00093 } ;
00094 
00095 static const char *target_bind[] = 
00096 {
00097         "unbound",
00098         "missing",
00099         "parents",
00100         "exists",
00101 } ;
00102 
00103 # define spaces(x) ( "                    " + ( x > 20 ? 0 : 20-x ) )
00104 
00105 /*
00106  * make() - make a target, given its name
00107  */
00108 
00109 int
00110 make( 
00111         int             n_targets,
00112         const char      **targets,
00113         int             anyhow )
00114 {
00115         int i;
00116         COUNTS counts[1];
00117         int status = 0;         /* 1 if anything fails */
00118 
00119 #ifdef OPT_HEADER_CACHE_EXT
00120         hcache_init();
00121 #endif
00122 
00123         memset( (char *)counts, 0, sizeof( *counts ) );
00124 
00125     /* First bind all targets with LOCATE_TARGET setting. This is
00126        needed to correctly handle dependencies to generated headers.       
00127     */
00128     bind_explicitly_located_targets();
00129 
00130         for( i = 0; i < n_targets; i++ )
00131         {
00132             TARGET *t = bindtarget( targets[i] );
00133 
00134             make0( t, 0, 0, counts, anyhow );
00135         }
00136         
00137 #ifdef OPT_GRAPH_DEBUG_EXT
00138         if( DEBUG_GRAPH )
00139         {
00140             for( i = 0; i < n_targets; i++ )
00141             {
00142                 TARGET *t = bindtarget( targets[i] );
00143                 dependGraphOutput( t, 0 );
00144             }
00145         }
00146 #endif
00147 
00148         if( DEBUG_MAKE )
00149         {
00150             if( counts->targets )
00151                 printf( "...found %d target%s...\n", counts->targets,
00152                         counts->targets > 1 ? "s" : "" );
00153             if( counts->temp )
00154                 printf( "...using %d temp target%s...\n", counts->temp,
00155                         counts->temp > 1 ? "s" : "" );
00156             if( counts->updating )
00157                 printf( "...updating %d target%s...\n", counts->updating,
00158                         counts->updating > 1 ? "s" : "" );
00159             if( counts->cantfind )
00160                 printf( "...can't find %d target%s...\n", counts->cantfind,
00161                         counts->cantfind > 1 ? "s" : "" );
00162             if( counts->cantmake )
00163                 printf( "...can't make %d target%s...\n", counts->cantmake,
00164                         counts->cantmake > 1 ? "s" : "" );
00165         }
00166 
00167 #ifdef OPT_HEADER_CACHE_EXT
00168         hcache_done();
00169 #endif
00170 
00171         status = counts->cantfind || counts->cantmake;
00172 
00173         for( i = 0; i < n_targets; i++ )
00174             status |= make1( bindtarget( targets[i] ) );
00175 
00176         return status;
00177 }
00178 
00179 /*
00180  * make0() - bind and scan everything to make a TARGET
00181  *
00182  * Make0() recursively binds a target, searches for #included headers,
00183  * calls itself on those headers, and calls itself on any dependents.
00184  */
00185 
00186 void
00187 make0( 
00188         TARGET  *t,
00189         TARGET  *p,             /* parent */
00190         int     depth,          /* for display purposes */
00191         COUNTS  *counts,        /* for reporting */
00192         int     anyhow )        /* forcibly touch all (real) targets */
00193 {
00194         TARGETS *c, *d, *incs;
00195         TARGET  *ptime = t;
00196         time_t  last, leaf, hlast;
00197         int     fate;
00198         const char *flag = "";
00199         SETTINGS *s;
00200 
00201 #ifdef OPT_GRAPH_DEBUG_EXT
00202         int     savedFate, oldTimeStamp;
00203 #endif
00204 
00205         if( DEBUG_MAKEPROG )
00206             printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
00207 
00208         /* 
00209          * Step 1: initialize
00210          */
00211 
00212         if( DEBUG_MAKEPROG )
00213             printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
00214 
00215         t->fate = T_FATE_MAKING;
00216 
00217         /*
00218          * Step 2: under the influence of "on target" variables,
00219          * bind the target and search for headers.
00220          */
00221 
00222         /* Step 2a: set "on target" variables. */
00223 
00224         s = copysettings( t->settings );
00225         pushsettings( s );
00226 
00227         /* Step 2b: find and timestamp the target file (if it's a file). */
00228 
00229         if( t->binding == T_BIND_UNBOUND && !( t->flags & T_FLAG_NOTFILE ) )
00230         {
00231             char* another_target;
00232             t->boundname = search( t->name, &t->time, &another_target );
00233             /* If it was detected that this target refers to an already
00234                existing and bound one, we add include dependency, so that
00235                every target which depends on us will depend on that other 
00236                target. */
00237             if( another_target )
00238             {
00239                 TARGET* includes;
00240                 if (!t->includes) {
00241                     t->includes = copytarget(t);
00242                     t->includes->original_target = t;
00243                 }
00244                 includes = t->includes;
00245                 includes->depends = targetlist( includes->depends,
00246                                               list_new( L0, another_target ) );
00247             }
00248         
00249             t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
00250         }
00251 
00252         /* INTERNAL, NOTFILE header nodes have the time of their parents */
00253 
00254         if( p && t->flags & T_FLAG_INTERNAL )
00255             ptime = p;
00256 
00257         /* If temp file doesn't exist but parent does, use parent */
00258         if( p && t->flags & T_FLAG_TEMP && 
00259             t->binding == T_BIND_MISSING && 
00260             p->binding != T_BIND_MISSING )
00261     {
00262             t->binding = T_BIND_PARENTS;
00263             ptime = p;
00264     }
00265 
00266 #ifdef OPT_SEMAPHORE
00267         {
00268             LIST *var = var_get( "JAM_SEMAPHORE" );
00269             if( var )
00270             {
00271                 TARGET *semaphore = bindtarget( var->string );
00272 
00273                 semaphore->progress = T_MAKE_SEMAPHORE;
00274                 t->semaphore = semaphore;
00275             }
00276         }
00277 #endif
00278 
00279         /* Step 2c: If its a file, search for headers. */
00280 
00281         if( t->binding == T_BIND_EXISTS )
00282             headers( t );
00283 
00284         /* Step 2d: reset "on target" variables */
00285 
00286         popsettings( s );
00287         freesettings( s );
00288 
00289         /* 
00290          * Pause for a little progress reporting 
00291          */
00292 
00293         if( DEBUG_BIND )
00294 
00295         {
00296             if( strcmp( t->name, t->boundname ) )
00297             {
00298                 printf( "bind\t--\t%s%s: %s\n",
00299                         spaces( depth ), t->name, t->boundname );
00300             }
00301 
00302             switch( t->binding )
00303             {
00304             case T_BIND_UNBOUND:
00305             case T_BIND_MISSING:
00306             case T_BIND_PARENTS:
00307                 printf( "time\t--\t%s%s: %s\n",
00308                         spaces( depth ), t->name, target_bind[ t->binding ] );
00309                 break;
00310 
00311             case T_BIND_EXISTS:
00312                 printf( "time\t--\t%s%s: %s",
00313                         spaces( depth ), t->name, ctime( &t->time ) );
00314                 break;
00315             }
00316         }
00317 
00318         /* 
00319          * Step 3: recursively make0() dependents & headers
00320          */
00321 
00322         /* Step 3a: recursively make0() dependents */
00323 
00324         for( c = t->depends; c; c = c->next )
00325         {
00326             int internal = t->flags & T_FLAG_INTERNAL;
00327 /* Seems like it's not relevant for us....
00328             if( DEBUG_DEPENDS )
00329                 printf( "%s \"%s\" : \"%s\" ;\n", 
00330                     internal ? "Includes" : "Depends",
00331                     t->name, c->target->name );
00332 */
00333 
00334             /* Warn about circular deps, except for includes, */
00335             /* which include each other alot. */
00336 
00337             if( c->target->fate == T_FATE_INIT )
00338                 make0( c->target, ptime, depth + 1, counts, anyhow );
00339             else if( c->target->fate == T_FATE_MAKING && !internal )
00340                 printf( "warning: %s depends on itself\n", c->target->name );
00341         }
00342 
00343         /* Step 3b: recursively make0() internal includes node */
00344 
00345         if( t->includes )
00346             make0( t->includes, p, depth + 1, counts, anyhow );
00347 
00348         /* Step 3c: add dependents' includes to our direct dependencies */
00349 
00350         incs = 0;
00351 
00352         for( c = t->depends; c; c = c->next )
00353             if( c->target->includes )
00354                 incs = targetentry( incs, c->target->includes );
00355 
00356         t->depends = targetchain( t->depends, incs );
00357 
00358         /*
00359          * Step 4: compute time & fate 
00360          */
00361 
00362         /* Step 4a: pick up dependents' time and fate */
00363 
00364 
00365         last = 0;
00366         leaf = 0;
00367         fate = T_FATE_STABLE;
00368 
00369         for( c = t->depends; c; c = c->next )
00370         {
00371             /* If LEAVES has been applied, we only heed the timestamps of */
00372             /* the leaf source nodes. */
00373 
00374             leaf = max( leaf, c->target->leaf );
00375 
00376             if( t->flags & T_FLAG_LEAVES )
00377             {
00378                 last = leaf;
00379                 continue;
00380             }
00381 
00382             last = max( last, c->target->time );
00383             fate = max( fate, c->target->fate );
00384 
00385 #ifdef OPT_GRAPH_DEBUG_EXT
00386             if( DEBUG_FATE )
00387                 if( fate < c->target->fate )
00388                     printf( "fate change  %s from %s to %s by dependency %s\n",
00389                             t->name,
00390                             target_fate[fate], target_fate[c->target->fate],
00391                             c->target->name);
00392 #endif
00393 
00394         }
00395 
00396         /* Step 4b: pick up included headers time */
00397 
00398         /* 
00399          * If a header is newer than a temp source that includes it, 
00400          * the temp source will need building.   
00401          */
00402 
00403         hlast = t->includes ? t->includes->time : 0;
00404 
00405         /* Step 4c: handle NOUPDATE oddity */
00406 
00407         /*
00408          * If a NOUPDATE file exists, make dependents eternally old.
00409          * Don't inherit our fate from our dependents.  Decide fate
00410          * based only upon other flags and our binding (done later).
00411          */
00412 
00413         if( t->flags & T_FLAG_NOUPDATE )
00414         {
00415 #ifdef OPT_GRAPH_DEBUG_EXT
00416             if( DEBUG_FATE )
00417                 if( fate != T_FATE_STABLE )
00418                     printf( "fate change  %s back to stable, NOUPDATE.\n",
00419                            t->name);
00420 #endif
00421 
00422             last = 0;
00423             t->time = 0;
00424 
00425 
00426             /*
00427              * Don't inherit our fate from our dependents.  Decide fate
00428              * based only upon other flags and our binding (done later).
00429              */
00430 
00431             fate = T_FATE_STABLE;
00432         }
00433 
00434         /* Step 4d: determine fate: rebuild target or what? */
00435 
00436         /* 
00437             In English:
00438                 If can't find or make child, can't make target.
00439                 If children changed, make target.
00440                 If target missing, make it.
00441                 If children newer, make target.
00442                 If temp's children newer than parent, make temp.
00443                 If temp's headers newer than parent, make temp.
00444                 If deliberately touched, make it.
00445                 If up-to-date temp file present, use it.
00446                 If target newer than non-notfile parent, mark target newer.
00447                 Otherwise, stable!
00448 
00449                 Note this block runs from least to most stable:
00450                 as we make it further down the list, the target's
00451                 fate is getting stabler.
00452         */
00453 
00454 #ifdef OPT_GRAPH_DEBUG_EXT
00455         savedFate = fate;
00456         oldTimeStamp = 0;
00457 #endif
00458 
00459         if( fate >= T_FATE_BROKEN )
00460         {
00461             fate = T_FATE_CANTMAKE;
00462         }
00463         else if( fate >= T_FATE_SPOIL )
00464         {
00465             fate = T_FATE_UPDATE;
00466         }
00467         else if( t->binding == T_BIND_MISSING )
00468         {
00469             fate = T_FATE_MISSING;
00470         }
00471         else if( t->binding == T_BIND_EXISTS && last > t->time )
00472         {
00473 #ifdef OPT_GRAPH_DEBUG_EXT
00474             oldTimeStamp = 1;
00475 #endif
00476             fate = T_FATE_OUTDATED;
00477         }
00478         else if( t->binding == T_BIND_PARENTS && last > p->time )
00479         {
00480 #ifdef OPT_GRAPH_DEBUG_EXT
00481             oldTimeStamp = 1;
00482 #endif
00483             fate = T_FATE_NEEDTMP;
00484         }
00485         else if( t->binding == T_BIND_PARENTS && hlast > p->time )
00486         {
00487             fate = T_FATE_NEEDTMP;
00488         }
00489         else if( t->flags & T_FLAG_TOUCHED )
00490         {
00491             fate = T_FATE_TOUCHED;
00492         }
00493         else if( anyhow && !( t->flags & T_FLAG_NOUPDATE ) )
00494         {
00495             fate = T_FATE_TOUCHED;
00496         }
00497         else if( t->binding == T_BIND_EXISTS && t->flags & T_FLAG_TEMP )
00498         {
00499             fate = T_FATE_ISTMP;
00500         }
00501         else if( t->binding == T_BIND_EXISTS && p && 
00502                  p->binding != T_BIND_UNBOUND && t->time > p->time )
00503         {
00504 #ifdef OPT_GRAPH_DEBUG_EXT
00505             oldTimeStamp = 1;
00506 #endif
00507             fate = T_FATE_NEWER;
00508         }
00509         else
00510         {
00511             fate = T_FATE_STABLE;
00512         }
00513 #ifdef OPT_GRAPH_DEBUG_EXT
00514         if( DEBUG_FATE && fate != savedFate )
00515             if( savedFate == T_FATE_STABLE )
00516                 printf( "fate change  %s set to %s%s\n",
00517                        t->name, target_fate[fate],
00518                        oldTimeStamp ? " (by timestamp)" : "" );
00519             else
00520                 printf( "fate change  %s adjusted from %s to %s%s\n",
00521                        t->name, target_fate[savedFate], target_fate[fate],
00522                        oldTimeStamp ? " (by timestamp)" : "" );
00523 #endif
00524 
00525         /* Step 4e: handle missing files */
00526         /* If it's missing and there are no actions to create it, boom. */
00527         /* If we can't make a target we don't care about, 'sokay */
00528         /* We could insist that there are updating actions for all missing */
00529         /* files, but if they have dependents we just pretend it's NOTFILE. */
00530 
00531         if( fate == T_FATE_MISSING && !t->actions && !t->depends )
00532         {
00533             if( t->flags & T_FLAG_NOCARE )
00534             {
00535 #ifdef OPT_GRAPH_DEBUG_EXT
00536                 if( DEBUG_FATE )
00537                     printf( "fate change  %s to STABLE from %s, "
00538                             "no actions, no dependents and don't care\n",
00539                             t->name, target_fate[fate]);
00540 #endif
00541                 fate = T_FATE_STABLE;
00542             }
00543             else
00544             {
00545                 printf( "don't know how to make %s\n", t->name );
00546 
00547                 fate = T_FATE_CANTFIND;
00548             }
00549         }
00550 
00551         /* Step 4f: propagate dependents' time & fate. */
00552         /* Set leaf time to be our time only if this is a leaf. */
00553 
00554         t->time = max( t->time, last );
00555         t->leaf = leaf ? leaf : t->time ;
00556         t->fate = fate;
00557 
00558         /* 
00559          * Step 5: sort dependents by their update time. 
00560          */
00561 
00562         if( globs.newestfirst )
00563             t->depends = make0sort( t->depends );
00564 
00565         /* 
00566          * Step 6: a little harmless tabulating for tracing purposes 
00567          */
00568 
00569         /* Don't count or report interal includes nodes. */
00570 
00571         if( t->flags & T_FLAG_INTERNAL )
00572             return;
00573 
00574     if (counts) {
00575 #ifdef OPT_IMPROVED_PATIENCE_EXT
00576         ++counts->targets;
00577 #else   
00578         if( !( ++counts->targets % 1000 ) && DEBUG_MAKE )
00579             printf( "...patience...\n" );
00580 #endif
00581 
00582         if( fate == T_FATE_ISTMP )
00583             counts->temp++;
00584         else if( fate == T_FATE_CANTFIND )
00585             counts->cantfind++;
00586         else if( fate == T_FATE_CANTMAKE && t->actions )
00587             counts->cantmake++;
00588         else if( fate >= T_FATE_BUILD && fate < T_FATE_BROKEN && t->actions )
00589             counts->updating++;
00590     }
00591 
00592         if( !( t->flags & T_FLAG_NOTFILE ) && fate >= T_FATE_SPOIL )
00593             flag = "+";
00594         else if( t->binding == T_BIND_EXISTS && p && t->time > p->time )
00595             flag = "*";
00596 
00597         if( DEBUG_MAKEPROG )
00598             printf( "made%s\t%s\t%s%s\n", 
00599                 flag, target_fate[ t->fate ], 
00600                 spaces( depth ), t->name );
00601 
00602 /* We don't have DEBUG_CAUSES. 
00603         if( DEBUG_CAUSES && 
00604             t->fate >= T_FATE_NEWER && 
00605             t->fate <= T_FATE_MISSING )
00606                 printf( "%s %s\n", target_fate[ t->fate ], t->name );
00607 */
00608 }
00609 
00610 #ifdef OPT_GRAPH_DEBUG_EXT
00611 
00612 static const char* target_name( TARGET* t )
00613 {
00614     static char buf[1000];
00615     if (t->flags & T_FLAG_INTERNAL) {
00616         sprintf(buf, "%s (internal node)", t->name);
00617         return buf;
00618     } else {
00619         return t->name;
00620     }
00621 }
00622 
00623 /*
00624  * dependGraphOutput() - output the DG after make0 has run
00625  */
00626 
00627 static void
00628 dependGraphOutput( TARGET *t, int depth )
00629 {
00630     TARGETS     *c;
00631 
00632     if (   (t->flags & T_FLAG_VISITED) != 0
00633         || !t->name
00634         || !t->boundname)
00635         return;
00636 
00637     t->flags |= T_FLAG_VISITED;
00638 
00639     switch (t->fate)
00640     {
00641       case T_FATE_TOUCHED:
00642       case T_FATE_MISSING:
00643       case T_FATE_OUTDATED:
00644       case T_FATE_UPDATE:
00645         printf( "->%s%2d Name: %s\n", spaces(depth), depth, target_name(t) );
00646         break;
00647       default:
00648         printf( "  %s%2d Name: %s\n", spaces(depth), depth, target_name(t) );
00649         break;
00650     }
00651 
00652     if( strcmp (t->name, t->boundname) )
00653     {
00654         printf( "  %s    Loc: %s\n", spaces(depth), t->boundname );
00655     }
00656 
00657     switch( t->fate )
00658     {
00659       case T_FATE_STABLE:
00660         printf( "  %s       : Stable\n", spaces(depth) );
00661         break;
00662       case T_FATE_NEWER:
00663         printf( "  %s       : Newer\n", spaces(depth) );
00664         break;
00665       case T_FATE_ISTMP:
00666         printf( "  %s       : Up to date temp file\n", spaces(depth) );
00667       case T_FATE_NEEDTMP:
00668         printf( "  %s       : Temporary file, to be updated\n", spaces(depth) );
00669         break;
00670       case T_FATE_TOUCHED:
00671         printf( "  %s       : Been touched, updating it\n", spaces(depth) );
00672         break;
00673       case T_FATE_MISSING:
00674         printf( "  %s       : Missing, creating it\n", spaces(depth) );
00675         break;
00676       case T_FATE_OUTDATED:
00677         printf( "  %s       : Outdated, updating it\n", spaces(depth) );
00678         break;
00679       case T_FATE_UPDATE:
00680         printf( "  %s       : Updating it\n", spaces(depth) );
00681         break;
00682       case T_FATE_CANTFIND:
00683         printf( "  %s       : Can't find it\n", spaces(depth) );
00684         break;
00685       case T_FATE_CANTMAKE:
00686         printf( "  %s       : Can't make it\n", spaces(depth) );
00687         break;
00688     }
00689 
00690     if( t->flags & ~T_FLAG_VISITED )
00691     {
00692         printf( "  %s       : ", spaces(depth) );
00693         if( t->flags & T_FLAG_TEMP ) printf ("TEMPORARY ");
00694         if( t->flags & T_FLAG_NOCARE ) printf ("NOCARE ");
00695         if( t->flags & T_FLAG_NOTFILE ) printf ("NOTFILE ");
00696         if( t->flags & T_FLAG_TOUCHED ) printf ("TOUCHED ");
00697         if( t->flags & T_FLAG_LEAVES ) printf ("LEAVES ");
00698         if( t->flags & T_FLAG_NOUPDATE ) printf ("NOUPDATE ");
00699         printf( "\n" );
00700     }
00701 
00702     for( c = t->depends; c; c = c->next )
00703     {
00704         printf( "  %s       : Depends on %s (%s)", spaces(depth),
00705                target_name(c->target), target_fate[ c->target->fate ] );
00706     if (c->target->time == t->time)
00707         printf( " (max time)");
00708     printf("\n");
00709     
00710     }
00711 
00712 
00713     for( c = t->depends; c; c = c->next )
00714     {
00715 
00716         dependGraphOutput( c->target, depth + 1 );
00717     }
00718 }
00719 
00720 #endif
00721 /*
00722  * make0sort() - reorder TARGETS chain by their time (newest to oldest)
00723  */
00724 
00725 static TARGETS *
00726 make0sort( TARGETS *chain )
00727 {
00728         TARGETS *result = 0;
00729 
00730         /* We walk chain, taking each item and inserting it on the */
00731         /* sorted result, with newest items at the front.  This involves */
00732         /* updating each TARGETS' c->next and c->tail.  Note that we */
00733         /* make c->tail a valid prev pointer for every entry.  Normally, */
00734         /* it is only valid at the head, where prev == tail.  Note also */
00735         /* that while tail is a loop, next ends at the end of the chain. */
00736 
00737         /* Walk current target list */
00738 
00739         while( chain )
00740         {
00741             TARGETS *c = chain;
00742             TARGETS *s = result;
00743 
00744             chain = chain->next;
00745 
00746             /* Find point s in result for c */
00747 
00748             while( s && s->target->time > c->target->time )
00749                 s = s->next;
00750 
00751             /* Insert c in front of s (might be 0). */
00752             /* Don't even think of deciphering this. */
00753 
00754             c->next = s;                        /* good even if s = 0 */
00755             if( result == s ) result = c;       /* new head of chain? */
00756             if( !s ) s = result;                /* wrap to ensure a next */
00757             if( result != c ) s->tail->next = c; /* not head? be prev's next */
00758             c->tail = s->tail;                  /* take on next's prev */
00759             s->tail = c;                        /* make next's prev us */
00760         }
00761 
00762         return result;
00763 }
00764 
00765 static LIST *targets_to_update_ = 0;
00766 
00767 void mark_target_for_updating(char *target)
00768 {
00769     targets_to_update_ = list_new( targets_to_update_, target );
00770 }
00771 
00772 LIST *targets_to_update()
00773 {
00774     return targets_to_update_;
00775 }
00776 
00777 void clear_targets_to_update()
00778 {
00779     list_free(targets_to_update_);
00780     targets_to_update_ = 0;
00781 }

Generated on Mon Nov 8 17:07:41 2004 for MPT by  doxygen 1.3.9.1