#if !defined (ORG_FOSSIL_SCM_FSL_CONFIG_H_INCLUDED) #define ORG_FOSSIL_SCM_FSL_CONFIG_H_INCLUDED /* Copyright 2013-2021 The Libfossil Authors, see LICENSES/BSD-2-Clause.txt SPDX-License-Identifier: BSD-2-Clause-FreeBSD SPDX-FileCopyrightText: 2021 The Libfossil Authors SPDX-ArtifactOfProjectName: Libfossil SPDX-FileType: Code Heavily indebted to the Fossil SCM project (https://fossil-scm.org). */ #if defined(_MSC_VER) && !defined(FSL_AMALGAMATION_BUILD) # include "config-win32.h" /* manually generated */ #else # include "autoconfig.h" /* auto-generated */ #endif #if !defined(_ISOC99_SOURCE) /* glibc apparently guards snprintf() on this #define, even though snprintf() is part of C99 and we're building in C99 mode. */ # define _ISOC99_SOURCE #endif #if !defined(_C99_SOURCE) /* Some Mac enviorments guard snprintf() on this #define but do not #define it when building in C99 mode. */ # define _C99_SOURCE #endif #ifdef _WIN32 # if defined(BUILD_libfossil_static) || defined(FSL_AMALGAMATION_BUILD) # define FSL_EXPORT extern # elif defined(BUILD_libfossil) # define FSL_EXPORT extern __declspec(dllexport) # else # define FSL_EXPORT extern __declspec(dllimport) # endif #else # define FSL_EXPORT extern #endif #if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) # if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS) /* inttypes.h needs this for the PRI* and SCN* macros in C++ mode. */ # define __STDC_FORMAT_MACROS # else # error "This tree requires a standards-compliant C99-capable compiler." # endif #endif #include <stdint.h> #include <inttypes.h> #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 /** @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 "result 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 int64_t fsl_int_t; /** The unsigned counterpart of fsl_int_t. */ typedef uint64_t fsl_uint_t; /** @def FSL_INT_T_PFMT Fossil's fsl_int_t equivalent of C99's PRIi32 and friends. */ #define FSL_INT_T_PFMT PRIi64 /** @def FSL_INT_T_SFMT Fossil's fsl_int_t equivalent of C99's SCNi32 and friends. */ #define FSL_INT_T_SFMT SCNi64 /** @def FSL_UINT_T_PFMT Fossil's fsl_uint_t equivalent of C99's PRIu32 and friends. */ #define FSL_UINT_T_PFMT PRIu64 /** @def FSL_UINT_T_SFMT Fossil's fsl_uint_t equivalent of C99's SCNu32 and friends. */ #define FSL_UINT_T_SFMT SCNu64 /** @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 and for some metrics reporting even for mid-sized repos. */ typedef uint64_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: ``` fsl_size_t sz = 3; fsl_fprintf( stdout, "%"FSL_SIZE_T_PFMT" %"FSL_SIZE_T_PFMT\n", sz, // OK! 3 // BAD! See below... ); ``` 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: ``` 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)); ``` 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 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 PRIi32 /** @def FSL_ID_T_SFMT Fossil's fsl_id_t equivalent of C99's SCNi32 and friends. */ #define FSL_ID_T_SFMT SCNi32 /** 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 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 PRIi64 /** @def FSL_TIME_T_SFMT Fossil's fsl_time_t equivalent of C99's SCNi32 and friends. */ #define FSL_TIME_T_SFMT SCNi64 /** If true, the fsl_timer_xxx() family of functions might do something useful, otherwise they do not. */ #define FSL_CONFIG_ENABLE_TIMER 1 #if !defined(FSL_SWITCH_FALL_THROUGH) # if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 7) /* #define FSL_USING_GCC gcc v7+ treats implicit 'switch' fallthrough as a warning (i.e. error because we always build with -Wall -Werror -Wextra -pedantic). Similarly braindead, clang #defines __GNUC__. _Sigh_. */ # define FSL_SWITCH_FALL_THROUGH __attribute__ ((fallthrough)) # else # define FSL_SWITCH_FALL_THROUGH # endif #endif /* /FSL_SWITCH_FALL_THROUGH TODO: add support for the C++ attributes for doing this. */ #if !defined(fsl__unused) #define fsl__unused #endif #endif /* ORG_FOSSIL_SCM_FSL_CONFIG_H_INCLUDED */