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

make1.c File Reference

#include "jam.h"
#include "lists.h"
#include "parse.h"
#include "assert.h"
#include "variable.h"
#include "rules.h"
#include "headers.h"
#include "search.h"
#include "newstr.h"
#include "make.h"
#include "command.h"
#include "execcmd.h"

Include dependency graph for make1.c:

Include dependency graph

Go to the source code of this file.

Classes

struct  _stack
struct  _state

Defines

#define T_STATE_MAKE1A   0
#define T_STATE_MAKE1ATAIL   1
#define T_STATE_MAKE1B   2
#define T_STATE_MAKE1C   3
#define T_STATE_MAKE1D   4

Typedefs

typedef _stack stack
typedef _state state

Functions

statealloc_state ()
void clear_state_freelist ()
statecurrent_state (stack *pStack)
void free_state (state *pState)
int make1 (TARGET *t)
void make1a (state *pState)
void make1atail (state *pState)
void make1b (state *pState)
void make1bind (TARGET *t, int warn)
void make1c (state *pState)
CMDmake1cmds (TARGET *t)
void make1d (state *pState)
LISTmake1list (LIST *l, TARGETS *targets, int flags)
SETTINGSmake1settings (LIST *vars)
void make_closure (void *closure, int status)
void pop_state (stack *pStack)
void push_stack_on_stack (stack *pDest, stack *pSrc)
statepush_state (stack *pStack, TARGET *t, TARGET *parent, int curstate)
void swap_settings (module_t **current_module, TARGET **current_target, module_t *new_module, TARGET *new_target)

Variables

struct {
   int   failed
   int   made
   int   skipped
   int   total
counts [1]
int intr = 0
statestate_freelist = NULL
stack state_stack = { NULL }


Define Documentation

#define T_STATE_MAKE1A   0
 

Definition at line 92 of file make1.c.

Referenced by make1(), make1a(), and make1c().

#define T_STATE_MAKE1ATAIL   1
 

Definition at line 93 of file make1.c.

Referenced by make1().

#define T_STATE_MAKE1B   2
 

Definition at line 94 of file make1.c.

Referenced by make1(), and make1c().

#define T_STATE_MAKE1C   3
 

Definition at line 95 of file make1.c.

Referenced by make1().

#define T_STATE_MAKE1D   4
 

Definition at line 96 of file make1.c.

Referenced by make1(), and make_closure().


Typedef Documentation

typedef struct _stack stack
 

Referenced by current_state(), make1a(), make1c(), pop_state(), push_stack_on_stack(), and push_state().

typedef struct _state state
 

Referenced by alloc_state(), clear_state_freelist(), current_state(), free_state(), make1(), make1a(), make1atail(), make1b(), make1c(), make1d(), parse_opt(), pop_state(), push_stack_on_stack(), and push_state().


Function Documentation

state* alloc_state  )  [static]
 

Definition at line 117 of file make1.c.

References _state::prev, state, and state_freelist.

Referenced by push_state().

00118 {
00119         if(state_freelist != NULL)
00120         {
00121                 state *pState;
00122 
00123                 pState = state_freelist;
00124                 state_freelist = pState->prev;
00125                 memset(pState, 0, sizeof(state));
00126                 return pState;
00127         }
00128         else
00129         {
00130                 return (state *)malloc(sizeof(state));
00131         }
00132 }

void clear_state_freelist  )  [static]
 

Definition at line 140 of file make1.c.

References _state::prev, state, and state_freelist.

Referenced by make1().

00141 {
00142         while(state_freelist != NULL)
00143         {
00144                 state *pState = state_freelist;
00145                 state_freelist = state_freelist->prev;
00146                 free(pState);
00147         }
00148 }

state* current_state stack pStack  )  [static]
 

Definition at line 150 of file make1.c.

References _stack::stack, stack, and state.

Referenced by make1().

00151 {
00152         return pStack->stack;
00153 }

void free_state state pState  )  [static]
 

Definition at line 134 of file make1.c.

References _state::prev, state, and state_freelist.

Referenced by pop_state().

00135 {
00136         pState->prev = state_freelist;
00137         state_freelist = pState;
00138 }

int make1 TARGET t  ) 
 

Definition at line 204 of file make1.c.

References clear_state_freelist(), counts, current_state(), _state::curstate, DEBUG_MAKE, execwait(), make1a(), make1atail(), make1b(), make1c(), make1d(), pop_state(), push_state(), state, state_stack, T_STATE_MAKE1A, T_STATE_MAKE1ATAIL, T_STATE_MAKE1B, T_STATE_MAKE1C, T_STATE_MAKE1D, and TARGET.

Referenced by make().

