ucl_init.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /* ucl_init.c -- initialization of the UCL library
  2. This file is part of the UCL data compression library.
  3. Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
  4. All Rights Reserved.
  5. The UCL library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of
  8. the License, or (at your option) any later version.
  9. The UCL library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with the UCL library; see the file COPYING.
  15. If not, write to the Free Software Foundation, Inc.,
  16. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. Markus F.X.J. Oberhumer
  18. <markus@oberhumer.com>
  19. http://www.oberhumer.com/opensource/ucl/
  20. */
  21. #include "ucl_conf.h"
  22. #include "ucl_util.h"
  23. #include <stdio.h>
  24. #if 0
  25. # define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0)
  26. # define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0)
  27. #else
  28. # define IS_SIGNED(type) (((type) (-1)) < ((type) 0))
  29. # define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0))
  30. #endif
  31. /***********************************************************************
  32. // Runtime check of the assumptions about the size of builtin types,
  33. // memory model, byte order and other low-level constructs.
  34. //
  35. // We are really paranoid here - UCL should either fail (or crash)
  36. // at startup or not at all.
  37. //
  38. // Because of inlining much of these functions evaluates to nothing.
  39. ************************************************************************/
  40. static ucl_bool schedule_insns_bug(void); /* avoid inlining */
  41. static ucl_bool strength_reduce_bug(int *); /* avoid inlining */
  42. #if 0 || defined(UCL_DEBUG)
  43. static ucl_bool __ucl_assert_fail(const char *s, unsigned line)
  44. {
  45. #if defined(__palmos__)
  46. printf("UCL assertion failed in line %u: '%s'\n",line,s);
  47. #else
  48. fprintf(stderr,"UCL assertion failed in line %u: '%s'\n",line,s);
  49. #endif
  50. return 0;
  51. }
  52. # define __ucl_assert(x) ((x) ? 1 : __ucl_assert_fail(#x,__LINE__))
  53. #else
  54. # define __ucl_assert(x) ((x) ? 1 : 0)
  55. #endif
  56. /***********************************************************************
  57. // The next two functions should get completely optimized out of existance.
  58. // Some assertions are redundant - but included for clarity.
  59. ************************************************************************/
  60. static ucl_bool basic_integral_check(void)
  61. {
  62. ucl_bool r = 1;
  63. ucl_bool sanity;
  64. /* paranoia */
  65. r &= __ucl_assert(CHAR_BIT == 8);
  66. r &= __ucl_assert(sizeof(char) == 1);
  67. r &= __ucl_assert(sizeof(short) >= 2);
  68. r &= __ucl_assert(sizeof(long) >= 4);
  69. r &= __ucl_assert(sizeof(int) >= sizeof(short));
  70. r &= __ucl_assert(sizeof(long) >= sizeof(int));
  71. r &= __ucl_assert(sizeof(ucl_uint32) >= 4);
  72. r &= __ucl_assert(sizeof(ucl_uint32) >= sizeof(unsigned));
  73. #if defined(__UCL_STRICT_16BIT)
  74. r &= __ucl_assert(sizeof(ucl_uint) == 2);
  75. #else
  76. r &= __ucl_assert(sizeof(ucl_uint) >= 4);
  77. r &= __ucl_assert(sizeof(ucl_uint) >= sizeof(unsigned));
  78. #endif
  79. #if defined(SIZEOF_UNSIGNED)
  80. r &= __ucl_assert(SIZEOF_UNSIGNED == sizeof(unsigned));
  81. #endif
  82. #if defined(SIZEOF_UNSIGNED_LONG)
  83. r &= __ucl_assert(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long));
  84. #endif
  85. #if defined(SIZEOF_UNSIGNED_SHORT)
  86. r &= __ucl_assert(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short));
  87. #endif
  88. #if !defined(__UCL_IN_MINIUCL)
  89. #if defined(SIZEOF_SIZE_T)
  90. r &= __ucl_assert(SIZEOF_SIZE_T == sizeof(size_t));
  91. #endif
  92. #endif
  93. /* assert the signedness of our integral types */
  94. sanity = IS_UNSIGNED(unsigned short) && IS_UNSIGNED(unsigned) &&
  95. IS_UNSIGNED(unsigned long) &&
  96. IS_SIGNED(short) && IS_SIGNED(int) && IS_SIGNED(long);
  97. if (sanity)
  98. {
  99. r &= __ucl_assert(IS_UNSIGNED(ucl_uint32));
  100. r &= __ucl_assert(IS_UNSIGNED(ucl_uint));
  101. r &= __ucl_assert(IS_SIGNED(ucl_int32));
  102. r &= __ucl_assert(IS_SIGNED(ucl_int));
  103. r &= __ucl_assert(INT_MAX == UCL_STYPE_MAX(sizeof(int)));
  104. r &= __ucl_assert(UINT_MAX == UCL_UTYPE_MAX(sizeof(unsigned)));
  105. r &= __ucl_assert(LONG_MAX == UCL_STYPE_MAX(sizeof(long)));
  106. r &= __ucl_assert(ULONG_MAX == UCL_UTYPE_MAX(sizeof(unsigned long)));
  107. r &= __ucl_assert(SHRT_MAX == UCL_STYPE_MAX(sizeof(short)));
  108. r &= __ucl_assert(USHRT_MAX == UCL_UTYPE_MAX(sizeof(unsigned short)));
  109. r &= __ucl_assert(UCL_UINT32_MAX == UCL_UTYPE_MAX(sizeof(ucl_uint32)));
  110. r &= __ucl_assert(UCL_UINT_MAX == UCL_UTYPE_MAX(sizeof(ucl_uint)));
  111. #if !defined(__UCL_IN_MINIUCL)
  112. r &= __ucl_assert(SIZE_T_MAX == UCL_UTYPE_MAX(sizeof(size_t)));
  113. #endif
  114. }
  115. return r;
  116. }
  117. static ucl_bool basic_ptr_check(void)
  118. {
  119. ucl_bool r = 1;
  120. ucl_bool sanity;
  121. r &= __ucl_assert(sizeof(char *) >= sizeof(int));
  122. r &= __ucl_assert(sizeof(ucl_byte *) >= sizeof(char *));
  123. r &= __ucl_assert(sizeof(ucl_voidp) == sizeof(ucl_byte *));
  124. r &= __ucl_assert(sizeof(ucl_voidp) == sizeof(ucl_voidpp));
  125. r &= __ucl_assert(sizeof(ucl_voidp) == sizeof(ucl_bytepp));
  126. r &= __ucl_assert(sizeof(ucl_voidp) >= sizeof(ucl_uint));
  127. r &= __ucl_assert(sizeof(ucl_ptr_t) == sizeof(ucl_voidp));
  128. r &= __ucl_assert(sizeof(ucl_ptr_t) >= sizeof(ucl_uint));
  129. r &= __ucl_assert(sizeof(ucl_ptrdiff_t) >= 4);
  130. r &= __ucl_assert(sizeof(ucl_ptrdiff_t) >= sizeof(ptrdiff_t));
  131. #if defined(SIZEOF_CHAR_P)
  132. r &= __ucl_assert(SIZEOF_CHAR_P == sizeof(char *));
  133. #endif
  134. #if defined(SIZEOF_PTRDIFF_T)
  135. r &= __ucl_assert(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t));
  136. #endif
  137. /* assert the signedness of our integral types */
  138. sanity = IS_UNSIGNED(unsigned short) && IS_UNSIGNED(unsigned) &&
  139. IS_UNSIGNED(unsigned long) &&
  140. IS_SIGNED(short) && IS_SIGNED(int) && IS_SIGNED(long);
  141. if (sanity)
  142. {
  143. r &= __ucl_assert(IS_UNSIGNED(ucl_ptr_t));
  144. r &= __ucl_assert(IS_SIGNED(ucl_ptrdiff_t));
  145. r &= __ucl_assert(IS_SIGNED(ucl_sptr_t));
  146. }
  147. return r;
  148. }
  149. /***********************************************************************
  150. //
  151. ************************************************************************/
  152. static ucl_bool ptr_check(void)
  153. {
  154. ucl_bool r = 1;
  155. int i;
  156. char _wrkmem[10 * sizeof(ucl_byte *) + sizeof(ucl_align_t)];
  157. ucl_bytep wrkmem;
  158. ucl_bytepp dict;
  159. unsigned char x[4 * sizeof(ucl_align_t)];
  160. long d;
  161. ucl_align_t a;
  162. ucl_align_t u;
  163. for (i = 0; i < (int) sizeof(x); i++)
  164. x[i] = UCL_BYTE(i);
  165. wrkmem = UCL_PTR_ALIGN_UP((ucl_byte *)_wrkmem,sizeof(ucl_align_t));
  166. #if 0
  167. dict = (ucl_bytepp) wrkmem;
  168. #else
  169. /* Avoid a compiler warning on architectures that
  170. * do not allow unaligned access. */
  171. u.a_ucl_bytep = wrkmem; dict = u.a_ucl_bytepp;
  172. #endif
  173. d = (long) ((const ucl_bytep) dict - (const ucl_bytep) _wrkmem);
  174. r &= __ucl_assert(d >= 0);
  175. r &= __ucl_assert(d < (long) sizeof(ucl_align_t));
  176. memset(&a,0xff,sizeof(a));
  177. r &= __ucl_assert(a.a_ushort == USHRT_MAX);
  178. r &= __ucl_assert(a.a_uint == UINT_MAX);
  179. r &= __ucl_assert(a.a_ulong == ULONG_MAX);
  180. r &= __ucl_assert(a.a_ucl_uint == UCL_UINT_MAX);
  181. /* sanity check of the memory model */
  182. if (r == 1)
  183. {
  184. for (i = 0; i < 8; i++)
  185. r &= __ucl_assert((const ucl_voidp) (&dict[i]) == (const ucl_voidp) (&wrkmem[i * sizeof(ucl_byte *)]));
  186. }
  187. /* check BZERO8_PTR and that NULL == 0 */
  188. memset(&a,0,sizeof(a));
  189. r &= __ucl_assert(a.a_char_p == NULL);
  190. r &= __ucl_assert(a.a_ucl_bytep == NULL);
  191. r &= __ucl_assert(NULL == (void*)0);
  192. if (r == 1)
  193. {
  194. for (i = 0; i < 10; i++)
  195. dict[i] = wrkmem;
  196. BZERO8_PTR(dict+1,sizeof(dict[0]),8);
  197. r &= __ucl_assert(dict[0] == wrkmem);
  198. for (i = 1; i < 9; i++)
  199. r &= __ucl_assert(dict[i] == NULL);
  200. r &= __ucl_assert(dict[9] == wrkmem);
  201. }
  202. /* check that the pointer constructs work as expected */
  203. if (r == 1)
  204. {
  205. unsigned k = 1;
  206. const unsigned n = (unsigned) sizeof(ucl_uint32);
  207. ucl_byte *p0;
  208. ucl_byte *p1;
  209. k += __ucl_align_gap(&x[k],n);
  210. p0 = (ucl_bytep) &x[k];
  211. #if defined(PTR_LINEAR)
  212. r &= __ucl_assert((PTR_LINEAR(p0) & (n-1)) == 0);
  213. #else
  214. r &= __ucl_assert(n == 4);
  215. r &= __ucl_assert(PTR_ALIGNED_4(p0));
  216. #endif
  217. r &= __ucl_assert(k >= 1);
  218. p1 = (ucl_bytep) &x[1];
  219. r &= __ucl_assert(PTR_GE(p0,p1));
  220. r &= __ucl_assert(k < 1+n);
  221. p1 = (ucl_bytep) &x[1+n];
  222. r &= __ucl_assert(PTR_LT(p0,p1));
  223. /* now check that aligned memory access doesn't core dump */
  224. if (r == 1)
  225. {
  226. ucl_uint32 v0, v1;
  227. #if 0
  228. v0 = * (ucl_uint32 *) &x[k];
  229. v1 = * (ucl_uint32 *) &x[k+n];
  230. #else
  231. /* Avoid compiler warnings on architectures that
  232. * do not allow unaligned access. */
  233. u.a_uchar_p = &x[k];
  234. v0 = *u.a_ucl_uint32_p;
  235. u.a_uchar_p = &x[k+n];
  236. v1 = *u.a_ucl_uint32_p;
  237. #endif
  238. r &= __ucl_assert(v0 > 0);
  239. r &= __ucl_assert(v1 > 0);
  240. }
  241. }
  242. return r;
  243. }
  244. /***********************************************************************
  245. //
  246. ************************************************************************/
  247. UCL_PUBLIC(int)
  248. _ucl_config_check(void)
  249. {
  250. ucl_bool r = 1;
  251. int i;
  252. union {
  253. ucl_uint32 a;
  254. unsigned short b;
  255. ucl_uint32 aa[4];
  256. unsigned char x[4*sizeof(ucl_align_t)];
  257. } u;
  258. #if 0
  259. /* paranoia - the following is guaranteed by definition anyway */
  260. r &= __ucl_assert((const void *)&u == (const void *)&u.a);
  261. r &= __ucl_assert((const void *)&u == (const void *)&u.b);
  262. r &= __ucl_assert((const void *)&u == (const void *)&u.x[0]);
  263. r &= __ucl_assert((const void *)&u == (const void *)&u.aa[0]);
  264. #endif
  265. r &= basic_integral_check();
  266. r &= basic_ptr_check();
  267. if (r != 1)
  268. return UCL_E_ERROR;
  269. u.a = 0; u.b = 0;
  270. for (i = 0; i < (int) sizeof(u.x); i++)
  271. u.x[i] = UCL_BYTE(i);
  272. #if 0
  273. /* check if the compiler correctly casts signed to unsigned */
  274. r &= __ucl_assert( (int) (unsigned char) ((char) -1) == 255);
  275. #endif
  276. /* check UCL_BYTE_ORDER */
  277. #if defined(UCL_BYTE_ORDER)
  278. if (r == 1)
  279. {
  280. # if (UCL_BYTE_ORDER == UCL_LITTLE_ENDIAN)
  281. ucl_uint32 a = (ucl_uint32) (u.a & UCL_UINT32_C(0xffffffff));
  282. unsigned short b = (unsigned short) (u.b & 0xffff);
  283. r &= __ucl_assert(a == UCL_UINT32_C(0x03020100));
  284. r &= __ucl_assert(b == 0x0100);
  285. # elif (UCL_BYTE_ORDER == UCL_BIG_ENDIAN)
  286. ucl_uint32 a = u.a >> (8 * sizeof(u.a) - 32);
  287. unsigned short b = u.b >> (8 * sizeof(u.b) - 16);
  288. r &= __ucl_assert(a == UCL_UINT32_C(0x00010203));
  289. r &= __ucl_assert(b == 0x0001);
  290. # else
  291. # error "invalid UCL_BYTE_ORDER"
  292. # endif
  293. }
  294. #endif
  295. /* check that unaligned memory access works as expected */
  296. #if defined(UCL_UNALIGNED_OK_2)
  297. r &= __ucl_assert(sizeof(short) == 2);
  298. if (r == 1)
  299. {
  300. unsigned short b[4];
  301. for (i = 0; i < 4; i++)
  302. b[i] = * (const unsigned short *) &u.x[i];
  303. # if (UCL_BYTE_ORDER == UCL_LITTLE_ENDIAN)
  304. r &= __ucl_assert(b[0] == 0x0100);
  305. r &= __ucl_assert(b[1] == 0x0201);
  306. r &= __ucl_assert(b[2] == 0x0302);
  307. r &= __ucl_assert(b[3] == 0x0403);
  308. # elif (UCL_BYTE_ORDER == UCL_BIG_ENDIAN)
  309. r &= __ucl_assert(b[0] == 0x0001);
  310. r &= __ucl_assert(b[1] == 0x0102);
  311. r &= __ucl_assert(b[2] == 0x0203);
  312. r &= __ucl_assert(b[3] == 0x0304);
  313. # endif
  314. }
  315. #endif
  316. #if defined(UCL_UNALIGNED_OK_4)
  317. r &= __ucl_assert(sizeof(ucl_uint32) == 4);
  318. if (r == 1)
  319. {
  320. ucl_uint32 a[4];
  321. for (i = 0; i < 4; i++)
  322. a[i] = * (const ucl_uint32 *) &u.x[i];
  323. # if (UCL_BYTE_ORDER == UCL_LITTLE_ENDIAN)
  324. r &= __ucl_assert(a[0] == UCL_UINT32_C(0x03020100));
  325. r &= __ucl_assert(a[1] == UCL_UINT32_C(0x04030201));
  326. r &= __ucl_assert(a[2] == UCL_UINT32_C(0x05040302));
  327. r &= __ucl_assert(a[3] == UCL_UINT32_C(0x06050403));
  328. # elif (UCL_BYTE_ORDER == UCL_BIG_ENDIAN)
  329. r &= __ucl_assert(a[0] == UCL_UINT32_C(0x00010203));
  330. r &= __ucl_assert(a[1] == UCL_UINT32_C(0x01020304));
  331. r &= __ucl_assert(a[2] == UCL_UINT32_C(0x02030405));
  332. r &= __ucl_assert(a[3] == UCL_UINT32_C(0x03040506));
  333. # endif
  334. }
  335. #endif
  336. #if defined(UCL_ALIGNED_OK_4)
  337. r &= __ucl_assert(sizeof(ucl_uint32) == 4);
  338. #endif
  339. /* check the ucl_adler32() function */
  340. if (r == 1)
  341. {
  342. ucl_uint32 adler;
  343. adler = ucl_adler32(0, NULL, 0);
  344. adler = ucl_adler32(adler, ucl_copyright(), 186);
  345. r &= __ucl_assert(adler == UCL_UINT32_C(0x47fb39fc));
  346. }
  347. /* check for the gcc schedule-insns optimization bug */
  348. if (r == 1)
  349. {
  350. r &= __ucl_assert(!schedule_insns_bug());
  351. }
  352. /* check for the gcc strength-reduce optimization bug */
  353. if (r == 1)
  354. {
  355. static int x[3];
  356. static unsigned xn = 3;
  357. register unsigned j;
  358. for (j = 0; j < xn; j++)
  359. x[j] = (int)j - 3;
  360. r &= __ucl_assert(!strength_reduce_bug(x));
  361. }
  362. /* now for the low-level pointer checks */
  363. if (r == 1)
  364. {
  365. r &= ptr_check();
  366. }
  367. return r == 1 ? UCL_E_OK : UCL_E_ERROR;
  368. }
  369. static ucl_bool schedule_insns_bug(void)
  370. {
  371. #if defined(__UCL_CHECKER)
  372. /* for some reason checker complains about uninitialized memory access */
  373. return 0;
  374. #else
  375. const int clone[] = {1, 2, 0};
  376. const int *q;
  377. q = clone;
  378. return (*q) ? 0 : 1;
  379. #endif
  380. }
  381. static ucl_bool strength_reduce_bug(int *x)
  382. {
  383. return x[0] != -3 || x[1] != -2 || x[2] != -1;
  384. }
  385. /***********************************************************************
  386. //
  387. ************************************************************************/
  388. int __ucl_init_done = 0;
  389. UCL_PUBLIC(int)
  390. __ucl_init2(ucl_uint32 v, int s1, int s2, int s3, int s4, int s5,
  391. int s6, int s7, int s8, int s9)
  392. {
  393. int r;
  394. __ucl_init_done = 1;
  395. if (v == 0)
  396. return UCL_E_ERROR;
  397. r = (s1 == -1 || s1 == (int) sizeof(short)) &&
  398. (s2 == -1 || s2 == (int) sizeof(int)) &&
  399. (s3 == -1 || s3 == (int) sizeof(long)) &&
  400. (s4 == -1 || s4 == (int) sizeof(ucl_uint32)) &&
  401. (s5 == -1 || s5 == (int) sizeof(ucl_uint)) &&
  402. (s6 == -1 || s6 > 0) &&
  403. (s7 == -1 || s7 == (int) sizeof(char *)) &&
  404. (s8 == -1 || s8 == (int) sizeof(ucl_voidp)) &&
  405. (s9 == -1 || s9 == (int) sizeof(ucl_compress_t));
  406. if (!r)
  407. return UCL_E_ERROR;
  408. r = _ucl_config_check();
  409. if (r != UCL_E_OK)
  410. return r;
  411. return r;
  412. }
  413. /*
  414. vi:ts=4:et
  415. */