version 1.106, 2012/10/02 10:29:31 |
version 1.107, 2012/10/09 19:45:34 |
|
|
|
|
static const char *parse_do_targets(Lst, unsigned int *, const char *); |
static const char *parse_do_targets(Lst, unsigned int *, const char *); |
static void parse_target_line(struct growableArray *, const char *, |
static void parse_target_line(struct growableArray *, const char *, |
const char *); |
const char *, bool *); |
|
|
static void finish_commands(struct growableArray *); |
static void finish_commands(struct growableArray *); |
static void parse_commands(struct growableArray *, const char *); |
static void parse_commands(struct growableArray *, const char *); |
|
|
} specials[] = { |
} specials[] = { |
{ P(NODE_EXEC), SPECIAL_EXEC | SPECIAL_TARGETSOURCE, OP_EXEC, }, |
{ P(NODE_EXEC), SPECIAL_EXEC | SPECIAL_TARGETSOURCE, OP_EXEC, }, |
{ P(NODE_IGNORE), SPECIAL_IGNORE | SPECIAL_TARGETSOURCE, OP_IGNORE, }, |
{ P(NODE_IGNORE), SPECIAL_IGNORE | SPECIAL_TARGETSOURCE, OP_IGNORE, }, |
{ P(NODE_INCLUDES), SPECIAL_DEPRECATED | SPECIAL_TARGET, 0, }, |
{ P(NODE_INCLUDES), SPECIAL_NOTHING | SPECIAL_TARGET, 0, }, |
{ P(NODE_INVISIBLE),SPECIAL_INVISIBLE | SPECIAL_TARGETSOURCE,OP_INVISIBLE, }, |
{ P(NODE_INVISIBLE),SPECIAL_INVISIBLE | SPECIAL_TARGETSOURCE,OP_INVISIBLE, }, |
{ P(NODE_JOIN), SPECIAL_JOIN | SPECIAL_TARGETSOURCE, OP_JOIN, }, |
{ P(NODE_JOIN), SPECIAL_JOIN | SPECIAL_TARGETSOURCE, OP_JOIN, }, |
{ P(NODE_LIBS), SPECIAL_DEPRECATED | SPECIAL_TARGET, 0, }, |
{ P(NODE_LIBS), SPECIAL_NOTHING | SPECIAL_TARGET, 0, }, |
{ P(NODE_MADE), SPECIAL_MADE | SPECIAL_TARGETSOURCE, OP_MADE, }, |
{ P(NODE_MADE), SPECIAL_MADE | SPECIAL_TARGETSOURCE, OP_MADE, }, |
{ P(NODE_MAIN), SPECIAL_MAIN | SPECIAL_TARGET, 0, }, |
{ P(NODE_MAIN), SPECIAL_MAIN | SPECIAL_TARGET, 0, }, |
{ P(NODE_MAKE), SPECIAL_MAKE | SPECIAL_TARGETSOURCE, OP_MAKE, }, |
{ P(NODE_MAKE), SPECIAL_MAKE | SPECIAL_TARGETSOURCE, OP_MAKE, }, |
|
|
{ P(NODE_NOTMAIN), SPECIAL_NOTMAIN | SPECIAL_TARGETSOURCE, OP_NOTMAIN, }, |
{ P(NODE_NOTMAIN), SPECIAL_NOTMAIN | SPECIAL_TARGETSOURCE, OP_NOTMAIN, }, |
{ P(NODE_NOTPARALLEL),SPECIAL_NOTPARALLEL | SPECIAL_TARGET, 0, }, |
{ P(NODE_NOTPARALLEL),SPECIAL_NOTPARALLEL | SPECIAL_TARGET, 0, }, |
{ P(NODE_NO_PARALLEL),SPECIAL_NOTPARALLEL | SPECIAL_TARGET, 0, }, |
{ P(NODE_NO_PARALLEL),SPECIAL_NOTPARALLEL | SPECIAL_TARGET, 0, }, |
{ P(NODE_NULL), SPECIAL_DEPRECATED | SPECIAL_TARGET, 0, }, |
{ P(NODE_NULL), SPECIAL_NOTHING | SPECIAL_TARGET, 0, }, |
{ P(NODE_OPTIONAL), SPECIAL_OPTIONAL | SPECIAL_TARGETSOURCE,OP_OPTIONAL, }, |
{ P(NODE_OPTIONAL), SPECIAL_OPTIONAL | SPECIAL_TARGETSOURCE,OP_OPTIONAL, }, |
{ P(NODE_ORDER), SPECIAL_ORDER | SPECIAL_TARGET, 0, }, |
{ P(NODE_ORDER), SPECIAL_ORDER | SPECIAL_TARGET, 0, }, |
{ P(NODE_PARALLEL), SPECIAL_PARALLEL | SPECIAL_TARGET, 0, }, |
{ P(NODE_PARALLEL), SPECIAL_PARALLEL | SPECIAL_TARGET, 0, }, |
|
|
{ P(NODE_PRECIOUS), SPECIAL_PRECIOUS | SPECIAL_TARGETSOURCE,OP_PRECIOUS, }, |
{ P(NODE_PRECIOUS), SPECIAL_PRECIOUS | SPECIAL_TARGETSOURCE,OP_PRECIOUS, }, |
{ P(NODE_RECURSIVE),SPECIAL_MAKE | SPECIAL_TARGETSOURCE, OP_MAKE, }, |
{ P(NODE_RECURSIVE),SPECIAL_MAKE | SPECIAL_TARGETSOURCE, OP_MAKE, }, |
{ P(NODE_SILENT), SPECIAL_SILENT | SPECIAL_TARGETSOURCE, OP_SILENT, }, |
{ P(NODE_SILENT), SPECIAL_SILENT | SPECIAL_TARGETSOURCE, OP_SILENT, }, |
{ P(NODE_SINGLESHELL),SPECIAL_SINGLESHELL | SPECIAL_TARGET, 0, }, |
{ P(NODE_SINGLESHELL),SPECIAL_NOTHING | SPECIAL_TARGET, 0, }, |
{ P(NODE_SUFFIXES), SPECIAL_SUFFIXES | SPECIAL_TARGET, 0, }, |
{ P(NODE_SUFFIXES), SPECIAL_SUFFIXES | SPECIAL_TARGET, 0, }, |
{ P(NODE_USE), SPECIAL_USE | SPECIAL_TARGETSOURCE, OP_USE, }, |
{ P(NODE_USE), SPECIAL_USE | SPECIAL_TARGETSOURCE, OP_USE, }, |
{ P(NODE_WAIT), SPECIAL_WAIT | SPECIAL_TARGETSOURCE, 0 }, |
{ P(NODE_WAIT), SPECIAL_WAIT | SPECIAL_TARGETSOURCE, 0 }, |
{ P(NODE_CHEAP), SPECIAL_CHEAP | SPECIAL_TARGETSOURCE, OP_CHEAP, }, |
{ P(NODE_CHEAP), SPECIAL_CHEAP | SPECIAL_TARGETSOURCE, OP_CHEAP, }, |
{ P(NODE_EXPENSIVE),SPECIAL_EXPENSIVE | SPECIAL_TARGETSOURCE,OP_EXPENSIVE, }, |
{ P(NODE_EXPENSIVE),SPECIAL_EXPENSIVE | SPECIAL_TARGETSOURCE,OP_EXPENSIVE, }, |
#if 0 |
{ P(NODE_POSIX), SPECIAL_NOTHING | SPECIAL_TARGET, 0 }, |
{ P(NODE_NOPATH), SPECIAL_NOPATH, }, |
{ P(NODE_SCCS_GET), SPECIAL_NOTHING | SPECIAL_TARGET, 0 }, |
#endif |
|
}; |
}; |
|
|
#undef P |
#undef P |
|
|
extern int maxJobs; |
extern int maxJobs; |
|
|
maxJobs = 1; |
maxJobs = 1; |
break; |
|
} |
|
case SPECIAL_SINGLESHELL: |
|
compatMake = 1; |
compatMake = 1; |
break; |
break; |
|
} |
case SPECIAL_ORDER: |
case SPECIAL_ORDER: |
predecessor = NULL; |
predecessor = NULL; |
break; |
break; |
|
|
break; |
break; |
} |
} |
} else if (specType == SPECIAL_MFLAGS) { |
} else if (specType == SPECIAL_MFLAGS) { |
/*Call on functions in main.c to deal with these arguments */ |
/* Call on functions in main.c to deal with these arguments */ |
Main_ParseArgLine(line); |
Main_ParseArgLine(line); |
return; |
return; |
} else if (specType == SPECIAL_NOTPARALLEL || |
} else if (specType == SPECIAL_NOTPARALLEL) { |
specType == SPECIAL_SINGLESHELL) { |
|
return; |
return; |
} |
} |
|
|
|
|
* NOW GO FOR THE SOURCES |
* NOW GO FOR THE SOURCES |
*/ |
*/ |
if (specType == SPECIAL_SUFFIXES || specType == SPECIAL_PATH || |
if (specType == SPECIAL_SUFFIXES || specType == SPECIAL_PATH || |
specType == SPECIAL_DEPRECATED) { |
specType == SPECIAL_NOTHING) { |
while (*line) { |
while (*line) { |
/* |
/* |
* If the target was one that doesn't take files as its |
* If the target was one that doesn't take files as its |
|
|
* ParseAddCmd -- |
* ParseAddCmd -- |
* Lst_ForEach function to add a command line to all targets |
* Lst_ForEach function to add a command line to all targets |
* |
* |
* Side Effects: |
* The new command may be added to the commands list of the node. |
* A new element is added to the commands list of the node. |
* |
|
* If the target already had commands, we ignore the new ones, but |
|
* we note that we got double commands (in case we actually get to run |
|
* that ambiguous target). |
|
* |
|
* Note this does not apply to :: dependency lines, since those |
|
* will generate fresh cloned nodes and add them to the cohorts |
|
* field of the main node. |
*/ |
*/ |
static void |
static void |
ParseAddCmd(void *gnp, void *cmd) |
ParseAddCmd(void *gnp, void *cmd) |
{ |
{ |
GNode *gn = (GNode *)gnp; |
GNode *gn = (GNode *)gnp; |
/* if target already supplied, ignore commands */ |
|
if (!(gn->type & OP_HAS_COMMANDS)) |
if (!(gn->type & OP_HAS_COMMANDS)) |
Lst_AtEnd(&gn->commands, cmd); |
Lst_AtEnd(&gn->commands, cmd); |
|
else |
|
gn->type |= OP_DOUBLE; |
} |
} |
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* ParseHasCommands -- |
* ParseHasCommands -- |
* Callback procedure for Parse_File when destroying the list of |
* Record that the target gained commands through OP_HAS_COMMANDS, |
* targets on the last dependency line. Marks a target as already |
* so that double command lists may be ignored. |
* having commands if it does, to keep from having shell commands |
|
* on multiple dependency lines. |
|
* |
|
* Side Effects: |
|
* OP_HAS_COMMANDS may be set for the target. |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
static void |
static void |
ParseHasCommands(void *gnp) /* Node to examine */ |
ParseHasCommands(void *gnp) |
{ |
{ |
GNode *gn = (GNode *)gnp; |
GNode *gn = (GNode *)gnp; |
if (!Lst_IsEmpty(&gn->commands)) |
gn->type |= OP_HAS_COMMANDS; |
gn->type |= OP_HAS_COMMANDS; |
|
} |
} |
|
|
|
|
|
|
***/ |
***/ |
|
|
static void |
static void |
|
build_target_group(struct growableArray *targets) |
|
{ |
|
unsigned int i; |
|
LstNode ln; |
|
bool seen_target = false; |
|
|
|
if (targets->n == 1) |
|
return; |
|
if (targets->a[0]->groupling != NULL) |
|
return; |
|
/* XXX */ |
|
if (targets->a[0]->type & OP_TRANSFORM) |
|
return; |
|
for (ln = Lst_First(&targets->a[0]->commands); ln != NULL; |
|
ln = Lst_Adv(ln)) { |
|
struct command *cmd = Lst_Datum(ln); |
|
if (Var_Check_for_target(cmd->string)) { |
|
seen_target = true; |
|
break; |
|
} |
|
} |
|
if (DEBUG(TARGGROUP)) { |
|
fprintf(stderr, |
|
seen_target ? "No target group at %lu: ": |
|
"Target group at %lu:", Parse_Getlineno()); |
|
for (i = 0; i < targets->n; i++) |
|
fprintf(stderr, " %s", targets->a[i]->name); |
|
fprintf(stderr, "\n"); |
|
} |
|
if (seen_target) |
|
return; |
|
|
|
for (i = 0; i < targets->n; i++) { |
|
targets->a[i]->groupling = targets->a[(i+1)%targets->n]; |
|
} |
|
} |
|
|
|
static void |
finish_commands(struct growableArray *targets) |
finish_commands(struct growableArray *targets) |
{ |
{ |
|
build_target_group(targets); |
Array_Every(targets, ParseHasCommands); |
Array_Every(targets, ParseHasCommands); |
Array_Reset(targets); |
|
} |
} |
|
|
static void |
static void |
|
|
memcpy(&cmd->string, line, len+1); |
memcpy(&cmd->string, line, len+1); |
Parse_FillLocation(&cmd->location); |
Parse_FillLocation(&cmd->location); |
|
|
|
|
Array_ForEach(targets, ParseAddCmd, cmd); |
Array_ForEach(targets, ParseAddCmd, cmd); |
} |
} |
|
|
|
|
|
|
static void |
static void |
parse_target_line(struct growableArray *targets, const char *line, |
parse_target_line(struct growableArray *targets, const char *line, |
const char *stripped) |
const char *stripped, bool *pcommands_seen) |
{ |
{ |
size_t pos; |
size_t pos; |
char *end; |
char *end; |
|
|
do { |
do { |
cmd++; |
cmd++; |
} while (isspace(*cmd)); |
} while (isspace(*cmd)); |
if (*cmd != '\0') |
if (*cmd != '\0') { |
parse_commands(targets, cmd); |
parse_commands(targets, cmd); |
|
*pcommands_seen = true; |
|
} |
} |
} |
} |
} |
|
|
|
|
{ |
{ |
char *line; |
char *line; |
bool expectingCommands = false; |
bool expectingCommands = false; |
|
bool commands_seen = false; |
|
|
/* somewhat permanent spaces to shave time */ |
/* somewhat permanent spaces to shave time */ |
BUFFER buf; |
BUFFER buf; |
|
|
do { |
do { |
while ((line = Parse_ReadNormalLine(&buf)) != NULL) { |
while ((line = Parse_ReadNormalLine(&buf)) != NULL) { |
if (*line == '\t') { |
if (*line == '\t') { |
if (expectingCommands) |
if (expectingCommands) { |
|
commands_seen = true; |
parse_commands(>argets, line+1); |
parse_commands(>argets, line+1); |
else |
} else |
Parse_Error(PARSE_FATAL, |
Parse_Error(PARSE_FATAL, |
"Unassociated shell command \"%s\"", |
"Unassociated shell command \"%s\"", |
line); |
line); |
|
|
line); |
line); |
if (!parse_as_special_line(&buf, ©, |
if (!parse_as_special_line(&buf, ©, |
stripped)) { |
stripped)) { |
if (expectingCommands) |
if (commands_seen) |
finish_commands(>argets); |
finish_commands(>argets); |
|
commands_seen = false; |
|
Array_Reset(>argets); |
if (Parse_As_Var_Assignment(stripped)) |
if (Parse_As_Var_Assignment(stripped)) |
expectingCommands = false; |
expectingCommands = false; |
else { |
else { |
parse_target_line(>argets, |
parse_target_line(>argets, |
line, stripped); |
line, stripped, |
|
&commands_seen); |
expectingCommands = true; |
expectingCommands = true; |
} |
} |
} |
} |
|
|
} |
} |
} while (Parse_NextFile()); |
} while (Parse_NextFile()); |
|
|
if (expectingCommands) |
if (commands_seen) |
finish_commands(>argets); |
finish_commands(>argets); |
/* Make sure conditionals are clean. */ |
/* Make sure conditionals are clean. */ |
Cond_End(); |
Cond_End(); |