mirror of
https://github.com/mirror/make.git
synced 2025-03-27 20:40:35 +08:00
Implement SysV-style $$@ support. I looked at E.Parmelan's patch but
decided to implement this a different way, and didn't use it.
This commit is contained in:
parent
6c9a393f95
commit
4d72c4c11e
15
ChangeLog
15
ChangeLog
@ -1,3 +1,18 @@
|
|||||||
|
2002-07-10 Paul D. Smith <psmith@gnu.org>
|
||||||
|
|
||||||
|
Implement the SysV make syntax $$@, $$(@D), and $$(@F) in the
|
||||||
|
prerequisite list. A real SysV make will expand the entire
|
||||||
|
prerequisites list _twice_: we don't do that as it's a big
|
||||||
|
backward-compatibility problem. We only replace those specific
|
||||||
|
variables.
|
||||||
|
|
||||||
|
* read.c (record_files): Replace any $@, $(@D), and $(@F) variable
|
||||||
|
references left in the list of prerequisites. Check for .POSIX as
|
||||||
|
we record targets, so we can disable non-POSIX behavior while
|
||||||
|
reading makefiles as well as running them.
|
||||||
|
(eval): Check the prerequisite list to see if we have anything
|
||||||
|
that looks like a SysV prerequisite variable reference.
|
||||||
|
|
||||||
2002-07-09 Paul D. Smith <psmith@gnu.org>
|
2002-07-09 Paul D. Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* doc/make.texi (Prerequisite Types): Add a new section describing
|
* doc/make.texi (Prerequisite Types): Add a new section describing
|
||||||
|
11
NEWS
11
NEWS
@ -1,6 +1,6 @@
|
|||||||
GNU make NEWS -*-indented-text-*-
|
GNU make NEWS -*-indented-text-*-
|
||||||
History of user-visible changes.
|
History of user-visible changes.
|
||||||
06 July 2002
|
10 July 2002
|
||||||
|
|
||||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||||
See the end for copying conditions.
|
See the end for copying conditions.
|
||||||
@ -12,7 +12,7 @@ Please send GNU make bug reports to <bug-make@gnu.org>.
|
|||||||
See the README file and the GNU make manual for details on sending bug
|
See the README file and the GNU make manual for details on sending bug
|
||||||
reports.
|
reports.
|
||||||
|
|
||||||
Version <next>
|
Version 3.80
|
||||||
|
|
||||||
* A new feature exists: order-only prerequisites. These prerequisites
|
* A new feature exists: order-only prerequisites. These prerequisites
|
||||||
affect the order in which targets are built, but they do not impact
|
affect the order in which targets are built, but they do not impact
|
||||||
@ -21,6 +21,13 @@ Version <next>
|
|||||||
requiring that target A will always be rebuilt if target B is updated.
|
requiring that target A will always be rebuilt if target B is updated.
|
||||||
Patch for this feature provided by Greg McGary <greg@mcgary.org>.
|
Patch for this feature provided by Greg McGary <greg@mcgary.org>.
|
||||||
|
|
||||||
|
* For compatibility with SysV make, GNU make now supports the peculiar
|
||||||
|
syntax $$@, $$(@D), and $$(@F) in the prerequisites list of a rule.
|
||||||
|
This syntax is only valid within explicit and static pattern rules: it
|
||||||
|
cannot be used in implicit (suffix or pattern) rules. Edouard G. Parmelan
|
||||||
|
<egp@free.fr> provided a patch implementing this feature; however, I
|
||||||
|
decided to implemented it myself in a different way.
|
||||||
|
|
||||||
* A new function is defined: $(quote ...). The argument to this
|
* A new function is defined: $(quote ...). The argument to this
|
||||||
function is the _name_ of a variable. The result of the function is
|
function is the _name_ of a variable. The result of the function is
|
||||||
the value of the variable, without having been expanded.
|
the value of the variable, without having been expanded.
|
||||||
|
@ -8410,6 +8410,16 @@ part of the first prerequisite.
|
|||||||
Lists of the directory parts and the file-within-directory
|
Lists of the directory parts and the file-within-directory
|
||||||
parts of all prerequisites.
|
parts of all prerequisites.
|
||||||
|
|
||||||
|
@vindex $(+D)
|
||||||
|
@vindex +D @r{(automatic variable)}
|
||||||
|
@item $(+D)
|
||||||
|
@vindex $(+F)
|
||||||
|
@vindex +F @r{(automatic variable)}
|
||||||
|
@itemx $(+F)
|
||||||
|
Lists of the directory parts and the file-within-directory
|
||||||
|
parts of all prerequisites, including multiple instances of duplicated
|
||||||
|
prerequisites.
|
||||||
|
|
||||||
@vindex $(?D)
|
@vindex $(?D)
|
||||||
@vindex ?D @r{(automatic variable)}
|
@vindex ?D @r{(automatic variable)}
|
||||||
@item $(?D)
|
@item $(?D)
|
||||||
@ -8429,6 +8439,32 @@ deep significance; @samp{$<} refers to the variable named @code{<} just
|
|||||||
as @samp{$(CFLAGS)} refers to the variable named @code{CFLAGS}.
|
as @samp{$(CFLAGS)} refers to the variable named @code{CFLAGS}.
|
||||||
You could just as well use @samp{$(<)} in place of @samp{$<}.
|
You could just as well use @samp{$(<)} in place of @samp{$<}.
|
||||||
|
|
||||||
|
@vindex $$@@
|
||||||
|
@vindex $$(@@D)
|
||||||
|
@vindex $$(@@F)
|
||||||
|
@cindex $$@@, support for
|
||||||
|
GNU @code{make} provides support for the SysV @code{make} feature that
|
||||||
|
allows special variable references @code{$$@@}, @code{$$(@@D)}, and
|
||||||
|
@code{$$(@@F)} (note the required double-''$''!) to appear with the
|
||||||
|
@emph{prerequisites list} (normal automatic variables are available
|
||||||
|
only within a command script). When appearing in a prerequisites
|
||||||
|
list, these variables are expanded to the name of the target, the
|
||||||
|
directory component of the target, and the file component of the
|
||||||
|
target, respectively.
|
||||||
|
|
||||||
|
Note that these variables are available only within explicit and
|
||||||
|
static pattern (@pxref{Static Pattern, ,Static Pattern Rules}) rules;
|
||||||
|
they have no special significance within implicit (suffix or pattern)
|
||||||
|
rules. Also note that while SysV @code{make} actually expands its
|
||||||
|
entire prerequisite list @emph{twice}, GNU @code{make} does not behave
|
||||||
|
this way: instead it simply expands these special variables without
|
||||||
|
re-expanding any other part of the prerequisites list.
|
||||||
|
|
||||||
|
This somewhat bizarre feature is included only to provide some
|
||||||
|
compatibility with SysV makefiles. In a native GNU @code{make} file
|
||||||
|
there are other ways to accomplish the same results. This feature is
|
||||||
|
disabled if the special pseudo target @code{.POSIX} is defined.
|
||||||
|
|
||||||
@node Pattern Match, Match-Anything Rules, Automatic, Pattern Rules
|
@node Pattern Match, Match-Anything Rules, Automatic, Pattern Rules
|
||||||
@subsection How Patterns Match
|
@subsection How Patterns Match
|
||||||
|
|
||||||
@ -9322,29 +9358,6 @@ pattern rules for extraction from SCCS, in combination with the
|
|||||||
general feature of rule chaining.
|
general feature of rule chaining.
|
||||||
@xref{Chained Rules, ,Chains of Implicit Rules}.
|
@xref{Chained Rules, ,Chains of Implicit Rules}.
|
||||||
|
|
||||||
@item
|
|
||||||
In System V @code{make}, the string @samp{$$@@} has the strange meaning
|
|
||||||
that, in the prerequisites of a rule with multiple targets, it stands
|
|
||||||
for the particular target that is being processed.
|
|
||||||
|
|
||||||
This is not defined in GNU @code{make} because @samp{$$} should always
|
|
||||||
stand for an ordinary @samp{$}.
|
|
||||||
|
|
||||||
It is possible to get portions of this functionality through the use of
|
|
||||||
static pattern rules (@pxref{Static Pattern, ,Static Pattern Rules}).
|
|
||||||
The System V @code{make} rule:
|
|
||||||
|
|
||||||
@example
|
|
||||||
$(targets): $$@@.o lib.a
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
can be replaced with the GNU @code{make} static pattern rule:
|
|
||||||
|
|
||||||
@example
|
|
||||||
$(targets): %: %.o lib.a
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@item
|
@item
|
||||||
In System V and 4.3 BSD @code{make}, files found by @code{VPATH} search
|
In System V and 4.3 BSD @code{make}, files found by @code{VPATH} search
|
||||||
(@pxref{Directory Search, ,Searching Directories for Prerequisites}) have their names changed inside command
|
(@pxref{Directory Search, ,Searching Directories for Prerequisites}) have their names changed inside command
|
||||||
|
4
main.c
4
main.c
@ -2169,9 +2169,9 @@ print_usage (bad)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!remote_description || *remote_description == '\0')
|
if (!remote_description || *remote_description == '\0')
|
||||||
fprintf (usageto, _("\nBuilt for %s"), make_host);
|
fprintf (usageto, _("\nThis program built for %s"), make_host);
|
||||||
else
|
else
|
||||||
fprintf (usageto, "\nBuilt for %s (%s)", make_host, remote_description);
|
fprintf (usageto, "\nThis program built for %s (%s)", make_host, remote_description);
|
||||||
|
|
||||||
fprintf (usageto, _("\nReport bugs to <bug-make@gnu.org>\n"));
|
fprintf (usageto, _("\nReport bugs to <bug-make@gnu.org>\n"));
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
*.gmo *.mo *.pot
|
*.gmo *.mo *.pot *.po
|
||||||
|
|
||||||
Makefile.in Makefile
|
Makefile.in Makefile
|
||||||
|
POTFILES
|
||||||
|
129
read.c
129
read.c
@ -132,7 +132,8 @@ static int conditional_line PARAMS ((char *line, const struct floc *flocp));
|
|||||||
static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
|
static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
|
||||||
struct dep *deps, unsigned int cmds_started, char *commands,
|
struct dep *deps, unsigned int cmds_started, char *commands,
|
||||||
unsigned int commands_idx, int two_colon,
|
unsigned int commands_idx, int two_colon,
|
||||||
const struct floc *flocp, int set_default));
|
int have_sysv_atvar,
|
||||||
|
const struct floc *flocp, int set_default));
|
||||||
static void record_target_var PARAMS ((struct nameseq *filenames, char *defn,
|
static void record_target_var PARAMS ((struct nameseq *filenames, char *defn,
|
||||||
int two_colon,
|
int two_colon,
|
||||||
enum variable_origin origin,
|
enum variable_origin origin,
|
||||||
@ -430,6 +431,7 @@ eval (ebuf, set_default)
|
|||||||
unsigned int cmds_started, tgts_started;
|
unsigned int cmds_started, tgts_started;
|
||||||
int ignoring = 0, in_ignored_define = 0;
|
int ignoring = 0, in_ignored_define = 0;
|
||||||
int no_targets = 0; /* Set when reading a rule without targets. */
|
int no_targets = 0; /* Set when reading a rule without targets. */
|
||||||
|
int have_sysv_atvar = 0;
|
||||||
struct nameseq *filenames = 0;
|
struct nameseq *filenames = 0;
|
||||||
struct dep *deps = 0;
|
struct dep *deps = 0;
|
||||||
long nlines = 0;
|
long nlines = 0;
|
||||||
@ -450,7 +452,7 @@ eval (ebuf, set_default)
|
|||||||
fi.lineno = tgts_started; \
|
fi.lineno = tgts_started; \
|
||||||
record_files (filenames, pattern, pattern_percent, deps, \
|
record_files (filenames, pattern, pattern_percent, deps, \
|
||||||
cmds_started, commands, commands_idx, two_colon, \
|
cmds_started, commands, commands_idx, two_colon, \
|
||||||
&fi, set_default); \
|
have_sysv_atvar, &fi, set_default); \
|
||||||
} \
|
} \
|
||||||
filenames = 0; \
|
filenames = 0; \
|
||||||
commands_idx = 0; \
|
commands_idx = 0; \
|
||||||
@ -1057,6 +1059,16 @@ eval (ebuf, set_default)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do any of the prerequisites appear to have $@ etc.? */
|
||||||
|
have_sysv_atvar = 0;
|
||||||
|
if (!posix_pedantic)
|
||||||
|
for (p = strchr (p2, '$'); p != 0; p = strchr (p+1, '$'))
|
||||||
|
if (p[1] == '@' || (p[1] == '(' && p[2] == '@'))
|
||||||
|
{
|
||||||
|
have_sysv_atvar = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is this a static pattern rule: `target: %targ: %dep; ...'? */
|
/* Is this a static pattern rule: `target: %targ: %dep; ...'? */
|
||||||
p = strchr (p2, ':');
|
p = strchr (p2, ':');
|
||||||
while (p != 0 && p[-1] == '\\')
|
while (p != 0 && p[-1] == '\\')
|
||||||
@ -1654,7 +1666,8 @@ record_target_var (filenames, defn, two_colon, origin, flocp)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
record_files (filenames, pattern, pattern_percent, deps, cmds_started,
|
record_files (filenames, pattern, pattern_percent, deps, cmds_started,
|
||||||
commands, commands_idx, two_colon, flocp, set_default)
|
commands, commands_idx, two_colon, have_sysv_atvar,
|
||||||
|
flocp, set_default)
|
||||||
struct nameseq *filenames;
|
struct nameseq *filenames;
|
||||||
char *pattern, *pattern_percent;
|
char *pattern, *pattern_percent;
|
||||||
struct dep *deps;
|
struct dep *deps;
|
||||||
@ -1662,6 +1675,7 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
|
|||||||
char *commands;
|
char *commands;
|
||||||
unsigned int commands_idx;
|
unsigned int commands_idx;
|
||||||
int two_colon;
|
int two_colon;
|
||||||
|
int have_sysv_atvar;
|
||||||
const struct floc *flocp;
|
const struct floc *flocp;
|
||||||
int set_default;
|
int set_default;
|
||||||
{
|
{
|
||||||
@ -1684,16 +1698,22 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
|
|||||||
|
|
||||||
for (; filenames != 0; filenames = nextf)
|
for (; filenames != 0; filenames = nextf)
|
||||||
{
|
{
|
||||||
|
char *name = filenames->name;
|
||||||
register char *name = filenames->name;
|
struct file *f;
|
||||||
register struct file *f;
|
struct dep *d;
|
||||||
register struct dep *d;
|
|
||||||
struct dep *this;
|
struct dep *this;
|
||||||
char *implicit_percent;
|
char *implicit_percent;
|
||||||
|
|
||||||
nextf = filenames->next;
|
nextf = filenames->next;
|
||||||
free (filenames);
|
free (filenames);
|
||||||
|
|
||||||
|
/* Check for .POSIX. We used to do this in snap_deps() but that's not
|
||||||
|
good enough: it doesn't happen until after the makefile is read,
|
||||||
|
which means we cannot use its value during parsing. */
|
||||||
|
|
||||||
|
if (streq (name, ".POSIX"))
|
||||||
|
posix_pedantic = 1;
|
||||||
|
|
||||||
implicit_percent = find_percent (name);
|
implicit_percent = find_percent (name);
|
||||||
implicit |= implicit_percent != 0;
|
implicit |= implicit_percent != 0;
|
||||||
|
|
||||||
@ -1772,6 +1792,101 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If at least one of the dependencies uses $$@ etc. deal with that.
|
||||||
|
It would be very nice and very simple to just expand everything, but
|
||||||
|
it would break a lot of backward compatibility. Maybe that's OK
|
||||||
|
since we're just emulating a SysV function, and if we do that then
|
||||||
|
why not emulate it completely (that's what SysV make does: it
|
||||||
|
re-expands the entire prerequisite list, all the time, with $@
|
||||||
|
etc. in scope. But, it would be a pain indeed to document this
|
||||||
|
("iff you use $$@, your prerequisite lists is expanded twice...")
|
||||||
|
Ouch. Maybe better to make the code more complex. */
|
||||||
|
|
||||||
|
if (have_sysv_atvar)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int tlen = strlen (name);
|
||||||
|
char *fnp = strrchr (name, '/');
|
||||||
|
int dlen;
|
||||||
|
int flen;
|
||||||
|
|
||||||
|
if (fnp)
|
||||||
|
{
|
||||||
|
dlen = fnp - name;
|
||||||
|
++fnp;
|
||||||
|
flen = strlen (fnp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dlen = 0;
|
||||||
|
fnp = name;
|
||||||
|
flen = tlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (d = this; d != 0; d = d->next)
|
||||||
|
for (p = strchr (d->name, '$'); p != 0; p = strchr (p+1, '$'))
|
||||||
|
{
|
||||||
|
char *s = p;
|
||||||
|
char *at;
|
||||||
|
int atlen;
|
||||||
|
|
||||||
|
/* If it's a '$@' or '$(@', it's escaped */
|
||||||
|
if ((++p)[0] == '$'
|
||||||
|
&& (p[1] == '@' || (p[1] == '(' && p[2] == '@')))
|
||||||
|
{
|
||||||
|
bcopy (p, s, strlen (p)+1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maybe found one. Check. p will point to '@' [for $@] or
|
||||||
|
')' [for $(@)] or 'D' [for $(@D)] or 'F' [for $(@F)]. */
|
||||||
|
if (p[0] != '@'
|
||||||
|
&& (p[0] != '(' || (++p)[0] != '@'
|
||||||
|
|| ((++p)[0] != ')'
|
||||||
|
&& (p[1] != ')' || (p[0] != 'D' && p[0] != 'F')))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Found one. Compute the length and string ptr. Move p
|
||||||
|
past the variable reference. */
|
||||||
|
switch (p[0])
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
atlen = dlen;
|
||||||
|
at = name;
|
||||||
|
p += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
atlen = flen;
|
||||||
|
at = fnp;
|
||||||
|
p += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
atlen = tlen;
|
||||||
|
at = name;
|
||||||
|
++p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get more space. */
|
||||||
|
{
|
||||||
|
int soff = s - d->name;
|
||||||
|
int poff = p - d->name;
|
||||||
|
d->name = (char *) xrealloc (d->name,
|
||||||
|
strlen (d->name) + atlen + 1);
|
||||||
|
s = d->name + soff;
|
||||||
|
p = d->name + poff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the string over. */
|
||||||
|
bcopy(p, s+atlen, strlen (p)+1);
|
||||||
|
bcopy(at, s, atlen);
|
||||||
|
p = s + atlen - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!two_colon)
|
if (!two_colon)
|
||||||
{
|
{
|
||||||
/* Single-colon. Combine these dependencies
|
/* Single-colon. Combine these dependencies
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2002-07-10 Paul D. Smith <psmith@gnu.org>
|
||||||
|
|
||||||
|
* scripts/variables/automatic: Add some tests for $$@, $$(@D), and
|
||||||
|
$$(@F).
|
||||||
|
|
||||||
2002-07-09 Paul D. Smith <psmith@gnu.org>
|
2002-07-09 Paul D. Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* scripts/variables/automatic: Create a test for automatic variables.
|
* scripts/variables/automatic: Create a test for automatic variables.
|
||||||
|
@ -30,9 +30,8 @@ close(MAKEFILE);
|
|||||||
# TEST #1 -- simple test
|
# TEST #1 -- simple test
|
||||||
# -------
|
# -------
|
||||||
|
|
||||||
&touch(qw(foo.x baz.z));
|
# Touch these into the past
|
||||||
|
&utouch(-10, qw(foo.x baz.z));
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
&run_make_with_options($makefile, "", &get_logfile);
|
&run_make_with_options($makefile, "", &get_logfile);
|
||||||
$answer = "touch $dir/bar.y
|
$answer = "touch $dir/bar.y
|
||||||
@ -47,4 +46,28 @@ touch $dir/foo.x\n";
|
|||||||
|
|
||||||
unlink(qw(foo.x bar.y baz.z));
|
unlink(qw(foo.x bar.y baz.z));
|
||||||
|
|
||||||
|
# TEST #2 -- test the SysV emulation of $$@ etc.
|
||||||
|
# -------
|
||||||
|
|
||||||
|
$makefile2 = &get_tmpfile;
|
||||||
|
|
||||||
|
open(MAKEFILE, "> $makefile2");
|
||||||
|
print MAKEFILE "dir = $dir\n";
|
||||||
|
print MAKEFILE <<'EOF';
|
||||||
|
.SUFFIXES:
|
||||||
|
.DEFAULT: ; @echo '$@'
|
||||||
|
|
||||||
|
$(dir)/foo $(dir)/bar: $@.x $$@.x $$$@.x $$$$@.x $$(@D).x $$(@F).x
|
||||||
|
|
||||||
|
$(dir)/x.z $(dir)/y.z: $(dir)/%.z : $@.% $$@.% $$$@.% $$$$@.% $$(@D).% $$(@F).%
|
||||||
|
EOF
|
||||||
|
|
||||||
|
&run_make_with_options($makefile2, "$dir/foo $dir/bar", &get_logfile);
|
||||||
|
$answer = ".x\n$dir/foo.x\n\$.x\n\$@.x\n$dir.x\nfoo.x\n$dir/bar.x\nbar.x\n";
|
||||||
|
&compare_output($answer, &get_logfile(1));
|
||||||
|
|
||||||
|
&run_make_with_options($makefile2, "$dir/x.z $dir/y.z", &get_logfile);
|
||||||
|
$answer = ".x\n$dir/x.z.x\n\$.x\n\$@.x\n$dir.x\nx.z.x\n.y\n$dir/y.z.y\n\$.y\n\$@.y\n$dir.y\ny.z.y\n";
|
||||||
|
&compare_output($answer, &get_logfile(1));
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -825,15 +825,29 @@ sub remove_directory_tree_inner
|
|||||||
|
|
||||||
sub touch
|
sub touch
|
||||||
{
|
{
|
||||||
local (@filenames) = @_;
|
|
||||||
local ($file);
|
local ($file);
|
||||||
|
|
||||||
foreach $file (@filenames) {
|
foreach $file (@_) {
|
||||||
(open(T, ">> $file") && print(T "\n") && close(T))
|
(open(T, ">> $file") && print(T "\n") && close(T))
|
||||||
|| &error("Couldn't touch $file: $!\n", 1);
|
|| &error("Couldn't touch $file: $!\n", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Touch with a time offset. To DTRT, call touch() then use stat() to get the
|
||||||
|
# access/mod time for each file and apply the offset.
|
||||||
|
|
||||||
|
sub utouch
|
||||||
|
{
|
||||||
|
local ($off) = shift;
|
||||||
|
local ($file);
|
||||||
|
|
||||||
|
&touch(@_);
|
||||||
|
|
||||||
|
local (@s) = stat($_[0]);
|
||||||
|
|
||||||
|
utime($s[8]+$off, $s[9]+$off, @_);
|
||||||
|
}
|
||||||
|
|
||||||
# open a file, write some stuff to it, and close it.
|
# open a file, write some stuff to it, and close it.
|
||||||
|
|
||||||
sub create_file
|
sub create_file
|
||||||
|
Loading…
Reference in New Issue
Block a user