mirror of
https://salsa.debian.org/srivasta/make-dfsg.git
synced 2024-12-29 00:05:59 +00:00
Implemented realpath' and
abspath' built-in functions.
This commit is contained in:
parent
be6a8bc869
commit
49ca261bd5
7 changed files with 368 additions and 6 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2004-11-30 Boris Kolpackov <boris@kolpackov.net>
|
||||
|
||||
Implementation of `realpath' and `abspath' built-in functions.
|
||||
|
||||
* configure.in: Check for realpath.
|
||||
* function.c (abspath): Return an absolute file name that does
|
||||
not contain any `.' or `..' components, nor repeated `/'.
|
||||
* function.c (func_abspath): For each name call abspath.
|
||||
* function.c (func_realpath): For each name call realpath
|
||||
from libc or delegate to abspath if realpath is not available.
|
||||
* doc/make.texi (Functions for File Names): Document new functions.
|
||||
* doc/make.texi (Quick Reference): Ditto.
|
||||
|
||||
2004-11-28 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* main.c (main) [WINDOWS32]: Remove any trailing slashes from -C
|
||||
|
|
|
@ -134,9 +134,9 @@ if test "$ac_cv_func_gettimeofday" = yes; then
|
|||
fi
|
||||
|
||||
AC_CHECK_FUNCS( memcpy memmove strchr strdup mkstemp mktemp fdopen \
|
||||
bsd_signal dup2 getcwd sigsetmask sigaction getgroups \
|
||||
seteuid setegid setlinebuf setreuid setregid setvbuf pipe \
|
||||
strerror strsignal)
|
||||
bsd_signal dup2 getcwd realpath sigsetmask sigaction \
|
||||
getgroups seteuid setegid setlinebuf setreuid setregid \
|
||||
setvbuf pipe strerror strsignal)
|
||||
|
||||
AC_FUNC_SETVBUF_REVERSED
|
||||
|
||||
|
|
|
@ -6188,6 +6188,27 @@ wildcard characters (as in shell file name patterns). The result of
|
|||
@code{wildcard} is a space-separated list of the names of existing files
|
||||
that match the pattern.
|
||||
@xref{Wildcards, ,Using Wildcard Characters in File Names}.
|
||||
|
||||
@item $(realpath @var{names}@dots{})
|
||||
@findex realpath
|
||||
@cindex realpath
|
||||
@cindex file name, realpath of
|
||||
For each file name in @var{names} return the canonical absolute name.
|
||||
A canonical name does not contain any @code{.} or @code{..} components,
|
||||
nor any repeated path separators (@code{/}) or symlinks. In case of a
|
||||
failure the empty string is returned. Consult the @code{realpath(3)}
|
||||
documentation for a list of possible failure causes.
|
||||
|
||||
@item $(abspath @var{names}@dots{})
|
||||
@findex abspath
|
||||
@cindex abspath
|
||||
@cindex file name, abspath of
|
||||
For each file name in @var{names} return an absolute name that does
|
||||
not contain any @code{.} or @code{..} components, nor any repeated path
|
||||
separators (@code{/}). Note that in contrast to @code{realpath}
|
||||
function, @code{abspath} does not resolve symlinks and does not require
|
||||
the file names to refer to an existing file or directory. Use the
|
||||
@code{wildcard} function to test for existence.
|
||||
@end table
|
||||
|
||||
@node Foreach Function, If Function, File Name Functions, Functions
|
||||
|
@ -9756,6 +9777,17 @@ Find file names matching a shell file name pattern (@emph{not} a
|
|||
@samp{%} pattern).@*
|
||||
@xref{Wildcard Function, ,The Function @code{wildcard}}.
|
||||
|
||||
@item $(realpath @var{names}@dots{})
|
||||
For each file name in @var{names}, expand to an absolute name that
|
||||
does not contain any @code{.}, @code{..}, nor symlinks.@*
|
||||
@xref{File Name Functions, ,Functions for File Names}.
|
||||
|
||||
@item $(abspath @var{names}@dots{})
|
||||
For each file name in @var{names}, expand to an absolute name that
|
||||
does not contain any @code{.} or @code{..} components, but preserves
|
||||
symlinks.@*
|
||||
@xref{File Name Functions, ,Functions for File Names}.
|
||||
|
||||
@item $(error @var{text}@dots{})
|
||||
|
||||
When this function is evaluated, @code{make} generates a fatal error
|
||||
|
|
163
function.c
163
function.c
|
@ -1715,7 +1715,7 @@ func_shell (char *o, char **argv, const char *funcname)
|
|||
equality. Return is string-boolean, ie, the empty string is false.
|
||||
*/
|
||||
static char *
|
||||
func_eq (char* o, char **argv, char *funcname)
|
||||
func_eq (char *o, char **argv, char *funcname)
|
||||
{
|
||||
int result = ! strcmp (argv[0], argv[1]);
|
||||
o = variable_buffer_output (o, result ? "1" : "", result);
|
||||
|
@ -1727,9 +1727,9 @@ func_eq (char* o, char **argv, char *funcname)
|
|||
string-boolean not operator.
|
||||
*/
|
||||
static char *
|
||||
func_not (char* o, char **argv, char *funcname)
|
||||
func_not (char *o, char **argv, char *funcname)
|
||||
{
|
||||
char * s = argv[0];
|
||||
char *s = argv[0];
|
||||
int result = 0;
|
||||
while (isspace ((unsigned char)*s))
|
||||
s++;
|
||||
|
@ -1740,6 +1740,161 @@ func_not (char* o, char **argv, char *funcname)
|
|||
#endif
|
||||
|
||||
|
||||
/* Return the absolute name of file NAME which does not contain any `.',
|
||||
`..' components nor any repeated path separators ('/'). */
|
||||
|
||||
static char *
|
||||
abspath (const char *name, char *apath)
|
||||
{
|
||||
char *dest;
|
||||
const char *start, *end, *apath_limit;
|
||||
|
||||
if (name[0] == '\0' || apath == NULL)
|
||||
return NULL;
|
||||
|
||||
apath_limit = apath + PATH_MAX;
|
||||
|
||||
if (name[0] != '/')
|
||||
{
|
||||
/* It is unlikely we would make it until here but just to make sure. */
|
||||
if (!starting_directory)
|
||||
return NULL;
|
||||
|
||||
strcpy (apath, starting_directory);
|
||||
|
||||
dest = strchr (apath, '\0');
|
||||
}
|
||||
else
|
||||
{
|
||||
apath[0] = '/';
|
||||
dest = apath + 1;
|
||||
}
|
||||
|
||||
for (start = end = name; *start != '\0'; start = end)
|
||||
{
|
||||
unsigned long len;
|
||||
|
||||
/* Skip sequence of multiple path-separators. */
|
||||
while (*start == '/')
|
||||
++start;
|
||||
|
||||
/* Find end of path component. */
|
||||
for (end = start; *end != '\0' && *end != '/'; ++end)
|
||||
;
|
||||
|
||||
len = end - start;
|
||||
|
||||
if (len == 0)
|
||||
break;
|
||||
else if (len == 1 && start[0] == '.')
|
||||
/* nothing */;
|
||||
else if (len == 2 && start[0] == '.' && start[1] == '.')
|
||||
{
|
||||
/* Back up to previous component, ignore if at root already. */
|
||||
if (dest > apath + 1)
|
||||
while ((--dest)[-1] != '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dest[-1] != '/')
|
||||
*dest++ = '/';
|
||||
|
||||
if (dest + len >= apath_limit)
|
||||
return NULL;
|
||||
|
||||
dest = memcpy (dest, start, len);
|
||||
dest += len;
|
||||
*dest = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Unless it is root strip trailing separator. */
|
||||
if (dest > apath + 1 && dest[-1] == '/')
|
||||
--dest;
|
||||
|
||||
*dest = '\0';
|
||||
|
||||
return apath;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
func_realpath (char *o, char **argv, const char *funcname UNUSED)
|
||||
{
|
||||
/* Expand the argument. */
|
||||
char *p = argv[0];
|
||||
char *path = 0;
|
||||
int doneany = 0;
|
||||
unsigned int len = 0;
|
||||
|
||||
char in[PATH_MAX];
|
||||
char out[PATH_MAX];
|
||||
|
||||
while ((path = find_next_token (&p, &len)) != 0)
|
||||
{
|
||||
if (len < PATH_MAX)
|
||||
{
|
||||
strncpy (in, path, len);
|
||||
in[len] = '\0';
|
||||
|
||||
if
|
||||
(
|
||||
#ifdef HAVE_REALPATH
|
||||
realpath (in, out)
|
||||
#else
|
||||
abspath (in, out)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
o = variable_buffer_output (o, out, strlen (out));
|
||||
o = variable_buffer_output (o, " ", 1);
|
||||
doneany = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Kill last space. */
|
||||
if (doneany)
|
||||
--o;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
static char *
|
||||
func_abspath (char *o, char **argv, const char *funcname UNUSED)
|
||||
{
|
||||
/* Expand the argument. */
|
||||
char *p = argv[0];
|
||||
char *path = 0;
|
||||
int doneany = 0;
|
||||
unsigned int len = 0;
|
||||
|
||||
char in[PATH_MAX];
|
||||
char out[PATH_MAX];
|
||||
|
||||
while ((path = find_next_token (&p, &len)) != 0)
|
||||
{
|
||||
if (len < PATH_MAX)
|
||||
{
|
||||
strncpy (in, path, len);
|
||||
in[len] = '\0';
|
||||
|
||||
if (abspath (in, out))
|
||||
{
|
||||
o = variable_buffer_output (o, out, strlen (out));
|
||||
o = variable_buffer_output (o, " ", 1);
|
||||
doneany = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Kill last space. */
|
||||
if (doneany)
|
||||
--o;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
/* Lookup table for builtin functions.
|
||||
|
||||
This doesn't have to be sorted; we use a straight lookup. We might gain
|
||||
|
@ -1758,6 +1913,7 @@ static char *func_call PARAMS ((char *o, char **argv, const char *funcname));
|
|||
static struct function_table_entry function_table_init[] =
|
||||
{
|
||||
/* Name/size */ /* MIN MAX EXP? Function */
|
||||
{ STRING_SIZE_TUPLE("abspath"), 0, 1, 1, func_abspath},
|
||||
{ STRING_SIZE_TUPLE("addprefix"), 2, 2, 1, func_addsuffix_addprefix},
|
||||
{ STRING_SIZE_TUPLE("addsuffix"), 2, 2, 1, func_addsuffix_addprefix},
|
||||
{ STRING_SIZE_TUPLE("basename"), 0, 1, 1, func_basename_dir},
|
||||
|
@ -1772,6 +1928,7 @@ static struct function_table_entry function_table_init[] =
|
|||
{ STRING_SIZE_TUPLE("join"), 2, 2, 1, func_join},
|
||||
{ STRING_SIZE_TUPLE("lastword"), 0, 1, 1, func_lastword},
|
||||
{ STRING_SIZE_TUPLE("patsubst"), 3, 3, 1, func_patsubst},
|
||||
{ STRING_SIZE_TUPLE("realpath"), 0, 1, 1, func_realpath},
|
||||
{ STRING_SIZE_TUPLE("shell"), 0, 1, 1, func_shell},
|
||||
{ STRING_SIZE_TUPLE("sort"), 0, 1, 1, func_sort},
|
||||
{ STRING_SIZE_TUPLE("strip"), 0, 1, 1, func_strip},
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2004-11-30 Boris Kolpackov <boris@kolpackov.net>
|
||||
|
||||
* tests/scripts/functions/abspath: New file: test `abspath'
|
||||
built-in function.
|
||||
|
||||
* tests/scripts/functions/realpath: New file: test `realpath'
|
||||
built-in function.
|
||||
|
||||
2004-11-28 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/options/dash-C [WINDOWS32]: Add a test for bug #10252;
|
||||
|
|
81
tests/scripts/functions/abspath
Normal file
81
tests/scripts/functions/abspath
Normal file
|
@ -0,0 +1,81 @@
|
|||
# -*-perl-*-
|
||||
$description = "Test the abspath functions.";
|
||||
|
||||
$details = "";
|
||||
|
||||
run_make_test('
|
||||
ifneq ($(realpath $(abspath .)),$(CURDIR))
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath $(abspath ./)),$(CURDIR))
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath $(abspath .///)),$(CURDIR))
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath /),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath ///),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath /.),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath ///.),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath /./),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath /.///),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath /..),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath ///..),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath /../),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath /..///),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($(abspath /foo/bar/..),/foo)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath /foo/bar/../../../baz),/baz)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(abspath /foo/bar/../ /..),/foo /)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: all
|
||||
all: ; @:
|
||||
',
|
||||
'',
|
||||
'');
|
||||
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
71
tests/scripts/functions/realpath
Normal file
71
tests/scripts/functions/realpath
Normal file
|
@ -0,0 +1,71 @@
|
|||
# -*-perl-*-
|
||||
$description = "Test the realpath functions.";
|
||||
|
||||
$details = "";
|
||||
|
||||
run_make_test('
|
||||
ifneq ($(realpath .),$(CURDIR))
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath ./),$(CURDIR))
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath .///),$(CURDIR))
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath /),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath ///),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath /.),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath ///.),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath /./),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath /.///),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath /..),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath ///..),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath /../),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath /..///),/)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
ifneq ($(realpath . /..),$(CURDIR) /)
|
||||
$(error )
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: ; @:
|
||||
',
|
||||
'',
|
||||
'');
|
||||
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
Loading…
Reference in a new issue