00205 {
00206         state *pState;
00207 
00208         memset( (char *)counts, 0, sizeof( *counts ) );
00209 
00210         /* Recursively make the target and its dependents */
00211         push_state(&state_stack, t, NULL, T_STATE_MAKE1A);
00212 
00213         do
00214         {
00215                 while((pState = current_state(&state_stack)) != NULL)
00216                 {
00217             if (intr) 
00218                 pop_state(&state_stack);
00219 
00220                         switch(pState->curstate)
00221                         {
00222                         case T_STATE_MAKE1A:
00223                                 make1a(pState);
00224                                 break;
00225                         case T_STATE_MAKE1ATAIL:
00226                                 make1atail(pState);
00227                                 break;
00228                         case T_STATE_MAKE1B:
00229                                 make1b(pState);
00230                                 break;
00231                         case T_STATE_MAKE1C:
00232                                 make1c(pState);
00233                                 break;
00234                         case T_STATE_MAKE1D:
00235                                 make1d(pState);
00236                                 break;
00237                         default:
00238                                 break;
00239                         }
00240                 }
00241         
00242 
00243         /* Wait for any outstanding commands to finish running. */
00244         } while( execwait() );
00245 
00246         clear_state_freelist();
00247 
00248         /* Talk about it */
00249         if( counts->failed )
00250             printf( "...failed updating %d target%s...\n", counts->failed,
00251                         counts->failed > 1 ? "s" : "" );
00252 
00253         if( DEBUG_MAKE && counts->skipped )
00254             printf( "...skipped %d target%s...\n", counts->skipped,
00255                         counts->skipped > 1 ? "s" : "" );
00256 
00257         if( DEBUG_MAKE && counts->made )
00258             printf( "...updated %d target%s...\n", counts->made,
00259                         counts->made > 1 ? "s" : "" );
00260 
00261         return counts->total != counts->made;
00262 }

Here is the call graph for this function:

void make1a state pState  )  [static]
 

Definition at line 269 of file make1.c.

References _target::asynccnt, c, _state::curstate, _target::depends, _target::includes, _targets::next, _state::parent, _target::parents, pop_state(), _target::progress, push_stack_on_stack(), push_state(), _target::rescanned, stack, state, state_stack, _state::t, T_MAKE_ACTIVE, T_MAKE_INIT, T_MAKE_RUNNING, T_STATE_MAKE1A, _targets::target, TARGET, targetchain(), targetentry(), and TARGETS.

Referenced by make1().

00270 {
00271     TARGET* t = pState->t;
00272         TARGETS *c;
00273     TARGETS   *inc;
00274 
00275         /* If the parent is the first to try to build this target */
00276         /* or this target is in the make1c() quagmire, arrange for the */
00277         /* parent to be notified when this target is built. */
00278 
00279         if( pState->parent )
00280             switch( pState->t->progress )
00281         {
00282         case T_MAKE_INIT:
00283         case T_MAKE_ACTIVE:
00284         case T_MAKE_RUNNING:
00285             pState->t->parents = targetentry( pState->t->parents, pState->parent );
00286             pState->parent->asynccnt++;
00287         }
00288 
00289         if( pState->t->progress != T_MAKE_INIT )
00290         {
00291                 pop_state(&state_stack);
00292                 return;
00293         }
00294 
00295         /* Asynccnt counts the dependents preventing this target from */
00296         /* proceeding to make1b() for actual building.  We start off with */
00297         /* a count of 1 to prevent anything from happening until we can */
00298         /* call all dependents.  This 1 is accounted for when we call */
00299         /* make1b() ourselves, below. */
00300 
00301         pState->t->asynccnt = 1;
00302 
00303     /* Add header node that was created during building process. */
00304 
00305     inc = 0;
00306     for (c = t->depends; c; c = c->next) {        
00307         if (c->target->rescanned && c->target->includes)
00308             inc = targetentry(inc, c->target->includes);           
00309     }
00310     t->depends = targetchain(t->depends, inc);
00311 
00312         /* against circular dependency. */
00313 
00314         pState->t->progress = T_MAKE_ONSTACK;
00315 
00316         {
00317                 stack temp_stack = { NULL };
00318         for( c = t->depends; c && !intr; c = c->next )            
00319             push_state(&temp_stack, c->target, pState->t, T_STATE_MAKE1A);
00320 
00321                 /* using stacks reverses the order of execution. Reverse it back */
00322                 push_stack_on_stack(&state_stack, &temp_stack);
00323         }
00324 
00325         pState->curstate = T_STATE_MAKE1ATAIL;
00326 }

Here is the call graph for this function:

void make1atail state pState  )  [static]
 

Definition at line 328 of file make1.c.

References _state::curstate, _target::progress, state, and _state::t.

Referenced by make1().

00329 {
00330         pState->t->progress = T_MAKE_ACTIVE;
00331 
00332         /* Now that all dependents have bumped asynccnt, we now allow */
00333         /* decrement our reference to asynccnt. */ 
00334         pState->curstate = T_STATE_MAKE1B;
00335 }

void make1b state pState  )  [static]
 

Definition at line 342 of file make1.c.

