diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/Makefile.in | 1 | ||||
-rw-r--r-- | gdb/common/pathstuff.c | 50 | ||||
-rw-r--r-- | gdb/common/pathstuff.h | 6 | ||||
-rw-r--r-- | gdb/unittests/child-path-selftests.c | 68 |
5 files changed, 133 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e4f74cd..2357a40 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,13 @@ 2019-02-12 John Baldwin <jhb@FreeBSD.org> + * Makefile.in (SUBDIR_UNITTESTS_SRCS): Add + unittests/child-path-selftests.c. + * common/pathstuff.c (child_path): New function. + * common/pathstuff.h (child_path): New prototype. + * unittests/child-path-selftests.c: New file. + +2019-02-12 John Baldwin <jhb@FreeBSD.org> + * symfile.c (find_separate_debug_file): Look for separate debug files in debug directories under the sysroot. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index cb5b740..5614cc3 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -411,6 +411,7 @@ SUBDIR_PYTHON_CFLAGS = SUBDIR_UNITTESTS_SRCS = \ unittests/array-view-selftests.c \ + unittests/child-path-selftests.c \ unittests/cli-utils-selftests.c \ unittests/common-utils-selftests.c \ unittests/copy_bitwise-selftests.c \ diff --git a/gdb/common/pathstuff.c b/gdb/common/pathstuff.c index 1167530..2b1669a 100644 --- a/gdb/common/pathstuff.c +++ b/gdb/common/pathstuff.c @@ -147,6 +147,56 @@ gdb_abspath (const char *path) /* 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) { diff --git a/gdb/common/pathstuff.h b/gdb/common/pathstuff.h index c264e78..67072a4 100644 --- a/gdb/common/pathstuff.h +++ b/gdb/common/pathstuff.h @@ -48,6 +48,12 @@ extern gdb::unique_xmalloc_ptr<char> extern gdb::unique_xmalloc_ptr<char> gdb_abspath (const char *path); +/* If the path in CHILD is a child of the path in PARENT, return a + pointer to the first component in the CHILD's pathname below the + PARENT. Otherwise, return NULL. */ + +extern const char *child_path (const char *parent, const char *child); + /* Return whether PATH contains a directory separator character. */ extern bool contains_dir_separator (const char *path); diff --git a/gdb/unittests/child-path-selftests.c b/gdb/unittests/child-path-selftests.c new file mode 100644 index 0000000..4c436ef --- /dev/null +++ b/gdb/unittests/child-path-selftests.c @@ -0,0 +1,68 @@ +/* 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); +} + |