#if !defined (NET_FOSSIL_SCM_FSL_CONFIG_H_INCLUDED) #define NET_FOSSIL_SCM_FSL_CONFIG_H_INCLUDED #include "autoconfig.h" /* auto-generated */ #if HAVE_C99_INT || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 fixed integers... */ #if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS) /* inttypes.h needs this for the PRI* and SCN* macros in C++ mode. */ # define __STDC_FORMAT_MACROS #endif #include #include #define FSL_HAS_FIXED_INTEGERS 1 #else #define FSL_HAS_FIXED_INTEGERS 0 #endif /* C99 */ #if !defined(FSL_AUX_SCHEMA) #error "Expecting FSL_AUX_SCHEMA to be defined by the configuration bits." #endif #if !defined(FSL_LIBRARY_VERSION) #error "Expecting FSL_LIBRARY_VERSION to be defined by the configuration bits." #endif #if FSL_HAS_FIXED_INTEGERS /* C99 specifies fixed-size integers and their printf-compatible format specifiers, so we'll use those... */ typedef int16_t fsl_int16_t; typedef uint16_t fsl_uint16_t; typedef int32_t fsl_int32_t; typedef uint32_t fsl_uint32_t; typedef int64_t fsl_int64_t; typedef uint64_t fsl_uint64_t; #define FSL_INT32_T_PFMT PRIi32 #define FSL_INT32_T_SFMT SCNi32 #define FSL_UINT32_T_PFMT PRIu32 #define FSL_UINT32_T_SFMT SCNu32 #define FSL_INT64_T_PFMT PRIi64 #define FSL_INT64_T_SFMT SCNi64 #define FSL_UINT64_T_PFMT PRIu64 #define FSL_UINT64_T_SFMT SCNu64 #else /* Guess some reasonable defaults... See FSL_SIZE_T_PFMT for some important notes regarding formatting strings, sizeof()s, and variadic arguments. */ typedef short fsl_int16_t; typedef unsigned short fsl_uint16_t; typedef int fsl_int32_t; typedef unsigned int fsl_uint32_t; #define FSL_INT32_T_PFMT "i" #define FSL_INT32_T_SFMT "i" #define FSL_UINT32_T_PFMT "u" #define FSL_UINT32_T_SFMT "u" #if defined(HAVE_LONG_LONG) && HAVE_LONG_LONG #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 fsl_int64_t; typedef unsigned __int64 fsl_uint64_t; #else typedef long long int fsl_int64_t; typedef unsigned long long int fsl_uint64_t; #endif #define FSL_INT64_T_PFMT "lli" #define FSL_INT64_T_SFMT "lli" #define FSL_UINT64_T_PFMT "llu" #define FSL_UINT64_T_SFMT "llu" #else /* We have no long long... */ #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 fsl_int64_t; typedef unsigned __int64 fsl_uint64_t; #else /* Make up a 64-bit integer type... WARNING: on 32-bit platforms 'long' is very likely to be 4 bytes, meaning that Fossil, while "generally functional and correct," and certainly won't overrun any values on normal repos, could run into overflow problems on some operations, e.g. the /stat page of the fossil(1) repo needs to count above 2GB at times. We "could" use sqlite_int64, BUT that header isn't included yet and we cannot, for portability reasons involving some of the lower-level config macros, include that header first. We "could" include it not first, though. Okay, let's try falling back to that one... */ #include typedef sqlite3_int64 fsl_int64_t; typedef sqlite3_uint64 fsl_uint64_t; #endif /* end MSC or BORLAND */ #define FSL_INT64_T_PFMT "lli" #define FSL_INT64_T_SFMT "lli" #define FSL_UINT64_T_PFMT "llu" #define FSL_UINT64_T_SFMT "llu" #endif /* HAVE_LONG_LONG */ #endif /* end configurable numeric bits. Moving on to fixed and derived numeric bits... */ /** @typedef some_int_type fsl_int_t fsl_int_t is a signed integer type used to denote "relative" ranges and lengths, or to tell a routine that it should try to figure out the length of some byte array itself (e.g. by using fsl_strlen() on it). It is provided primarily for documentation/readability purposes, to avoid confusion with the widely varying integer semantics used by various APIs. This type is never used as a return type for functions which use "error code semantics." Those always use an unadorned integer type or some API-specific enum type. The library typedefs this to a 64-bit type if possible, else a 32-bit type. */ typedef fsl_int64_t fsl_int_t; /** The unsigned counterpart of fsl_int_t. */ typedef fsl_uint64_t fsl_uint_t; /** printf format specifier for fsl_int_t. */ #define FSL_INT_T_PFMT FSL_INT64_T_PFMT /** scanf format specifier for fsl_int_t. */ #define FSL_INT_T_SFMT FSL_INT64_T_SFMT /** printf format specifier for fsl_uint_t. */ #define FSL_UINT_T_PFMT FSL_UINT64_T_PFMT /** scanf format specifier for fsl_uint_t. */ #define FSL_UINT_T_SFMT FSL_UINT64_T_SFMT /** @def FSL_INT_T_PFMT Fossil's fsl_int_t equivalent of C99's PRIi32 and friends. */ /** @def FSL_INT_T_SFMT Fossil's fsl_int_t equivalent of C99's SCNi32 and friends. */ /** @def FSL_UINT_T_PFMT Fossil's fsl_uint_t equivalent of C99's PRIu32 and friends. */ /** @def FSL_UINT_T_SFMT Fossil's fsl_uint_t equivalent of C99's SCNu32 and friends. */ /** fsl_double_t is the double type used by the library. It is currently hard-coded to double but the API allows for it to eventually be used with long double, or potentially even with integers as a substitute (but note that Fossil generally stores times in Julian Date format, which requires double precision). */ typedef double fsl_double_t; /** @def FSL_DOUBLE_T_PFMT Fossil's fsl_double_t-equivalent of FSL_INT_T_PFMT and friends. */ #define FSL_DOUBLE_T_PFMT "f" /** @def FSL_JULIAN_T_PFMT An output format specifier for Julian-format doubles. */ #define FSL_JULIAN_T_PFMT ".17g" /** fsl_size_t is an unsigned integer type used to denote absolute ranges and lengths. It is provided primarily for documentation/readability purposes, to avoid confusion with the widely varying integer semantics used by various APIs. While a 32-bit type is legal, a 64-bit type is required for "unusually large" repos. */ typedef fsl_uint_t fsl_size_t; /** @def FSL_SIZE_T_PFMT Fossil's fsl_size_t equivalent of C99's PRIu32 and friends. ACHTUNG: when passing arguments of this type of fsl_appendf(), or any function which uses it for formatting purposes, it is very important if if you pass _literal integers_ OR enum values, that they be cast to fsl_size_t, or the va_list handling might extract the wrong number of bytes from the argument list, leading to really weird side-effects via what is effectively memory corruption. That warning applies primarily to the following typedefs and their format specifiers: fsl_size_t, fsl_int_t, fsl_uint_t, fsl_id_t. The warning does not apply to strongly-typed arguments, e.g. variables of the proper type, so long as the format specifier string matches the argument type. For example: @code fsl_size_t sz = 3; fsl_fprintf( stdout, "%"FSL_SIZE_T_PFMT" %"FSL_SIZE_T_PFMT\n", sz, // OK! 3 // BAD! See below... ); @endcode The "fix" is to cast the literal 3 to a fsl_size_t resp. the type appropriate for the format specifier. That ensures that there is no (or much less ;) confusion when va_arg() extracts arguments from the variadic array. Reminders to self: @code int i = 0; f_out(("#%d: %"FSL_ID_T_PFMT" %"FSL_ID_T_PFMT" %"FSL_ID_T_PFMT"\n", ++i, 1, 2, 3)); f_out(("#%d: %"FSL_SIZE_T_PFMT" %"FSL_ID_T_PFMT" %"FSL_SIZE_T_PFMT"\n", ++i, (fsl_size_t)1, (fsl_id_t)2, (fsl_size_t)3)); // This one is the (generally) problematic case: f_out(("#%d: %"FSL_SIZE_T_PFMT" %"FSL_ID_T_PFMT" %"FSL_SIZE_T_PFMT"\n", ++i, 1, 2, 3)); @endcode The above was Tested with gcc, clang, tcc on a 32-bit linux platform (it has not been problematic on 64-bit builds!). The above problem was reproduced on all compiler combinations i tried. Current code (20130824) seems to be behaving well as long as callers always cast to help variadic arg handling DTRT. */ #define FSL_SIZE_T_PFMT FSL_UINT_T_PFMT /** @def FSL_SIZE_T_SFMT Fossil's fsl_int_t equivalent of C99's SCNu32 and friends. */ #define FSL_SIZE_T_SFMT FSL_UINT_T_SFMT /** fsl_id_t is a signed integer type used to store database record IDs. It is provided primarily for documentation/readability purposes, to avoid confusion with the widely varying integer semantics used by various APIs. This type "could" be 32-bit (instead of 64) because the oldest/largest Fossil repo (the TCL tree, with 15 years of history) currently (August 2013) has only 131k RIDs. HOWEVER, changing this type can have side-effects vis-a-vis va_arg() deep in the fsl_appendf() implementation if FSL_ID_T_PFMT is not 100% correct for this typedef. After changing this, _make sure_ to do a full clean rebuild and test thoroughly because changing a sizeof can produce weird side-effects (effectively memory corruption) on unclean rebuilds. */ typedef fsl_int32_t fsl_id_t; /** @def FSL_ID_T_PFMT Fossil's fsl_id_t equivalent of C99's PRIi32 and friends. ACHTUNG: see FSL_SIZE_T_PFMT for important details. */ #define FSL_ID_T_PFMT FSL_INT32_T_PFMT /** @def FSL_ID_T_SFMT Fossil's fsl_id_t equivalent of C99's SCNi32 and friends. */ #define FSL_ID_T_SFMT FSL_INT32_T_SFMT /** The type used to represent type values. Unless noted otherwise, the general convention is Unix Epoch. That said, Fossil internally uses Julian Date for times, so this typedef is clearly the result of over-specification/over-thinking the problem. THAT said, application-level code more commonly works with Unix timestamps, so... here it is. Over-specified, perhaps, but not 100% unjustifiable. */ typedef fsl_int64_t fsl_time_t; /** @def FSL_TIME_T_PFMT Fossil's fsl_time_t equivalent of C99's PRIi32 and friends. */ #define FSL_TIME_T_PFMT FSL_INT64_T_PFMT /** @def FSL_TIME_T_SFMT Fossil's fsl_time_t equivalent of C99's SCNi32 and friends. */ #define FSL_TIME_T_SFMT FSL_INT64_T_SFMT #endif /* NET_FOSSIL_SCM_FSL_CONFIG_H_INCLUDED */