References _target::actions, _target::asynccnt, _target::boundname, c, _target::cmds, counts, _state::curstate, DEBUG_MAKE, _target::depends, EXEC_CMD_FAIL, _target::failed, failed, _target::fate, _target::flags, make1cmds(), _target::name, _targets::next, _target::parents, pop_state(), _target::progress, state, state_stack, _target::status, _state::t, T_FATE_CANTFIND, T_FATE_CANTMAKE, T_FATE_INIT, T_FATE_ISTMP, T_FATE_MAKING, T_FATE_MISSING, T_FATE_NEEDTMP, T_FATE_NEWER, T_FATE_OUTDATED, T_FATE_STABLE, T_FATE_TOUCHED, T_FATE_UPDATE, T_FLAG_RMOLD, _targets::target, TARGET, targetentry(), and TARGETS.

Referenced by make1().

00343 {
00344     TARGET      *t = pState->t;
00345     TARGETS     *c;
00346     TARGET      *failed = 0;
00347     char* failed_name = "dependencies";
00348 
00349     /* If any dependents are still outstanding, wait until they */
00350     /* call make1b() to signal their completion. */
00351 
00352     if( --(pState->t->asynccnt) )
00353         {
00354                 pop_state(&state_stack);
00355                 return;
00356         }
00357     
00358     /* Try to aquire a semaphore. If it's locked, wait until the target
00359        that locked it is build and signals completition. */
00360 #ifdef OPT_SEMAPHORE
00361         if( t->semaphore && t->semaphore->asynccnt )
00362         {
00363         /* Append 't' to the list of targets waiting on semaphore. */
00364             t->semaphore->parents = targetentry( t->semaphore->parents, t );
00365             t->asynccnt++;
00366 
00367             if( DEBUG_EXECCMD )
00368                 printf( "SEM: %s is busy, delaying launch of %s\n",
00369                         t->semaphore->name, t->name);
00370                 pop_state(&state_stack);
00371             return;
00372         }
00373 #endif
00374 
00375 
00376     /* Now ready to build target 't'... if dependents built ok. */
00377 
00378     /* Collect status from dependents */
00379 
00380 
00381     for( c = t->depends; c; c = c->next )
00382         if( c->target->status > t->status && !( c->target->flags & T_FLAG_NOCARE ))
00383         {
00384             failed = c->target;
00385             pState->t->status = c->target->status;
00386         }
00387     /* If a internal header node failed to build, we'd want to output the 
00388        target that it failed on. */
00389     if (failed && (failed->flags & T_FLAG_INTERNAL)) {
00390         failed_name = failed->failed;
00391     } else if (failed) {
00392         failed_name = failed->name;
00393     }
00394     t->failed = failed_name;
00395 
00396     /* If actions on deps have failed, bail. */
00397     /* Otherwise, execute all actions to make target */
00398 
00399     if( pState->t->status == EXEC_CMD_FAIL && pState->t->actions )
00400     {
00401         ++counts->skipped;
00402         if ( ( pState->t->flags & ( T_FLAG_RMOLD | T_FLAG_NOTFILE ) ) == T_FLAG_RMOLD )
00403         {
00404             if( !unlink( pState->t->boundname ) )
00405                 printf( "...removing outdated %s\n", pState->t->boundname );
00406         }
00407         else {
00408             printf( "...skipped %s for lack of %s...\n", pState->t->name, failed_name );
00409         }
00410     }
00411 
00412     if( pState->t->status == EXEC_CMD_OK )
00413         switch( pState->t->fate )
00414         {
00415         case T_FATE_INIT:
00416         case T_FATE_MAKING:
00417             /* shouldn't happen */
00418 
00419         case T_FATE_STABLE:
00420         case T_FATE_NEWER:
00421             break;
00422 
00423         case T_FATE_CANTFIND:
00424         case T_FATE_CANTMAKE:
00425             pState->t->status = EXEC_CMD_FAIL;
00426             break;
00427 
00428         case T_FATE_ISTMP:
00429             if( DEBUG_MAKE )
00430                 printf( "...using %s...\n", pState->t->name );
00431             break;
00432 
00433         case T_FATE_TOUCHED:
00434         case T_FATE_MISSING:
00435         case T_FATE_NEEDTMP:
00436         case T_FATE_OUTDATED:
00437         case T_FATE_UPDATE:
00438 
00439             /* Set "on target" vars, build actions, unset vars */
00440             /* Set "progress" so that make1c() counts this target among */
00441             /* the successes/failures. */
00442 
00443             if( pState->t->actions )
00444             {
00445                 ++counts->total;
00446                 if( DEBUG_MAKE && !( counts->total % 100 ) )
00447                     printf( "...on %dth target...\n", counts->total );
00448 
00449                 pState->t->cmds = (char *)make1cmds( pState->t );
00450                 pState->t->progress = T_MAKE_RUNNING;
00451             }
00452 
00453             break;
00454         }
00455 
00456                 /* Call make1c() to begin the execution of the chain of commands */
00457                 /* needed to build target.  If we're not going to build target */
00458                 /* (because of dependency failures or because no commands need to */
00459                 /* be run) the chain will be empty and make1c() will directly */
00460                 /* signal the completion of target. */
00461 
00462         /* Recurse on our dependents, manipulating progress to guard */
00463 
00464 #ifdef OPT_SEMAPHORE
00465         /* If there is a semaphore, indicate that its in use */
00466         if( pState->t->semaphore )
00467         {
00468             ++(pState->t->semaphore->asynccnt);
00469 
00470             if( DEBUG_EXECCMD )
00471                 printf( "SEM: %s now used by %s\n", pState->t->semaphore->name,
00472                        pState->t->name );
00473         }
00474 #endif
00475 
00476         pState->curstate = T_STATE_MAKE1C;
00477 }

