/* See common/pathstuff.h. */
+const char *
+child_path (const char *parent, const char *child)
+{
+ /* The child path must start with the parent path. */
+ size_t parent_len = strlen (parent);
+ if (filename_ncmp (parent, child, parent_len) != 0)
+ return NULL;
+
+ /* The parent path must be a directory and the child must contain at
+ least one component underneath the parent. */
+ const char *child_component;
+ if (IS_DIR_SEPARATOR (parent[parent_len - 1]))
+ {
+ /* The parent path ends in a directory separator, so it is a
+ directory. The first child component starts after the common
+ prefix. */
+ child_component = child + parent_len;
+ }
+ else
+ {
+ /* The parent path does not end in a directory separator. The
+ first character in the child after the common prefix must be
+ a directory separator.
+
+ Note that CHILD must hold at least parent_len characters for
+ filename_ncmp to return zero. If the character at parent_len
+ is nul due to CHILD containing the same path as PARENT, the
+ IS_DIR_SEPARATOR check will fail here. */
+ if (!IS_DIR_SEPARATOR (child[parent_len]))
+ return NULL;
+
+ /* The first child component starts after the separator after the
+ common prefix. */
+ child_component = child + parent_len + 1;
+ }
+
+ /* The child must contain at least one non-separator character after
+ the parent. */
+ while (*child_component != '\0')
+ {
+ if (!IS_DIR_SEPARATOR (*child_component))
+ return child_component;
+
+ child_component++;
+ }
+ return NULL;
+}
+
+/* See common/pathstuff.h. */
+
bool
contains_dir_separator (const char *path)
{
--- /dev/null
+/* Self tests for child_path for GDB, the GNU debugger.
+
+ Copyright (C) 2019 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "common/pathstuff.h"
+#include "common/selftest.h"
+
+namespace selftests {
+namespace child_path {
+
+/* Verify the result of a single child_path test. */
+
+static bool
+child_path_check (const char *parent, const char *child, const char *expected)
+{
+ const char *result = ::child_path (parent, child);
+ if (result == NULL || expected == NULL)
+ return result == expected;
+ return strcmp (result, expected) == 0;
+}
+
+/* Test child_path. */
+
+static void
+test ()
+{
+ SELF_CHECK (child_path_check ("/one", "/two", NULL));
+ SELF_CHECK (child_path_check ("/one", "/one", NULL));
+ SELF_CHECK (child_path_check ("/one", "/one/", NULL));
+ SELF_CHECK (child_path_check ("/one", "/one//", NULL));
+ SELF_CHECK (child_path_check ("/one", "/one/two", "two"));
+ SELF_CHECK (child_path_check ("/one/", "/two", NULL));
+ SELF_CHECK (child_path_check ("/one/", "/one", NULL));
+ SELF_CHECK (child_path_check ("/one/", "/one/", NULL));
+ SELF_CHECK (child_path_check ("/one/", "/one//", NULL));
+ SELF_CHECK (child_path_check ("/one/", "/one/two", "two"));
+ SELF_CHECK (child_path_check ("/one/", "/one//two", "two"));
+ SELF_CHECK (child_path_check ("/one/", "/one//two/", "two/"));
+ SELF_CHECK (child_path_check ("/one", "/onetwo", NULL));
+ SELF_CHECK (child_path_check ("/one", "/onetwo/three", NULL));
+}
+
+}
+}
+
+void
+_initialize_child_path_selftests ()
+{
+ selftests::register_test ("child_path",
+ selftests::child_path::test);
+}
+