Merge branch 'master' into sim-target-tree
[kugel-rb.git] / tools / ucl / src / ucl_init.c
blob4798acae97b7892b76e17225240f61eb8c715145
1 /* ucl_init.c -- initialization of the UCL library
3 This file is part of the UCL data compression library.
5 Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
6 All Rights Reserved.
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.
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.
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.
23 Markus F.X.J. Oberhumer
24 <markus@oberhumer.com>
25 http://www.oberhumer.com/opensource/ucl/
29 #include "ucl_conf.h"
30 #include "ucl_util.h"
31 #include <stdio.h>
34 #if 0
35 # define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0)
36 # define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0)
37 #else
38 # define IS_SIGNED(type) (((type) (-1)) < ((type) 0))
39 # define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0))
40 #endif
43 /***********************************************************************
44 // Runtime check of the assumptions about the size of builtin types,
45 // memory model, byte order and other low-level constructs.
47 // We are really paranoid here - UCL should either fail (or crash)
48 // at startup or not at all.
50 // Because of inlining much of these functions evaluates to nothing.
51 ************************************************************************/
53 static ucl_bool schedule_insns_bug(void); /* avoid inlining */
54 static ucl_bool strength_reduce_bug(int *); /* avoid inlining */
57 #if 0 || defined(UCL_DEBUG)
58 static ucl_bool __ucl_assert_fail(const char *s, unsigned line)
60 #if defined(__palmos__)
61 printf("UCL assertion failed in line %u: '%s'\n",line,s);
62 #else
63 fprintf(stderr,"UCL assertion failed in line %u: '%s'\n",line,s);
64 #endif
65 return 0;
67 # define __ucl_assert(x) ((x) ? 1 : __ucl_assert_fail(#x,__LINE__))
68 #else
69 # define __ucl_assert(x) ((x) ? 1 : 0)
70 #endif
73 /***********************************************************************
74 // The next two functions should get completely optimized out of existance.
75 // Some assertions are redundant - but included for clarity.
76 ************************************************************************/
78 static ucl_bool basic_integral_check(void)
80 ucl_bool r = 1;
81 ucl_bool sanity;
83 /* paranoia */
84 r &= __ucl_assert(CHAR_BIT == 8);
85 r &= __ucl_assert(sizeof(char) == 1);
86 r &= __ucl_assert(sizeof(short) >= 2);
87 r &= __ucl_assert(sizeof(long) >= 4);
88 r &= __ucl_assert(sizeof(int) >= sizeof(short));
89 r &= __ucl_assert(sizeof(long) >= sizeof(int));
91 r &= __ucl_assert(sizeof(ucl_uint32) >= 4);
92 r &= __ucl_assert(sizeof(ucl_uint32) >= sizeof(unsigned));
93 #if defined(__UCL_STRICT_16BIT)
94 r &= __ucl_assert(sizeof(ucl_uint) == 2);
95 #else
96 r &= __ucl_assert(sizeof(ucl_uint) >= 4);
97 r &= __ucl_assert(sizeof(ucl_uint) >= sizeof(unsigned));
98 #endif
100 #if defined(SIZEOF_UNSIGNED)
101 r &= __ucl_assert(SIZEOF_UNSIGNED == sizeof(unsigned));
102 #endif
103 #if defined(SIZEOF_UNSIGNED_LONG)
104 r &= __ucl_assert(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long));
105 #endif
106 #if defined(SIZEOF_UNSIGNED_SHORT)
107 r &= __ucl_assert(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short));
108 #endif
109 #if !defined(__UCL_IN_MINIUCL)
110 #if defined(SIZEOF_SIZE_T)
111 r &= __ucl_assert(SIZEOF_SIZE_T == sizeof(size_t));
112 #endif
113 #endif
115 /* assert the signedness of our integral types */
116 sanity = IS_UNSIGNED(unsigned short) && IS_UNSIGNED(unsigned) &&
117 IS_UNSIGNED(unsigned long) &&
118 IS_SIGNED(short) && IS_SIGNED(int) && IS_SIGNED(long);
119 if (sanity)
121 r &= __ucl_assert(IS_UNSIGNED(ucl_uint32));
122 r &= __ucl_assert(IS_UNSIGNED(ucl_uint));
123 r &= __ucl_assert(IS_SIGNED(ucl_int32));
124 r &= __ucl_assert(IS_SIGNED(ucl_int));
126 r &= __ucl_assert(INT_MAX == UCL_STYPE_MAX(sizeof(int)));
127 r &= __ucl_assert(UINT_MAX == UCL_UTYPE_MAX(sizeof(unsigned)));
128 r &= __ucl_assert(LONG_MAX == UCL_STYPE_MAX(sizeof(long)));
129 r &= __ucl_assert(ULONG_MAX == UCL_UTYPE_MAX(sizeof(unsigned long)));
130 r &= __ucl_assert(SHRT_MAX == UCL_STYPE_MAX(sizeof(short)));
131 r &= __ucl_assert(USHRT_MAX == UCL_UTYPE_MAX(sizeof(unsigned short)));
132 r &= __ucl_assert(UCL_UINT32_MAX == UCL_UTYPE_MAX(sizeof(ucl_uint32)));
133 r &= __ucl_assert(UCL_UINT_MAX == UCL_UTYPE_MAX(sizeof(ucl_uint)));
134 #if !defined(__UCL_IN_MINIUCL)
135 r &= __ucl_assert(SIZE_T_MAX == UCL_UTYPE_MAX(sizeof(size_t)));
136 #endif
139 return r;
143 static ucl_bool basic_ptr_check(void)
145 ucl_bool r = 1;
146 ucl_bool sanity;
148 r &= __ucl_assert(sizeof(char *) >= sizeof(int));
149 r &= __ucl_assert(sizeof(ucl_byte *) >= sizeof(char *));
151 r &= __ucl_assert(sizeof(ucl_voidp) == sizeof(ucl_byte *));
152 r &= __ucl_assert(sizeof(ucl_voidp) == sizeof(ucl_voidpp));
153 r &= __ucl_assert(sizeof(ucl_voidp) == sizeof(ucl_bytepp));
154 r &= __ucl_assert(sizeof(ucl_voidp) >= sizeof(ucl_uint));
156 r &= __ucl_assert(sizeof(ucl_ptr_t) == sizeof(ucl_voidp));
157 r &= __ucl_assert(sizeof(ucl_ptr_t) >= sizeof(ucl_uint));
159 r &= __ucl_assert(sizeof(ucl_ptrdiff_t) >= 4);
160 r &= __ucl_assert(sizeof(ucl_ptrdiff_t) >= sizeof(ptrdiff_t));
162 #if defined(SIZEOF_CHAR_P)
163 r &= __ucl_assert(SIZEOF_CHAR_P == sizeof(char *));
164 #endif
165 #if defined(SIZEOF_PTRDIFF_T)
166 r &= __ucl_assert(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t));
167 #endif
169 /* assert the signedness of our integral types */
170 sanity = IS_UNSIGNED(unsigned short) && IS_UNSIGNED(unsigned) &&
171 IS_UNSIGNED(unsigned long) &&
172 IS_SIGNED(short) && IS_SIGNED(int) && IS_SIGNED(long);
173 if (sanity)
175 r &= __ucl_assert(IS_UNSIGNED(ucl_ptr_t));
176 r &= __ucl_assert(IS_SIGNED(ucl_ptrdiff_t));
177 r &= __ucl_assert(IS_SIGNED(ucl_sptr_t));
180 return r;
184 /***********************************************************************
186 ************************************************************************/
188 static ucl_bool ptr_check(void)
190 ucl_bool r = 1;
191 int i;
192 char _wrkmem[10 * sizeof(ucl_byte *) + sizeof(ucl_align_t)];
193 ucl_bytep wrkmem;
194 ucl_bytepp dict;
195 unsigned char x[4 * sizeof(ucl_align_t)];
196 long d;
197 ucl_align_t a;
198 ucl_align_t u;
200 for (i = 0; i < (int) sizeof(x); i++)
201 x[i] = UCL_BYTE(i);
203 wrkmem = UCL_PTR_ALIGN_UP((ucl_byte *)_wrkmem,sizeof(ucl_align_t));
205 #if 0
206 dict = (ucl_bytepp) wrkmem;
207 #else
208 /* Avoid a compiler warning on architectures that
209 * do not allow unaligned access. */
210 u.a_ucl_bytep = wrkmem; dict = u.a_ucl_bytepp;
211 #endif
213 d = (long) ((const ucl_bytep) dict - (const ucl_bytep) _wrkmem);
214 r &= __ucl_assert(d >= 0);
215 r &= __ucl_assert(d < (long) sizeof(ucl_align_t));
217 memset(&a,0xff,sizeof(a));
218 r &= __ucl_assert(a.a_ushort == USHRT_MAX);
219 r &= __ucl_assert(a.a_uint == UINT_MAX);
220 r &= __ucl_assert(a.a_ulong == ULONG_MAX);
221 r &= __ucl_assert(a.a_ucl_uint == UCL_UINT_MAX);
223 /* sanity check of the memory model */
224 if (r == 1)
226 for (i = 0; i < 8; i++)
227 r &= __ucl_assert((const ucl_voidp) (&dict[i]) == (const ucl_voidp) (&wrkmem[i * sizeof(ucl_byte *)]));
230 /* check BZERO8_PTR and that NULL == 0 */
231 memset(&a,0,sizeof(a));
232 r &= __ucl_assert(a.a_char_p == NULL);
233 r &= __ucl_assert(a.a_ucl_bytep == NULL);
234 r &= __ucl_assert(NULL == (void*)0);
235 if (r == 1)
237 for (i = 0; i < 10; i++)
238 dict[i] = wrkmem;
239 BZERO8_PTR(dict+1,sizeof(dict[0]),8);
240 r &= __ucl_assert(dict[0] == wrkmem);
241 for (i = 1; i < 9; i++)
242 r &= __ucl_assert(dict[i] == NULL);
243 r &= __ucl_assert(dict[9] == wrkmem);
246 /* check that the pointer constructs work as expected */
247 if (r == 1)
249 unsigned k = 1;
250 const unsigned n = (unsigned) sizeof(ucl_uint32);
251 ucl_byte *p0;
252 ucl_byte *p1;
254 k += __ucl_align_gap(&x[k],n);
255 p0 = (ucl_bytep) &x[k];
256 #if defined(PTR_LINEAR)
257 r &= __ucl_assert((PTR_LINEAR(p0) & (n-1)) == 0);
258 #else
259 r &= __ucl_assert(n == 4);
260 r &= __ucl_assert(PTR_ALIGNED_4(p0));
261 #endif
263 r &= __ucl_assert(k >= 1);
264 p1 = (ucl_bytep) &x[1];
265 r &= __ucl_assert(PTR_GE(p0,p1));
267 r &= __ucl_assert(k < 1+n);
268 p1 = (ucl_bytep) &x[1+n];
269 r &= __ucl_assert(PTR_LT(p0,p1));
271 /* now check that aligned memory access doesn't core dump */
272 if (r == 1)
274 ucl_uint32 v0, v1;
275 #if 0
276 v0 = * (ucl_uint32 *) &x[k];
277 v1 = * (ucl_uint32 *) &x[k+n];
278 #else
279 /* Avoid compiler warnings on architectures that
280 * do not allow unaligned access. */
281 u.a_uchar_p = &x[k];
282 v0 = *u.a_ucl_uint32_p;
283 u.a_uchar_p = &x[k+n];
284 v1 = *u.a_ucl_uint32_p;
285 #endif
286 r &= __ucl_assert(v0 > 0);
287 r &= __ucl_assert(v1 > 0);
291 return r;
295 /***********************************************************************
297 ************************************************************************/
299 UCL_PUBLIC(int)
300 _ucl_config_check(void)
302 ucl_bool r = 1;
303 int i;
304 union {
305 ucl_uint32 a;
306 unsigned short b;
307 ucl_uint32 aa[4];
308 unsigned char x[4*sizeof(ucl_align_t)];
309 } u;
311 #if 0
312 /* paranoia - the following is guaranteed by definition anyway */
313 r &= __ucl_assert((const void *)&u == (const void *)&u.a);
314 r &= __ucl_assert((const void *)&u == (const void *)&u.b);
315 r &= __ucl_assert((const void *)&u == (const void *)&u.x[0]);
316 r &= __ucl_assert((const void *)&u == (const void *)&u.aa[0]);
317 #endif
319 r &= basic_integral_check();
320 r &= basic_ptr_check();
321 if (r != 1)
322 return UCL_E_ERROR;
324 u.a = 0; u.b = 0;
325 for (i = 0; i < (int) sizeof(u.x); i++)
326 u.x[i] = UCL_BYTE(i);
328 #if 0
329 /* check if the compiler correctly casts signed to unsigned */
330 r &= __ucl_assert( (int) (unsigned char) ((char) -1) == 255);
331 #endif
333 /* check UCL_BYTE_ORDER */
334 #if defined(UCL_BYTE_ORDER)
335 if (r == 1)
337 # if (UCL_BYTE_ORDER == UCL_LITTLE_ENDIAN)
338 ucl_uint32 a = (ucl_uint32) (u.a & UCL_UINT32_C(0xffffffff));
339 unsigned short b = (unsigned short) (u.b & 0xffff);
340 r &= __ucl_assert(a == UCL_UINT32_C(0x03020100));
341 r &= __ucl_assert(b == 0x0100);
342 # elif (UCL_BYTE_ORDER == UCL_BIG_ENDIAN)
343 ucl_uint32 a = u.a >> (8 * sizeof(u.a) - 32);
344 unsigned short b = u.b >> (8 * sizeof(u.b) - 16);
345 r &= __ucl_assert(a == UCL_UINT32_C(0x00010203));
346 r &= __ucl_assert(b == 0x0001);
347 # else
348 # error "invalid UCL_BYTE_ORDER"
349 # endif
351 #endif
353 /* check that unaligned memory access works as expected */
354 #if defined(UCL_UNALIGNED_OK_2)
355 r &= __ucl_assert(sizeof(short) == 2);
356 if (r == 1)
358 unsigned short b[4];
360 for (i = 0; i < 4; i++)
361 b[i] = * (const unsigned short *) &u.x[i];
363 # if (UCL_BYTE_ORDER == UCL_LITTLE_ENDIAN)
364 r &= __ucl_assert(b[0] == 0x0100);
365 r &= __ucl_assert(b[1] == 0x0201);
366 r &= __ucl_assert(b[2] == 0x0302);
367 r &= __ucl_assert(b[3] == 0x0403);
368 # elif (UCL_BYTE_ORDER == UCL_BIG_ENDIAN)
369 r &= __ucl_assert(b[0] == 0x0001);
370 r &= __ucl_assert(b[1] == 0x0102);
371 r &= __ucl_assert(b[2] == 0x0203);
372 r &= __ucl_assert(b[3] == 0x0304);
373 # endif
375 #endif
377 #if defined(UCL_UNALIGNED_OK_4)
378 r &= __ucl_assert(sizeof(ucl_uint32) == 4);
379 if (r == 1)
381 ucl_uint32 a[4];
383 for (i = 0; i < 4; i++)
384 a[i] = * (const ucl_uint32 *) &u.x[i];
386 # if (UCL_BYTE_ORDER == UCL_LITTLE_ENDIAN)
387 r &= __ucl_assert(a[0] == UCL_UINT32_C(0x03020100));
388 r &= __ucl_assert(a[1] == UCL_UINT32_C(0x04030201));
389 r &= __ucl_assert(a[2] == UCL_UINT32_C(0x05040302));
390 r &= __ucl_assert(a[3] == UCL_UINT32_C(0x06050403));
391 # elif (UCL_BYTE_ORDER == UCL_BIG_ENDIAN)
392 r &= __ucl_assert(a[0] == UCL_UINT32_C(0x00010203));
393 r &= __ucl_assert(a[1] == UCL_UINT32_C(0x01020304));
394 r &= __ucl_assert(a[2] == UCL_UINT32_C(0x02030405));
395 r &= __ucl_assert(a[3] == UCL_UINT32_C(0x03040506));
396 # endif
398 #endif
400 #if defined(UCL_ALIGNED_OK_4)
401 r &= __ucl_assert(sizeof(ucl_uint32) == 4);
402 #endif
404 /* check the ucl_adler32() function */
405 if (r == 1)
407 ucl_uint32 adler;
408 adler = ucl_adler32(0, NULL, 0);
409 adler = ucl_adler32(adler, ucl_copyright(), 186);
410 r &= __ucl_assert(adler == UCL_UINT32_C(0x47fb39fc));
413 /* check for the gcc schedule-insns optimization bug */
414 if (r == 1)
416 r &= __ucl_assert(!schedule_insns_bug());
419 /* check for the gcc strength-reduce optimization bug */
420 if (r == 1)
422 static int x[3];
423 static unsigned xn = 3;
424 register unsigned j;
426 for (j = 0; j < xn; j++)
427 x[j] = (int)j - 3;
428 r &= __ucl_assert(!strength_reduce_bug(x));
431 /* now for the low-level pointer checks */
432 if (r == 1)
434 r &= ptr_check();
437 return r == 1 ? UCL_E_OK : UCL_E_ERROR;
441 static ucl_bool schedule_insns_bug(void)
443 #if defined(__UCL_CHECKER)
444 /* for some reason checker complains about uninitialized memory access */
445 return 0;
446 #else
447 const int clone[] = {1, 2, 0};
448 const int *q;
449 q = clone;
450 return (*q) ? 0 : 1;
451 #endif
455 static ucl_bool strength_reduce_bug(int *x)
457 return x[0] != -3 || x[1] != -2 || x[2] != -1;
461 /***********************************************************************
463 ************************************************************************/
465 int __ucl_init_done = 0;
467 UCL_PUBLIC(int)
468 __ucl_init2(ucl_uint32 v, int s1, int s2, int s3, int s4, int s5,
469 int s6, int s7, int s8, int s9)
471 int r;
473 __ucl_init_done = 1;
475 if (v == 0)
476 return UCL_E_ERROR;
478 r = (s1 == -1 || s1 == (int) sizeof(short)) &&
479 (s2 == -1 || s2 == (int) sizeof(int)) &&
480 (s3 == -1 || s3 == (int) sizeof(long)) &&
481 (s4 == -1 || s4 == (int) sizeof(ucl_uint32)) &&
482 (s5 == -1 || s5 == (int) sizeof(ucl_uint)) &&
483 (s6 == -1 || s6 > 0) &&
484 (s7 == -1 || s7 == (int) sizeof(char *)) &&
485 (s8 == -1 || s8 == (int) sizeof(ucl_voidp)) &&
486 (s9 == -1 || s9 == (int) sizeof(ucl_compress_t));
487 if (!r)
488 return UCL_E_ERROR;
490 r = _ucl_config_check();
491 if (r != UCL_E_OK)
492 return r;
494 return r;
499 vi:ts=4:et