Here is the call graph for this function:

void make1bind TARGET t,
int  warn
[static]
 

Definition at line 1029 of file make1.c.

References _target::binding, _target::boundname, _target::flags, _target::name, popsettings(), pushsettings(), search(), _target::settings, T_BIND_EXISTS, TARGET, and _target::time.

Referenced by make1list(), and make1settings().

01032 {
01033         if( t->flags & T_FLAG_NOTFILE )
01034             return;
01035 
01036         /* Sources to 'actions existing' are never in the dependency */
01037         /* graph (if they were, they'd get built and 'existing' would */
01038         /* be superfluous, so throttle warning message about independent */
01039         /* targets. */
01040 
01041         if( warn )
01042             printf( "warning: using independent target %s\n", t->name );
01043 
01044         pushsettings( t->settings );
01045         t->boundname = search( t->name, &t->time, 0 );
01046         t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
01047         popsettings( t->settings );
01048 }

Here is the call graph for this function:

void make1c state pState  )  [static]
 

Definition at line 484 of file make1.c.

References _actions::action, _target::actions, ACTIONS, _rule::actions, _cmd::args, _target::asynccnt, _cmd::buf, c, CMD, _target::cmds, copysettings(), counts, _state::curstate, DEBUG_MAKEQ, _target::depends, EXEC_CMD_FAIL, EXEC_CMD_OK, execcmd(), _target::failed, _target::fate, _target::flags, rule_actions::flags, fprintf(), freesettings(), headers(), _target::includes, list_print(), lol_get(), make0(), make_closure(), _target::name, _rule::name, _targets::next, _actions::next, _target::original_target, _target::parents, pop_state(), popsettings(), _target::progress, push_stack_on_stack(), push_state(), pushsettings(), _target::rescanned, _cmd::rule, s, _target::settings, SETTINGS, _cmd::shell, stack, state, state_stack, _action::status, _state::status, _target::status, _state::t, T_FATE_MISSING, T_STATE_MAKE1A, T_STATE_MAKE1B, _targets::tail, _targets::target, TARGET, targetentry(), and TARGETS.

Referenced by make1().

