Compare commits

..

2 Commits

Author SHA1 Message Date
Paul Smith
75f879f37f * Fix backslash-escape in targets.
* Release 3.78.91.
2000-02-09 19:57:15 +00:00
Paul Smith
e68a27ec7b * Fix some warnings in gettext.c and function.c
* Don't try to execute tests which are actually directories.
2000-02-09 07:02:18 +00:00
14 changed files with 324 additions and 419 deletions

147
ChangeLog
View File

@@ -1,128 +1,22 @@
2000-03-13 Tim Magill <magill@gate.net>
2000-02-09 Paul D. Smith <psmith@gnu.org>
* remake.c:
(update_file_1):
(check_dep): fixed problem with double colon rules and circular
precursor detection.
* Version 3.78.91 released.
2000-03-12 Tim Magill <magill@gate.net>
* remake.c (update_goal_chain): re-arranged logic so that it makes
more sense. After update_file(), the target status is used to
handle the goal and possibly remove it from the goal chain.
* remake.c (update_file_1): simplified handling of files with no
command into a single block.
* remake.c (notice_finished_file): fixed obsolete comment.
* remake.c (update_file): If -q we can bail as soon as we detect
that something needs to be remade.
2000-03-11 Tim Magill <magill@gate.net>
* remake.c
(update_file): If not -k, we can bail when a failure is detected.
If we don't, its possible that dependecies of double_colon rules
will get built after a failure has been detected.
(update_goal_chain): removed unused updating_makefiles
(update_file_1): cleaned up post remake_file() handling
2000-02-29 Tim Magill <magill@gate.net>
* remake.c (update_goal_chain): eliminated double colon loop.
update_file() handles the double colon logic, so
update_goal_chain() doesn't have to.
* remake.c (update_file):
(update_file_1): Moved consedered test to update_file_1() so
update_file() can more easily return a target_state_t which
represents the state of the entire double colon rule.
2000-02-20 Tim Magill <magill@gate.net>
* remake.c (check_dep):
(update_file_1):
(update_goal_chain):
(check_dep): Changed return value of target updating functions to
be enum target_state_t. This allows each caller to know the state
of the target being processed after each call. Thus,
update_goal_chain() can know from the return value of
update_file() whether or not a target has completed and can be
removed from the goal chain.
* remake.c (update_goal_chain): removed variable
ocommands_started, it was essentially unused.
2000-02-12 Tim Magill <magill@gate.net>
* remake.c (update_file_1):
(notice_finished_file):
(remake_file):
* main.c (main):
* job.c (reap_children):
(start_job_command):
* file.c (enter_file)
(remove_intermediates):
(print_file):
* filedef.h: converted update_status field from a short int, to an
unsigned int :1. previously, update status indicated whether the
file had actually executed any commands, won, lost, or lost under
-q conditions. command_state indicates more clearly whether or
not any commands have been executed for this file. lost or lost
under -q conditions can be determined by a combination of
question_flag and lost. Thus, update_status needs only indicate
won or lost.
* implicit.c (try_implicit_rule):
* remake.c (check_dep):
* remake.c (update_file_1):
move setting of tried_implicit into try_implicit_rule(). It is
only called in two places and the flag is set immediately after.
* remake.c (update_file_1): collapsed if statement based on
file->command_state into switch statment which immediately
follows. Removed code that could not be reached.
* remake.c (update_file): advance f pointer so as not to consider
same file twice after breaking loop.
* file.c (rehash_file): replaced hard coded check_renamed loop
with standard macro. seemed like the right thing to do.
2000-02-09 Tim Magill <magill@gate.net>
Started branch for cleaning up internal make structure regarding
recursion paths. Branch name is filedef-cleanup and was started
from a point on the mainline at filedef-cleanup-base. either tags
are suitable for cvs commands.
* file.c, filedef.h, main.c, remake.c (updated): Removed updated
member from 'struct filedef'. filedef->command_state fully
contains the same information and more.
2000-02-07 Paul D. Smith <psmith@gnu.org>
* read.c (read_makefile): Reset *p2 to ':', not *colonp. If any
filenames contained backslashes the resulting output (without
backslashes) will be shorter, so setting *colonp doesn't change
the right character. Fix for PR/1586.
For += target-specific variables we need to remember which
variable set we found the variable in, so we can start looking
there in the next iteration (otherwise we'll see it again in
recursively_expand and fail!). This is getting to be a hack; if
it gets any worse we'll have to rethink this entire algorithm;
probably implementing expansion of these separately from the
"normal" expansion, instead of alongside.
from there in the next iteration (otherwise we might see it again
in recursively_expand and fail!). This is turning into a hack; if
it gets any worse we'll have to rethink this entire algorithm...
implementing expansion of these references separately from the
"normal" expansion, say, instead of using the same codepath.
Actually, it's already "worse enough" :-/.
* variable.h (recursively_expand_setlist): Rename
recursively_expand to add a struct variable_set_list argument, and
@@ -131,8 +25,7 @@
variable_set_list argument, and make a macro for lookup_variable.
* expand.c (recursively_expand_setlist): Take an extra struct
variable_set_list argument and pass it to
allocated_variable_append().
variable_set_list argument and pass it to allocated_variable_append().
(reference_variable): Use lookup_variable_setlist() and pass the
returned variable_set_list to recursively_expand_setlist.
(allocated_variable_append): Take an extra setlist argument and
@@ -140,7 +33,7 @@
expansion. If it's null, use current_variable_set_list as before.
* variable.c (lookup_variable_setlist): If the LISTP argument is
not nil, return the list where we found the variable in it.
not nil, set it to the list containing the variable we found.
2000-02-04 Paul D. Smith <psmith@gnu.org>
@@ -203,6 +96,16 @@
* default.c (default_variables) [__MSDOS__]: Define CXX to gpp.
2000-01-27 Paul D. Smith <psmith@gnu.org>
* gettext.c: Some warning cleanups, and a fix for systems which
don't define HAVE_ALLOCA (the workaround code was included
twice).
2000-01-26 Paul D. Smith <psmith@gnu.org>
* Version 3.78.90 released.
2000-01-25 Paul D. Smith <psmith@gnu.org>
Change gettext support to use the simplified version in libit 0.7.

