From 000ba73a815f4f0efe2253cb4373972415bf016a Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sun, 29 Jan 2006 01:17:49 +0000 Subject: [PATCH] Add functions to split a path into a directory and base filename. * splitpath.c (yasm__splitpath_unix, yasm__splitpath_win): New. * coretype.h: Prototype above and alias yasm__splitpath. * splitpath_test.c: New test for above. svn path=/trunk/yasm/; revision=1345 --- libyasm/Makefile.inc | 1 + libyasm/coretype.h | 29 +++++++ libyasm/splitpath.c | 82 +++++++++++++++++++ libyasm/tests/Makefile.inc | 4 + libyasm/tests/splitpath_test.c | 140 +++++++++++++++++++++++++++++++++ 5 files changed, 256 insertions(+) create mode 100644 libyasm/splitpath.c create mode 100644 libyasm/tests/splitpath_test.c diff --git a/libyasm/Makefile.inc b/libyasm/Makefile.inc index 847ad69f..78d59a0d 100644 --- a/libyasm/Makefile.inc +++ b/libyasm/Makefile.inc @@ -20,6 +20,7 @@ libyasm_a_SOURCES += libyasm/xstrdup.c libyasm_a_SOURCES += libyasm/strcasecmp.c libyasm_a_SOURCES += libyasm/mergesort.c libyasm_a_SOURCES += libyasm/strsep.c +libyasm_a_SOURCES += libyasm/splitpath.c libyasm_a_SOURCES += module.c module.c: $(top_srcdir)/libyasm/module.in genmodule$(EXEEXT) Makefile diff --git a/libyasm/coretype.h b/libyasm/coretype.h index 0ece06cc..c1394742 100644 --- a/libyasm/coretype.h +++ b/libyasm/coretype.h @@ -256,6 +256,35 @@ int yasm__strcasecmp(const char *s1, const char *s2); */ int yasm__strncasecmp(const char *s1, const char *s2, size_t n); +/** Split a UNIX pathname into head (directory) and tail (base filename) + * portions. + * \internal + * \param path pathname + * \param tail (returned) base filename + * \return Length of head (directory). + */ +size_t yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail); + +/** Split a Windows pathname into head (directory) and tail (base filename) + * portions. + * \internal + * \param path pathname + * \param tail (returned) base filename + * \return Length of head (directory). + */ +size_t yasm__splitpath_win(const char *path, /*@out@*/ const char **tail); + +#ifndef yasm__splitpath +/** Split a pathname into head (directory) and tail (base filename) portions. + * Unless otherwise defined, defaults to yasm__splitpath_unix(). + * \internal + * \param path pathname + * \param head (returned) directory + * \return Length of head (directory). + */ +#define yasm__splitpath(path, tail) yasm__splitpath_unix(path, tail) +#endif + /** strdup() implementation using yasm_xmalloc(). * \internal * \param str string diff --git a/libyasm/splitpath.c b/libyasm/splitpath.c new file mode 100644 index 00000000..5629ada9 --- /dev/null +++ b/libyasm/splitpath.c @@ -0,0 +1,82 @@ +/* + * Split a path into directory name and file name. + * + * Copyright (C) 2006 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#define YASM_LIB_INTERNAL +#include "util.h" +/*@unused@*/ RCSID("$Id$"); + +#include "coretype.h" + +size_t +yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail) +{ + const char *s; + s = strrchr(path, '/'); + if (!s) { + /* No head */ + *tail = path; + return 0; + } + *tail = s+1; + /* Strip trailing slashes on path (except leading) */ + while (s>path && *s == '/') + s--; + /* Return length of head */ + return s-path+1; +} + +size_t +yasm__splitpath_win(const char *path, /*@out@*/ const char **tail) +{ + const char *basepath = path; + const char *s; + + /* split off drive letter first, if any */ + if (isalpha(path[0]) && path[1] == ':') + basepath += 2; + + s = basepath; + while (*s != '\0') + s++; + while (s >= basepath && *s != '\\' && *s != '/') + s--; + if (s < basepath) { + *tail = basepath; + if (path == basepath) + return 0; /* No head */ + else + return 2; /* Drive letter is head */ + } + *tail = s+1; + /* Strip trailing slashes on path (except leading) */ + while (s>basepath && (*s == '/' || *s == '\\')) + s--; + /* Return length of head */ + return s-path+1; +} + diff --git a/libyasm/tests/Makefile.inc b/libyasm/tests/Makefile.inc index 7d2ad8cb..d7ef0053 100644 --- a/libyasm/tests/Makefile.inc +++ b/libyasm/tests/Makefile.inc @@ -3,6 +3,7 @@ TESTS += bitvect_test TESTS += floatnum_test TESTS += leb128_test +TESTS += splitpath_test TESTS += libyasm/tests/libyasm_test.sh EXTRA_DIST += libyasm/tests/libyasm_test.sh @@ -26,6 +27,7 @@ EXTRA_DIST += libyasm/tests/unary.hex check_PROGRAMS += bitvect_test check_PROGRAMS += floatnum_test check_PROGRAMS += leb128_test +check_PROGRAMS += splitpath_test bitvect_test_SOURCES = libyasm/tests/bitvect_test.c bitvect_test_LDADD = libyasm.a $(INTLLIBS) @@ -36,3 +38,5 @@ floatnum_test_LDADD = libyasm.a $(INTLLIBS) leb128_test_SOURCES = libyasm/tests/leb128_test.c leb128_test_LDADD = libyasm.a $(INTLLIBS) +splitpath_test_SOURCES = libyasm/tests/splitpath_test.c + diff --git a/libyasm/tests/splitpath_test.c b/libyasm/tests/splitpath_test.c new file mode 100644 index 00000000..68785ead --- /dev/null +++ b/libyasm/tests/splitpath_test.c @@ -0,0 +1,140 @@ +/* $Id$ + * + * Copyright (C) 2006 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + +#include "libyasm/splitpath.c" + +typedef struct Test_Entry { + /* splitpath function to test */ + size_t (*splitpath) (const char *path, const char **tail); + + /* input path */ + const char *input; + + /* correct head length returned */ + size_t headlen; + + /* correct tail returned */ + const char *tail; +} Test_Entry; + +static Test_Entry tests[] = { + /* UNIX split */ + {yasm__splitpath_unix, "file.ext", 0, "file.ext"}, + {yasm__splitpath_unix, "/file.ext", 1, "file.ext"}, + {yasm__splitpath_unix, "/foo/file.ext", 4, "file.ext"}, + {yasm__splitpath_unix, "/foo/bar/file.ext", 8, "file.ext"}, + {yasm__splitpath_unix, "foo/file.ext", 3, "file.ext"}, + {yasm__splitpath_unix, "foo/bar/file.ext", 7, "file.ext"}, + {yasm__splitpath_unix, "foo/bar//file.ext", 7, "file.ext"}, + /* Windows split */ + {yasm__splitpath_win, "file.ext", 0, "file.ext"}, + {yasm__splitpath_win, "/file.ext", 1, "file.ext"}, + {yasm__splitpath_win, "/foo/file.ext", 4, "file.ext"}, + {yasm__splitpath_win, "/foo/bar/file.ext", 8, "file.ext"}, + {yasm__splitpath_win, "foo/file.ext", 3, "file.ext"}, + {yasm__splitpath_win, "foo/bar/file.ext", 7, "file.ext"}, + {yasm__splitpath_win, "foo/bar//file.ext", 7, "file.ext"}, + {yasm__splitpath_win, "c:file.ext", 2, "file.ext"}, + {yasm__splitpath_win, "d:/file.ext", 3, "file.ext"}, + {yasm__splitpath_win, "e:/foo/file.ext", 6, "file.ext"}, + {yasm__splitpath_win, "f:/foo/bar/file.ext", 10, "file.ext"}, + {yasm__splitpath_win, "g:foo/file.ext", 5, "file.ext"}, + {yasm__splitpath_win, "h:foo/bar/file.ext", 9, "file.ext"}, + {yasm__splitpath_win, "i:foo/bar//file.ext", 9, "file.ext"}, + {yasm__splitpath_win, "d:\\file.ext", 3, "file.ext"}, + {yasm__splitpath_win, "e:\\foo/file.ext", 6, "file.ext"}, + {yasm__splitpath_win, "f:/foo\\bar\\file.ext", 10, "file.ext"}, + {yasm__splitpath_win, "g:foo\\file.ext", 5, "file.ext"}, + {yasm__splitpath_win, "h:foo/bar\\file.ext", 9, "file.ext"}, + {yasm__splitpath_win, "i:foo\\bar//\\file.ext", 9, "file.ext"}, +}; + +static char failed[1000]; +static char failmsg[100]; + +static int +run_test(Test_Entry *test) +{ + size_t headlen; + const char *tail; + const char *funcname; + + if (test->splitpath == &yasm__splitpath_unix) + funcname = "unix"; + else + funcname = "win"; + + headlen = test->splitpath(test->input, &tail); + if (headlen != test->headlen) { + sprintf(failmsg, + "splitpath_%s(\"%s\") bad head len: expected %lu, got %lu!", + funcname, test->input, (unsigned long)test->headlen, + (unsigned long)headlen); + return 1; + } + + if (strcmp(tail, test->tail) != 0) { + sprintf(failmsg, + "splitpath_%s(\"%s\") bad tail: expected \"%s\", got \"%s\"!", + funcname, test->input, test->tail, tail); + return 1; + } + + return 0; +} + +int +main(void) +{ + int nf = 0; + int numtests = sizeof(tests)/sizeof(Test_Entry); + int i; + + failed[0] = '\0'; + printf("Test splitpath_test: "); + for (i=0; i0 ? 'F':'.'); + fflush(stdout); + if (fail) + sprintf(failed, "%s ** F: %s\n", failed, failmsg); + nf += fail; + } + + printf(" +%d-%d/%d %d%%\n%s", + numtests-nf, nf, numtests, 100*(numtests-nf)/numtests, failed); + return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} -- 2.40.0