mirror of
https://salsa.debian.org/srivasta/make-dfsg.git
synced 2024-12-31 17:18:25 +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>
|
2004-11-28 Paul D. Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* main.c (main) [WINDOWS32]: Remove any trailing slashes from -C
|
* main.c (main) [WINDOWS32]: Remove any trailing slashes from -C
|
||||||
|
|
|
@ -134,9 +134,9 @@ if test "$ac_cv_func_gettimeofday" = yes; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_FUNCS( memcpy memmove strchr strdup mkstemp mktemp fdopen \
|
AC_CHECK_FUNCS( memcpy memmove strchr strdup mkstemp mktemp fdopen \
|
||||||
bsd_signal dup2 getcwd sigsetmask sigaction getgroups \
|
bsd_signal dup2 getcwd realpath sigsetmask sigaction \
|
||||||
seteuid setegid setlinebuf setreuid setregid setvbuf pipe \
|
getgroups seteuid setegid setlinebuf setreuid setregid \
|
||||||
strerror strsignal)
|
setvbuf pipe strerror strsignal)
|
||||||
|
|
||||||
AC_FUNC_SETVBUF_REVERSED
|
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
|
@code{wildcard} is a space-separated list of the names of existing files
|
||||||
that match the pattern.
|
that match the pattern.
|
||||||
@xref{Wildcards, ,Using Wildcard Characters in File Names}.
|
@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
|
@end table
|
||||||
|
|
||||||
@node Foreach Function, If Function, File Name Functions, Functions
|
@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).@*
|
@samp{%} pattern).@*
|
||||||
@xref{Wildcard Function, ,The Function @code{wildcard}}.
|
@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{})
|
@item $(error @var{text}@dots{})
|
||||||
|
|
||||||
When this function is evaluated, @code{make} generates a fatal error
|
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.
|
equality. Return is string-boolean, ie, the empty string is false.
|
||||||
*/
|
*/
|
||||||
static char *
|
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]);
|
int result = ! strcmp (argv[0], argv[1]);
|
||||||
o = variable_buffer_output (o, result ? "1" : "", result);
|
o = variable_buffer_output (o, result ? "1" : "", result);
|
||||||
|
@ -1727,9 +1727,9 @@ func_eq (char* o, char **argv, char *funcname)
|
||||||
string-boolean not operator.
|
string-boolean not operator.
|
||||||
*/
|
*/
|
||||||
static char *
|
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;
|
int result = 0;
|
||||||
while (isspace ((unsigned char)*s))
|
while (isspace ((unsigned char)*s))
|
||||||
s++;
|
s++;
|
||||||
|
@ -1740,6 +1740,161 @@ func_not (char* o, char **argv, char *funcname)
|
||||||
#endif
|
#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.
|
/* Lookup table for builtin functions.
|
||||||
|
|
||||||
This doesn't have to be sorted; we use a straight lookup. We might gain
|
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[] =
|
static struct function_table_entry function_table_init[] =
|
||||||
{
|
{
|
||||||
/* Name/size */ /* MIN MAX EXP? Function */
|
/* 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("addprefix"), 2, 2, 1, func_addsuffix_addprefix},
|
||||||
{ STRING_SIZE_TUPLE("addsuffix"), 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},
|
{ 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("join"), 2, 2, 1, func_join},
|
||||||
{ STRING_SIZE_TUPLE("lastword"), 0, 1, 1, func_lastword},
|
{ STRING_SIZE_TUPLE("lastword"), 0, 1, 1, func_lastword},
|
||||||
{ STRING_SIZE_TUPLE("patsubst"), 3, 3, 1, func_patsubst},
|
{ 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("shell"), 0, 1, 1, func_shell},
|
||||||
{ STRING_SIZE_TUPLE("sort"), 0, 1, 1, func_sort},
|
{ STRING_SIZE_TUPLE("sort"), 0, 1, 1, func_sort},
|
||||||
{ STRING_SIZE_TUPLE("strip"), 0, 1, 1, func_strip},
|
{ 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>
|
2004-11-28 Paul D. Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* scripts/options/dash-C [WINDOWS32]: Add a test for bug #10252;
|
* 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