Subversion Repositories QNX 8.QNX8 IFS tool

Rev

Blame | Last modification | View Log | Download | RSS feed

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