From 6c1a45a4e4c31f0b829ca742b0dc373dc9089e7d Mon Sep 17 00:00:00 2001 From: David Declerck Date: Tue, 17 Oct 2023 17:20:14 +0200 Subject: [PATCH] Use inttypes.h and stdint.h where appropriate (fixes 920) --- ChangeLog | 4 +++ cobc/codegen.c | 2 +- configure.ac | 2 +- libcob/ChangeLog | 5 ++++ libcob/common.h | 71 ++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 70 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index b34676236..ac15f8e54 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ +2023-10-17 David Declerck + + * configure.ac: add checks to allow using stdint.h and inttypes.h + 2023-07-28 Simon Sobisch * configure.ac: check for mousemask and mmask_t diff --git a/cobc/codegen.c b/cobc/codegen.c index f32391606..5f6971a74 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -3135,7 +3135,7 @@ output_long_integer (cb_tree x) switch (CB_TREE_TAG (x)) { case CB_TAG_CONST: if (x == cb_zero) { - output (CB_FMT_LLD_F, 0LL); + output (CB_FMT_LLD_F, COB_S64_C(0)); } else if (x == cb_null) { output ("(cob_u8_ptr)NULL"); } else { diff --git a/configure.ac b/configure.ac index 477f877ce..a8e2dbc6b 100644 --- a/configure.ac +++ b/configure.ac @@ -583,7 +583,7 @@ dnl AC_CHECK_HEADERS([stdint.h whcar.h malloc.h]) AC_CHECK_HEADERS([sys/types.h signal.h stddef.h], [], [AC_MSG_ERROR([mandatory header could not be found or included])]) # optional: -AC_CHECK_HEADERS([sys/time.h locale.h fcntl.h dlfcn.h]) +AC_CHECK_HEADERS([sys/time.h locale.h fcntl.h dlfcn.h stdint.h inttypes.h]) # Checks for typedefs, structures, and compiler characteristics. diff --git a/libcob/ChangeLog b/libcob/ChangeLog index c47fc3186..cb58bbd1a 100644 --- a/libcob/ChangeLog +++ b/libcob/ChangeLog @@ -1,4 +1,9 @@ +2023-10-17 David Declerck + + * common.h: use stdint.h and inttypes.h when available to + define cob_s64_t, cob_u64_t and the various CB_FMT_ macros + 2023-07-28 Simon Sobisch * screenio.c, common.c: replace use of NCURSES_MOUSE_VERSION by diff --git a/libcob/common.h b/libcob/common.h index c01965eff..bd7e5e1b8 100644 --- a/libcob/common.h +++ b/libcob/common.h @@ -45,7 +45,43 @@ typedef __mpz_struct mpz_t[1]; #define cob_sli_t long int #define cob_uli_t unsigned long int -#if defined(_WIN32) && !defined(__MINGW32__) +/* If both stdint.h and inttypes.h from C99 are present, use them. + Note that recent Visual C++ (>= 2012) and most MinGW versions are + C99-compliant (even when MinGW uses the old MSVCRT, it provides + a printf compatiblity layer to support standard format strings). */ +#if defined(HAVE_STDINT_H) && defined(HAVE_INTTYPES_H) + +#include +#include + +#define cob_s64_t int64_t +#define cob_u64_t uint64_t + +#define COB_S64_C(x) INT64_C(x) +#define COB_U64_C(x) UINT64_C(x) + +#define CB_FMT_LLD "%"PRId64 +#define CB_FMT_LLU "%"PRIu64 +#define CB_FMT_LLX "%"PRIx64 +#define CB_FMT_PLLD "%+*.*"PRId64 +#define CB_FMT_PLLU "%*.*"PRIu64 +#define CB_FMT_LLD_F "%"PRId64 STR(INT64_C()) +#define CB_FMT_LLU_F "%"PRIu64 STR(UINT64_C()) + +/* The only way to retrive the proper suffix (L or LL) is by using the + INT64_C() macro. Despite expecting an argument (an integer), it is valid + to call it without an argument: it will just give us the suffix we need. + However we then have to convert it to a string: we use macro stringization + together with the double-macro "trick" below to force the argument to be + expanded before being converted to string. */ +#define STR(s) XSTR(s) +#define XSTR(s) #s + +/* If the compiler is not C99-compliant and is MSVC, then it is an old version + (stdint.h was introduced in Visual C++ 2010 and inttypes.h in 2012) ; + in this case we use the Microsoft-specific __int64 type and the + corresponding suffixes and format strings */ +#elif defined(_WIN32) && defined(MSC_VER) #define cob_s64_t __int64 #define cob_u64_t unsigned __int64 @@ -53,7 +89,19 @@ typedef __mpz_struct mpz_t[1]; #define COB_S64_C(x) x ## I64 #define COB_U64_C(x) x ## UI64 -#else +#define CB_FMT_LLD "%I64d" +#define CB_FMT_LLU "%I64u" +#define CB_FMT_LLX "%I64x" +#define CB_FMT_PLLD "%+*.*I64d" +#define CB_FMT_PLLU "%*.*I64u" +#define CB_FMT_LLD_F "%I64dI64" +#define CB_FMT_LLU_F "%I64uUI64" + +/* If the compiler is not C99-compliant and is MinGW, then it is a VERY old + MinGW-32 version (all MinGW-64 versions are C99-compliant) ; we use + the standard long long type and LL suffixes, however we have to use + the MSVCRT-specific format strings */ +#elif defined(_WIN32) && defined(__MINGW32__) #define cob_s64_t long long #define cob_u64_t unsigned long long @@ -61,26 +109,25 @@ typedef __mpz_struct mpz_t[1]; #define COB_S64_C(x) x ## LL #define COB_U64_C(x) x ## ULL -#endif - -#if defined(_WIN32) - #define CB_FMT_LLD "%I64d" #define CB_FMT_LLU "%I64u" #define CB_FMT_LLX "%I64x" #define CB_FMT_PLLD "%+*.*I64d" #define CB_FMT_PLLU "%*.*I64u" - -#if defined (__MINGW32__) #define CB_FMT_LLD_F "%I64dLL" #define CB_FMT_LLU_F "%I64uULL" -#else -#define CB_FMT_LLD_F "%I64dI64" -#define CB_FMT_LLU_F "%I64uUI64" -#endif +/* Finally, if the compiler is not C99-compliant and is neither MSVC not MinGW, + then we assume it provides the long long type as an extension, with + the usual suffixes and format strings. */ #else +#define cob_s64_t long long +#define cob_u64_t unsigned long long + +#define COB_S64_C(x) x ## LL +#define COB_U64_C(x) x ## ULL + #define CB_FMT_LLD "%lld" #define CB_FMT_LLU "%llu" #define CB_FMT_LLX "%llx"