00485 {
00486         CMD     *cmd = (CMD *)pState->t->cmds;
00487 
00488         /* If there are (more) commands to run to build this target */
00489         /* (and we haven't hit an error running earlier comands) we */
00490         /* launch the command with execcmd(). */
00491         
00492         /* If there are no more commands to run, we collect the status */
00493         /* from all the actions then report our completion to all the */
00494         /* parents. */
00495 
00496         if( cmd && pState->t->status == EXEC_CMD_OK )
00497         {
00498                 if( DEBUG_MAKEQ || 
00499             ! ( cmd->rule->actions->flags & RULE_QUIETLY ) && DEBUG_MAKE)
00500             {
00501                 printf( "%s ", cmd->rule->name );
00502                 list_print( lol_get( &cmd->args, 0 ) );
00503                 printf( "\n" );
00504             }
00505 
00506             if( DEBUG_EXEC )
00507                 printf( "%s\n", cmd->buf );
00508 
00509             if( globs.cmdout )
00510                 fprintf( globs.cmdout, "%s", cmd->buf );
00511 
00512             if( globs.noexec )
00513             {
00514                         pState->curstate = T_STATE_MAKE1D;
00515                         pState->status = EXEC_CMD_OK;
00516             } 
00517             else
00518             {
00519                         TARGET *t = pState->t;
00520                         fflush( stdout );
00521 
00522                         pop_state(&state_stack); /* pop state first because execcmd could push state */
00523                         execcmd( cmd->buf, make_closure, t, cmd->shell );
00524             }
00525         }
00526         else
00527         {
00528             TARGETS     *c;
00529             ACTIONS     *actions;
00530 
00531             /* Collect status from actions, and distribute it as well */
00532 
00533             for( actions = pState->t->actions; actions; actions = actions->next )
00534                 if( actions->action->status > pState->t->status )
00535                     pState->t->status = actions->action->status;
00536 
00537             for( actions = pState->t->actions; actions; actions = actions->next )
00538                 if( pState->t->status > actions->action->status )
00539                     actions->action->status = pState->t->status;
00540 
00541             /* Tally success/failure for those we tried to update. */
00542 
00543             if( pState->t->progress == T_MAKE_RUNNING )
00544                 switch( pState->t->status )
00545             {
00546             case EXEC_CMD_OK:
00547                 ++counts->made;
00548                 break;
00549             case EXEC_CMD_FAIL:
00550                 ++counts->failed;
00551                 break;
00552             }
00553 
00554             /* Tell parents dependent has been built */
00555                 {
00556                         stack temp_stack = { NULL };
00557                         TARGET *t = pState->t;            
00558             TARGET* additional_includes = NULL;
00559 
00560                         t->progress = T_MAKE_DONE;
00561 
00562             /* Target was updated. Rescan dependencies. */
00563             if (t->fate >= T_FATE_MISSING &&
00564                 t->status == EXEC_CMD_OK &&
00565                 !t->rescanned) {
00566 
00567                 TARGET *target_to_rescan = t;
00568                 SETTINGS *s;               
00569 
00570                 target_to_rescan->rescanned = 1;
00571 
00572                 if (target_to_rescan->flags & T_FLAG_INTERNAL) {
00573                     target_to_rescan = t->original_target;                    
00574                 }
00575 
00576                 /* Clean current includes */
00577                 if (target_to_rescan->includes) {
00578                     target_to_rescan->includes = 0;
00579                 }
00580 
00581                 s = copysettings( target_to_rescan->settings );
00582                 pushsettings( s );
00583                 headers(target_to_rescan);
00584                 popsettings( s );
00585                 freesettings( s );
00586 
00587                 if (target_to_rescan->includes) {
00588                     target_to_rescan->includes->rescanned = 1;
00589                     /* Tricky. The parents were already processed, but they
00590                        did not seen the internal node, because it was just 
00591                        created. We need to make the calls to make1a that would
00592                        have been done by parents here, and also make sure all
00593                        unprocessed parents will pick up the includes. We must
00594                        make sure processing of the additional make1a invocations
00595                        is done before make1b which means this target is built,
00596                        otherwise the parent will be considered built before this
00597                        make1a processing is even started.
00598                     */
00599                     make0(target_to_rescan->includes, target_to_rescan->parents->target, 0, 0, 0);
00600                     for( c = target_to_rescan->parents; c; c = c->next) {
00601                         c->target->depends = targetentry( c->target->depends, 
00602                                                           target_to_rescan->includes );
00603                     }
00604                     /* Will be processed below. */
00605                     additional_includes = target_to_rescan->includes;
00606                 }                
00607             }
00608 
00609             if (additional_includes)
00610                 for ( c = t->parents; c; c = c->next ) {                            
00611                     push_state(&temp_stack, additional_includes, c->target, T_STATE_MAKE1A);
00612                     
00613                 }
00614 
00615                         for( c = t->parents; c; c = c->next ) {
00616                                 push_state(&temp_stack, c->target, NULL, T_STATE_MAKE1B);
00617             }
00618              
00619 
00620 
00621 #ifdef OPT_SEMAPHORE
00622             /* If there is a semaphore, its now free */
00623             if( t->semaphore )
00624             {
00625                 assert( t->semaphore->asynccnt == 1 );
00626                 --(t->semaphore->asynccnt);
00627 
00628                 if( DEBUG_EXECCMD )
00629                     printf( "SEM: %s is now free\n", t->semaphore->name);
00630 
00631                 /* If anything is waiting, notify the next target. There's no
00632             point in notifying all waiting targets, since they'll be
00633             serialized again. */
00634                 if( t->semaphore->parents )
00635                 {
00636                     TARGETS *first = t->semaphore->parents;
00637                     if( first->next )
00638                         first->next->tail = first->tail;
00639                     t->semaphore->parents = first->next;
00640 
00641                     if( DEBUG_EXECCMD )
00642                         printf( "SEM: placing %s on stack\n", first->target->name);
00643             push_state(&temp_stack, first->target, NULL, T_STATE_MAKE1B);
00644                     free( first );
00645                 }
00646             }
00647 #endif
00648 
00649                 
00650                         /* must pop state before pushing any more */
00651                         pop_state(&state_stack);
00652                 
00653                         /* using stacks reverses the order of execution. Reverse it back */
00654                         push_stack_on_stack(&state_stack, &temp_stack);
00655 
00656                 }
00657         }
00658 }

Here is the call graph for this function:

CMD * make1cmds TARGET t  )  [static]
 

Definition at line 783 of file make1.c.

References _actions::action, _rule::actions, _target::actions, ACTIONS, rule_actions::bindlist, _cmd::buf, CMD, cmd_new(), EXITBAD, rule_actions::flags, freesettings(), L0, LIST, list_copy(), list_free(), list_length(), list_new(), list_sublist(), make1list(), make1settings(), MAXLINE, _rule::module, _rule::name, newstr(), _cmd::next, _actions::next, popsettings(), pushsettings(), _action::rule, RULE, RULE_NEWSRCS, _action::running, SETTINGS, _action::sources, swap_settings(), _cmd::tail, TARGET, _action::targets, and var_get().

Referenced by make1b().

