libcompat.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * Check: a unit test framework for C
  3. * Copyright (C) 2001, 2002 Arien Malec
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the
  17. * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  18. * MA 02110-1301, USA.
  19. */
  20. #ifndef LIBCOMPAT_H
  21. #define LIBCOMPAT_H
  22. #if HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. /**
  26. * __GNUC_PATCHLEVEL__ is new to GCC 3.0;
  27. * it is also present in the widely-used development snapshots leading up to 3.0
  28. * (which identify themselves as GCC 2.96 or 2.97, depending on which snapshot you have).
  29. *
  30. * https://stackoverflow.com/questions/1936719/what-are-the-gcc-predefined-macros-for-the-compilers-version-number/1936745#1936745
  31. */
  32. #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
  33. #define GCC_VERSION_AT_LEAST(major, minor, patch) \
  34. ((__GNUC__ > (major)) || \
  35. (__GNUC__ == (major) && __GNUC_MINOR__ > (minor)) || \
  36. (__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patch)) )
  37. #elif defined(__GNUC__) && defined(__GNUC_MINOR__)
  38. #define GCC_VERSION_AT_LEAST(major, minor, patch) \
  39. ((__GNUC__ > (major)) || \
  40. (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
  41. #else
  42. #define GCC_VERSION_AT_LEAST(major, minor, patch) 0
  43. #endif
  44. #if GCC_VERSION_AT_LEAST(2,95,3)
  45. #define CK_ATTRIBUTE_UNUSED __attribute__ ((unused))
  46. #define CK_ATTRIBUTE_FORMAT(a, b, c) __attribute__ ((format (a, b, c)))
  47. #else
  48. #define CK_ATTRIBUTE_UNUSED
  49. #define CK_ATTRIBUTE_FORMAT(a, b, c)
  50. #endif /* GCC 2.95 */
  51. #if GCC_VERSION_AT_LEAST(2,5,0)
  52. #define CK_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
  53. #else
  54. #define CK_ATTRIBUTE_NORETURN
  55. #endif /* GCC 2.5 */
  56. #if GCC_VERSION_AT_LEAST(4,7,4) && (__STDC_VERSION__ >= 199901L)
  57. /* Operator _Pragma introduced in C99 */
  58. #define CK_DIAGNOSTIC_STRINGIFY(x) #x
  59. #define CK_DIAGNOSTIC_HELPER1(y) CK_DIAGNOSTIC_STRINGIFY(GCC diagnostic ignored y)
  60. #define CK_DIAGNOSTIC_HELPER2(z) CK_DIAGNOSTIC_HELPER1(#z)
  61. #define CK_DIAGNOSTIC_PUSH_IGNORE(w) \
  62. _Pragma("GCC diagnostic push") \
  63. _Pragma(CK_DIAGNOSTIC_HELPER2(w))
  64. #define CK_DIAGNOSTIC_POP(w) _Pragma ("GCC diagnostic pop")
  65. #else
  66. #define CK_DIAGNOSTIC_PUSH_IGNORE(w)
  67. #define CK_DIAGNOSTIC_POP(w)
  68. #endif /* GCC 4.7.4 */
  69. /*
  70. * Used for MSVC to create the export attribute
  71. * CK_DLL_EXP is defined during the compilation of the library
  72. * on the command line.
  73. */
  74. #ifndef CK_DLL_EXP
  75. #define CK_DLL_EXP
  76. #endif
  77. #if defined(_MSC_VER)
  78. #include <WinSock2.h> /* struct timeval, API used in gettimeofday implementation */
  79. #include <io.h> /* read, write */
  80. #include <process.h> /* getpid */
  81. #endif /* _MSC_VER */
  82. /*
  83. * On some not so old version of Visual Studio (< 2015), or with mingw-w64 not
  84. * supporting POSIX printf family function, use the size prefix specifiers
  85. * in msvcrt.dll. See the following link for the list of the size prefix
  86. * specifiers:
  87. * https://docs.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=vs-2019
  88. */
  89. #ifdef _WIN32
  90. #define CK_FMT_ZU "%Iu"
  91. #define CK_FMT_ZD "%Id"
  92. #define CK_FMT_TD "%Id"
  93. #else
  94. #define CK_FMT_ZU "%zu"
  95. #define CK_FMT_ZD "%zd"
  96. #define CK_FMT_TD "%td"
  97. #endif
  98. /* defines size_t */
  99. #include <sys/types.h>
  100. /* provides assert */
  101. #include <assert.h>
  102. /* defines FILE */
  103. #include <stdio.h>
  104. /* defines exit() */
  105. #include <stdlib.h>
  106. /* defines NAN, INFINITY, isnan(), isinf(), isfinite() */
  107. #include <math.h>
  108. /* However, some older Visual Studio Versions do not */
  109. #if !defined(INFINITY) || !defined(NAN)
  110. extern double DOUBLE_ZERO;
  111. #define INFINITY (1.0/DOUBLE_ZERO)
  112. #define NAN (DOUBLE_ZERO/DOUBLE_ZERO)
  113. #endif
  114. #if !defined(isnan) || !defined(isinf) || !defined(isfinite)
  115. #define NEED_fpclassify
  116. extern int fpclassify(double d);
  117. #define FP_INFINITE (1)
  118. #define FP_NAN (2)
  119. #define FP_ZERO (4)
  120. #define FP_NORMAL (8)
  121. #define FP_SUBNORMAL (16)
  122. #define isnan(x) ((fpclassify((double)(x)) & FP_NAN) == FP_NAN)
  123. #define isinf(x) ((fpclassify((double)(x)) & FP_INFINITE) == FP_INFINITE)
  124. #define isfinite(x) ((fpclassify((double)(x)) & (FP_NAN|FP_INFINITE)) == 0)
  125. #endif
  126. /* provides localtime and struct tm */
  127. #ifdef HAVE_SYS_TIME_H
  128. #include <sys/time.h>
  129. #endif /* !HAVE_SYS_TIME_H */
  130. #include <time.h>
  131. /* declares fork(), _POSIX_VERSION. according to Autoconf.info,
  132. unistd.h defines _POSIX_VERSION if the system is POSIX-compliant,
  133. so we will use this as a test for all things uniquely provided by
  134. POSIX like sigaction() and fork() */
  135. #ifdef HAVE_UNISTD_H
  136. #include <unistd.h>
  137. #endif
  138. #ifdef HAVE_SYS_WAIT_H
  139. #include <sys/wait.h>
  140. #endif
  141. #if defined(HAVE_INIT_ONCE_BEGIN_INITIALIZE) && defined(HAVE_INIT_ONCE_COMPLETE)
  142. #define HAVE_WIN32_INIT_ONCE 1
  143. #endif
  144. /* declares pthread_create and friends */
  145. #if defined HAVE_PTHREAD
  146. #include <pthread.h>
  147. #elif defined HAVE_WIN32_INIT_ONCE
  148. typedef void pthread_mutexattr_t;
  149. typedef struct
  150. {
  151. INIT_ONCE init;
  152. HANDLE mutex;
  153. } pthread_mutex_t;
  154. #define PTHREAD_MUTEX_INITIALIZER { \
  155. INIT_ONCE_STATIC_INIT, \
  156. NULL, \
  157. }
  158. int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);
  159. int pthread_mutex_destroy(pthread_mutex_t *mutex);
  160. int pthread_mutex_lock(pthread_mutex_t *mutex);
  161. int pthread_mutex_unlock(pthread_mutex_t *mutex);
  162. #endif
  163. #ifdef HAVE_STDINT_H
  164. #include <stdint.h>
  165. #endif
  166. /* replacement functions for broken originals */
  167. #if !HAVE_DECL_ALARM
  168. CK_DLL_EXP unsigned int alarm(unsigned int seconds);
  169. #endif /* !HAVE_DECL_ALARM */
  170. #if !HAVE_MALLOC
  171. CK_DLL_EXP void *rpl_malloc(size_t n);
  172. #endif /* !HAVE_MALLOC */
  173. #if !HAVE_REALLOC
  174. CK_DLL_EXP void *rpl_realloc(void *p, size_t n);
  175. #endif /* !HAVE_REALLOC */
  176. #if !HAVE_GETPID && HAVE__GETPID
  177. #define getpid _getpid
  178. #endif /* !HAVE_GETPID && HAVE__GETPID */
  179. #if !HAVE_GETTIMEOFDAY
  180. CK_DLL_EXP int gettimeofday(struct timeval *tv, void *tz);
  181. #endif /* !HAVE_GETTIMEOFDAY */
  182. #if !HAVE_DECL_LOCALTIME_R
  183. #if !defined(localtime_r)
  184. CK_DLL_EXP struct tm *localtime_r(const time_t * clock, struct tm *result);
  185. #endif
  186. #endif /* !HAVE_DECL_LOCALTIME_R */
  187. #if !HAVE_DECL_STRDUP && !HAVE__STRDUP
  188. CK_DLL_EXP char *strdup(const char *str);
  189. #elif !HAVE_DECL_STRDUP && HAVE__STRDUP
  190. #define strdup _strdup
  191. #endif /* !HAVE_DECL_STRDUP && HAVE__STRDUP */
  192. #if !HAVE_DECL_STRSIGNAL
  193. CK_DLL_EXP char *strsignal(int sig);
  194. #endif /* !HAVE_DECL_STRSIGNAL */
  195. /*
  196. * On systems where clock_gettime() is not available, or
  197. * on systems where some clocks may not be supported, the
  198. * definition for CLOCK_MONOTONIC and CLOCK_REALTIME may not
  199. * be available. These should define which type of clock
  200. * clock_gettime() should use. We define it here if it is
  201. * not defined simply so the reimplementation can ignore it.
  202. *
  203. * We set the values of these clocks to some (hopefully)
  204. * invalid value, to avoid the case where we define a
  205. * clock with a valid value, and unintentionally use
  206. * an actual good clock by accident.
  207. */
  208. #ifndef CLOCK_MONOTONIC
  209. #define CLOCK_MONOTONIC -1
  210. #endif
  211. #ifndef CLOCK_REALTIME
  212. #define CLOCK_REALTIME -1
  213. #endif
  214. #ifndef HAVE_LIBRT
  215. #ifdef STRUCT_TIMESPEC_DEFINITION_MISSING
  216. /*
  217. * The following structure is defined in POSIX 1003.1 for times
  218. * specified in seconds and nanoseconds. If it is not defined in
  219. * time.g, then we need to define it here
  220. */
  221. struct timespec
  222. {
  223. time_t tv_sec;
  224. long tv_nsec;
  225. };
  226. #endif /* STRUCT_TIMESPEC_DEFINITION_MISSING */
  227. #ifdef STRUCT_ITIMERSPEC_DEFINITION_MISSING
  228. /*
  229. * The following structure is defined in POSIX.1b for timer start values and intervals.
  230. * If it is not defined in time.h, then we need to define it here.
  231. */
  232. struct itimerspec
  233. {
  234. struct timespec it_interval;
  235. struct timespec it_value;
  236. };
  237. #endif /* STRUCT_ITIMERSPEC_DEFINITION_MISSING */
  238. /*
  239. * Do a simple forward declaration in case the struct is not defined.
  240. * In the versions of timer_create in libcompat, sigevent is never
  241. * used.
  242. */
  243. struct sigevent;
  244. CK_DLL_EXP int clock_gettime(clockid_t clk_id, struct timespec *ts);
  245. CK_DLL_EXP int timer_create(clockid_t clockid, struct sigevent *sevp,
  246. timer_t * timerid);
  247. CK_DLL_EXP int timer_settime(timer_t timerid, int flags,
  248. const struct itimerspec *new_value,
  249. struct itimerspec *old_value);
  250. CK_DLL_EXP int timer_delete(timer_t timerid);
  251. #endif /* HAVE_LIBRT */
  252. /*
  253. * The following checks are to determine if the system's
  254. * snprintf (or its variants) should be replaced with
  255. * the C99 compliant version in libcompat.
  256. */
  257. #if HAVE_CONFIG_H
  258. #include <config.h>
  259. #endif
  260. #if HAVE_STDARG_H
  261. #include <stdarg.h>
  262. #if !HAVE_VSNPRINTF
  263. CK_DLL_EXP int rpl_vsnprintf(char *, size_t, const char *, va_list);
  264. #define vsnprintf rpl_vsnprintf
  265. #endif
  266. #if !HAVE_SNPRINTF
  267. CK_DLL_EXP int rpl_snprintf(char *, size_t, const char *, ...);
  268. #define snprintf rpl_snprintf
  269. #endif
  270. #endif /* HAVE_STDARG_H */
  271. #if !HAVE_GETLINE
  272. CK_DLL_EXP ssize_t getline(char **lineptr, size_t *n, FILE *stream);
  273. #endif
  274. /* silence warnings about an empty library */
  275. CK_DLL_EXP void ck_do_nothing(void) CK_ATTRIBUTE_NORETURN;
  276. #endif /* !LIBCOMPAT_H */