+
+/* Zap trailing slashes. */
+char *
+zap_slashes (char *name)
+{
+ char *q;
+
+ if (!name || *name == 0)
+ return name;
+ q = name + strlen (name) - 1;
+ while (q > name && ISSLASH (*q))
+ *q-- = '\0';
+ return name;
+}
+
+/* Normalize NAME by resolving any relative references and
+ removing trailing slashes. Destructive version: modifies its argument. */
+int
+normalize_filename_x (char *name)
+{
+ char *p, *q;
+
+ p = name;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && ISSLASH (*p))
+ p++;
+
+ /* Remove /./, resolve /../ and compress sequences of slashes */
+ for (q = p; *q; )
+ {
+ if (ISSLASH (*q))
+ {
+ *p++ = *q++;
+ while (ISSLASH (*q))
+ q++;
+ continue;
+ }
+ else if (p == name)
+ {
+ if (*q == '.')
+ {
+ if (ISSLASH (q[1]))
+ {
+ q += 2;
+ continue;
+ }
+ if (q[1] == '.' && ISSLASH (q[2]))
+ return 1;
+ }
+ }
+ else
+ {
+ if (*q == '.' && ISSLASH (p[-1]))
+ {
+ if (ISSLASH (q[1]))
+ {
+ q += 2;
+ while (ISSLASH (*q))
+ q++;
+ continue;
+ }
+ else if (q[1] == '.' && ISSLASH (q[2]))
+ {
+ do
+ {
+ --p;
+ }
+ while (p > name && !ISSLASH (p[-1]));
+ q += 3;
+ continue;
+ }
+ }
+ }
+ *p++ = *q++;
+ }
+
+ /* Remove trailing slashes */
+ while (p - 1 > name && ISSLASH (p[-1]))
+ p--;
+
+ *p = 0;
+ return 0;
+}
+
+/* Normalize NAME by resolving any relative references, removing trailing
+ slashes, and converting it to absolute file name. Return the normalized
+ name, or NULL in case of error. */
+
+char *
+normalize_filename (const char *name)
+{
+ char *copy;
+
+ if (name[0] != '/')
+ {
+ copy = xgetcwd ();
+ copy = xrealloc (copy, strlen (copy) + strlen (name) + 2);
+
+ strcat (copy, "/");
+ strcat (copy, name);
+ }
+ else
+ copy = xstrdup (name);
+ if (normalize_filename_x (copy))
+ {
+ free (copy);
+ return NULL;
+ }
+ return xrealloc (copy, strlen (copy) + 1);
+}
+
+\f
+void
+replace_prefix (char **pname, const char *samp, size_t slen,
+ const char *repl, size_t rlen)
+{
+ char *name = *pname;
+ size_t nlen = strlen (name);
+ if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
+ {
+ if (rlen > slen)
+ {
+ name = xrealloc (name, nlen - slen + rlen + 1);
+ *pname = name;
+ }
+ memmove (name + rlen, name + slen, nlen - slen + 1);
+ memcpy (name, repl, rlen);
+ }
+}
+