00784 {
00785         CMD *cmds = 0;
00786         LIST *shell = 0;
00787         
00788         module_t *settings_module = 0;
00789         TARGET *settings_target = 0;
00790         
00791         /* Step through actions */
00792         /* Actions may be shared with other targets or grouped with */
00793         /* RULE_TOGETHER, so actions already seen are skipped. */
00794         
00795         ACTIONS* a0;
00796         for(a0 = t->actions ; a0; a0 = a0->next )
00797         {
00798             RULE    *rule = a0->action->rule;
00799             rule_actions *actions = rule->actions;
00800             SETTINGS *boundvars;
00801             LIST    *nt, *ns;
00802             ACTIONS *a1;
00803             int     start, chunk, length;
00804 
00805             /* Only do rules with commands to execute. */
00806             /* If this action has already been executed, use saved status */
00807 
00808             if( !actions || a0->action->running )
00809                 continue;
00810 
00811             a0->action->running = 1;
00812             
00813             /* Make LISTS of targets and sources */
00814             /* If `execute together` has been specified for this rule, tack */
00815             /* on sources from each instance of this rule for this target. */
00816 
00817             nt = make1list( L0, a0->action->targets, 0 );
00818             ns = make1list( L0, a0->action->sources, actions->flags );
00819 
00820             if( actions->flags & RULE_TOGETHER )
00821                 for( a1 = a0->next; a1; a1 = a1->next )
00822                     if( a1->action->rule == rule && !a1->action->running )
00823             {
00824                 ns = make1list( ns, a1->action->sources, actions->flags );
00825                 a1->action->running = 1;
00826             }
00827 
00828             /* If doing only updated (or existing) sources, but none have */
00829             /* been updated (or exist), skip this action. */
00830 
00831             if( !ns && ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) )
00832             {
00833                 list_free( nt );
00834                 continue;
00835             }
00836 
00837             swap_settings( &settings_module, &settings_target, rule->module, t );
00838             if (!shell)
00839                 shell = var_get( "JAMSHELL" );  /* shell is per-target */
00840                 
00841             /* If we had 'actions xxx bind vars' we bind the vars now */
00842 
00843             boundvars = make1settings( actions->bindlist );
00844             pushsettings( boundvars );
00845 
00846             /*
00847              * Build command, starting with all source args. 
00848              *
00849              * If cmd_new returns 0, it's because the resulting command
00850              * length is > MAXLINE.  In this case, we'll slowly reduce
00851              * the number of source arguments presented until it does
00852              * fit.  This only applies to actions that allow PIECEMEAL 
00853              * commands.
00854              *
00855              * While reducing slowly takes a bit of compute time to get
00856              * things just right, it's worth it to get as close to MAXLINE
00857              * as possible, because launching the commands we're executing 
00858              * is likely to be much more compute intensive!
00859              *
00860              * Note we loop through at least once, for sourceless actions.
00861              */
00862 
00863             start = 0;
00864             chunk = length = list_length( ns );
00865 
00866             do
00867             {
00868                 /* Build cmd: cmd_new consumes its lists. */
00869 
00870                 CMD *cmd = cmd_new( rule, 
00871                         list_copy( L0, nt ), 
00872                         list_sublist( ns, start, chunk ),
00873                         list_copy( L0, shell ) );
00874 
00875                 if( cmd )
00876                 {
00877                     /* It fit: chain it up. */
00878 
00879                     if( !cmds ) cmds = cmd;
00880                     else cmds->tail->next = cmd;
00881                     cmds->tail = cmd;
00882                     start += chunk;
00883                 }
00884                 else if( ( actions->flags & RULE_PIECEMEAL ) && chunk > 1 )
00885                 {
00886                     /* Reduce chunk size slowly. */
00887 
00888                     chunk = chunk * 9 / 10;
00889                 }
00890                 else
00891                 {
00892                     /* Too long and not splittable. */
00893 
00894                     printf( "%s actions too long (max %d):\n", 
00895                         rule->name, MAXLINE );
00896 
00897                     /* Tell the user what didn't fit */
00898                     cmd = cmd_new(
00899                         rule, list_copy( L0, nt ), 
00900                         list_sublist( ns, start, chunk ),
00901                         list_new( L0, newstr( "%" ) ) );
00902 
00903                     printf( cmd->buf );
00904                 
00905                     exit( EXITBAD );
00906                 }
00907             }
00908             while( start < length );
00909 
00910             /* These were always copied when used. */
00911 
00912             list_free( nt );
00913             list_free( ns );
00914 
00915             /* Free the variables whose values were bound by */
00916             /* 'actions xxx bind vars' */
00917 
00918             popsettings( boundvars );
00919             freesettings( boundvars );
00920         }
00921 
00922         swap_settings( &settings_module, &settings_target, 0, 0 );
00923         return cmds;
00924 }

Here is the call graph for this function:

void make1d state pState  )  [static]
 

Definition at line 670 of file make1.c.

