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 5ed8c41..2fb7a32 100644 --- a/c89stringutils/c89stringutils_string_extras.c +++ b/c89stringutils/c89stringutils_string_extras.c @@ -92,22 +92,69 @@ 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; + int rc = 0; + size_t i; + if (s1 == NULL || s2 == NULL) { LOG_DEBUG("s1 or s2 is NULL"); return -1; } - rc = _strnicmp(s1, s2, n); + + 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; + int rc = 0; + size_t i = 0; + if (s1 == NULL || s2 == NULL) { LOG_DEBUG("s1 or s2 is NULL"); return -1; } - rc = _stricmp(s1, s2); + + 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; } @@ -175,6 +222,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 diff --git a/c89stringutils/c89stringutils_string_extras.h b/c89stringutils/c89stringutils_string_extras.h index 159e059..ff4a6cc 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__) || \ @@ -102,7 +106,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")