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..df49746aa 100644 --- a/libcob/common.h +++ b/libcob/common.h @@ -45,7 +45,34 @@ 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 "COB_S64_C(%"PRId64")" +#define CB_FMT_LLU_F "COB_U64_C(%"PRIu64")" + +/* 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 +80,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 "COB_S64_C(%I64d)" +#define CB_FMT_LLU_F "COB_U64_C(%I64u)" + +/* 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,33 +100,32 @@ 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" +#define CB_FMT_LLD_F "COB_S64_C(%I64d)" +#define CB_FMT_LLU_F "COB_U64_C(%I64u)" -#if defined (__MINGW32__) -#define CB_FMT_LLD_F "%I64dLL" -#define CB_FMT_LLU_F "%I64uULL" +/* 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 CB_FMT_LLD_F "%I64dI64" -#define CB_FMT_LLU_F "%I64uUI64" -#endif -#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" #define CB_FMT_PLLD "%+*.*lld" #define CB_FMT_PLLU "%*.*llu" -#define CB_FMT_LLD_F "%lldLL" -#define CB_FMT_LLU_F "%lluULL" +#define CB_FMT_LLD_F "COB_S64_C(%lld)" +#define CB_FMT_LLU_F "COB_U64_C(%llu)" #endif