References _rule::actions, _cmd::args, _cmd::buf, CMD, cmd_free(), cmd_next, _target::cmds, _state::curstate, EXEC_CMD_FAIL, EXEC_CMD_OK, rule_actions::flags, _target::flags, LIST, list_next, list_print(), lol_get(), _rule::name, _cmd::rule, state, _target::status, _state::status, _list::string, _state::t, and TARGET.

Referenced by make1().

00671 {
00672         TARGET  *t = pState->t;
00673         CMD     *cmd = (CMD *)t->cmds;
00674         int status = pState->status;
00675 
00676         /* Execcmd() has completed.  All we need to do is fiddle with the */
00677         /* status and signal our completion so make1c() can run the next */
00678         /* command.  On interrupts, we bail heavily. */
00679 
00680         if ( t->flags & T_FLAG_FAIL_EXPECTED )
00681         {
00682           /* invert execution result when FAIL_EXPECTED was applied */
00683           switch (status)
00684           {
00685             case EXEC_CMD_FAIL: status = EXEC_CMD_OK; break;
00686             case EXEC_CMD_OK:   status = EXEC_CMD_FAIL; break;
00687             default:
00688               ;
00689           }
00690         }
00691         
00692         if( status == EXEC_CMD_FAIL && ( cmd->rule->actions->flags & RULE_IGNORE ) )
00693             status = EXEC_CMD_OK;
00694 
00695         /* On interrupt, set intr so _everything_ fails */
00696 
00697         if( status == EXEC_CMD_INTR )
00698             ++intr;
00699 
00700         if( status == EXEC_CMD_FAIL && DEBUG_MAKE )
00701         {
00702             /* Print command text on failure */
00703 
00704             if( !DEBUG_EXEC )
00705                 printf( "%s\n", cmd->buf );
00706 
00707             printf( "...failed %s ", cmd->rule->name );
00708             list_print( lol_get( &cmd->args, 0 ) );
00709             printf( "...\n" );
00710         }
00711 
00712         if (status == EXEC_CMD_FAIL)
00713                 if( globs.quitquick ) ++intr;
00714 
00715         /* If the command was interrupted or failed and the target */
00716         /* is not "precious", remove the targets */
00717 
00718         if( status != EXEC_CMD_OK && !( cmd->rule->actions->flags & RULE_TOGETHER ) )
00719         {
00720             LIST *targets = lol_get( &cmd->args, 0 );
00721 
00722             for( ; targets; targets = list_next( targets ) )
00723                 if( !unlink( targets->string ) )
00724                     printf( "...removing %s\n", targets->string );
00725         }
00726 
00727         /* Free this command and call make1c() to move onto next command. */
00728 
00729         t->status = status;
00730         t->cmds = (char *)cmd_next( cmd );
00731 
00732         cmd_free( cmd );
00733 
00734         pState->curstate = T_STATE_MAKE1C;
00735 }

Here is the call graph for this function:

LIST * make1list LIST l,
TARGETS targets,
int  flags
[static]
 

Definition at line 931 of file make1.c.

References _target::binding, _target::boundname, copystr(), _target::fate, LIST, list_new(), m, make1bind(), _list::next, _targets::next, RULE_EXISTING, _list::string, T_BIND_EXISTS, _targets::target, TARGET, and TARGETS.

Referenced by make1cmds().

00935 {
00936     for( ; targets; targets = targets->next )
00937     {
00938         TARGET *t = targets->target;
00939 
00940         /* Sources to 'actions existing' are never in the dependency */
00941         /* graph (if they were, they'd get built and 'existing' would */
00942         /* be superfluous, so throttle warning message about independent */
00943         /* targets. */
00944 
00945         if( t->binding == T_BIND_UNBOUND )
00946             make1bind( t, !( flags & RULE_EXISTING ) );
00947 
00948     if ( ( flags & RULE_EXISTING ) && ( flags & RULE_NEWSRCS ) )
00949     {
00950         if ( t->binding != T_BIND_EXISTS && t->fate <= T_FATE_STABLE)
00951             continue;
00952     }
00953     else
00954     { 
00955         if( ( flags & RULE_EXISTING ) && t->binding != T_BIND_EXISTS )
00956             continue;
00957 
00958         if( ( flags & RULE_NEWSRCS ) && t->fate <= T_FATE_STABLE )
00959             continue;
00960     }
00961 
00962         /* Prohibit duplicates for RULE_TOGETHER */
00963 
00964         if( flags & RULE_TOGETHER )
00965         {
00966             LIST *m;
00967 
00968             for( m = l; m; m = m->next )
00969                 if( !strcmp( m->string, t->boundname ) )
00970                     break;
00971 
00972             if( m )
00973                 continue;
00974         }
00975 
00976         /* Build new list */
00977 
00978         l = list_new( l, copystr( t->boundname ) );
00979     }
00980 
00981     return l;
00982 }

Here is the call graph for this function:

SETTINGS * make1settings LIST vars  )  [static]
 

Definition at line 989 of file make1.c.

