summaryrefslogtreecommitdiff
path: root/function.c
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@kolpackov.net>2004-11-30 19:51:24 +0000
committerBoris Kolpackov <boris@kolpackov.net>2004-11-30 19:51:24 +0000
commit49ca261bd5a40d933719ab6b2b1fd183a81bf35b (patch)
tree091a838b31da80405fcd882aab7d8a387e4c5bd1 /function.c
parentbe6a8bc869ece930f3bd5f725efd9fab7a2c2940 (diff)
downloadgunmake-49ca261bd5a40d933719ab6b2b1fd183a81bf35b.tar.gz
Implemented `realpath' and `abspath' built-in functions.
Diffstat (limited to 'function.c')
-rw-r--r--function.c163
1 files changed, 160 insertions, 3 deletions
diff --git a/function.c b/function.c
index ed5cc44..bbb86d2 100644
--- a/function.c
+++ b/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},