From ff7a315acbc5713685adf55fe3e09539c4d2fa02 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 15 Dec 2025 09:52:13 -0800 Subject: [PATCH] nasmlib: move filename_set_extension() into path.c Move filename_set_extension() into path.c, so it has access to the filesystem-specific character constants. This prevents something like: nasm-code.d/foobar ... from getting truncated to ... nasm-code.bin ... instead of producing ... nasm-code.d/foobar.bin Make the extension character (normally '.') configurable; this MIGHT be usable on RISCOS at some point, although it is not entirely clear that trying to make sense of RISCOS paths actually is meaningful, because RISCOS compiler chains seem to do all kinds of path translation magic trying to behave like other operating systems... it might simply be more trouble than it is worth, especially for a non-x86 platform. As a side bonus, this removes the only use of strrchrnul(), so that function can be dropped. Signed-off-by: H. Peter Anvin (Intel) --- Makefile.in | 4 +-- Mkfiles/msvc.mak | 4 +-- Mkfiles/openwcom.mak | 4 +-- configure.ac | 3 -- include/compiler.h | 4 --- nasmlib/filename.c | 33 --------------------- nasmlib/path.c | 69 +++++++++++++++++++++++++++++++++++++------- stdlib/strrchrnul.c | 19 ------------ 8 files changed, 64 insertions(+), 76 deletions(-) delete mode 100644 nasmlib/filename.c delete mode 100644 stdlib/strrchrnul.c diff --git a/Makefile.in b/Makefile.in index 38f099dec..55de18eef 100644 --- a/Makefile.in +++ b/Makefile.in @@ -149,14 +149,14 @@ ZLIBOBJ = \ # Common library objects LIBOBJ_COM = \ stdlib/snprintf.$(O) stdlib/vsnprintf.$(O) stdlib/strlcpy.$(O) \ - stdlib/strnlen.$(O) stdlib/strrchrnul.$(O) \ + stdlib/strnlen.$(O) \ \ nasmlib/ver.$(O) \ nasmlib/alloc.$(O) nasmlib/asprintf.$(O) \ nasmlib/crc32b.$(O) nasmlib/crc64.$(O) nasmlib/md5c.$(O) \ nasmlib/string.$(O) nasmlib/nctype.$(O) \ nasmlib/file.$(O) nasmlib/fileio.$(O) nasmlib/mmap.$(O) \ - nasmlib/realpath.$(O) nasmlib/path.$(O) nasmlib/filename.$(O) \ + nasmlib/realpath.$(O) nasmlib/path.$(O) \ nasmlib/ilog2.$(O) nasmlib/numstr.$(O) \ nasmlib/rlimit.$(O) \ nasmlib/zerobuf.$(O) nasmlib/bsi.$(O) \ diff --git a/Mkfiles/msvc.mak b/Mkfiles/msvc.mak index 7b3a4f7a9..4117df2e4 100644 --- a/Mkfiles/msvc.mak +++ b/Mkfiles/msvc.mak @@ -100,14 +100,14 @@ ZLIBOBJ = \ # Common library objects LIBOBJ_COM = \ stdlib\snprintf.obj stdlib\vsnprintf.obj stdlib\strlcpy.obj \ - stdlib\strnlen.obj stdlib\strrchrnul.obj \ + stdlib\strnlen.obj \ \ nasmlib\ver.obj \ nasmlib\alloc.obj nasmlib\asprintf.obj \ nasmlib\crc32b.obj nasmlib\crc64.obj nasmlib\md5c.obj \ nasmlib\string.obj nasmlib\nctype.obj \ nasmlib\file.obj nasmlib\fileio.obj nasmlib\mmap.obj \ - nasmlib\realpath.obj nasmlib\path.obj nasmlib\filename.obj \ + nasmlib\realpath.obj nasmlib\path.obj \ nasmlib\ilog2.obj nasmlib\numstr.obj \ nasmlib\rlimit.obj \ nasmlib\zerobuf.obj nasmlib\bsi.obj \ diff --git a/Mkfiles/openwcom.mak b/Mkfiles/openwcom.mak index e733b2af4..a18e4a28c 100644 --- a/Mkfiles/openwcom.mak +++ b/Mkfiles/openwcom.mak @@ -86,14 +86,14 @@ ZLIBOBJ = & # Common library objects LIBOBJ_COM = & stdlib\snprintf.obj stdlib\vsnprintf.obj stdlib\strlcpy.obj & - stdlib\strnlen.obj stdlib\strrchrnul.obj & + stdlib\strnlen.obj & & nasmlib\ver.obj & nasmlib\alloc.obj nasmlib\asprintf.obj & nasmlib\crc32b.obj nasmlib\crc64.obj nasmlib\md5c.obj & nasmlib\string.obj nasmlib\nctype.obj & nasmlib\file.obj nasmlib\fileio.obj nasmlib\mmap.obj & - nasmlib\realpath.obj nasmlib\path.obj nasmlib\filename.obj & + nasmlib\realpath.obj nasmlib\path.obj & nasmlib\ilog2.obj nasmlib\numstr.obj & nasmlib\rlimit.obj & nasmlib\zerobuf.obj nasmlib\bsi.obj & diff --git a/configure.ac b/configure.ac index acd7461bf..2f4462623 100644 --- a/configure.ac +++ b/configure.ac @@ -197,7 +197,6 @@ AC_CHECK_FUNCS(strcasecmp stricmp) AC_CHECK_FUNCS(strncasecmp strnicmp) AC_CHECK_FUNCS(strsep) AC_CHECK_FUNCS(strnlen) -AC_CHECK_FUNCS(strrchrnul) AC_CHECK_FUNCS(iscntrl) AC_CHECK_FUNCS(isascii) AC_CHECK_FUNCS(mempcpy) @@ -229,7 +228,6 @@ PA_HAVE_FUNC(__builtin_unreachable,()) PA_FUNC_SNPRINTF PA_FUNC_VSNPRINTF AC_CHECK_FUNCS([strlcpy]) -AC_CHECK_FUNCS([strrchrnul]) dnl These types are POSIX-specific, and Windows does it differently... AC_CHECK_TYPES([struct stat], [AC_CHECK_FUNCS([stat fstat])]) @@ -246,7 +244,6 @@ AC_CHECK_DECLS(strnicmp) AC_CHECK_DECLS(strsep) AC_CHECK_DECLS(strlcpy) AC_CHECK_DECLS(strnlen) -AC_CHECK_DECLS(strrchrnul) dnl Check for missing types AC_TYPE_UINTMAX_T diff --git a/include/compiler.h b/include/compiler.h index df6688008..3ba5f7c9c 100644 --- a/include/compiler.h +++ b/include/compiler.h @@ -177,10 +177,6 @@ int vsnprintf(char *, size_t, const char *, va_list); size_t strlcpy(char *, const char *, size_t); #endif -#if !defined(HAVE_STRCHRNUL) || !HAVE_DECL_STRCHRNUL -char * pure_func strrchrnul(const char *, int); -#endif - /* C++ and C23 have bool, false, and true as proper keywords */ #if !defined(__cplusplus) && (__STDC_VERSION__ < 202311L) # ifdef HAVE_STDBOOL_H diff --git a/nasmlib/filename.c b/nasmlib/filename.c deleted file mode 100644 index 2c29d3864..000000000 --- a/nasmlib/filename.c +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* Copyright 1996-2017 The NASM Authors - All Rights Reserved */ - -/* - * nasmlib.c library routines for the Netwide Assembler - */ - -#include "compiler.h" -#include "nasmlib.h" -#include "error.h" - -/* - * Add/modify a filename extension, assumed to be a period-delimited - * field at the very end of the filename. Returns a newly allocated - * string buffer. - */ -const char *filename_set_extension(const char *inname, const char *extension) -{ - const char *q = inname; - char *p; - size_t elen = strlen(extension); - size_t baselen; - - q = strrchrnul(inname, '.'); /* find extension or end of string */ - baselen = q - inname; - - p = nasm_malloc(baselen + elen + 1); - - memcpy(p, inname, baselen); - memcpy(p+baselen, extension, elen+1); - - return p; -} diff --git a/nasmlib/path.c b/nasmlib/path.c index eb3330cfc..6d5f74f79 100644 --- a/nasmlib/path.c +++ b/nasmlib/path.c @@ -69,37 +69,39 @@ # define leaveonclean 0 # define leave_leading 1 #elif PATHSTYLE == PATH_VMS -/* - * VMS filenames may have ;version at the end. Assume we should count that - * as part of the filename anyway. - */ # define separators ":]" # define curdir "[]" +# define postext ";" #else /* No idea what to do here, do nothing. Feel free to add new ones. */ # define curdir "" #endif +#ifndef extsep +# define extsep '.' +#endif + /* * This is an inline, because most compilers can greatly simplify this * for a fixed string, like we have here. */ static inline bool pure_func ismatch(const char *charset, char ch) { - const char *p; - - for (p = charset; *p; p++) { - if (ch == *p) - return true; + if (charset && *charset) { + const char *p; + for (p = charset; *p; p++) { + if (ch == *p) + return true; + } } return false; } -static const char * pure_func first_filename_char(const char *path) +static inline const char * pure_func first_filename_char(const char *path) { #ifdef separators - const char *p = path + strlen(path); + const char *p = strchr(path, '\0'); while (p > path) { if (ismatch(separators, p[-1])) @@ -178,3 +180,48 @@ char *nasm_catfile(const char *dir, const char *file) return p; #endif } + +/* + * Add/modify a filename extension. Returns a newly allocated + * string buffer. If the extension is not an empty string, the first + * character is replaced by the appropriate extsep for the filesystem. + */ +const char *filename_set_extension(const char *inname, const char *extension) +{ + const char *nulp, *ep, *p; + char *outname, *q; + size_t elen = strlen(extension); + size_t baselen; + + ep = nulp = strchr(inname, '\0'); + for (p = nulp-1; p >= inname; p--) { + char c = *p; + if (c == extsep) { + /* Found the beginning of an existing extension */ + ep = p; + break; + } + if (ismatch(separators, c)) { + /* Found the beginning of the file name */ + ep = p+1; + break; + } +#ifdef postext + if (ismatch(postext, c)) { + /* Found the beginning of a character sequence + that should be stripped off; keep searching from here */ + ep = p; + continue; + } +#endif + } + baselen = ep - inname; + + q = outname = nasm_malloc(baselen + elen + 1); + q = mempcpy(q, inname, baselen); + if (*extension) + *q++ = extsep; + memcpy(q, extension+1, elen); + + return outname; +} diff --git a/stdlib/strrchrnul.c b/stdlib/strrchrnul.c deleted file mode 100644 index 372da26df..000000000 --- a/stdlib/strrchrnul.c +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* Copyright 2017 The NASM Authors - All Rights Reserved */ - -#include "compiler.h" - -#ifndef HAVE_STRRCHRNUL - -char * pure_func strrchrnul(const char *s, int c) -{ - char *p; - - p = strrchr(s, c); - if (!p) - p = strchr(s, '\0'); - - return p; -} - -#endif