References addsettings(), _target::binding, bindtarget(), _target::boundname, copystr(), LIST, list_new(), list_next, make1bind(), SETTINGS, _list::string, TARGET, and var_get().

Referenced by make1cmds().

00990 {
00991         SETTINGS *settings = 0;
00992 
00993         for( ; vars; vars = list_next( vars ) )
00994         {
00995             LIST *l = var_get( vars->string );
00996             LIST *nl = 0;
00997 
00998             for( ; l; l = list_next( l ) ) 
00999             {
01000                 TARGET *t = bindtarget( l->string );
01001 
01002                 /* Make sure the target is bound, warning if it is not in the */
01003                 /* dependency graph. */
01004 
01005                 if( t->binding == T_BIND_UNBOUND )
01006                     make1bind( t, 1 );
01007 
01008                 /* Build new list */
01009 
01010                 nl = list_new( nl, copystr( t->boundname ) );
01011             }
01012 
01013             /* Add to settings chain */
01014 
01015             settings = addsettings( settings, 0, vars->string, nl );
01016         }
01017 
01018         return settings;
01019 }

Here is the call graph for this function:

void make_closure void *  closure,
int  status
[static]
 

Definition at line 660 of file make1.c.

References closure, push_state(), state_stack, _state::status, T_STATE_MAKE1D, and TARGET.

Referenced by make1c().

00661 {
00662         push_state(&state_stack, (TARGET *)closure, NULL, T_STATE_MAKE1D)->status = status;
00663 }

Here is the call graph for this function:

void pop_state stack pStack  )  [static]
 

Definition at line 155 of file make1.c.

References free_state(), _state::prev, _stack::stack, stack, and state.

Referenced by make1(), make1a(), make1b(), and make1c().

00156 {
00157         state *pState;
00158 
00159         if(pStack->stack != NULL)
00160         {
00161                 pState = pStack->stack->prev;
00162                 free_state(pStack->stack);
00163                 pStack->stack = pState;
00164         }
00165 }

Here is the call graph for this function:

void push_stack_on_stack stack pDest,
stack pSrc
[static]
 

Definition at line 184 of file make1.c.

References _state::prev, _stack::stack, stack, and state.

Referenced by make1a(), and make1c().

00185 {
00186         while(pSrc->stack != NULL)
00187         {
00188                 state *pState;
00189 
00190                 pState = pSrc->stack;
00191                 pSrc->stack = pSrc->stack->prev;
00192                 pState->prev = pDest->stack;
00193                 pDest->stack = pState;
00194         }
00195 }

state* push_state stack pStack,
TARGET t,
TARGET parent,
int  curstate
[static]
 

Definition at line 167 of file make1.c.

References alloc_state(), _state::curstate, _state::parent, _state::prev, _stack::stack, stack, state, _state::t, and TARGET.

Referenced by make1(), make1a(), make1c(), and make_closure().

00168 {
00169         state *pState;
00170 
00171         pState = alloc_state();
00172 
00173         pState->t = t;
00174         pState->parent = parent;
00175         pState->prev = pStack->stack;
00176         pState->curstate = curstate;
00177 
00178         pStack->stack = pState;
00179 
00180         return pStack->stack;
00181 }

Here is the call graph for this function:

void swap_settings module_t **  current_module,
TARGET **  current_target,
module_t new_module,
TARGET new_target
[static]
 

Definition at line 741 of file make1.c.

References enter_module(), exit_module(), popsettings(), pushsettings(), root_module(), _target::settings, and TARGET.

Referenced by make1cmds().

00746 {
00747     if (new_module == root_module())
00748         new_module = 0;
00749     
00750     if (new_target == *current_target && new_module == *current_module)
00751         return;
00752 
00753     if (*current_target)
00754         popsettings( (*current_target)->settings );
00755         
00756     if (new_module != *current_module)
00757     {
00758         if (*current_module)
00759             exit_module( *current_module );
00760 
00761         *current_module = new_module;
00762         
00763         if (new_module)
00764             enter_module( new_module );
00765     }
00766 
00767     *current_target = new_target;
00768     if (new_target)
00769         pushsettings( new_target->settings );
00770 }

Here is the call graph for this function:


Variable Documentation

struct { ... } counts[1] [static]
 

Referenced by make1(), make1b(), and make1c().

int failed
 

Definition at line 78 of file make1.c.

Referenced by make1b().

int intr = 0 [static]
 

Definition at line 201 of file make1.c.

int made
 

Definition at line 81 of file make1.c.

int skipped
 

Definition at line 79 of file make1.c.

state* state_freelist = NULL [static]
 

Definition at line 115 of file make1.c.

Referenced by alloc_state(), clear_state_freelist(), and free_state().

stack state_stack = { NULL } [static]
 

Definition at line 113 of file make1.c.

Referenced by make1(), make1a(), make1b(), make1c(), and make_closure().

int total
 

Definition at line 80 of file make1.c.

Referenced by ObjectList::overlap().


Generated on Mon Nov 8 17:08:12 2004 for MPT by  doxygen 1.3.9.1