View File

@@ -30,10 +30,18 @@ site. There is information there about ordering hardcopy documentation.
You can also find the latest versions of GNU Make from there.
You can send GNU make bug reports to bug-make@gnu.org. Please see the
You can send GNU make bug reports to <bug-make@gnu.org>. Please see the
section of the GNU make manual entitled `Problems and Bugs' for
information on submitting useful and complete bug reports.
You can also use the FSF's online bug tracking system to submit new
problem reports or search for existing ones. A web interface is
available here:
http://www-gnats.gnu.org:8080/cgi-bin/wwwgnats.pl
Use the Category "make".
If you need help using GNU make, try these forums:
help-make@gnu.org
@@ -46,6 +54,8 @@ Also:
- See README.customs for details on integrating GNU make with the
Customs distributed build environment from the Pmake distribution.
- See readme.vms for details about GNU Make on OpenVMS.
- See README.W32 for details about GNU Make on Windows NT, 95, or 98.
- See README.Amiga for details about GNU Make on AmigaDOS.

27
file.c
View File

@@ -166,7 +166,7 @@ enter_file (name)
new = (struct file *) xmalloc (sizeof (struct file));
bzero ((char *) new, sizeof (struct file));
new->name = new->hname = name;
new->update_status = 0; /* assume the file won */
new->update_status = -1;
if (f == 0)
{
@@ -199,7 +199,8 @@ rehash_file (file, name)
register unsigned int oldhash;
register char *n;
check_renamed(file);
while (file->renamed != 0)
file = file->renamed;
/* Find the hash values of the old and new names. */
@@ -360,6 +361,7 @@ in favor of those for `%s'."),
MERGE (precious);
MERGE (tried_implicit);
MERGE (updating);
MERGE (updated);
MERGE (is_target);
MERGE (cmd_target);
MERGE (phony);
@@ -395,7 +397,7 @@ remove_intermediates (sig)
&& !f->secondary)
{
int status;
if (f->command_state == cs_not_started)
if (f->update_status == -1)
/* If nothing would have created this file yet,
don't print an "rm" command for it. */
continue;
@@ -657,7 +659,7 @@ print_file (f)
file_timestamp_sprintf (buf, f->last_mtime);
printf (_("# Last modified %s\n"), buf);
}
puts ((f->command_state == cs_finished)
puts (f->updated
? _("# File has been updated.") : _("# File has not been updated."));
switch (f->command_state)
{
@@ -668,19 +670,26 @@ print_file (f)
puts (_("# Dependencies commands running (THIS IS A BUG)."));
break;
case cs_not_started:
break;
case cs_finished:
switch (f->update_status)
{
case -1:
break;
case 0:
/* file won */
puts (_("# Successfully updated."));
break;
case 1:
/* file lost */
puts (question_flag ? _("# Needs to be updated (-q is set).")
:_("# Failed to be updated."));
assert (question_flag);
puts (_("# Needs to be updated (-q is set)."));
break;
case 2:
puts (_("# Failed to be updated."));
break;
default:
puts (_("# Invalid value in `update_status' member!"));
fflush (stdout);
fflush (stderr);
abort ();
}
break;
default:

View File

@@ -60,6 +60,9 @@ struct file
the same file. Otherwise this is null. */
struct file *double_colon;
short int update_status; /* Status of the last attempt to update,
or -1 if none has been made. */
enum /* State of the commands. */
{ /* Note: It is important that cs_not_started be zero. */
cs_not_started, /* Not yet started. */
@@ -68,15 +71,12 @@ struct file
cs_finished /* Commands finished. */
} command_state ENUM_BITFIELD (2);
unsigned int update_status:1; /* update status signifies only
whether the file won or lost */
unsigned int precious:1; /* Non-0 means don't delete file on quit */
unsigned int tried_implicit:1; /* Nonzero if have searched
for implicit rule for making
this file; don't search again. */
unsigned int updating:1; /* Nonzero while updating deps of this file */
unsigned int updated:1; /* Nonzero if this file has been remade. */
unsigned int is_target:1; /* Nonzero if file is described as target. */
unsigned int cmd_target:1; /* Nonzero if file was given on cmd line. */
unsigned int phony:1; /* Nonzero if this is a phony file

View File

@@ -492,9 +492,9 @@ func_notdir_suffix(o, argv, funcname)
char *list_iterator = argv[0];
char *p2 =0;
int doneany =0;
int len=0;
unsigned int len=0;
int is_suffix = streq(funcname, "suffix");
int is_suffix = streq (funcname, "suffix");
int is_notdir = !is_suffix;
while ((p2 = find_next_token (&list_iterator, &len)) != 0)
{
@@ -555,7 +555,7 @@ func_basename_dir(o, argv, funcname)
int doneany=0;
unsigned int len=0;
char *p=0;
int is_basename= streq(funcname, "basename");
int is_basename= streq (funcname, "basename");
int is_dir= !is_basename;
while ((p2 = find_next_token (&p3, &len)) != 0)
@@ -563,7 +563,7 @@ func_basename_dir(o, argv, funcname)
p = p2 + len;
while (p >= p2 && (!is_basename || *p != '.'))
{
if (IS_PATHSEP(*p))
if (IS_PATHSEP (*p))
break;
--p;
}

View File

@@ -563,7 +563,8 @@ _nl_explode_name (name, language, modifier, territory, codeset,
if (*codeset != cp && (*codeset)[0] != '\0')
{
*normalized_codeset = _nl_normalize_codeset (*codeset,
*normalized_codeset = _nl_normalize_codeset ((const unsigned
char *)*codeset,
cp - *codeset);
if (strcmp (*codeset, *normalized_codeset) == 0)
free ((char *) *normalized_codeset);
@@ -1220,13 +1221,13 @@ read_alias_file (fname, fname_len)
unsigned char *value;
unsigned char *cp;
if (fgets (buf, sizeof buf, fp) == NULL)
if (fgets ((char *)buf, sizeof buf, fp) == NULL)
/* EOF reached. */
break;
/* Possibly not the whole line fits into the buffer. Ignore
the rest of the line. */
if (strchr (buf, '\n') == NULL)
if (strchr ((char *)buf, '\n') == NULL)
{
char altbuf[BUFSIZ];
do
@@ -1279,8 +1280,8 @@ read_alias_file (fname, fname_len)
if (nmap >= maxmap)
extend_alias_table ();
alias_len = strlen (alias) + 1;
value_len = strlen (value) + 1;
alias_len = strlen ((char *)alias) + 1;
value_len = strlen ((char *)value) + 1;
if (string_space_act + alias_len + value_len > string_space_max)
{
@@ -1750,41 +1751,6 @@ static const char *guess_category_value PARAMS ((int category,
const char *categoryname))
internal_function;
/* For those loosing systems which don't have `alloca' we have to add
some additional code emulating it. */
#ifdef HAVE_ALLOCA
/* Nothing has to be done. */
# define ADD_BLOCK(list, address) /* nothing */
# define FREE_BLOCKS(list) /* nothing */
#else
struct block_list
{
void *address;
struct block_list *next;
};
# define ADD_BLOCK(list, addr) \
do { \
struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
/* If we cannot get a free block we cannot add the new element to \
the list. */ \
if (newp != NULL) { \
newp->address = (addr); \
newp->next = (list); \
(list) = newp; \
} \
} while (0)
# define FREE_BLOCKS(list) \
do { \
while (list != NULL) { \
struct block_list *old = list; \
list = list->next; \
free (old); \
} \
} while (0)
# undef alloca
# define alloca(size) (malloc (size))
#endif /* have alloca */
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __

View File

@@ -37,7 +37,6 @@ try_implicit_rule (file, depth)
struct file *file;
unsigned int depth;
{
int ret = 0;
DBF (DB_IMPLICIT, _("Looking for an implicit rule for `%s'.\n"));
/* The order of these searches was previously reversed. My logic now is
@@ -46,24 +45,21 @@ try_implicit_rule (file, depth)
should come first. */
if (pattern_search (file, 0, depth, 0))
ret = 1;
return 1;
#ifndef NO_ARCHIVES
/* If this is an archive member reference, use just the
archive member name to search for implicit rules. */
else if (ar_name (file->name))
if (ar_name (file->name))
{
DBF (DB_IMPLICIT,
_("Looking for archive-member implicit rule for `%s'.\n"));
if (pattern_search (file, 1, depth, 0))
{
ret = 1;
}
return 1;
}
#endif
file->tried_implicit = 1;
return ret;
return 0;
}

6
job.c
View File

@@ -665,7 +665,7 @@ reap_children (block, err)
delete non-precious targets, and abort. */
static int delete_on_error = -1;
child_error (c->file->name, exit_code, exit_sig, coredump, 0);
c->file->update_status = 1;
c->file->update_status = 2;
if (delete_on_error == -1)
{
struct file *f = lookup_file (".DELETE_ON_ERROR");
@@ -693,7 +693,7 @@ reap_children (block, err)
Since there are more commands that wanted to be run,
the target was not completely remade. So we treat
this as if a command had failed. */
c->file->update_status = 1;
c->file->update_status = 2;
}
else
{
@@ -1250,7 +1250,7 @@ start_job_command (child)
return;
error:
child->file->update_status = 1;
child->file->update_status = 2;
notice_finished_file (child->file);
return;
}

25
main.c
View File

@@ -1254,6 +1254,7 @@ int main (int argc, char ** argv)
/* Make sure the temporary file will not be remade. */
stdin_nm = savestring (name, sizeof (name) -1);
f = enter_file (stdin_nm);
f->updated = 1;
f->update_status = 0;
f->command_state = cs_finished;
/* Can't be intermediate, or it'll be removed too early for
@@ -1517,6 +1518,7 @@ int main (int argc, char ** argv)
{
f = enter_command_line_file (*p);
f->last_mtime = f->mtime_before_update = (FILE_TIMESTAMP) 1;
f->updated = 1;
f->update_status = 0;
f->command_state = cs_finished;
}
@@ -1604,11 +1606,17 @@ int main (int argc, char ** argv)
switch (update_goal_chain (read_makefiles, 1))
{
case 1:
default:
#define BOGUS_UPDATE_STATUS 0
assert (BOGUS_UPDATE_STATUS);
break;
case -1:
/* Did nothing. */
break;
case 1:
case 2:
/* Failed to update. Figure out if we care. */
{
/* Nonzero if any makefile was successfully remade. */
@@ -1625,7 +1633,7 @@ int main (int argc, char ** argv)
again to print an error. */
d->file->considered = 0;
if (d->file->command_state == cs_finished)
if (d->file->updated)
{
/* This makefile was updated. */
if (d->file->update_status == 0)
@@ -1828,19 +1836,18 @@ int main (int argc, char ** argv)
{
case -1:
/* Nothing happened. */
/* FALL THRU */
case 0:
/* Updated successfully. */
status = EXIT_SUCCESS;
break;
case 2:
/* Updating failed. POSIX.2 specifies exit status >1 for this;
but in VMS, there is only success and failure. */
status = EXIT_FAILURE ? 2 : EXIT_FAILURE;
break;
case 1:
if (question_flag)
/* We are under -q and would run some commands. */
status = EXIT_FAILURE;
else
/* Updating failed. POSIX.2 specifies exit status >1 for this;
but in VMS, there is only success and failure. */
status = EXIT_FAILURE ? 2 : EXIT_FAILURE;
status = EXIT_FAILURE;
break;
default:
abort ();

2
read.c
View File

@@ -879,7 +879,7 @@ read_makefile (filename, flags)
sizeof (struct nameseq),
1),
sizeof (struct nameseq));
*colonp = ':';
*p2 = ':';
if (!filenames)
{

410
remake.c
View File

@@ -43,39 +43,12 @@ Boston, MA 02111-1307, USA. */
extern int try_implicit_rule PARAMS ((struct file *file, unsigned int depth));
/* this enum encapsulates the return status of the recursive update
functions. Note: these values are important so that the state of
precursors can be or'ed together */
typedef enum {
ts_done = 0, /* all precursors and target are complete */
ts_incomplete = 1, /* some precursor or target is still running */
ts_failed = 3, /* some precursor or target failed */
ts_sentinal /* make ANSI happy with non trailing , */
} target_state_t;
/* the test for circular dependencies is based just on the 'updating'
bit in 'struct file'. However double colon targets have seperate
'struct file's. Therefore, we will lose if we don't notice that a
double colon targets are really the same file. Use the 'struct
file' at the base of the double colon chain. */
#define set_updating(file) (((file)->double_colon ? \
(file)->double_colon : (file))->updating = 1)
#define clr_updating(file) (((file)->double_colon ? \
(file)->double_colon : (file))->updating = 0)
#define tst_updating(file) (((file)->double_colon ? \
(file)->double_colon : (file))->updating)
/* Incremented when a command is started (under -n, when one would be). */
unsigned int commands_started = 0;
static target_state_t update_file PARAMS ((struct file *file, unsigned int depth));
static target_state_t update_file_1 PARAMS ((struct file *file, unsigned int depth));
static target_state_t check_dep PARAMS ((struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr));
static int update_file PARAMS ((struct file *file, unsigned int depth));
static int update_file_1 PARAMS ((struct file *file, unsigned int depth));
static int check_dep PARAMS ((struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr));
static int touch_file PARAMS ((struct file *file));
static void remake_file PARAMS ((struct file *file));
static FILE_TIMESTAMP name_mtime PARAMS ((char *name));
@@ -89,7 +62,6 @@ static int library_search PARAMS ((char **lib, FILE_TIMESTAMP *mtime_ptr));
should only make one goal at a time and return as soon as one goal whose
`changed' member is nonzero is successfully made. */
int
update_goal_chain (goals, makefiles)
register struct dep *goals;
@@ -99,6 +71,8 @@ update_goal_chain (goals, makefiles)
unsigned int j = job_slots;
int status = -1;
#define MTIME(file) (makefiles ? file_mtime_no_search (file) \
: file_mtime (file))
/* Duplicate the chain so we can remove things from it. */
@@ -138,73 +112,103 @@ update_goal_chain (goals, makefiles)
{
/* Iterate over all double-colon entries for this file. */
struct file *file;
target_state_t target_state;
int stop = 0, any_not_updated = 0;
target_state = ts_done;
file = g->file;
check_renamed (file);
if (makefiles)
for (file = g->file->double_colon ? g->file->double_colon : g->file;
file != NULL;
file = file->prev)
{
if (file->cmd_target)
unsigned int ocommands_started;
int x;
check_renamed (file);
if (makefiles)
{
touch_flag = t;
question_flag = q;
just_print_flag = n;
if (file->cmd_target)
{
touch_flag = t;
question_flag = q;
just_print_flag = n;
}
else
touch_flag = question_flag = just_print_flag = 0;
}
else
touch_flag = question_flag = just_print_flag = 0;
/* Save the old value of `commands_started' so we can compare
later. It will be incremented when any commands are
actually run. */
ocommands_started = commands_started;
x = update_file (file, makefiles ? 1 : 0);
check_renamed (file);
/* Set the goal's `changed' flag if any commands were started
by calling update_file above. We check this flag below to
decide when to give an "up to date" diagnostic. */
g->changed += commands_started - ocommands_started;
/* If we updated a file and STATUS was not already 1, set it to
1 if updating failed, or to 0 if updating succeeded. Leave
STATUS as it is if no updating was done. */
stop = 0;
if ((x != 0 || file->updated) && status < 1)
{
if (file->update_status != 0)
{
/* Updating failed, or -q triggered. The STATUS value
tells our caller which. */
status = file->update_status;
/* If -q just triggered, stop immediately. It doesn't
matter how much more we run, since we already know
the answer to return. */
stop = (!keep_going_flag && !question_flag
&& !makefiles);
}
else
{
FILE_TIMESTAMP mtime = MTIME (file);
check_renamed (file);
if (file->updated && g->changed &&
mtime != file->mtime_before_update)
{
/* Updating was done. If this is a makefile and
just_print_flag or question_flag is set (meaning
-n or -q was given and this file was specified
as a command-line target), don't change STATUS.
If STATUS is changed, we will get re-exec'd, and
enter an infinite loop. */
if (!makefiles
|| (!just_print_flag && !question_flag))
status = 0;
if (makefiles && file->dontcare)
/* This is a default makefile; stop remaking. */
stop = 1;
}
}
}
/* Keep track if any double-colon entry is not finished.
When they are all finished, the goal is finished. */
any_not_updated |= !file->updated;
if (stop)
break;
}
commands_started = 0;
/* Reset FILE since it is null at the end of the loop. */
file = g->file;
target_state = update_file (file, makefiles ? 1 : 0);
check_renamed (file);
/* Set the goal's `changed' flag if any commands were started
by calling update_file above. We check this flag below to
decide when to give an "up to date" diagnostic. */
g->changed |= commands_started ? 1 : 0;
/* process the file according to its return */
switch (target_state)
if (stop || !any_not_updated)
{
case ts_failed:
/* Bail early? */
if (!keep_going_flag && !question_flag && !makefiles)
return 1;
/* If we have found nothing whatever to do for the goal,
print a message saying nothing needs doing. */
status = 1; /* mark status failed, keep going */
/* -k, Fall Though !!! */
case ts_done:
{
FILE_TIMESTAMP mtime =
(makefiles ? file_mtime_no_search (file) : file_mtime (file));
check_renamed (file);
if (g->changed && mtime != file->mtime_before_update)
{
/* Updating was done. If this is a makefile and
just_print_flag or question_flag is set (meaning
-n or -q was given and this file was specified
as a command-line target), don't change STATUS.
If STATUS is changed, we will get re-exec'd, and
enter an infinite loop. */
if (status < 0)
{
if (!makefiles || (!just_print_flag && !question_flag))
status = 0;
}
}
}
if (!makefiles
/* If the update_status is zero, we updated successfully
or not at all. G->changed will have been set above if
any commands were actually started for this goal. */
&& !file->update_status && !g->changed
&& file->update_status == 0 && !g->changed
/* Never give a message under -s or -q. */
&& !silent_flag && !question_flag)
message (1, ((file->phony || file->cmds == 0)
@@ -212,27 +216,24 @@ update_goal_chain (goals, makefiles)
: _("`%s' is up to date.")),
file->name);
case ts_incomplete:
break; /* do nothing */
}
/* advance to next target in goal chain */
if (target_state == ts_incomplete)
{
lastgoal = g;
g = g->next;
}
else
{
/* This goal is finished. Remove it from the chain. */
if (lastgoal == 0)
goals = g->next;
else
lastgoal->next = g->next;
free (g);
/* Free the storage. */
free ((char *) g);
g = lastgoal == 0 ? goals : lastgoal->next;
if (stop)
break;
}
else
{
lastgoal = g;
g = g->next;
}
}
@@ -252,10 +253,9 @@ update_goal_chain (goals, makefiles)
return status;
}
/* If FILE is not up to date, execute the commands for it. Return
ts_done if FILE has completed successfully, ts_incomplete if FILE
or any of its precursors are incomplete, or ts_failed if FILE or
any of its precursors failed.
/* If FILE is not up to date, execute the commands for it.
Return 0 if successful, 1 if unsuccessful;
but with some flag settings, just call `exit' if unsuccessful.
DEPTH is the depth in recursions of this function.
We increment it during the consideration of our dependencies,
@@ -265,32 +265,36 @@ update_goal_chain (goals, makefiles)
If there are multiple double-colon entries for FILE,
each is considered in turn. */
static target_state_t
static int
update_file (file, depth)
struct file *file;
unsigned int depth;
{
register target_state_t status = ts_done;
register int status = 0;
register struct file *f;
f = file->double_colon ? file->double_colon : file;
/* Prune the dependency graph: if we've already been here on _this_
pass through the dependency graph, we don't have to go any further.
We won't reap_children until we start the next pass, so no state
change is possible below here until then. */
if (f->considered == considered)
{
DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
return 0;
}
/* This loop runs until we start commands for a double colon rule, or until
the chain is exhausted. */
for (; f != 0; f = f->prev)
{
f->considered = considered;
status |= update_file_1 (f, depth);
check_renamed (f);
if (status == ts_failed)
{
if (!keep_going_flag || question_flag)
return ts_failed;
else
break;
}
if (status == ts_incomplete)
if (status != 0 && !keep_going_flag)
break;
if (f->command_state == cs_running
@@ -298,88 +302,65 @@ update_file (file, depth)
{
/* Don't run the other :: rules for this
file until this rule is finished. */
status = ts_incomplete;
status = 0;
break;
}
}
/* Process the remaining rules in the double colon chain so they're marked
considered. Start their prerequisites, too. */
for (f = (f ? f->prev : 0); f != 0 ; f = f->prev)
for (; f != 0 ; f = f->prev)
{
struct dep *d;
f->considered = considered;
for (d = f->deps; d != 0; d = d->next)
if ((status |= update_file (d->file, depth + 1)) == ts_failed)
{
if (!keep_going_flag || question_flag)
return ts_failed;
}
status |= update_file (d->file, depth + 1);
}
return status;
}
/* Consider a single `struct file' and update it as appropriate.
/* Consider a single `struct file' and update it as appropriate. */
Return ts_done if FILE has completed successfully, ts_incomplete if
FILE or any of its precursors are incomplete, or ts_failed if FILE
or any of its precursors failed.
*/
static target_state_t
static int
update_file_1 (file, depth)
struct file *file;
unsigned int depth;
{
register FILE_TIMESTAMP this_mtime;
int noexist, must_make, deps_changed;
target_state_t dep_status = ts_done;
int dep_status = 0;
register struct dep *d, *lastd;
int running = 0;
/* Prune the dependency graph: if we've already been here on _this_
pass through the dependency graph, we don't have to go any further.
We won't reap_children until we start the next pass, so no state
change is possible below here until then. */
if (file->considered == considered)
{
DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
if (file->command_state == cs_finished)
{
return file->update_status ? ts_failed : ts_done;
}
return ts_incomplete;
}
file->considered = considered;
DBF (DB_VERBOSE, _("Considering target file `%s'.\n"));
if (file->updated)
{
if (file->update_status > 0)
{
DBF (DB_VERBOSE,
_("Recently tried and failed to update file `%s'.\n"));
return file->update_status;
}
DBF (DB_VERBOSE, _("File `%s' was considered already.\n"));
return 0;
}
switch (file->command_state)
{
case cs_not_started:
case cs_deps_running:
break;
case cs_running:
DBF (DB_VERBOSE, _("Still updating file `%s'.\n"));
return ts_incomplete;
return 0;
case cs_finished:
if (file->update_status != 0)
{
DBF (DB_VERBOSE,
_("Recently tried and failed to update file `%s'.\n"));
return ts_failed;
}
DBF (DB_VERBOSE, _("File `%s' was considered already.\n"));
return ts_done;
DBF (DB_VERBOSE, _("Finished updating file `%s'.\n"));
return file->update_status;
default:
abort ();
}
@@ -387,7 +368,7 @@ update_file_1 (file, depth)
++depth;
/* Notice recursive update of the same file. */
set_updating(file);
file->updating = 1;
/* Looking at the file's modtime beforehand allows the possibility
that its name may be changed by a VPATH search, and thus it may
@@ -397,30 +378,28 @@ update_file_1 (file, depth)
this_mtime = file_mtime (file);
check_renamed (file);
must_make = noexist = this_mtime == (FILE_TIMESTAMP) -1;
noexist = this_mtime == (FILE_TIMESTAMP) -1;
if (noexist)
DBF (DB_BASIC, _("File `%s' does not exist.\n"));
must_make = noexist;
/* If file was specified as a target with no commands,
come up with some default commands. */
if (file->cmds == 0)
if (!file->phony && file->cmds == 0 && !file->tried_implicit)
{
if (!file->phony && !file->tried_implicit)
{
if (try_implicit_rule (file, depth))
DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
else
DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
}
if (!file->is_target
&& default_file != 0 && default_file->cmds != 0)
{
DBF (DB_IMPLICIT, _("Using default commands for `%s'.\n"));
file->cmds = default_file->cmds;
}
if (try_implicit_rule (file, depth))
DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
else
DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
file->tried_implicit = 1;
}
if (file->cmds == 0 && !file->is_target
&& default_file != 0 && default_file->cmds != 0)
{
DBF (DB_IMPLICIT, _("Using default commands for `%s'.\n"));
file->cmds = default_file->cmds;
}
/* Update all non-intermediate files we depend on, if necessary,
@@ -437,7 +416,7 @@ update_file_1 (file, depth)
mtime = file_mtime (d->file);
check_renamed (d->file);
if (tst_updating(d->file))
if (d->file->updating)
{
error (NILF, _("Circular %s <- %s dependency dropped."),
file->name, d->file->name);
@@ -469,7 +448,7 @@ update_file_1 (file, depth)
while (f != 0);
}
if (dep_status == ts_failed && !keep_going_flag)
if (dep_status != 0 && !keep_going_flag)
break;
if (!running)
@@ -506,7 +485,7 @@ update_file_1 (file, depth)
while (f != 0);
}
if (dep_status == ts_failed && !keep_going_flag)
if (dep_status != 0 && !keep_going_flag)
break;
if (!running)
@@ -515,7 +494,7 @@ update_file_1 (file, depth)
}
}
clr_updating(file);
file->updating = 0;
DBF (DB_VERBOSE, _("Finished prerequisites of target file `%s'.\n"));
@@ -524,14 +503,14 @@ update_file_1 (file, depth)
set_command_state (file, cs_deps_running);
--depth;
DBF (DB_VERBOSE, _("The prerequisites of `%s' are being made.\n"));
return ts_incomplete;
return 0;
}
/* If any dependency failed, give up now. */
if (dep_status == ts_failed)
if (dep_status != 0)
{
file->update_status = 1; /* if any precursors failed, so did we */
file->update_status = dep_status;
notice_finished_file (file);
depth--;
@@ -543,7 +522,7 @@ update_file_1 (file, depth)
error (NILF,
_("Target `%s' not remade because of errors."), file->name);
return ts_failed;
return dep_status;
}
if (file->command_state == cs_deps_running)
@@ -648,7 +627,7 @@ update_file_1 (file, depth)
file = file->prev;
}
return ts_done;
return 0;
}
DBF (DB_BASIC, _("Must remake target `%s'.\n"));
@@ -667,24 +646,32 @@ update_file_1 (file, depth)
if (file->command_state != cs_finished)
{
DBF (DB_VERBOSE, _("Commands of `%s' are being run.\n"));
return ts_incomplete;
return 0;
}
if (file->update_status)
{
DBF (DB_BASIC, (question_flag ? _("Target file `%s' needs remade under -q.\n")
: _("Failed to remake target file `%s'.\n")));
return ts_failed;
}
else
switch (file->update_status)
{
case 2:
DBF (DB_BASIC, _("Failed to remake target file `%s'.\n"));
break;
case 0:
DBF (DB_BASIC, _("Successfully remade target file `%s'.\n"));
return ts_done;
break;
case 1:
DBF (DB_BASIC, _("Target file `%s' needs remade under -q.\n"));
break;
default:
assert (file->update_status >= 0 && file->update_status <= 2);
break;
}
file->updated = 1;
return file->update_status;
}
/* re-check FILE's mtime and the mtime's of all files listed in its
`also_make' member. Under -t, this function also touches FILE.
/* Set FILE's `updated' flag and re-check its mtime and the mtime's of all
files listed in its `also_make' member. Under -t, this function also
touches FILE.
On return, FILE->update_status will no longer be -1 if it was. */
@@ -696,6 +683,7 @@ notice_finished_file (file)
int ran = file->command_state == cs_running;
file->command_state = cs_finished;
file->updated = 1;
if (touch_flag
/* The update status will be:
@@ -722,7 +710,7 @@ notice_finished_file (file)
file->update_status = 0;
else
/* Should set file's modification date and do nothing else. */
file->update_status = touch_file (file) ? 1 : 0;
file->update_status = touch_file (file);
}
}
@@ -758,7 +746,7 @@ notice_finished_file (file)
f->last_mtime = file->last_mtime;
}
if (ran)
if (ran && file->update_status != -1)
/* We actually tried to update FILE, which has
updated its also_make's as well (if it worked).
If it didn't work, it wouldn't work again for them.
@@ -766,6 +754,7 @@ notice_finished_file (file)
for (d = file->also_make; d != 0; d = d->next)
{
d->file->command_state = cs_finished;
d->file->updated = 1;
d->file->update_status = file->update_status;
if (ran && !d->file->phony)
@@ -775,6 +764,10 @@ notice_finished_file (file)
never be done because the target is already updated. */
(void) f_mtime (d->file, 0);
}
else if (file->update_status == -1)
/* Nothing was done for FILE, but it needed nothing done.
So mark it now as "succeeded". */
file->update_status = 0;
}
/* Check whether another file (whose mtime is THIS_MTIME)
@@ -782,13 +775,9 @@ notice_finished_file (file)
If it does, store 1 in *MUST_MAKE_PTR.
In the process, update any non-intermediate files
that FILE depends on (including FILE itself).
Return nonzero if any updating failed. */
Return ts_done if FILE has completed successfully, ts_incomplete if
FILE or any of its precursors are incomplete, or ts_failed if FILE
or any of its precursors failed.
*/
static target_state_t
static int
check_dep (file, depth, this_mtime, must_make_ptr)
struct file *file;
unsigned int depth;
@@ -796,10 +785,10 @@ check_dep (file, depth, this_mtime, must_make_ptr)
int *must_make_ptr;
{
register struct dep *d;
target_state_t dep_status = ts_done;
int dep_status = 0;
++depth;
set_updating(file);
file->updating = 1;
if (!file->intermediate)
/* If this is a non-intermediate file, update it and record
@@ -824,6 +813,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
else
DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
file->tried_implicit = 1;
}
if (file->cmds == 0 && !file->is_target
&& default_file != 0 && default_file->cmds != 0)
@@ -850,7 +840,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
d = file->deps;
while (d != 0)
{
if (tst_updating(d->file))
if (d->file->updating)
{
error (NILF, _("Circular %s <- %s dependency dropped."),
file->name, d->file->name);
@@ -873,7 +863,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
dep_status |= check_dep (d->file, depth, this_mtime,
must_make_ptr);
check_renamed (d->file);
if (dep_status == ts_failed && !keep_going_flag)
if (dep_status != 0 && !keep_going_flag)
break;
if (d->file->command_state == cs_running
@@ -889,7 +879,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
}
}
clr_updating(file);
file->updating = 0;
return dep_status;
}
@@ -990,7 +980,7 @@ remake_file (file)
error (NILF, msg_parent, "*** ",
file->name, file->parent->name, ".");
}
file->update_status = 1;
file->update_status = 2;
}
}
else
@@ -1143,7 +1133,7 @@ f_mtime (file, search)
static FILE_TIMESTAMP now = 0;
if (!clock_skew_detected
&& mtime != (FILE_TIMESTAMP)-1 && mtime > now
&& !(file->command_state == cs_finished))
&& !file->updated)
{
/* This file's time appears to be in the future.
Update our concept of the present, and compare again. */

View File

@@ -1,11 +1,17 @@
2000-02-07 Paul D. Smith <psmith@gnu.org>
* scripts/features/escape: Add a test for backslash-escaped spaces
in a target name (PR/1586).
2000-02-04 Paul D. Smith <psmith@gnu.org>
* scripts/features/patspecific_vars: Add a test for PR/1407.
* scripts/features/patspecific_vars: Add a test for pattern-specific
target variables inherited from the parent target (PR/1407).
2000-02-02 Paul D. Smith <psmith@gnu.org>
* run_make_tests.pl (set_more_defaults): Hard-code the LANG to C
to make sure porting order, etc. is predictable.
to make sure sorting order, etc. is predictable.
Reported by Andreas Jaeger <aj@suse.de>.
* run_make_tests.pl (set_more_defaults): Set the $wtime variable
@@ -17,6 +23,11 @@
* scripts/targets/SECONDARY: Ditto.
* scripts/targets/INTERMEDIATE: Ditto.
2000-01-27 Paul D. Smith <psmith@gnu.org>
* test_driver.pl (toplevel): Don't try to run test scripts which
are really directories.
2000-01-23 Paul D. Smith <psmith@gnu.org>
* scripts/features/include: Remove a check; the fix caused more
@@ -27,7 +38,7 @@
* scripts/functions/call: Add a test for PR/1517 and PR/1527: make
sure $(call ...) doesn't eval its arguments and that you can
invoke foreach from it without infinitely looping.
invoke foreach from it without looping forever.
1999-12-15 Paul D. Smith <psmith@gnu.org>

View File

@@ -1,11 +1,17 @@
# -*-perl-*-
$description = "Test various types of escaping in makefiles.";
$details = "Make sure that escaping of `:' works in target names.";
$details = "\
Make sure that escaping of `:' works in target names.
Also make sure escaping of whitespace works in target names";
open(MAKEFILE,"> $makefile");
print MAKEFILE '$(path)foo : ; @echo cp $^ $@
';
print MAKEFILE <<'EOF';
$(path)foo : ; @echo cp $^ $@
foo\ bar: ; @echo 'touch "$@"'
EOF
close(MAKEFILE);
@@ -34,5 +40,11 @@ $answer = "cp p:foo\n";
$answer = "$makefile:1: *** target pattern contains no `%'. Stop.\n";
&compare_output($answer,&get_logfile(1));
# TEST 5: This one should work
&run_make_with_options($makefile, "'foo bar'", &get_logfile, 0);
$answer = "touch \"foo bar\"\n";
&compare_output($answer,&get_logfile(1));
# This tells the test driver that the perl test script executed properly.
1;

View File

@@ -117,7 +117,8 @@ sub toplevel
closedir (SCRIPTDIR);
foreach $dir (@dirs)
{
next if ! -d "$scriptpath/$dir" || $dir =~ /^\.\.?$/ || $dir eq 'CVS';
next if ($dir =~ /^\.\.?$/ || $dir eq 'CVS' || $dir eq 'RCS'
|| ! -d "$scriptpath/$dir");
push (@rmdirs, $dir);
mkdir ("$workpath/$dir", 0777)
|| &error ("Couldn't mkdir $workpath/$dir: $!\n");
@@ -127,7 +128,7 @@ sub toplevel
closedir (SCRIPTDIR);
foreach $test (@files)
{
next if $test =~ /^\.\.?$/ || $test =~ /~$/ || $test eq 'CVS';
next if $test =~ /~$/ || -d $test;
push (@TESTS, "$dir/$test");
}
}