From 1766d490bfcfcb4b96b49644e7620657fe3eb10a Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:08:32 +1100 Subject: [PATCH 01/20] AVRO-2955: Only VS2010 or before requires /TP. Use C11 for VS2019 or later. --- lang/c/CMakeLists.txt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lang/c/CMakeLists.txt b/lang/c/CMakeLists.txt index 49e2a36bc8f..23c8c5dafb7 100644 --- a/lang/c/CMakeLists.txt +++ b/lang/c/CMakeLists.txt @@ -104,13 +104,18 @@ if(APPLE) endif(APPLE) if(CMAKE_COMPILER_IS_GNUCC) - add_definitions(-W -Wall) + add_compile_options(-W -Wall) endif(CMAKE_COMPILER_IS_GNUCC) -if (WIN32) +if (MSVC) +if(MSVC_VERSION LESS 1700) # Compile win32 in C++ to allow declarations after statements - add_definitions(/TP) -endif(WIN32) + add_compile_options(/TP) +elseif(MSVC_VERSION LESS 1920) +else() + add_compile_options(/std:c11) +endif(MSVC_VERSION LESS 1700) +endif(MSVC) # Uncomment to allow missing fields in the resolved-writer # add_definitions(-DAVRO_ALLOW_MISSING_FIELDS_IN_RESOLVED_WRITER) From a472a53b2ce16b27aa165808d387180d369f0d09 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:09:29 +1100 Subject: [PATCH 02/20] AVRO-2955: Enforcing that VS2010 or before is not supported. --- lang/c/CMakeLists.txt | 4 +++- lang/c/README.maintaining_win32.txt | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lang/c/CMakeLists.txt b/lang/c/CMakeLists.txt index 23c8c5dafb7..76e51154da3 100644 --- a/lang/c/CMakeLists.txt +++ b/lang/c/CMakeLists.txt @@ -109,8 +109,10 @@ endif(CMAKE_COMPILER_IS_GNUCC) if (MSVC) if(MSVC_VERSION LESS 1700) - # Compile win32 in C++ to allow declarations after statements + # Compile as C++ to allow declarations after statements. (C11 feature) add_compile_options(/TP) + # However, this does not work as the code is not C++ compliant either. + message(FATAL_ERROR "MSVC_VERSION(${MSVC_VERSION}) is not supported.") elseif(MSVC_VERSION LESS 1920) else() add_compile_options(/std:c11) diff --git a/lang/c/README.maintaining_win32.txt b/lang/c/README.maintaining_win32.txt index b603b1ec3cc..13dcc64867a 100644 --- a/lang/c/README.maintaining_win32.txt +++ b/lang/c/README.maintaining_win32.txt @@ -31,6 +31,11 @@ Limitations of Windows Build: statements were removed, that Avro-C would compile under Microsoft's C compiler also. I have not tried this. + Note: This is referring to a C11 feature which is supported from VS2013 + onward. However, compiling as C++ does not work as the code is not C++ + compliant either. Basically, VS2010 or before just cannot be supported + unless significant changes are made to the code. + 2. The shared library, i.e. DLL, for avro has not been built. There are instructions on how to build DLLs using CMake at https://www.cmake.org/Wiki/BuildingWinDLL From 15c7d375f5bde7687b94c23ed7674cfda908033e Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:10:24 +1100 Subject: [PATCH 03/20] AVRO-2955: Conditional compile GCC only features. --- lang/c/src/dump.h | 4 ++++ lang/c/src/st.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lang/c/src/dump.h b/lang/c/src/dump.h index 23e8066724e..e374dd2bc11 100644 --- a/lang/c/src/dump.h +++ b/lang/c/src/dump.h @@ -26,9 +26,13 @@ extern "C" { #include +#ifdef __GNUC__ #pragma GCC visibility push(hidden) +#endif void dump(FILE * out, const char *addr, const long len); +#ifdef __GNUC__ #pragma GCC visibility pop +#endif CLOSE_EXTERN #endif diff --git a/lang/c/src/st.h b/lang/c/src/st.h index 93da018bd9b..1d0f892253f 100644 --- a/lang/c/src/st.h +++ b/lang/c/src/st.h @@ -18,7 +18,9 @@ extern "C" { #include /* for uintptr_t */ +#ifdef __GNUC__ #pragma GCC visibility push(hidden) +#endif #ifdef _WIN32 typedef int (__cdecl *hash_function_compare)(void*, void*); @@ -77,7 +79,9 @@ st_table *st_copy _((st_table *)); int st_strhash(); +#ifdef __GNUC__ #pragma GCC visibility pop +#endif CLOSE_EXTERN #endif /* ST_INCLUDED */ From 1cb9ec3df39a59e2237917d519e967ff9d9f181b Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:11:19 +1100 Subject: [PATCH 04/20] AVRO-2955: Fix missing typedef of ssize_t for MSVC. --- lang/c/src/avro_generic_internal.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lang/c/src/avro_generic_internal.h b/lang/c/src/avro_generic_internal.h index 9843ed65285..f3fa9c279a4 100644 --- a/lang/c/src/avro_generic_internal.h +++ b/lang/c/src/avro_generic_internal.h @@ -30,6 +30,14 @@ extern "C" { #include "avro/schema.h" #include "avro/value.h" +#ifdef _MSC_VER +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef int ssize_t; +#endif +#endif + /* * Each generic value implementation struct defines a couple of extra * methods that we use to control the lifecycle of the value objects. From 03e87c4b5856bc7a535ccad4596906fb0ee1a6c0 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:12:10 +1100 Subject: [PATCH 05/20] AVRO-2955: Newer MSVC has its own stdint.h and inttypes.h. --- lang/c/src/avro/msinttypes.h | 4 ++++ lang/c/src/avro/msstdint.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lang/c/src/avro/msinttypes.h b/lang/c/src/avro/msinttypes.h index 29be14b9512..1dea1009a4c 100644 --- a/lang/c/src/avro/msinttypes.h +++ b/lang/c/src/avro/msinttypes.h @@ -33,6 +33,9 @@ #error "Use this header only with Microsoft Visual C++ compilers!" #endif // _MSC_VER ] +#if _MSC_VER >= 1700 +#include +#else #ifndef _MSC_INTTYPES_H_ // [ #define _MSC_INTTYPES_H_ @@ -313,3 +316,4 @@ imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) #endif // _MSC_INTTYPES_H_ ] +#endif diff --git a/lang/c/src/avro/msstdint.h b/lang/c/src/avro/msstdint.h index d02608a5972..3f96c5cd104 100644 --- a/lang/c/src/avro/msstdint.h +++ b/lang/c/src/avro/msstdint.h @@ -33,6 +33,9 @@ #error "Use this header only with Microsoft Visual C++ compilers!" #endif // _MSC_VER ] +#if _MSC_VER >= 1600 +#include +#else #ifndef _MSC_STDINT_H_ // [ #define _MSC_STDINT_H_ @@ -245,3 +248,4 @@ typedef uint64_t uintmax_t; #endif // _MSC_STDINT_H_ ] +#endif From 3a54547b56f0d2297347976dc6681cc62a8cde51 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:13:16 +1100 Subject: [PATCH 06/20] AVRO-2955: Do not define snprintf as macro for VS2019 or later. --- lang/c/src/avro_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/c/src/avro_private.h b/lang/c/src/avro_private.h index f97ef6b5a71..caf4163c2d3 100644 --- a/lang/c/src/avro_private.h +++ b/lang/c/src/avro_private.h @@ -33,7 +33,7 @@ extern "C" { #include "config.h" #endif -#ifdef _WIN32 +#if defined(_MSC_VER) && _MSC_VER < 1900 && !defined(snprintf) #define snprintf _snprintf #endif From f0946c8936d3f45daad5e64494eaeb6814a56087 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:14:17 +1100 Subject: [PATCH 07/20] AVRO-2955: Fix strrchr() returns const char* in newer MSVC. --- lang/c/src/schema.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/c/src/schema.c b/lang/c/src/schema.c index a4d8e9f898a..cc50cb4c6c6 100644 --- a/lang/c/src/schema.c +++ b/lang/c/src/schema.c @@ -74,7 +74,7 @@ static int is_avro_id(const char *name) * namespace (as a newly allocated buffer using Avro's allocator). */ static char *split_namespace_name(const char *fullname, const char **name_out) { - char *last_dot = strrchr(fullname, '.'); + const char *last_dot = strrchr(fullname, '.'); if (last_dot == NULL) { *name_out = fullname; return NULL; From 369a576f07e053395d9314f30a3b5116fc60de1a Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:15:34 +1100 Subject: [PATCH 08/20] AVRO-2955: Fix MSVC does not support empty struct. --- lang/c/src/generic.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lang/c/src/generic.c b/lang/c/src/generic.c index e614eb3f823..0767fa9b329 100644 --- a/lang/c/src/generic.c +++ b/lang/c/src/generic.c @@ -2850,11 +2850,16 @@ typedef struct avro_generic_record_value_iface { avro_generic_value_iface_t **field_ifaces; } avro_generic_record_value_iface_t; +#ifdef _MSC_VER +typedef struct avro_generic_record avro_generic_record_t; +#define SIZEOF_avro_generic_record_t 0 +#else typedef struct avro_generic_record { /* The rest of the struct is taken up by the inline storage * needed for each field. */ } avro_generic_record_t; - +#define SIZEOF_avro_generic_record_t sizeof(avro_generic_record_t) +#endif /** Return a pointer to the given field within a record struct. */ #define avro_generic_record_field(iface, rec, index) \ @@ -3123,11 +3128,11 @@ avro_generic_record_class(avro_schema_t schema, memoize_state_t *state) } } - size_t next_offset = sizeof(avro_generic_record_t); + size_t next_offset = SIZEOF_avro_generic_record_t; #if DEBUG_FIELD_OFFSETS fprintf(stderr, " Record %s\n Header: Offset 0, size %" PRIsz "\n", avro_schema_type_name(schema), - sizeof(avro_generic_record_t)); + SIZEOF_avro_generic_record_t); #endif size_t i; for (i = 0; i < iface->field_count; i++) { From 5c3c7da887622edbc8c14b22e65646d77f3388a4 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:16:18 +1100 Subject: [PATCH 09/20] AVRO-2955: Avoid non-Windows headers. --- lang/c/src/avroappend.c | 2 +- lang/c/tests/test_interop_data.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lang/c/src/avroappend.c b/lang/c/src/avroappend.c index 7243c6009bd..84a38099872 100644 --- a/lang/c/src/avroappend.c +++ b/lang/c/src/avroappend.c @@ -19,7 +19,7 @@ #include #include #include -#ifdef _WIN32 +#ifndef _WIN32 #include #endif diff --git a/lang/c/tests/test_interop_data.c b/lang/c/tests/test_interop_data.c index 4738f318298..f87828ef845 100644 --- a/lang/c/tests/test_interop_data.c +++ b/lang/c/tests/test_interop_data.c @@ -17,9 +17,11 @@ #include "avro.h" #include "avro_private.h" -#include #include #include +#ifndef _WIN32 +#include +#endif int should_test(char *d_name) { From cb56547ada2219d83403d3474e679d7d251f52d1 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:16:48 +1100 Subject: [PATCH 10/20] AVRO-2955: Define _CRT_SECURE_NO_WARNINGS to reduce compiler warnings. --- lang/c/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/lang/c/CMakeLists.txt b/lang/c/CMakeLists.txt index 76e51154da3..efd46d19354 100644 --- a/lang/c/CMakeLists.txt +++ b/lang/c/CMakeLists.txt @@ -108,6 +108,7 @@ if(CMAKE_COMPILER_IS_GNUCC) endif(CMAKE_COMPILER_IS_GNUCC) if (MSVC) +add_definitions(-D_CRT_SECURE_NO_WARNINGS) if(MSVC_VERSION LESS 1700) # Compile as C++ to allow declarations after statements. (C11 feature) add_compile_options(/TP) From db2ad890c4d64fc41ed7e37892a4398449ba301e Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:17:29 +1100 Subject: [PATCH 11/20] AVRO-2955: MSVC offers _stricmp() instead of strcasecmp(). --- lang/c/tests/test_avro_data.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lang/c/tests/test_avro_data.c b/lang/c/tests/test_avro_data.c index 3a26c67e242..3406d8cba36 100644 --- a/lang/c/tests/test_avro_data.c +++ b/lang/c/tests/test_avro_data.c @@ -22,6 +22,10 @@ #include #include +#ifdef _MSC_VER +#define strcasecmp _stricmp +#endif + char buf[4096]; avro_reader_t reader; avro_writer_t writer; From 330ac84d4ceaaa6106cefd81226e129d7d29bff8 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:18:03 +1100 Subject: [PATCH 12/20] AVRO-2955: Fix running tests with ninja. --- lang/c/examples/CMakeLists.txt | 6 +++++- lang/c/tests/CMakeLists.txt | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lang/c/examples/CMakeLists.txt b/lang/c/examples/CMakeLists.txt index 1c96b71c48a..6607836b6be 100644 --- a/lang/c/examples/CMakeLists.txt +++ b/lang/c/examples/CMakeLists.txt @@ -21,7 +21,11 @@ add_executable(quickstop quickstop.c) target_link_libraries(quickstop avro-static) if (WIN32) - set(exec_name ${CMAKE_CURRENT_BINARY_DIR}/Debug/quickstop.exe) + if (CMAKE_GENERATOR MATCHES "Ninja") + set(exec_name ${CMAKE_CURRENT_BINARY_DIR}/quickstop.exe) + else(CMAKE_GENERATOR MATCHES "Ninja") + set(exec_name ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/quickstop.exe) + endif(CMAKE_GENERATOR MATCHES "Ninja") else (WIN32) set(exec_name ${CMAKE_CURRENT_BINARY_DIR}/quickstop) endif (WIN32) diff --git a/lang/c/tests/CMakeLists.txt b/lang/c/tests/CMakeLists.txt index 3200164770d..7842d1a5683 100644 --- a/lang/c/tests/CMakeLists.txt +++ b/lang/c/tests/CMakeLists.txt @@ -29,7 +29,11 @@ endmacro(add_avro_executable) macro(add_avro_test name) add_avro_executable(${name} ${ARGN}) if (WIN32) - set(exec_name ${CMAKE_CURRENT_BINARY_DIR}/Debug/${name}.exe) + if (CMAKE_GENERATOR MATCHES "Ninja") + set(exec_name ${CMAKE_CURRENT_BINARY_DIR}/${name}.exe) + else(CMAKE_GENERATOR MATCHES "Ninja") + set(exec_name ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${name}.exe) + endif(CMAKE_GENERATOR MATCHES "Ninja") else (WIN32) set(exec_name ${CMAKE_CURRENT_BINARY_DIR}/${name}) endif (WIN32) From ca08ce801b3a4d882db913d01bfe41bba4479671 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:18:58 +1100 Subject: [PATCH 13/20] AVRO-2955: Use opendir()/readdir() from "msdirent.h" for Windows. --- lang/c/tests/test_interop_data.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lang/c/tests/test_interop_data.c b/lang/c/tests/test_interop_data.c index f87828ef845..9875f471a54 100644 --- a/lang/c/tests/test_interop_data.c +++ b/lang/c/tests/test_interop_data.c @@ -19,7 +19,9 @@ #include "avro_private.h" #include #include -#ifndef _WIN32 +#ifdef _WIN32 +#include "msdirent.h" +#else #include #endif From ccfe2241a885616e79e6ebcb184ec0ac82d70d15 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:19:31 +1100 Subject: [PATCH 14/20] AVRO-2955: Fix file mode. --- lang/c/tests/test_avro_766.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 lang/c/tests/test_avro_766.c diff --git a/lang/c/tests/test_avro_766.c b/lang/c/tests/test_avro_766.c old mode 100755 new mode 100644 From af23ba37ed619d015107aef069a7b3c9d02d8783 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:19:59 +1100 Subject: [PATCH 15/20] AVRO-2955: VS2013 or before does not support inline keyword. --- lang/c/src/avro/refcount.h | 4 ++++ lang/c/src/value-hash.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lang/c/src/avro/refcount.h b/lang/c/src/avro/refcount.h index fd431f3ccea..8626738691e 100644 --- a/lang/c/src/avro/refcount.h +++ b/lang/c/src/avro/refcount.h @@ -23,6 +23,10 @@ #include #endif +#if defined(_MSC_VER) && _MSC_VER < 1900 && !defined(__cplusplus) +#define inline __inline +#endif + #ifdef __cplusplus extern "C" { #define CLOSE_EXTERN } diff --git a/lang/c/src/value-hash.c b/lang/c/src/value-hash.c index c717924be80..b37f94a830e 100644 --- a/lang/c/src/value-hash.c +++ b/lang/c/src/value-hash.c @@ -25,6 +25,10 @@ #include "avro/value.h" #include "avro_private.h" +#if defined(_MSC_VER) && _MSC_VER < 1900 && !defined(__cplusplus) +#define inline __inline +#endif + #define check_return(retval, call) \ do { \ int rval = call; \ From ea49e5c261ddfe6124a1d8725459b0d7a7962b2e Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:21:10 +1100 Subject: [PATCH 16/20] AVRO-2955: Fix C++ compliance for VS2010. --- lang/c/src/schema.c | 4 ++++ lang/c/tests/test_interop_data.c | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lang/c/src/schema.c b/lang/c/src/schema.c index cc50cb4c6c6..3d762b594fa 100644 --- a/lang/c/src/schema.c +++ b/lang/c/src/schema.c @@ -32,6 +32,10 @@ #include "st.h" #include "schema.h" +#if defined(_MSC_VER) && _MSC_VER < 1700 && defined(__cplusplus) +#define namespace _Namespace +#endif + #define DEFAULT_TABLE_SIZE 32 /* forward declaration */ diff --git a/lang/c/tests/test_interop_data.c b/lang/c/tests/test_interop_data.c index 9875f471a54..354d5d2c4e1 100644 --- a/lang/c/tests/test_interop_data.c +++ b/lang/c/tests/test_interop_data.c @@ -35,7 +35,7 @@ int should_test(char *d_name) } ptrdiff_t diff = d_name + strlen(d_name) - ext_pos; - char *substr = malloc(sizeof(char) * diff); + char *substr = (char *) malloc(sizeof(char) * diff); strncpy(substr, ext_pos + 1, diff - 1); *(substr + diff - 1) = '\0'; if (strcmp(substr, "avro") != 0) @@ -57,7 +57,7 @@ int should_test(char *d_name) } diff = ext_pos - codec_pos; - substr = malloc(sizeof(char) * diff); + substr = (char *) malloc(sizeof(char) * diff); strncpy(substr, codec_pos + 1, diff - 1); *(substr + diff - 1) = '\0'; if (strcmp(substr, "deflate") == 0 || strcmp(substr, "snappy") == 0) @@ -96,7 +96,7 @@ int main(int argc, char *argv[]) char *d_name = ent->d_name; size_t d_name_len = strlen(d_name); size_t size = strlen(argv[1]) + d_name_len + 2; - char* path = malloc(sizeof(char) * size); + char* path = (char *) malloc(sizeof(char) * size); sprintf(path, "%s/%s", argv[1], d_name); if (!should_test(d_name)) From 612a4e3562e4bcbabc238d80e8bb564fd6a1e431 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Sat, 7 Nov 2020 23:21:40 +1100 Subject: [PATCH 17/20] AVRO-2955: Fix VS2010 support. --- lang/c/CMakeLists.txt | 23 ++++++++++++----------- lang/c/README.maintaining_win32.txt | 6 ++---- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/lang/c/CMakeLists.txt b/lang/c/CMakeLists.txt index efd46d19354..471990cb85a 100644 --- a/lang/c/CMakeLists.txt +++ b/lang/c/CMakeLists.txt @@ -107,17 +107,18 @@ if(CMAKE_COMPILER_IS_GNUCC) add_compile_options(-W -Wall) endif(CMAKE_COMPILER_IS_GNUCC) -if (MSVC) -add_definitions(-D_CRT_SECURE_NO_WARNINGS) -if(MSVC_VERSION LESS 1700) - # Compile as C++ to allow declarations after statements. (C11 feature) - add_compile_options(/TP) - # However, this does not work as the code is not C++ compliant either. - message(FATAL_ERROR "MSVC_VERSION(${MSVC_VERSION}) is not supported.") -elseif(MSVC_VERSION LESS 1920) -else() - add_compile_options(/std:c11) -endif(MSVC_VERSION LESS 1700) +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + if(MSVC_VERSION LESS 1700) + # VS2010 and earlier. + # Compile as C++ to allow declarations after statements. (C11 feature) + add_compile_options(/TP) + elseif(MSVC_VERSION LESS 1920) + # VS2013|VS2015|VS2017 + else() + # VS2019 and later. + add_compile_options(/std:c11) + endif(MSVC_VERSION LESS 1700) endif(MSVC) # Uncomment to allow missing fields in the resolved-writer diff --git a/lang/c/README.maintaining_win32.txt b/lang/c/README.maintaining_win32.txt index 13dcc64867a..237311ced29 100644 --- a/lang/c/README.maintaining_win32.txt +++ b/lang/c/README.maintaining_win32.txt @@ -31,10 +31,8 @@ Limitations of Windows Build: statements were removed, that Avro-C would compile under Microsoft's C compiler also. I have not tried this. - Note: This is referring to a C11 feature which is supported from VS2013 - onward. However, compiling as C++ does not work as the code is not C++ - compliant either. Basically, VS2010 or before just cannot be supported - unless significant changes are made to the code. + Note: This is referring to a C11 feature which is supported in VS2013 + and later. 2. The shared library, i.e. DLL, for avro has not been built. There are instructions on how to build DLLs using CMake at From 7de8437e0ada504a2b8574947ac30542b780bb7f Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Fri, 13 Nov 2020 08:03:09 +1100 Subject: [PATCH 18/20] AVRO-2955: Fix z_stream buffer pointer assignment. --- lang/c/src/codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/c/src/codec.c b/lang/c/src/codec.c index 613a914373a..b29f6b7e379 100644 --- a/lang/c/src/codec.c +++ b/lang/c/src/codec.c @@ -340,7 +340,7 @@ static int decode_deflate(avro_codec_t c, void * data, int64_t len) if (err == Z_BUF_ERROR) { c->block_data = avro_realloc(c->block_data, c->block_size, c->block_size * 2); - s->next_out = c->block_data + s->total_out; + s->next_out = (Bytef*) c->block_data + s->total_out; s->avail_out += c->block_size; c->block_size = c->block_size * 2; } From 1260449a916c3f304cad79cc13abdf2d2a1b52d2 Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Thu, 3 Feb 2022 09:58:53 +1100 Subject: [PATCH 19/20] AVRO-2955: Build avromod and avropipe for Windows Import getopt_long() from FreeBSD. --- lang/c/src/CMakeLists.txt | 11 +- lang/c/src/avromod.c | 18 +- lang/c/src/avropipe.c | 16 +- lang/c/src/getopt/getopt.h | 93 +++++ lang/c/src/getopt/getopt_long.c | 644 ++++++++++++++++++++++++++++++++ 5 files changed, 775 insertions(+), 7 deletions(-) create mode 100644 lang/c/src/getopt/getopt.h create mode 100644 lang/c/src/getopt/getopt_long.c diff --git a/lang/c/src/CMakeLists.txt b/lang/c/src/CMakeLists.txt index c1761c8defb..3794d9a0f27 100644 --- a/lang/c/src/CMakeLists.txt +++ b/lang/c/src/CMakeLists.txt @@ -138,13 +138,18 @@ add_executable(avroappend avroappend.c) target_link_libraries(avroappend avro-static) install(TARGETS avroappend RUNTIME DESTINATION bin) -if (NOT WIN32) -#TODO: Port getopt() to Windows to compile avropipe.c and avromod.c +if(MSVC) +add_executable(avropipe avropipe.c getopt/getopt_long.c) +else(MSVC) add_executable(avropipe avropipe.c) +endif(MSVC) target_link_libraries(avropipe avro-static) install(TARGETS avropipe RUNTIME DESTINATION bin) +if(MSVC) +add_executable(avromod avromod.c getopt/getopt_long.c) +else(MSVC) add_executable(avromod avromod.c) +endif(MSVC) target_link_libraries(avromod avro-static) install(TARGETS avromod RUNTIME DESTINATION bin) -endif(NOT WIN32) diff --git a/lang/c/src/avromod.c b/lang/c/src/avromod.c index 7415d6e2fcd..e25923a4bee 100644 --- a/lang/c/src/avromod.c +++ b/lang/c/src/avromod.c @@ -16,11 +16,15 @@ */ #include -#include #include #include #include #include +#ifdef _WIN32 +#include "getopt/getopt.h" +#else +#include +#endif #include "avro.h" #include "avro_private.h" @@ -130,6 +134,15 @@ int main(int argc, char **argv) char *in_filename; char *out_filename; +#ifdef _MSC_VER + { + const char *cp = argv[0] + strlen(argv[0]); + while (cp > argv[0] && *(cp-1) != '/' && *(cp-1) != '\\' && *(cp-1) != ':') + --cp; + opt_progname = cp; + } +#endif + int ch; while ((ch = getopt_long(argc, argv, "b:c:", longopts, NULL)) != -1) { switch (ch) { @@ -157,7 +170,8 @@ int main(int argc, char **argv) in_filename = NULL; out_filename = argv[0]; } else { - fprintf(stderr, "Can't read from multiple input files.\n"); + if (argc > 2) + fprintf(stderr, "Can't read from multiple input files.\n"); usage(); exit(1); } diff --git a/lang/c/src/avropipe.c b/lang/c/src/avropipe.c index 7bda1253491..0a11e03131a 100644 --- a/lang/c/src/avropipe.c +++ b/lang/c/src/avropipe.c @@ -17,12 +17,15 @@ #include #include -#include -#include #include #include #include #include +#ifdef _WIN32 +#include "getopt/getopt.h" +#else +#include +#endif #include "avro.h" #include "avro_private.h" @@ -400,6 +403,15 @@ int main(int argc, char **argv) { char *data_filename; +#ifdef _MSC_VER + { + const char *cp = argv[0] + strlen(argv[0]); + while (cp > argv[0] && *(cp-1) != '/' && *(cp-1) != '\\' && *(cp-1) != ':') + --cp; + opt_progname = cp; + } +#endif + int ch; while ((ch = getopt_long(argc, argv, "s:", longopts, NULL) ) != -1) { switch (ch) { diff --git a/lang/c/src/getopt/getopt.h b/lang/c/src/getopt/getopt.h new file mode 100644 index 00000000000..fb85b9e26a3 --- /dev/null +++ b/lang/c/src/getopt/getopt.h @@ -0,0 +1,93 @@ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ +/* $FreeBSD$ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * 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 NETBSD FOUNDATION, INC. AND 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 FOUNDATION OR 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. + */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +#ifdef __CYGWIN__ +#error Not for cygwin. +#endif + +#ifdef unix +#include +#endif + +/* + * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension. + * getopt() is declared here too for GNU programs. + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +#ifdef __FreeBSD__ +__BEGIN_DECLS +#endif +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); +#ifndef _GETOPT_DECLARED +#define _GETOPT_DECLARED +int getopt(int, char * const [], const char *); + +extern char *optarg; /* getopt(3) external variables */ +extern int optind, opterr, optopt; +#endif +#ifndef _OPTRESET_DECLARED +#define _OPTRESET_DECLARED +extern int optreset; /* getopt(3) external variable */ +#endif +#ifdef _MSC_VER +extern const char *opt_progname; +#endif +#ifdef __FreeBSD__ +__END_DECLS +#endif + +#endif /* !_GETOPT_H_ */ diff --git a/lang/c/src/getopt/getopt_long.c b/lang/c/src/getopt/getopt_long.c new file mode 100644 index 00000000000..d88b87d7fad --- /dev/null +++ b/lang/c/src/getopt/getopt_long.c @@ -0,0 +1,644 @@ +/* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ + +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * 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 NETBSD FOUNDATION, INC. AND 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 FOUNDATION OR 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 __CYGWIN__ +#error Not for cygwin. +#endif + +#if 0 +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ +#endif +#ifdef unix +#include +#endif +#ifdef __FreeBSD__ +__FBSDID("$FreeBSD$"); +#endif + +#include +#include +#include +#ifndef _MSC_VER +#include +#include +#else +#include +#include +#include "getopt.h" +#endif + +#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ + +#if 1 /* we prefer to keep our getopt(3) */ +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ +#endif + +#ifdef REPLACE_GETOPT +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset = 0; /* reset getopt */ +char *optarg = NULL; /* argument associated with option */ +#endif + +#ifdef _MSC_VER +const char *opt_progname = NULL; +#endif + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +static char EMSG[] = ""; + +#ifdef GNU_COMPATIBLE +#define NO_PREFIX (-1) +#define D_PREFIX 0 +#define DD_PREFIX 1 +#define W_PREFIX 2 +#endif + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */ +#ifdef GNU_COMPATIBLE +static int dash_prefix = NO_PREFIX; +static const char gnuoptchar[] = "invalid option -- %c"; + +static const char recargstring[] = "option `%s%s' requires an argument"; +static const char ambig[] = "option `%s%.*s' is ambiguous"; +static const char noarg[] = "option `%s%.*s' doesn't allow an argument"; +static const char illoptstring[] = "unrecognized option `%s%s'"; +#else +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptstring[] = "unknown option -- %s"; +#endif + +#ifdef _MSC_VER +static void warnx(const char *fmt, ...) { + va_list va; + if (opt_progname && *opt_progname) + fprintf(stderr, "%s: ", opt_progname); + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); + fputc('\n', stderr); +} +#endif + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too, int flags) +{ + char *current_argv, *has_equal; +#ifdef GNU_COMPATIBLE + const char *current_dash; +#endif + size_t current_argv_len; + int i, match, exact_match, second_partial_match; + + current_argv = place; +#ifdef GNU_COMPATIBLE + switch (dash_prefix) { + case D_PREFIX: + current_dash = "-"; + break; + case DD_PREFIX: + current_dash = "--"; + break; + case W_PREFIX: + current_dash = "-W "; + break; + default: + current_dash = ""; + break; + } +#endif + match = -1; + exact_match = 0; + second_partial_match = 0; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + exact_match = 1; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* first partial match */ + match = i; + else if ((flags & FLAG_LONGONLY) || + long_options[i].has_arg != + long_options[match].has_arg || + long_options[i].flag != long_options[match].flag || + long_options[i].val != long_options[match].val) + second_partial_match = 1; + } + if (!exact_match && second_partial_match) { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; +#ifdef GNU_COMPATIBLE + return (BADCH); +#else + return (BADARG); +#endif + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + const char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1 || optreset) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + if (*options == '+' || *options == '-') + options++; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || +#ifdef GNU_COMPATIBLE + place[1] == '\0') { +#else + (place[1] == '\0' && strchr(options, '-') == NULL)) { +#endif + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; +#ifdef GNU_COMPATIBLE + dash_prefix = D_PREFIX; +#endif + if (*place == '-') { + place++; /* --foo long option */ + if (*place == '\0') + return (BADARG); /* malformed option */ +#ifdef GNU_COMPATIBLE + dash_prefix = DD_PREFIX; +#endif + } else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too, flags); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; +#ifdef GNU_COMPATIBLE + if (PRINT_ERROR) + warnx(posixly_correct ? illoptchar : gnuoptchar, + optchar); +#else + if (PRINT_ERROR) + warnx(illoptchar, optchar); +#endif + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; +#ifdef GNU_COMPATIBLE + dash_prefix = W_PREFIX; +#endif + optchar = parse_long_options(nargv, options, long_options, + idx, 0, flags); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif /* REPLACE_GETOPT */ + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} From fffe6a73bad22434f07de0368e283b5f1d2e424c Mon Sep 17 00:00:00 2001 From: Kelvin Lee Date: Thu, 3 Feb 2022 20:29:33 +1100 Subject: [PATCH 20/20] AVRO-2955: Add copyright notice for getopt --- lang/c/NOTICE | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/lang/c/NOTICE b/lang/c/NOTICE index 5562db8476c..cad58d88cf0 100644 --- a/lang/c/NOTICE +++ b/lang/c/NOTICE @@ -4,3 +4,54 @@ Copyright 2010 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). +lang/c/src/getopt/getopt_long.c and lang/c/src/getopt/getopt.h are taken +from The FreeBSD Project and they have the following copyright notice: +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * 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 NETBSD FOUNDATION, INC. AND 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 FOUNDATION OR 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. + */