diff --git a/.cirrus.yml b/.cirrus.yml index c3799ca..cf7fc17 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,5 +1,5 @@ freebsd_instance: - image_family: freebsd-13-0 + image_family: freebsd-15 task: install_script: pkg install -y cmake diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d33f9ec..84e398a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: EOF - name: Compile Test Amalgamation - run: gcc -Wall -Wextra -Werror -o test_amalg test_amalg.c + run: gcc -std=c89 -Wpedantic -Wall -Wextra -Werror -o test_amalg test_amalg.c - name: Run Test Amalgamation run: ./test_amalg diff --git a/CMakeLists.txt b/CMakeLists.txt index 07bcffa..62c2476 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,45 @@ cmake_minimum_required(VERSION 3.11) project(c89stringutils VERSION 0.0.2 LANGUAGES C) +include(CheckCSourceCompiles) + +check_c_source_compiles("#include + void t(int i, ...) { va_list a, b; va_start(a,i); va_copy(b,a); va_end(b); va_end(a); } + int main() { return 0; }" HAVE_VA_COPY) + +check_c_source_compiles("#include + void t(int i, ...) { va_list a, b; va_start(a,i); __va_copy(b,a); va_end(b); va_end(a); } + int main() { return 0; }" HAVE___VA_COPY) + +check_c_source_compiles("#include + void t(int i, ...) { va_list a, b; va_start(a,i); b = a; va_end(a); } + int main() { return 0; }" HAVE_VA_LIST_ASSIGNMENT) + +check_c_source_compiles(" +int main(void) { + long long x = 0; + return (int)x; +} +" HAVE_LONG_LONG) + set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN YES) set(CMAKE_C_STANDARD 90) add_library("${PROJECT_NAME}_compiler_flags" INTERFACE) + +if(HAVE_VA_COPY) + target_compile_definitions("${PROJECT_NAME}_compiler_flags" INTERFACE HAVE_VA_COPY) +elseif(HAVE___VA_COPY) + target_compile_definitions("${PROJECT_NAME}_compiler_flags" INTERFACE HAVE___VA_COPY) +elseif(HAVE_VA_LIST_ASSIGNMENT) + target_compile_definitions("${PROJECT_NAME}_compiler_flags" INTERFACE HAVE_VA_LIST_ASSIGNMENT) +endif() + +if(HAVE_LONG_LONG) + target_compile_definitions("${PROJECT_NAME}_compiler_flags" INTERFACE HAVE_LONG_LONG) +endif() + if (NOT DEFINED MSVC_VERSION OR MSVC_VERSION STRGREATER "1900" # 2015 OR NOT (CMAKE_C_COMPILER_ID STREQUAL "OpenWatcom")) diff --git a/c89stringutils/CMakeLists.txt b/c89stringutils/CMakeLists.txt index 8e0bcac..e4647e9 100644 --- a/c89stringutils/CMakeLists.txt +++ b/c89stringutils/CMakeLists.txt @@ -8,6 +8,8 @@ source_group("Source Files" FILES "${Source_Files}") add_library("${LIBRARY_NAME}" "${Header_Files}" "${Source_Files}") +target_link_libraries("${LIBRARY_NAME}" PUBLIC "${PROJECT_NAME}_compiler_flags") + include(GNUInstallDirs) target_include_directories( "${LIBRARY_NAME}" diff --git a/c89stringutils/c89stringutils_string_extras.c b/c89stringutils/c89stringutils_string_extras.c index b24edda..d0e5452 100644 --- a/c89stringutils/c89stringutils_string_extras.c +++ b/c89stringutils/c89stringutils_string_extras.c @@ -69,14 +69,59 @@ static int wtf_vsnprintf(char *buffer, size_t count, const char *format, #define HAVE_STRNCASECMP_H int strncasecmp(const char *s1, const char *s2, size_t n) { - int rc; - rc = _strnicmp(s1, s2, n); + int rc = 0; + size_t i; + + for (i = 0; i < n && s1[i] && s2[i]; i++) { + char c1 = s1[i]; + char c2 = s2[i]; + + /* Convert to lowercase for comparison */ + if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A'; + + if (c1 != c2) { + rc = (c1 < c2) ? -1 : 1; + break; + } + } + + /* Handle end of string cases */ + if (rc == 0 && i < n) { + if (!s1[i] && !s2[i]) rc = 0; + else if (!s1[i]) rc = -1; + else rc = 1; + } + return rc; } int strcasecmp(const char *s1, const char *s2) { - int rc; - rc = _stricmp(s1, s2); + int rc = 0; + size_t i = 0; + + while (s1[i] && s2[i]) { + char c1 = s1[i]; + char c2 = s2[i]; + + /* Convert to lowercase for comparison */ + if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A'; + + if (c1 != c2) { + rc = (c1 < c2) ? -1 : 1; + break; + } + i++; + } + + /* Handle end of string cases */ + if (rc == 0) { + if (!s1[i] && !s2[i]) rc = 0; + else if (!s1[i]) rc = -1; + else rc = 1; + } + return rc; } @@ -105,6 +150,7 @@ char *strnstr(const char *buffer, const char *target, size_t bufferLength) { [this doc (c) FreeBSD <3 clause BSD license> from their manpage] */ const size_t targetLength = strlen(target); const char *start; + if (targetLength == 0) return (char *)buffer; for (start = buffer; *start && start + targetLength <= buffer + bufferLength; @@ -126,9 +172,16 @@ char *strnstr(const char *buffer, const char *target, size_t bufferLength) { char *strcasestr(const char *h, const char *n) { const size_t l = strlen(n); - for (; *h; h++) - if (!strncasecmp(h, n, l)) - return (char *)h; + if (l == 0) return (char *)h; + + for (; *h; h++) { + if (h[0] == n[0] || + (h[0] >= 'A' && h[0] <= 'Z' && h[0] + 32 == n[0]) || + (h[0] >= 'a' && h[0] <= 'z' && h[0] - 32 == n[0])) { + if (!strncasecmp(h, n, l)) + return (char *)h; + } + } return 0; } @@ -144,6 +197,42 @@ size_t strerrorlen_s(errno_t errnum) { #define ESNULLP (400) /* null ptr */ #endif +#ifndef ESZEROL +#define ESZEROL (401) /* length is zero */ +#endif + +#ifndef ESLEMIN +#define ESLEMIN (402) /* length is below min */ +#endif + +#ifndef ESLEMAX +#define ESLEMAX (403) /* length exceeds RSIZE_MAX */ +#endif + +#ifndef ESOVRLP +#define ESOVRLP (404) /* overlap undefined */ +#endif + +#ifndef ESEMPTY +#define ESEMPTY (405) /* empty string */ +#endif + +#ifndef ESNOSPC +#define ESNOSPC (406) /* not enough space */ +#endif + +#ifndef ESUNTERM +#define ESUNTERM (407) /* unterminated string */ +#endif + +#ifndef ESNODIFF +#define ESNODIFF (408) /* no difference */ +#endif + +#ifndef ESNOTFND +#define ESNOTFND (409) /* not found */ +#endif + #ifndef ESLEWRNG #define ESLEWRNG (410) /* wrong size */ #endif @@ -186,16 +275,16 @@ size_t strerrorlen_s(errno_t errnum) { #define HAVE_ASPRINTF #ifndef VA_COPY -#if defined(HAVE_VA_COPY) || defined(va_copy) -#define VA_COPY(dest, src) va_copy(dest, src) -#else -#ifdef HAVE___VA_COPY -#define VA_COPY(dest, src) __va_copy(dest, src) -#else -#define VA_COPY(dest, src) (dest) = (src) -#endif -#endif -#endif /* ! VA_COPY */ +# if defined(HAVE_VA_COPY) +# define VA_COPY(dest, src) va_copy(dest, src) +# elif defined(HAVE___VA_COPY) +# define VA_COPY(dest, src) __va_copy(dest, src) +# elif defined(HAVE_VA_LIST_ASSIGNMENT) +# define VA_COPY(dest, src) ((dest) = (src)) +# else +# define VA_COPY(dest, src) memcpy(&(dest), &(src), sizeof(va_list)) +# endif +#endif /* !VA_COPY */ #define INIT_SZ 128 @@ -301,11 +390,17 @@ char *jasprintf(char **unto, const char *fmt, ...) { return NULL; /* check result for failure */ - result = - (char *)realloc(unto ? *unto : NULL, base_length + (size_t)length + 1); - - if (result == NULL) + result = (char *)realloc(unto ? *unto : NULL, base_length + (size_t)length + 1); + + /* if realloc failed, check if we have a valid pointer to free */ + if (result == NULL) { + if (unto && *unto) { + LOG_DEBUG("Reallocation failed but we have a valid pointer to free"); + } else { + LOG_DEBUG("Reallocation failed and no valid pointer to free"); + } return NULL; + } va_start(args, fmt); /* check for failure*/ diff --git a/c89stringutils/c89stringutils_string_extras.h b/c89stringutils/c89stringutils_string_extras.h index d4b4e15..22768a3 100644 --- a/c89stringutils/c89stringutils_string_extras.h +++ b/c89stringutils/c89stringutils_string_extras.h @@ -19,7 +19,11 @@ extern "C" { #if defined(_MSC_VER) #define NUM_FORMAT "%I64d" #else +#if defined(HAVE_LONG_LONG) #define NUM_FORMAT "%lld" +#else +#define NUM_FORMAT "%ld" +#endif #endif #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ @@ -94,7 +98,6 @@ typedef int errno_t; #if defined(__linux__) || defined(linux) || defined(__linux) || defined(ANY_BSD) #define strerror_s strerror_r -#define HAVE_STRERRORLEN_S #endif /* defined(__linux__) || defined(linux) || defined(__linux) || \ defined(ANY_BSD) */ @@ -102,7 +105,6 @@ typedef int errno_t; #ifndef _MSC_VER #define HAVE_STRINGS_H -#define HAVE_STRNCASECMP_H #endif #if !defined(HAVE_ASPRINTF) && \ diff --git a/c89stringutils/tests/CMakeLists.txt b/c89stringutils/tests/CMakeLists.txt index b5626d6..c447ffc 100644 --- a/c89stringutils/tests/CMakeLists.txt +++ b/c89stringutils/tests/CMakeLists.txt @@ -25,7 +25,7 @@ source_group("Source Files" FILES "${Source_Files}") add_executable("${EXEC_NAME}" "${Header_Files}" "${Source_Files}") -target_link_libraries("${EXEC_NAME}" PRIVATE "${PROJECT_NAME}") +target_link_libraries("${EXEC_NAME}" PRIVATE c89stringutils) if (NOT CMAKE_C_COMPILER_ID STREQUAL "OpenWatcom") target_link_libraries("${EXEC_NAME}" PRIVATE "${PROJECT_NAME}_compiler_flags") endif (NOT CMAKE_C_COMPILER_ID STREQUAL "OpenWatcom")