command.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach/***********************************************************************
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder* *
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett* This software is part of the ast package *
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder* Copyright (c) 1984-2012 AT&T Intellectual Property *
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder* and is licensed under the *
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu* Eclipse Public License, Version 1.0 *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach* by AT&T Intellectual Property *
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder* *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach* A copy of the License is available at *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach* http://www.eclipse.org/org/documents/epl-v10.html *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett* *
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett* Information and Software Systems Research *
78718c37b1a50086a27e0f031db4cf82bea934aeChristian Maeder* AT&T Research *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach* Florham Park NJ *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach* *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach* Glenn Fowler <gsf@research.att.com> *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach* *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach***********************************************************************/
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#pragma prototyped
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/*
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder * Glenn Fowler
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett * AT&T Research
dfc58f5ec6492d1a9b9babd9cdcdbb15baa6e657Christian Maeder *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * make command execution routines
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder */
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder#include "make.h"
1538a6e8d77301d6de757616ffc69ee61f1482e4Andy Gimblett
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach#include <sig.h>
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder#if !_all_shells_the_same
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach#undef EXIT_CODE
792df0347edab377785d98c63e2be8e2ce0a8bdeChristian Maeder#define EXIT_CODE(x) ((x)&0177)
0ea916d1e6aea10fd7b84f802fb5148a79d8c20aAndy Gimblett#endif
04ceed96d1528b939f2e592d0656290d81d1c045Andy Gimblett
d9e78002fb0bf01a9b72d3d3415fdf9790bdfee8Andy Gimblett#define AFTER 0 /* done -- making after prereqs */
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#define BEFORE 001 /* done -- before after prereqs */
9f93b2a8b552789cd939d599504d39732672dc84Christian Maeder#define BLOCKED 002 /* waiting for prereqs */
1538a6e8d77301d6de757616ffc69ee61f1482e4Andy Gimblett#define INTERMEDIATE 003 /* waiting for parent cancel */
3b48e17c1da54ee669e70b626d9fbc32ce495b2cChristian Maeder#define READY 004 /* job ready to run */
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#define RUNNING 005 /* job action sent to coshell */
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder#define PUSHED 010 /* currently push'd */
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder#define STATUS (~PUSHED) /* status mask */
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder#define MAMNAME(r) ((state.mam.dynamic||(r)!=state.frame->target||((r)->property&P_after))?mamname(r):(char*)0)
c4b2418421546a337f83332fe0db04742dcd735dAndy Gimblett
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder#if DEBUG
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederstatic char* statusname[] =
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder{
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder "AFTER", "BEFORE", "BLOCKED", "INTERMEDIATE", "READY", "RUNNING",
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder};
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
e54c5af823b9775dd2c058185ea5bdf7593950faAndy Gimblett#define jobstatus() do { if (state.test & 0x00001000) dumpjobs(2, JOB_status); else if (error_info.trace <= CMDTRACE) dumpjobs(CMDTRACE, JOB_status); } while (0)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder#else
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder#define jobstatus()
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder
a78bb62cd6f0beb2dab862db865357fc9d3c25feChristian Maeder#endif
a78bb62cd6f0beb2dab862db865357fc9d3c25feChristian Maeder
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maederstruct Context_s; typedef struct Context_s Context_t;
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maederstruct Joblist_s; typedef struct Joblist_s Joblist_t;
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maederstruct Context_s /* job target context */
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder{
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder Context_t* next; /* for free list link */
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder Frame_t* frame; /* active target frames */
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder Frame_t* last; /* last active target frame */
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder int targetview; /* state.targetview */
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder};
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maederstruct Joblist_s /* job list cell */
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder{
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder Joblist_t* next; /* next in list */
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder Joblist_t* prev; /* prev in list */
a78bb62cd6f0beb2dab862db865357fc9d3c25feChristian Maeder Cojob_t* cojob; /* coshell job info */
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder Rule_t* target; /* target for job */
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett List_t* prereqs; /* these must be done */
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett Context_t* context; /* job target context */
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett char* action; /* unexpanded action */
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett int status; /* job status */
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly Flags_t flags; /* job flags */
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett};
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimbletttypedef struct Jobstate_s /* job state */
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett{
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett Joblist_t* firstjob; /* first job */
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder Joblist_t* lastjob; /* last job */
f4a5178450076ee54f3a9adb4f91e241aea3ba75Christian Maeder Joblist_t* freejob; /* free jobs */
f4a5178450076ee54f3a9adb4f91e241aea3ba75Christian Maeder Frame_t* freeframe; /* free target frames */
90047eafd2de482c67bcd13103c6064e9b0cb254Andy Gimblett Context_t* freecontext; /* free job context headers */
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett int intermediate; /* # INTERMEDIATE jobs */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Sfio_t* tmp; /* tmp stream */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Rule_t* triggered; /* triggered but not yet a job */
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett} Jobstate_t;
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maederstatic Jobstate_t jobs;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder/*
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder * accept r as up to date
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder */
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder
842ae753ab848a8508c4832ab64296b929167a97Christian Maederstatic void
842ae753ab848a8508c4832ab64296b929167a97Christian Maederaccept(register Rule_t* r)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder{
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (r->property & P_state)
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett {
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett if (!state.silent)
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach error(0, "touch %s", r->name);
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett if (state.exec)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.savestate = 1;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder goto done;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
dfc58f5ec6492d1a9b9babd9cdcdbb15baa6e657Christian Maeder if (r->property & P_archive)
dfc58f5ec6492d1a9b9babd9cdcdbb15baa6e657Christian Maeder {
dfc58f5ec6492d1a9b9babd9cdcdbb15baa6e657Christian Maeder if (state.exec)
dfc58f5ec6492d1a9b9babd9cdcdbb15baa6e657Christian Maeder {
dfc58f5ec6492d1a9b9babd9cdcdbb15baa6e657Christian Maeder artouch(r->name, NiL);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder statetime(r, 0);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett if (!state.silent)
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett error(0, "touch %s", r->name);
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett goto done;
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett }
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maeder if (r->active && (r->active->parent->target->property & P_archive) && !(r->property & (P_after|P_before|P_use)))
e54c5af823b9775dd2c058185ea5bdf7593950faAndy Gimblett {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly char* t;
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett if (t = strrchr(r->name, '/'))
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (!r->uname)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly r->uname = r->name;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly r->name = maprule(t + 1, r);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (state.exec)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder artouch(r->active->parent->target->name, r->name);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly else if (!state.silent)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly error(0, "touch %s/%s", r->active->parent->target->name, r->name);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (!(r->dynamic & D_regular))
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly goto done;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (!(r->property & P_virtual))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (!state.silent)
f4a5178450076ee54f3a9adb4f91e241aea3ba75Christian Maeder error(0, "touch %s", r->name);
f4a5178450076ee54f3a9adb4f91e241aea3ba75Christian Maeder if (state.exec)
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett {
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett Stat_t st;
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (stat(r->name, &st) || tmxgetmtime(&st) < state.start && tmxtouch(r->name, (Time_t)0, (Time_t)0, (Time_t)0, 0))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder error(ERROR_SYSTEM|1, "cannot touch %s", r->name);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder statetime(r, 0);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly done:
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (r->status != TOUCH)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly r->status = r->time ? EXISTS : (r->property & P_dontcare) ? IGNORE : FAILED;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly}
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder/*
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder * apply operator or action with attributes in r given lhs, rhs and job flags
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder * blocks until action is complete
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly */
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillyint
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederapply(register Rule_t* r, char* lhs, char* rhs, char* act, Flags_t flags)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly{
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly register Rule_t* x;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly int oop;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly int errors;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly Rule_t lhs_rule;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly Rule_t rhs_rule;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly List_t lhs_prereqs;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly Frame_t lhs_frame;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly Frame_t* oframe;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly zero(lhs_rule);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly zero(rhs_rule);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly lhs_prereqs.rule = &rhs_rule;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly lhs_prereqs.next = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder x = &lhs_rule;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder x->prereqs = &lhs_prereqs;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder zero(lhs_frame);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder lhs_frame.parent = state.frame;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder lhs_frame.target = x;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly x->active = &lhs_frame;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly x->property = r->property & (P_make|P_operator);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (x->property & P_operator)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly x->action = act;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly act = r->action;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly else
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly x->action = r->action;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly x->name = lhs;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly x->statedata = r->name;
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett x->time = state.start;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly rhs_rule.name = rhs;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly rhs_rule.time = x->time + 1;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder oframe = state.frame;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.frame = &lhs_frame;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if ((r->property & (P_make|P_operator)) == (P_make|P_operator))
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly {
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy Gimblett if (r->prereqs)
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy Gimblett {
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly Time_t t;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly char* oaction;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly oaction = r->action;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly r->action = null;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly make(r, &t, NiL, 0);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly r->action = oaction;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly oop = state.op;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly state.op = 1;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly errors = parse(NiL, act, r->name, NiL) == FAILED;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly state.op = oop;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly else
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly r->status = UPDATE;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder trigger(r, NiL, act, flags);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder errors = complete(r, NiL, NiL, 0);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.frame = oframe;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder return errors;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder}
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly/*
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly * apply() returning (temporary) CO_DATAFILE pointer to stdout of action
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly */
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'ReillySfio_t*
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederfapply(Rule_t* r, char* lhs, char* rhs, char* act, Flags_t flags)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder{
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Sfio_t* fp;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder fp = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (!apply(r, lhs, rhs, act, flags|CO_DATAFILE))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (fp = sfopen(NiL, state.tmpfile, "re"))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder remove(state.tmpfile);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly else
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly error(2, "%s: cannot read temporary data output file %s", r->name, state.tmpfile);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.tmpfile = 0;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly return fp;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly}
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy Gimblett
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett/*
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * call functional r with args
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly * functional return value returned
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly * 0 returned if not functional or empty return
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederchar*
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maedercall(register Rule_t* r, char* args)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder{
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register Var_t* v;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
e95030058b77cb83593c85aa4c506caf154f63b7Andy Gimblett if (r->property & P_functional)
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett {
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly maketop(r, 0, args);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if ((v = getvar(r->name)) && *v->value)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder return v->value;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder return 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder}
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy Gimblett/*
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett * commit target/virtual directory
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederstatic void
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maedercommit(Joblist_t* job, register char* s)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder{
5858e6262048894b0e933b547852f04aed009b58Andy Gimblett register char* t;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly register char* v;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett register Rule_t* r;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly Stat_t st;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly if (t = strrchr(s, '/'))
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly {
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly *t = 0;
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly if (r = bindfile(NiL, s, 0))
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly {
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett if (!r->view)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder *t = '/';
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly return;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (*(v = r->name) != '/')
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly sfprintf(internal.nam, "%s/%s", state.view[r->view].root, v);
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett v = sfstruse(internal.nam);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (stat(v, &st))
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly r = 0;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett }
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (r || state.targetcontext && (!r || !r->time) && (st.st_mode = (S_IRWXU|S_IRWXG|S_IRWXO)) && tmxsetmtime(&st, state.start))
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly {
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly /*
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * why not mkdir -p here?
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett */
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly commit(job, s);
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly if (((job->flags & CO_ALWAYS) || state.exec && state.touch) && (mkdir(s, st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) || stat(s, &st)))
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly error(1, "%s: cannot create target directory %s", job->target->name, s);
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett if (state.mam.out)
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly {
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly Sfio_t* tmp = sfstropen();
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sfprintf(tmp, "mkdir %s", s);
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly dumpaction(state.mam.out, MAMNAME(job->target), sfstruse(tmp), NiL);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly sfstrclose(tmp);
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett }
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly r = makerule(s);
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly if (r->dynamic & D_alias)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder oldname(r);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder r->view = 0;
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly r->time = tmxgetmtime(&st);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (r->dynamic & D_scanned)
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett unbind(NiL, (char*)r, NiL);
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly }
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly *t = '/';
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder}
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly/*
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett * push job context
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly */
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly
842ae753ab848a8508c4832ab64296b929167a97Christian Maederstatic void
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederpush(Joblist_t* job)
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly{
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly register Context_t* z;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett register Frame_t* p;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly register Rule_t* r;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly int n;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder Time_t tm;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly job->status |= PUSHED;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (z = job->context)
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett {
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly p = z->frame;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly for (;;)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (!(r = getrule(p->context.name)))
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly r = makerule(p->context.name);
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly p->target = r;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly tm = r->time;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett r->time = p->context.time;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly p->context.time = tm;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly p->context.frame = r->active;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly r->active = p;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (p == p->parent)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder break;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly p = p->parent;
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly n = state.targetview;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett state.targetview = z->targetview;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly z->targetview = n;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly p = state.frame;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly state.frame = z->frame;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly z->frame = p;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly }
5858e6262048894b0e933b547852f04aed009b58Andy Gimblett}
5858e6262048894b0e933b547852f04aed009b58Andy Gimblett
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder/*
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * pop job context
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly */
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillystatic void
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblettpop(Joblist_t* job)
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly{
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly register Context_t* z;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register Frame_t* p;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register Rule_t* r;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder int n;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly Time_t tm;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly if (z = job->context)
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder n = state.targetview;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.targetview = z->targetview;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder z->targetview = n;
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly p = state.frame;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly state.frame = z->frame;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett z->frame = p;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly for (;;)
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly {
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly if (!(r = getrule(p->context.name)))
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett r = makerule(p->context.name);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder r->active = p->context.frame;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder tm = r->time;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder r->time = p->context.time;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder p->context.time = tm;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (p == p->parent)
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly break;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly p = p->parent;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder job->status &= ~PUSHED;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder}
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/*
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly * discard (free) job context
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly */
7996f5f893cc14b5e22fdb7ec90a3474ba3c51abAndy Gimblett
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillystatic void
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillydiscard(register Joblist_t* job)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly{
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register Context_t* z;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register List_t* p;
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (job->flags & CO_SEMAPHORES)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly for (p = job->prereqs; p; p = p->next)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (p->rule->semaphore)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly p->rule->semaphore++;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly p->rule->status = EXISTS;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (job->flags & CO_PRIMARY)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder job->prereqs->next = 0;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly freelist(job->prereqs);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (z = job->context)
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder z->last->parent = jobs.freeframe;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder jobs.freeframe = z->frame;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder z->next = jobs.freecontext;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder jobs.freecontext = z;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder job->context = 0;
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (job->next)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder job->next->prev = job->prev;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder else
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder jobs.lastjob = job->prev;
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett if (job->prev)
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett job->prev->next = job->next;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder else
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett jobs.firstjob = job->next;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder job->next = jobs.freejob;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder jobs.freejob = job;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder}
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder/*
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder * save job context for later execute()
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederstatic void
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maedersave(Joblist_t* job)
c56c0630e0299eca5dd603cdac49aab4463c0671Liam O'Reilly{
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register Frame_t* o;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register Frame_t* p;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register Frame_t* x;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Context_t* z;
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett if (job->action && !job->context)
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (z = jobs.freecontext)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder jobs.freecontext = jobs.freecontext->next;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly else
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly z = newof(0, Context_t, 1, 0);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly z->targetview = state.targetview;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly o = state.frame;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly p = 0;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly for (;;)
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (x = jobs.freeframe)
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly jobs.freeframe = jobs.freeframe->parent;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly else
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly x = newof(0, Frame_t, 1, 0);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (p)
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly p->parent = x;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly else
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly z->frame = x;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly p = x;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder p->original = o->original;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder p->primary = o->primary;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder p->stem = o->stem ? strdup(o->stem) : 0;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly p->context.name = o->target->name;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly p->context.time = o->target->time;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder if (o->parent == o)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly break;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder o = o->parent;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder z->last = p->parent = p;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder job->context = z;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly}
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly/*
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * restore action by expanding into buf using original context
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * coexec attributes placed in att
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder */
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maederstatic void
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maederrestore(register Joblist_t* job, Sfio_t* buf, Sfio_t* att)
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maeder{
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register char* s;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register char* b;
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maeder char* u;
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maeder char* down;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder char* back;
9582375827616730f146b77f9d5a4fd0cc78bc47Andy Gimblett char* sep;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder int downlen;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder int localview;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder void* pos;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder Var_t* v;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder Sfio_t* opt;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Sfio_t* tmp;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Sfio_t* context;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder push(job);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder localview = state.localview;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.localview = state.mam.statix && !state.expandview && state.user && !(job->flags & CO_ALWAYS);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if ((job->flags & CO_LOCALSTACK) || (job->target->dynamic & D_hasscope))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder register Rule_t* r;
9582375827616730f146b77f9d5a4fd0cc78bc47Andy Gimblett register List_t* p;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder job->flags |= CO_LOCALSTACK;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder pos = pushlocal();
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder opt = sfstropen();
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder if (job->target->dynamic & D_hasscope)
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder for (p = job->prereqs; p; p = p->next)
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder if ((r = p->rule)->dynamic & D_scope)
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder {
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder if (*r->name == '-')
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder set(r->name, 1, opt);
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder else
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder parse(NiL, r->name, r->name, opt);
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder }
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder else if ((r->property & (P_make|P_local|P_use)) == (P_make|P_local) && r->action)
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder parse(NiL, r->action, r->name, opt);
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder }
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder context = state.context;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder if (state.targetcontext && *(u = unbound(job->target)) != '/' && (s = strrchr(u, '/')))
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder {
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder size_t n;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder int c;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder tmp = sfstropen();
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder downlen = s - u;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder *s = 0;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder sfprintf(tmp, "%s%c", u, 0);
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder n = sfstrtell(tmp);
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder c = '/';
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder do
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder {
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder if (u = strchr(u, '/'))
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder u++;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder else
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder c = 0;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder sfputr(tmp, "..", c);
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder } while (c);
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder *s = '/';
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett back = (down = sfstrbase(tmp)) + n;
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett state.context = buf;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder buf = sfstropen();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.localview++;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly else
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly state.context = 0;
2bb060537a37352251aa04d8dc09aa53aad5d4bfLiam O'Reilly if (job->action)
2bb060537a37352251aa04d8dc09aa53aad5d4bfLiam O'Reilly expand(buf, job->action);
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly if (state.context)
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly {
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly s = sfstruse(buf);
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly sep = strchr(s, '\n') ? "\n" : "; ";
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly sfprintf(state.context, "{ cd %s%s", down, sep);
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly while (b = strchr(s, MARK_CONTEXT))
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly {
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly sfwrite(state.context, s, b - s);
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly if (!(s = strchr(++b, MARK_CONTEXT)))
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly error(PANIC, "unbalanced MARK_CONTEXT");
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly *s++ = 0;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly if (*b == '/' || (u = getbound(b)) && *u == '/')
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly sfputr(state.context, b, -1);
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly else if (*b)
2bb060537a37352251aa04d8dc09aa53aad5d4bfLiam O'Reilly {
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly if (strneq(b, down, downlen))
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly switch (*(b + downlen))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder case 0:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sfputc(state.context, '.');
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder continue;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly case '/':
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly sfputr(state.context, b + downlen + 1, -1);
2bb060537a37352251aa04d8dc09aa53aad5d4bfLiam O'Reilly continue;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly }
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly if (streq(b, "."))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sfputr(state.context, back, -1);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder else if (isspace(*b))
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly sfputr(state.context, b, -1);
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly else
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly sfprintf(state.context, "%s/%s", back, b);
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly }
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sfprintf(state.context, "%s%s}", s, sep);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sfstrclose(tmp);
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly sfstrclose(buf);
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly }
2bb060537a37352251aa04d8dc09aa53aad5d4bfLiam O'Reilly state.context = context;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly sfprintf(att, "label=%s", job->target->name);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if ((v = getvar(CO_ENV_ATTRIBUTES)) && !(v->property & V_import))
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly sfprintf(att, ",%s", v->value);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (job->flags & CO_LOCALSTACK)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder poplocal(pos);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (*(s = sfstruse(opt)))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder set(s, 1, NiL);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sfclose(opt);
9582375827616730f146b77f9d5a4fd0cc78bc47Andy Gimblett }
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett state.localview = localview;
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly pop(job);
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly}
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reillystatic int done(Joblist_t* job, int, Cojob_t*);
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder/*
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly * send a job to the coshell for execution
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederstatic void
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederexecute(register Joblist_t* job)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder{
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly register List_t* p;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly char* s;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly char* t;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly int flags;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder Rule_t* r;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly Var_t* v;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly Sfio_t* tmp;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly Sfio_t* att;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly Sfio_t* sp;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder att = sfstropen();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder tmp = sfstropen();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder restore(job, tmp, att);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder job->status = RUNNING;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder job->target->mark &= ~M_waiting;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state.targetcontext || state.maxview && !state.fsview && *job->target->name != '/' && (!(job->target->dynamic & D_regular) || job->target->view))
9582375827616730f146b77f9d5a4fd0cc78bc47Andy Gimblett commit(job, job->target->name);
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett if ((state.mam.dynamic || state.mam.regress) && state.user && !(job->target->property & (P_after|P_before|P_dontcare|P_make|P_state|P_virtual)))
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett sfprintf(state.mam.out, "%sinit %s %s\n", state.mam.label, mamname(job->target), timefmt(NiL, CURTIME));
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder t = sfstruse(tmp);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (!(job->flags & CO_ALWAYS))
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state.touch)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state.virtualdot)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett state.virtualdot = 0;
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett lockstate(1);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (!(job->target->property & (P_attribute|P_virtual)))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder accept(job->target);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if ((job->target->property & (P_joint|P_target)) == (P_joint|P_target))
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder for (p = job->target->prereqs->rule->prereqs; p; p = p->next)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (p->rule != job->target)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder accept(p->rule);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder else if (*t && (!state.silent || state.mam.regress))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder dumpaction(state.mam.out ? state.mam.out : sfstdout, NiL, t, NiL);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder done(job, 0, NiL);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder else
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state.virtualdot && !notfile(job->target))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.virtualdot = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder lockstate(1);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (!state.coshell)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder#if !O_cloexec
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (internal.openfile)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder fcntl(internal.openfd, F_SETFD, FD_CLOEXEC);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder#endif
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder sp = sfstropen();
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder sfprintf(sp, "label=%s", idname);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder expand(sp, " $(" CO_ENV_OPTIONS ")");
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder flags = CO_ANY;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state.cross)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder flags |= CO_CROSS;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state.serialize && state.jobs > 1)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder flags |= CO_SERIALIZE;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (!(state.coshell = coopen(getval(CO_ENV_SHELL, VAL_PRIMARY), flags, sfstruse(sp))))
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder error(ERROR_SYSTEM|3, "coshell open error");
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder sfstrclose(sp);
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (p = internal.exports->prereqs)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Sfio_t* exp;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder exp = sfstropen();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder do
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (v = getvar(p->rule->name))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
9582375827616730f146b77f9d5a4fd0cc78bc47Andy Gimblett expand(exp, v->value);
9582375827616730f146b77f9d5a4fd0cc78bc47Andy Gimblett coexport(state.coshell, p->rule->name, sfstruse(exp));
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder else if (s = strchr(p->rule->name, '='))
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder *s = 0;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder expand(exp, s + 1);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder coexport(state.coshell, p->rule->name, sfstruse(exp));
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder *s = '=';
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder } while (p = p->next);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder sfstrclose(exp);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#if 0
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder freelist(internal.exports->prereqs);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#endif
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder internal.exports->prereqs = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (job->flags & CO_DATAFILE)
f18cf8a4e7d512a2f57365ab1e9e7fdbb98ba257Andy Gimblett {
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett static char* dot;
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett static char* tmp;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (job->target->property & P_read)
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly {
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (!dot)
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly dot = pathtemp(NiL, 0, null, idname, NiL);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state.tmpfile = dot;
bba1e274cf727c39b4f1dd8970539a2bb967f20fLiam O'Reilly }
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly else
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly {
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (!tmp)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder tmp = pathtemp(NiL, 0, NiL, idname, NiL);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.tmpfile = tmp;
bba1e274cf727c39b4f1dd8970539a2bb967f20fLiam O'Reilly }
bba1e274cf727c39b4f1dd8970539a2bb967f20fLiam O'Reilly }
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly#if !_HUH_1992_02_29 /* i386 and ftx m68k dump without this statement -- help */
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly message((-99, "execute: %s: t=0x%08x &t=0x%08x", job->target->name, t, &t));
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly#endif
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state.mam.out)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder dumpaction(state.mam.out, MAMNAME(job->target), t, NiL);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (r = getrule(external.makerun))
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly maketop(r, P_dontcare|P_foreground, NiL);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder#if _WINIX
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (internal.openfile)
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly#else
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if ((state.test & 0x00020000) && internal.openfile)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder#endif
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly internal.openfile = 0;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly close(internal.openfd);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly }
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (!(job->cojob = coexec(state.coshell, t, job->flags, state.tmpfile, NiL, sfstruse(att))))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder error(3, "%s: cannot send action to coshell", job->target->name);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder job->cojob->local = (void*)job;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly /*
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett * grab semaphores
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (job->target->dynamic & D_hassemaphore)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder job->flags |= CO_SEMAPHORES;
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett for (p = job->prereqs; p; p = p->next)
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett if (p->rule->semaphore && --p->rule->semaphore == 1)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder p->rule->status = MAKING;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett /*
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * check status and sync
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder */
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (job->target->dynamic & D_hasafter)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder save(job);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (job->flags & (CO_DATAFILE|CO_FOREGROUND))
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett complete(job->target, NiL, NiL, 0);
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett if (job->target->property & (P_functional|P_read))
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (sp = sfopen(NiL, state.tmpfile, "r"))
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett remove(state.tmpfile);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (job->target->property & P_read)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder parse(sp, NiL, job->target->name, NiL);
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett else
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder char* e;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sfmove(sp, tmp, SF_UNBOUND, -1);
f18cf8a4e7d512a2f57365ab1e9e7fdbb98ba257Andy Gimblett t = sfstrbase(tmp);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder e = sfstrseek(tmp, 0, SEEK_CUR);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder while (e > t && *(e - 1) == '\n')
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder e--;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sfstrseek(tmp, e - t, SEEK_SET);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder setvar(job->target->name, sfstruse(tmp), 0);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sfclose(sp);
f18cf8a4e7d512a2f57365ab1e9e7fdbb98ba257Andy Gimblett }
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett else
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett error(2, "%s: cannot read temporary data output file %s", job->target->name, state.tmpfile);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.tmpfile = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett sfstrclose(att);
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett sfstrclose(tmp);
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett}
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett/*
c909c215242232fe78ce335e677e6f22264a0ee9Christian Maeder * check if job for r with completed prereqs p can be cancelled
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett */
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maederstatic int
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maedercancel(register Rule_t* r, register List_t* p)
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder{
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder register Rule_t* a;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register Rule_t* s;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder register Rule_t* t;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett if (r->must)
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder {
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder s = staterule(RULE, r, NiL, 0);
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder for (; p; p = p->next)
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett {
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett if ((a = p->rule)->dynamic & D_alias)
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett a = makerule(a->name);
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett if ((a->dynamic & D_same) && (!s || !(t = staterule(RULE, a, NiL, 0)) || s->event >= t->event))
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett r->must--;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (!r->must)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (error_info.trace || state.explain)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder error(state.explain ? 0 : -1, "cancelling %s action", r->name);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder r->status = EXISTS;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder r->dynamic |= D_same;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder r->dynamic &= ~D_triggered;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (t = staterule(PREREQS, r, NiL, 0))
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder t->time = CURTIME;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder return 1;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett return 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder}
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett/*
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * all actions on behalf of job are done
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * with the possible exception of after prereqs
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * clear!=0 to clear job queue
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * 0 returned if further blocking required
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder */
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reillystatic int
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblettdone(register Joblist_t* job, int clear, Cojob_t* cojob)
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett{
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett register List_t* p;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett register Rule_t* a;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett Time_t tm;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett int n;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett int semaphore;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Rule_t* jammed;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Rule_t* waiting;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett if (clear && jobs.triggered && (((a = jobs.triggered)->property & P_state) || (a = staterule(RULE, a, NiL, 0))) && (a->property & P_force))
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder {
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder a->time = 0;
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder state.savestate = 1;
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly }
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett another:
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett jobstatus();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (job->status == INTERMEDIATE)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.intermediate--;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder else if (!clear && job->status == RUNNING && (job->target->dynamic & D_hasafter) && hasafter(job->target, (job->flags & CO_ERRORS) ? P_failure : P_after))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder job->status = BEFORE;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder for (p = job->target->prereqs; p; p = p->next)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if ((a = p->rule)->dynamic & D_alias)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder a = makerule(a->name);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (a->status == MAKING && !a->semaphore || !(a->property & P_make) && a->status == UPDATE)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder return 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder after:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#if __GNUC__ == 3 && ( sparc || _sparc || __sparc ) && !_HUH_2008_10_25 /* gcc code generation bug -- first hit on solaris -- not sure if for all gcc 3.* */
#ifndef __GNUC_MINOR__
#define __GNUC_MINOR__ 0
#endif
#ifndef __GNUC_PATCHLEVEL__
#define __GNUC_PATCHLEVEL__ 1
#endif
if (!jobs.firstjob)
{
static int warned = 0;
if (!warned)
{
warned = 1;
error(state.mam.regress || state.regress ? -1 : 1, "command.c:%d: gcc %d.%d.%d code generation bug workaround -- pass this on to the vendor", __LINE__, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
}
return !clear;
}
#endif
push(job);
n = makeafter(job->target, (job->flags & CO_ERRORS) ? P_failure : P_after);
pop(job);
if (n)
job->flags |= CO_ERRORS;
else
{
job->flags &= ~CO_ERRORS;
for (p = job->prereqs; p; p = p->next)
{
if ((a = p->rule)->dynamic & D_alias)
a = makerule(a->name);
if (!a->semaphore && a->status == MAKING)
{
job->status = AFTER;
return !state.coshell || cojobs(state.coshell) < state.jobs;
}
}
}
}
/*
* update rule times and status
*/
if (job->target->status != TOUCH)
job->target->status = (job->flags & CO_ERRORS) ? ((job->target->property & P_dontcare) ? IGNORE : FAILED) : EXISTS;
tm = statetime(job->target, 0);
if (n = cojob && (state.mam.dynamic || state.mam.regress) && state.user && !(job->target->property & (P_after|P_before|P_dontcare|P_make|P_state|P_virtual)))
sfprintf(state.mam.out, "%scode %s %d %s %s%s%s\n", state.mam.label, (job->target != state.frame->target || (job->target->property & P_after)) ? mamname(job->target) : "-", EXIT_CODE(cojob->status), timefmt(NiL, tm), timefmt(NiL, CURTIME), (job->target->dynamic & D_same) ? " same" : null, cojob->status && (job->flags & CO_IGNORE) ? " ignore" : null);
if ((job->target->property & (P_joint|P_target)) == (P_joint|P_target))
for (p = job->target->prereqs->rule->prereqs; p; p = p->next)
if (p->rule != job->target)
{
if (p->rule->status != TOUCH)
p->rule->status = (job->flags & CO_ERRORS) ? ((p->rule->property & P_dontcare) ? IGNORE : FAILED) : EXISTS;
tm = statetime(p->rule, 0);
if (n)
sfprintf(state.mam.out, "%scode %s %d %s%s%s\n", state.mam.label, mamname(p->rule), EXIT_CODE(cojob->status), timefmt(NiL, tm), (p->rule->dynamic & D_same) ? " same" : null, cojob->status && (job->flags & CO_IGNORE) ? " ignore" : null);
}
/*
* update the job list
*/
discard(job);
again:
jammed = 0;
if (job = jobs.firstjob)
for (;;)
{
switch (job->status)
{
case AFTER:
case BEFORE:
case BLOCKED:
case READY:
n = READY;
semaphore = 1;
waiting = 0;
for (p = job->prereqs; p; p = p->next)
{
if ((a = p->rule)->dynamic & D_alias)
a = makerule(a->name);
if ((a->property & P_after) && job->status != BEFORE && job->status != AFTER)
continue;
switch (a->status)
{
case FAILED:
if (a->property & P_repeat)
continue;
job->flags |= CO_ERRORS;
goto another;
case MAKING:
if (!jammed && (a->mark & M_waiting) && !(a->property & P_archive))
{
waiting = a;
continue;
}
waiting = 0;
n = BLOCKED;
if (!a->semaphore)
semaphore = 0;
break;
default:
continue;
}
break;
}
if (waiting)
jammed = waiting;
else if (!clear && job->status == AFTER)
{
if (n == READY || semaphore)
goto another;
}
else if (!clear && job->status == BEFORE)
{
if (n == READY || semaphore)
goto after;
}
else if ((job->status = n) == READY)
{
unjam:
if (clear || cancel(job->target, job->prereqs))
goto another;
if ((job->target->dynamic & D_intermediate) && job->target->must == 1)
{
job->status = INTERMEDIATE;
jobs.intermediate++;
}
else if ((job->target->dynamic & (D_hasbefore|D_triggered)) == (D_hasbefore|D_triggered))
{
push(job);
n = makebefore(job->target);
pop(job);
if (n)
{
job->flags |= CO_ERRORS;
goto another;
}
}
else if (!state.coshell || cojobs(state.coshell) < state.jobs)
{
execute(job);
goto again;
}
}
break;
case RUNNING:
if (clear && job->cojob && (job->cojob->flags & CO_SERVICE))
{
job->status = FAILED;
job->flags |= CO_ERRORS;
cokill(state.coshell, job->cojob, 0);
}
break;
}
if (!(job = job->next))
{
/*
* jammed is the first discovered member
* of a possible deadlock and we arbitrarily
* break it here
*/
if (jammed)
{
if (error_info.trace || state.explain)
error(state.explain ? 0 : -1, "breaking possible job deadlock at %s", jammed->name);
for (job = jobs.firstjob; job; job = job->next)
#if __GNUC__ >= 4 && !_HUH_2006_01_11 /* gcc code generation bug -- first hit on macos -- not sure if for all gcc 4.* */
#ifndef __GNUC_MINOR__
#define __GNUC_MINOR__ 0
#endif
#ifndef __GNUC_PATCHLEVEL__
#define __GNUC_PATCHLEVEL__ 1
#endif
if (!job)
{
static int warned = 0;
if (!warned)
{
warned = 1;
error(state.mam.regress || state.regress ? -1 : 1, "command.c:%d: gcc %d.%d.%d code generation bug workaround -- pass this on to the vendor", __LINE__, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
}
break;
}
else
#endif
if (job->target == jammed)
{
if (job->status == AFTER)
goto another;
if (job->status != RUNNING)
{
jammed = 0;
job->status = READY;
state.jobs++;
goto unjam;
}
}
}
break;
}
}
return !clear;
}
/*
* block until one job completes
* update the job list
* clear job list on any unexpected action error
*/
int
block(int check)
{
register Cojob_t* cojob;
register Joblist_t* job;
Rule_t* r;
int n;
int clear = 0;
int resume = 0;
if (!state.coshell || !copending(state.coshell))
{
if (jobs.intermediate)
{
/*
* mark the jobs that must be generated
*/
n = 0;
for (job = jobs.firstjob; job; job = job->next)
if (job->target->must > ((unsigned int)(job->target->dynamic & D_intermediate) != 0))
{
n = 1;
break;
}
if (n)
{
/*
* some intermediates must be generated
*/
error(2, "some intermediates must be generated");
}
else
{
/*
* accept missing intermediates
*/
while (job = jobs.firstjob)
{
if (error_info.trace || state.explain)
error(state.explain ? 0 : -1, "cancelling %s action -- %s", job->target->name, job->status == INTERMEDIATE ? "intermediate not needed" : "missing intermediates accepted");
job->target->status = EXISTS;
discard(job);
}
jobs.intermediate = 0;
return 1;
}
}
return 0;
}
for (;;)
{
state.waiting = 1;
if ((cojob = cowait(state.coshell, check ? (Cojob_t*)state.coshell : (Cojob_t*)0, -1)) && (job = (Joblist_t*)cojob->local))
job->cojob = 0;
if (trap())
{
if (state.interpreter)
clear = resume = 1;
if (!cojob)
continue;
}
state.waiting = 0;
if (!cojob)
{
if (check)
return 0;
break;
}
if (r = getrule(external.jobdone))
{
if (!jobs.tmp)
jobs.tmp = sfstropen();
sfprintf(jobs.tmp, "%s %d %s %s", job->target->name, cojob->status, fmtelapsed(cojob->user, CO_QUANT), fmtelapsed(cojob->sys, CO_QUANT));
call(r, sfstruse(jobs.tmp));
}
if (cojob->status)
{
if (n = !EXITED_TERM(cojob->status) || EXIT_CODE(cojob->status))
{
if ((job->target->dynamic & D_hasafter) && hasafter(job->target, P_failure))
n = 0;
error(n ? 2 : state.explain ? 0 : -1, "%s%s code %d making %s%s", n ? "*** " : null, ERROR_translate(NiL, NiL, NiL, EXITED_TERM(cojob->status) ? "termination" : "exit"), EXIT_CODE(cojob->status), job->target->name, (job->flags & CO_IGNORE) ? ERROR_translate(NiL, NiL, NiL, " ignored") : null);
}
if (!(job->flags & CO_IGNORE))
{
job->flags |= CO_ERRORS;
if (state.keepgoing || !n)
{
if (n)
state.errors++;
job->flags |= CO_KEEPGOING;
}
}
if (state.interrupt || !(job->flags & (CO_IGNORE|CO_KEEPGOING)))
clear = 1;
}
message((-3, "job: %s: interrupt=%d clear=%d status=%d flags=%08x", job->target->name, state.interrupt, clear, cojob->status, job->flags));
/*
* job is done
*/
if (done(job, clear, cojob))
return 1;
}
if (resume)
longjmp(state.resume.label, 1);
if (!state.finish)
{
if (!copending(state.coshell))
{
if (clear)
finish(1);
}
else if (!state.interrupt)
error(3, "lost contact with coshell");
}
return 0;
}
/*
* wait until all actions for r and/or the rules in list p have completed
* r==0 and p==0 waits for all actions
* the number of FAILED actions is returned
*/
int
complete(register Rule_t* r, register List_t* p, Time_t* tm, Flags_t flags)
{
register int errors = 0;
int check = 0;
int recent;
List_t tmp;
List_t* q;
Time_t tprereqs;
if (r)
{
tmp.next = p;
p = &tmp;
p->rule = r;
}
else
{
if (p && streq(p->rule->name, "-"))
{
p = p->next;
check = 1;
}
if (!p)
{
while (block(check));
return 0;
}
}
for (tprereqs = 0; p; p = p->next)
{
if ((r = p->rule)->dynamic & D_alias)
r = makerule(r->name);
if (recent = r->status == MAKING)
{
message((-1, "waiting for %s%s", r->semaphore ? "semaphore " : null, r->name));
r->mark |= M_waiting;
do
{
if (!block(check))
{
if (recent = r->status == MAKING)
{
r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
error(1, "%s did not complete", r->name);
}
break;
}
} while (r->status == MAKING);
r->mark &= ~M_waiting;
}
if (r->status == UPDATE && !(r->property & P_make) && !(flags & P_implicit))
r->status = EXISTS;
if (recent && (r->property & (P_joint|P_target)) == (P_joint|P_target))
{
register Rule_t* x;
register Rule_t* s;
s = staterule(RULE, r, NiL, 1);
for (q = r->prereqs->rule->prereqs; q; q = q->next)
if ((x = q->rule) != r)
{
if (x->status != r->status)
{
x->status = r->status;
x->time = r->time;
}
if (s && (x = staterule(RULE, x, NiL, 1)))
{
x->dynamic |= D_built;
x->action = s->action;
x->prereqs = s->prereqs;
}
}
}
if (r->status == FAILED)
errors++;
if (!(r->property & (P_after|P_before|P_ignore)) && r->time > tprereqs)
tprereqs = r->time;
}
if (tm)
*tm = tprereqs;
return errors;
}
/*
* terminate all jobs
*/
void
terminate(void)
{
if (state.coshell && cokill(state.coshell, NiL, SIGTERM))
error(2, "coshell job kill error");
}
/*
* complete all jobs and drop the coshell
*/
void
drop(void)
{
if (state.coshell)
{
while (block(0));
message((-1, "jobs %d user %s sys %s", state.coshell->total, fmtelapsed(state.coshell->user, CO_QUANT), fmtelapsed(state.coshell->sys, CO_QUANT)));
coclose(state.coshell);
state.coshell = 0;
}
}
/*
* trigger action to build r
* a contains the action attributes
*
* NOTE: the prereqs cons() may not be freed
*/
void
trigger(register Rule_t* r, Rule_t* a, char* action, Flags_t flags)
{
register Joblist_t* job;
register List_t* p;
List_t* prereqs;
int n;
/*
* update flags
*/
if (!a)
a = r;
if (state.exec && !state.touch || (a->property & P_always) && (!state.never || (flags & CO_URGENT)))
flags |= CO_ALWAYS;
if ((a->property | r->property) & P_local)
flags |= CO_LOCAL;
if (!state.jobs || (r->property & P_foreground) || (r->property & (P_make|P_functional)) == P_functional || (r->dynamic & D_hasmake))
flags |= CO_FOREGROUND|CO_LOCAL;
if (state.keepgoing || state.unwind)
flags |= CO_KEEPGOING;
if (state.silent)
flags |= CO_SILENT;
if (state.ignore)
flags |= CO_IGNORE;
if (r->property & (P_functional|P_read))
flags |= CO_DATAFILE;
if (action)
{
message((-1, "triggering %s action%s%s", r->name, r == a ? null : " using ", r == a ? null : a->name));
if (state.exec)
jobs.triggered = r;
r->dynamic |= D_triggered;
if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
for (p = r->prereqs->rule->prereqs; p; p = p->next)
p->rule->dynamic |= D_triggered;
if (!*action)
action = 0;
}
if (state.coshell && (action && !(r->property & P_make) || (flags & CO_FOREGROUND)))
{
/*
* the make thread blocks when too many jobs are outstanding
*/
n = (flags & CO_FOREGROUND) ? 0 : (state.jobs - 1);
while ((cozombie(state.coshell) || cojobs(state.coshell) > n) && block(0));
}
prereqs = r->prereqs;
if (r->active && r->active->primary)
{
prereqs = cons(getrule(r->active->primary), prereqs);
flags |= CO_PRIMARY;
}
if (r->property & P_make)
{
if (r->property & P_local)
{
r->status = EXISTS;
return;
}
/*
* make actions are done immediately, bypassing the job queue
*/
if (prereqs && complete(NiL, prereqs, NiL, 0))
r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
else
{
if (action && cancel(r, prereqs))
r->status = EXISTS;
else if ((r->dynamic & (D_hasbefore|D_triggered)) == (D_hasbefore|D_triggered) && (makebefore(r) || complete(NiL, prereqs, NiL, 0)))
r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
else
{
if (r->property & P_functional)
setvar(r->name, null, 0);
if (action)
switch (parse(NiL, action, r->name, NiL))
{
case EXISTS:
if (!(r->property & (P_state|P_virtual)))
statetime(r, 0);
break;
case FAILED:
r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
break;
case TOUCH:
r->time = internal.internal->time;
break;
case UPDATE:
if ((r->property & (P_state|P_virtual)) != (P_state|P_virtual))
r->time = CURTIME;
break;
}
if (r->status == UPDATE)
r->status = EXISTS;
}
}
if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
for (p = r->prereqs->rule->prereqs; p; p = p->next)
if (p->rule != r)
{
p->rule->status = r->status;
p->rule->time = r->time;
}
if ((r->dynamic & (D_hasafter|D_triggered)) == (D_hasafter|D_triggered))
{
if (r->status == FAILED)
{
if (hasafter(r, P_failure) && !makeafter(r, P_failure) && !complete(NiL, prereqs, NiL, 0))
r->status = EXISTS;
}
else if (hasafter(r, P_after) && (makeafter(r, P_after) || complete(NiL, prereqs, NiL, 0)))
r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
}
}
else
{
/*
* only one repeat action at a time
*/
if ((r->property & P_repeat) && (r->property & (P_before|P_after)) && !(r->dynamic & D_hassemaphore))
{
a = catrule(internal.semaphore->name, ".", r->name, 1);
a->semaphore = 2;
r->prereqs = append(r->prereqs, cons(a, NiL));
r->dynamic |= D_hassemaphore;
}
/*
* check if any prerequisites are blocking execution
* FAILED prerequisites cause the target to fail too
*/
n = READY;
for (;;)
{
for (p = prereqs; p; p = p->next)
{
if ((a = p->rule)->dynamic & D_alias)
a = makerule(a->name);
if (a->property & P_after)
continue;
switch (a->status)
{
case FAILED:
if (a->property & P_repeat)
continue;
r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
for (p = r->prereqs->rule->prereqs; p; p = p->next)
if (p->rule != r)
p->rule->status = (p->rule->property & P_dontcare) ? IGNORE : FAILED;
return;
case MAKING:
if (a->active)
error(1, "%s: prerequisite %s is active", r->name, a->name);
else
n = BLOCKED;
break;
}
}
if (n != READY)
break;
if (action)
{
if (cancel(r, prereqs))
return;
if ((r->dynamic & D_intermediate) && r->must == 1)
{
n = INTERMEDIATE;
jobs.intermediate++;
break;
}
}
if ((r->dynamic & (D_hasbefore|D_triggered)) != (D_hasbefore|D_triggered))
break;
if (makebefore(r))
{
r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
for (p = r->prereqs->rule->prereqs; p; p = p->next)
if (p->rule != r)
p->rule->status = (p->rule->property & P_dontcare) ? IGNORE : FAILED;
return;
}
}
if (action || n != READY)
{
/*
* allocate a job cell and add to job list
* the first READY job from the top is executed next
*/
if (job = jobs.freejob)
jobs.freejob = jobs.freejob->next;
else
job = newof(0, Joblist_t, 1, 0);
if (flags & CO_URGENT)
{
job->prev = 0;
if (job->next = jobs.firstjob)
jobs.firstjob->prev = job;
else
jobs.lastjob = job;
jobs.firstjob = job;
}
else
{
job->next = 0;
if (job->prev = jobs.lastjob)
jobs.lastjob->next = job;
else
jobs.firstjob = job;
jobs.lastjob = job;
}
/*
* fill in the info
*/
job->target = r;
job->prereqs = prereqs;
job->status = n;
job->flags = flags;
job->action = action;
r->status = MAKING;
if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
for (p = r->prereqs->rule->prereqs; p; p = p->next)
if (p->rule != r)
p->rule->status = r->status;
if (n == READY)
{
execute(job);
if (r->dynamic & D_hasafter)
save(job);
}
else
save(job);
jobstatus();
}
else
{
if (r->status == UPDATE)
r->status = EXISTS;
if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
for (p = r->prereqs->rule->prereqs; p; p = p->next)
if (p->rule->status == UPDATE)
p->rule->status = EXISTS;
if ((r->dynamic & (D_hasafter|D_triggered)) == (D_hasafter|D_triggered))
{
if (r->status == FAILED)
{
if (hasafter(r, P_failure) && !makeafter(r, P_failure) && !complete(NiL, prereqs, NiL, 0))
r->status = EXISTS;
}
else if (hasafter(r, P_after) && (makeafter(r, P_after) || complete(NiL, prereqs, NiL, 0)))
r->status = (r->property & P_dontcare) ? IGNORE : FAILED;
if (r->status == EXISTS)
{
char* t;
Sfio_t* tmp;
tmp = sfstropen();
edit(tmp, r->name, KEEP, DELETE, DELETE);
if (*(t = sfstruse(tmp)))
newfile(r, t, r->time);
sfstrclose(tmp);
}
}
}
if (r->dynamic & D_triggered)
{
r->time = CURTIME;
if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
for (p = r->prereqs->rule->prereqs; p; p = p->next)
p->rule->time = r->time;
}
}
}
/*
* resolve any cached info on file opened on fd
*/
int
resolve(char* file, int fd, int mode)
{
return state.coshell ? cosync(state.coshell, file, fd, mode) : 0;
}
#if DEBUG
/*
* dump the job table
*/
void
dumpjobs(int level, int op)
{
register Joblist_t* job;
register List_t* p;
register Rule_t* a;
int indent;
int line;
if (state.coshell && error_info.trace <= level)
{
indent = error_info.indent;
error_info.indent = 0;
line = error_info.line;
error_info.line = 0;
switch (op)
{
case JOB_blocked:
for (job = jobs.firstjob; job; job = job->next)
if (job->status == BLOCKED)
{
sfprintf(sfstderr, "%8s %s :", statusname[job->status & STATUS], job->target->name);
for (p = job->prereqs; p; p = p->next)
{
if ((a = p->rule)->dynamic & D_alias)
a = makerule(a->name);
if ((a->property & P_after) && job->status != BEFORE && job->status != AFTER)
continue;
if (a->status == MAKING)
sfprintf(sfstderr, " %s", a->name);
}
sfprintf(sfstderr, "\n");
}
else if (job->status == READY)
sfprintf(sfstderr, "%8s %s\n", statusname[job->status & STATUS], job->target->name);
break;
case JOB_status:
sfprintf(sfstderr, "JOB STATUS TARGET tot=%d pend=%d done=%d\n", state.coshell->total, copending(state.coshell), cozombie(state.coshell));
for (job = jobs.firstjob; job; job = job->next)
{
if (job->cojob)
sfsprintf(tmpname, MAXNAME, "[%d]%s", job->cojob->id, job->cojob->id > 99 ? null : job->cojob->id > 9 ? " " : " ");
else
sfsprintf(tmpname, MAXNAME, "[-] ");
sfprintf(sfstderr, "%s %-13s%s\t%s%s%s\n"
, tmpname
, job->status == RUNNING && !job->cojob ? "DONE" : statusname[job->status & STATUS]
, job->target->name
, (job->target->must > ((unsigned int)(job->target->dynamic & D_intermediate) != 0)) ? " [must]" : null
, job->context ? null : " [popped]"
, (job->target->mark & M_waiting) ? " [waiting]" : null
);
}
break;
default:
error(1, "%d: unknown op index", op);
break;
}
error_info.indent = indent;
error_info.line = line;
}
}
#endif