Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
160 theseven 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-2002 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
#include "ucl_util.h"
184 farthen 31
#include "embiosapp.h"
160 theseven 32
 
33
#if 0
34
#  define IS_SIGNED(type)       (((type) (1ul << (8 * sizeof(type) - 1))) < 0)
35
#  define IS_UNSIGNED(type)     (((type) (1ul << (8 * sizeof(type) - 1))) > 0)
36
#else
37
#  define IS_SIGNED(type)       (((type) (-1)) < ((type) 0))
38
#  define IS_UNSIGNED(type)     (((type) (-1)) > ((type) 0))
39
#endif
40
 
41
 
42
/***********************************************************************
43
// Runtime check of the assumptions about the size of builtin types,
44
// memory model, byte order and other low-level constructs.
45
//
46
// We are really paranoid here - UCL should either fail (or crash)
47
// at startup or not at all.
48
//
49
// Because of inlining much of these functions evaluates to nothing.
50
************************************************************************/
51
 
52
static ucl_bool schedule_insns_bug(void);   /* avoid inlining */
53
static ucl_bool strength_reduce_bug(int *); /* avoid inlining */
54
 
55
 
56
#if 0 || defined(UCL_DEBUG)
57
static ucl_bool __ucl_assert_fail(const char *s, unsigned line)
58
{
59
#if defined(__palmos__)
60
    printf("UCL assertion failed in line %u: '%s'\n",line,s);
61
#else
62
    fprintf(stderr,"UCL assertion failed in line %u: '%s'\n",line,s);
63
#endif
64
    return 0;
65
}
66
#  define __ucl_assert(x)   ((x) ? 1 : __ucl_assert_fail(#x,__LINE__))
67
#else
68
#  define __ucl_assert(x)   ((x) ? 1 : 0)
69
#endif
70
 
71
 
72
/***********************************************************************
73
// The next two functions should get completely optimized out of existance.
74
// Some assertions are redundant - but included for clarity.
75
************************************************************************/
76
 
77
static ucl_bool basic_integral_check(void)
78
{
79
    ucl_bool r = 1;
80
    ucl_bool sanity;
81
 
82
    /* paranoia */
83
    r &= __ucl_assert(CHAR_BIT == 8);
84
    r &= __ucl_assert(sizeof(char) == 1);
85
    r &= __ucl_assert(sizeof(short) >= 2);
86
    r &= __ucl_assert(sizeof(long) >= 4);
87
    r &= __ucl_assert(sizeof(int) >= sizeof(short));
88
    r &= __ucl_assert(sizeof(long) >= sizeof(int));
89
 
90
    r &= __ucl_assert(sizeof(ucl_uint32) >= 4);
91
    r &= __ucl_assert(sizeof(ucl_uint32) >= sizeof(unsigned));
92
#if defined(__UCL_STRICT_16BIT)
93
    r &= __ucl_assert(sizeof(ucl_uint) == 2);
94
#else
95
    r &= __ucl_assert(sizeof(ucl_uint) >= 4);
96
    r &= __ucl_assert(sizeof(ucl_uint) >= sizeof(unsigned));
97
#endif
98
 
99
#if defined(SIZEOF_UNSIGNED)
100
    r &= __ucl_assert(SIZEOF_UNSIGNED == sizeof(unsigned));
101
#endif
102
#if defined(SIZEOF_UNSIGNED_LONG)
103
    r &= __ucl_assert(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long));
104
#endif
105
#if defined(SIZEOF_UNSIGNED_SHORT)
106
    r &= __ucl_assert(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short));
107
#endif
108
#if !defined(__UCL_IN_MINIUCL)
109
#if defined(SIZEOF_SIZE_T)
110
    r &= __ucl_assert(SIZEOF_SIZE_T == sizeof(size_t));
111
#endif
112
#endif
113
 
114
    /* assert the signedness of our integral types */
115
    sanity = IS_UNSIGNED(unsigned short) && IS_UNSIGNED(unsigned) &&
116
             IS_UNSIGNED(unsigned long) &&
117
             IS_SIGNED(short) && IS_SIGNED(int) && IS_SIGNED(long);
118
    if (sanity)
119
    {
120
        r &= __ucl_assert(IS_UNSIGNED(ucl_uint32));
121
        r &= __ucl_assert(IS_UNSIGNED(ucl_uint));
122
        r &= __ucl_assert(IS_SIGNED(ucl_int32));
123
        r &= __ucl_assert(IS_SIGNED(ucl_int));
124
 
125
        r &= __ucl_assert(INT_MAX    == UCL_STYPE_MAX(sizeof(int)));
126
        r &= __ucl_assert(UINT_MAX   == UCL_UTYPE_MAX(sizeof(unsigned)));
127
        r &= __ucl_assert(LONG_MAX   == UCL_STYPE_MAX(sizeof(long)));
128
        r &= __ucl_assert(ULONG_MAX  == UCL_UTYPE_MAX(sizeof(unsigned long)));
129
        r &= __ucl_assert(SHRT_MAX   == UCL_STYPE_MAX(sizeof(short)));
130
        r &= __ucl_assert(USHRT_MAX  == UCL_UTYPE_MAX(sizeof(unsigned short)));
131
        r &= __ucl_assert(UCL_UINT32_MAX == UCL_UTYPE_MAX(sizeof(ucl_uint32)));
132
        r &= __ucl_assert(UCL_UINT_MAX   == UCL_UTYPE_MAX(sizeof(ucl_uint)));
133
#if !defined(__UCL_IN_MINIUCL)
134
        r &= __ucl_assert(SIZE_T_MAX     == UCL_UTYPE_MAX(sizeof(size_t)));
135
#endif
136
    }
137
 
138
    return r;
139
}
140
 
141
 
142
static ucl_bool basic_ptr_check(void)
143
{
144
    ucl_bool r = 1;
145
    ucl_bool sanity;
146
 
147
    r &= __ucl_assert(sizeof(char *) >= sizeof(int));
148
    r &= __ucl_assert(sizeof(ucl_byte *) >= sizeof(char *));
149
 
150
    r &= __ucl_assert(sizeof(ucl_voidp) == sizeof(ucl_byte *));
151
    r &= __ucl_assert(sizeof(ucl_voidp) == sizeof(ucl_voidpp));
152
    r &= __ucl_assert(sizeof(ucl_voidp) == sizeof(ucl_bytepp));
153
    r &= __ucl_assert(sizeof(ucl_voidp) >= sizeof(ucl_uint));
154
 
155
    r &= __ucl_assert(sizeof(ucl_ptr_t) == sizeof(ucl_voidp));
156
    r &= __ucl_assert(sizeof(ucl_ptr_t) >= sizeof(ucl_uint));
157
 
158
    r &= __ucl_assert(sizeof(ucl_ptrdiff_t) >= 4);
159
    r &= __ucl_assert(sizeof(ucl_ptrdiff_t) >= sizeof(ptrdiff_t));
160
 
161
#if defined(SIZEOF_CHAR_P)
162
    r &= __ucl_assert(SIZEOF_CHAR_P == sizeof(char *));
163
#endif
164
#if defined(SIZEOF_PTRDIFF_T)
165
    r &= __ucl_assert(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t));
166
#endif
167
 
168
    /* assert the signedness of our integral types */
169
    sanity = IS_UNSIGNED(unsigned short) && IS_UNSIGNED(unsigned) &&
170
             IS_UNSIGNED(unsigned long) &&
171
             IS_SIGNED(short) && IS_SIGNED(int) && IS_SIGNED(long);
172
    if (sanity)
173
    {
174
        r &= __ucl_assert(IS_UNSIGNED(ucl_ptr_t));
175
        r &= __ucl_assert(IS_SIGNED(ucl_ptrdiff_t));
176
        r &= __ucl_assert(IS_SIGNED(ucl_sptr_t));
177
    }
178
 
179
    return r;
180
}
181
 
182
 
183
/***********************************************************************
184
//
185
************************************************************************/
186
 
187
static ucl_bool ptr_check(void)
188
{
189
    ucl_bool r = 1;
190
    int i;
191
    char _wrkmem[10 * sizeof(ucl_byte *) + sizeof(ucl_align_t)];
192
    ucl_bytep wrkmem;
193
    ucl_bytepp dict;
194
    unsigned char x[4 * sizeof(ucl_align_t)];
195
    long d;
196
    ucl_align_t a;
197
    ucl_align_t u;
198
 
199
    for (i = 0; i < (int) sizeof(x); i++)
200
        x[i] = UCL_BYTE(i);
201
 
202
    wrkmem = UCL_PTR_ALIGN_UP((ucl_byte *)_wrkmem,sizeof(ucl_align_t));
203
 
204
#if 0
205
    dict = (ucl_bytepp) wrkmem;
206
#else
207
    /* Avoid a compiler warning on architectures that
208
     * do not allow unaligned access. */
209
    u.a_ucl_bytep = wrkmem; dict = u.a_ucl_bytepp;
210
#endif
211
 
212
    d = (long) ((const ucl_bytep) dict - (const ucl_bytep) _wrkmem);
213
    r &= __ucl_assert(d >= 0);
214
    r &= __ucl_assert(d < (long) sizeof(ucl_align_t));
215
 
216
    memset(&a,0xff,sizeof(a));
217
    r &= __ucl_assert(a.a_ushort == USHRT_MAX);
218
    r &= __ucl_assert(a.a_uint == UINT_MAX);
219
    r &= __ucl_assert(a.a_ulong == ULONG_MAX);
220
    r &= __ucl_assert(a.a_ucl_uint == UCL_UINT_MAX);
221
 
222
    /* sanity check of the memory model */
223
    if (r == 1)
224
    {
225
        for (i = 0; i < 8; i++)
226
            r &= __ucl_assert((const ucl_voidp) (&dict[i]) == (const ucl_voidp) (&wrkmem[i * sizeof(ucl_byte *)]));
227
    }
228
 
229
    /* check BZERO8_PTR and that NULL == 0 */
230
    memset(&a,0,sizeof(a));
231
    r &= __ucl_assert(a.a_char_p == NULL);
232
    r &= __ucl_assert(a.a_ucl_bytep == NULL);
233
    r &= __ucl_assert(NULL == (void*)0);
234
    if (r == 1)
235
    {
236
        for (i = 0; i < 10; i++)
237
            dict[i] = wrkmem;
238
        BZERO8_PTR(dict+1,sizeof(dict[0]),8);
239
        r &= __ucl_assert(dict[0] == wrkmem);
240
        for (i = 1; i < 9; i++)
241
            r &= __ucl_assert(dict[i] == NULL);
242
        r &= __ucl_assert(dict[9] == wrkmem);
243
    }
244
 
245
    /* check that the pointer constructs work as expected */
246
    if (r == 1)
247
    {
248
        unsigned k = 1;
249
        const unsigned n = (unsigned) sizeof(ucl_uint32);
250
        ucl_byte *p0;
251
        ucl_byte *p1;
252
 
253
        k += __ucl_align_gap(&x[k],n);
254
        p0 = (ucl_bytep) &x[k];
255
#if defined(PTR_LINEAR)
256
        r &= __ucl_assert((PTR_LINEAR(p0) & (n-1)) == 0);
257
#else
258
        r &= __ucl_assert(n == 4);
259
        r &= __ucl_assert(PTR_ALIGNED_4(p0));
260
#endif
261
 
262
        r &= __ucl_assert(k >= 1);
263
        p1 = (ucl_bytep) &x[1];
264
        r &= __ucl_assert(PTR_GE(p0,p1));
265
 
266
        r &= __ucl_assert(k < 1+n);
267
        p1 = (ucl_bytep) &x[1+n];
268
        r &= __ucl_assert(PTR_LT(p0,p1));
269
 
270
        /* now check that aligned memory access doesn't core dump */
271
        if (r == 1)
272
        {
273
            ucl_uint32 v0, v1;
274
#if 0
275
            v0 = * (ucl_uint32 *) &x[k];
276
            v1 = * (ucl_uint32 *) &x[k+n];
277
#else
278
            /* Avoid compiler warnings on architectures that
279
             * do not allow unaligned access. */
280
            u.a_uchar_p = &x[k];
281
            v0 = *u.a_ucl_uint32_p;
282
            u.a_uchar_p = &x[k+n];
283
            v1 = *u.a_ucl_uint32_p;
284
#endif
285
            r &= __ucl_assert(v0 > 0);
286
            r &= __ucl_assert(v1 > 0);
287
        }
288
    }
289
 
290
    return r;
291
}
292
 
293
 
294
/***********************************************************************
295
//
296
************************************************************************/
297
 
298
UCL_PUBLIC(int)
299
_ucl_config_check(void)
300
{
301
    ucl_bool r = 1;
302
    int i;
303
    union {
304
        ucl_uint32 a;
305
        unsigned short b;
306
        ucl_uint32 aa[4];
307
        unsigned char x[4*sizeof(ucl_align_t)];
308
    } u;
309
 
310
#if 0
311
    /* paranoia - the following is guaranteed by definition anyway */
312
    r &= __ucl_assert((const void *)&u == (const void *)&u.a);
313
    r &= __ucl_assert((const void *)&u == (const void *)&u.b);
314
    r &= __ucl_assert((const void *)&u == (const void *)&u.x[0]);
315
    r &= __ucl_assert((const void *)&u == (const void *)&u.aa[0]);
316
#endif
317
 
318
    r &= basic_integral_check();
319
    r &= basic_ptr_check();
320
    if (r != 1)
321
        return UCL_E_ERROR;
322
 
323
    u.a = 0; u.b = 0;
324
    for (i = 0; i < (int) sizeof(u.x); i++)
325
        u.x[i] = UCL_BYTE(i);
326
 
327
#if 0
328
    /* check if the compiler correctly casts signed to unsigned */
329
    r &= __ucl_assert( (int) (unsigned char) ((char) -1) == 255);
330
#endif
331
 
332
    /* check UCL_BYTE_ORDER */
333
#if defined(UCL_BYTE_ORDER)
334
    if (r == 1)
335
    {
336
#  if (UCL_BYTE_ORDER == UCL_LITTLE_ENDIAN)
337
        ucl_uint32 a = (ucl_uint32) (u.a & UCL_UINT32_C(0xffffffff));
338
        unsigned short b = (unsigned short) (u.b & 0xffff);
339
        r &= __ucl_assert(a == UCL_UINT32_C(0x03020100));
340
        r &= __ucl_assert(b == 0x0100);
341
#  elif (UCL_BYTE_ORDER == UCL_BIG_ENDIAN)
342
        ucl_uint32 a = u.a >> (8 * sizeof(u.a) - 32);
343
        unsigned short b = u.b >> (8 * sizeof(u.b) - 16);
344
        r &= __ucl_assert(a == UCL_UINT32_C(0x00010203));
345
        r &= __ucl_assert(b == 0x0001);
346
#  else
347
#    error "invalid UCL_BYTE_ORDER"
348
#  endif
349
    }
350
#endif
351
 
352
    /* check that unaligned memory access works as expected */
353
#if defined(UCL_UNALIGNED_OK_2)
354
    r &= __ucl_assert(sizeof(short) == 2);
355
    if (r == 1)
356
    {
357
        unsigned short b[4];
358
 
359
        for (i = 0; i < 4; i++)
360
            b[i] = * (const unsigned short *) &u.x[i];
361
 
362
#  if (UCL_BYTE_ORDER == UCL_LITTLE_ENDIAN)
363
        r &= __ucl_assert(b[0] == 0x0100);
364
        r &= __ucl_assert(b[1] == 0x0201);
365
        r &= __ucl_assert(b[2] == 0x0302);
366
        r &= __ucl_assert(b[3] == 0x0403);
367
#  elif (UCL_BYTE_ORDER == UCL_BIG_ENDIAN)
368
        r &= __ucl_assert(b[0] == 0x0001);
369
        r &= __ucl_assert(b[1] == 0x0102);
370
        r &= __ucl_assert(b[2] == 0x0203);
371
        r &= __ucl_assert(b[3] == 0x0304);
372
#  endif
373
    }
374
#endif
375
 
376
#if defined(UCL_UNALIGNED_OK_4)
377
    r &= __ucl_assert(sizeof(ucl_uint32) == 4);
378
    if (r == 1)
379
    {
380
        ucl_uint32 a[4];
381
 
382
        for (i = 0; i < 4; i++)
383
            a[i] = * (const ucl_uint32 *) &u.x[i];
384
 
385
#  if (UCL_BYTE_ORDER == UCL_LITTLE_ENDIAN)
386
        r &= __ucl_assert(a[0] == UCL_UINT32_C(0x03020100));
387
        r &= __ucl_assert(a[1] == UCL_UINT32_C(0x04030201));
388
        r &= __ucl_assert(a[2] == UCL_UINT32_C(0x05040302));
389
        r &= __ucl_assert(a[3] == UCL_UINT32_C(0x06050403));
390
#  elif (UCL_BYTE_ORDER == UCL_BIG_ENDIAN)
391
        r &= __ucl_assert(a[0] == UCL_UINT32_C(0x00010203));
392
        r &= __ucl_assert(a[1] == UCL_UINT32_C(0x01020304));
393
        r &= __ucl_assert(a[2] == UCL_UINT32_C(0x02030405));
394
        r &= __ucl_assert(a[3] == UCL_UINT32_C(0x03040506));
395
#  endif
396
    }
397
#endif
398
 
399
#if defined(UCL_ALIGNED_OK_4)
400
    r &= __ucl_assert(sizeof(ucl_uint32) == 4);
401
#endif
402
 
403
    /* check the ucl_adler32() function */
404
    if (r == 1)
405
    {
406
        ucl_uint32 adler;
407
        adler = ucl_adler32(0, NULL, 0);
408
        adler = ucl_adler32(adler, ucl_copyright(), 186);
409
        r &= __ucl_assert(adler == UCL_UINT32_C(0x47fb39fc));
410
    }
411
 
412
    /* check for the gcc schedule-insns optimization bug */
413
    if (r == 1)
414
    {
415
        r &= __ucl_assert(!schedule_insns_bug());
416
    }
417
 
418
    /* check for the gcc strength-reduce optimization bug */
419
    if (r == 1)
420
    {
421
        static int x[3];
422
        static unsigned xn = 3;
423
        register unsigned j;
424
 
425
        for (j = 0; j < xn; j++)
426
            x[j] = (int)j - 3;
427
        r &= __ucl_assert(!strength_reduce_bug(x));
428
    }
429
 
430
    /* now for the low-level pointer checks */
431
    if (r == 1)
432
    {
433
        r &= ptr_check();
434
    }
435
 
436
    return r == 1 ? UCL_E_OK : UCL_E_ERROR;
437
}
438
 
439
 
440
static ucl_bool schedule_insns_bug(void)
441
{
442
#if defined(__UCL_CHECKER)
443
    /* for some reason checker complains about uninitialized memory access */
444
    return 0;
445
#else
446
    const int clone[] = {1, 2, 0};
447
    const int *q;
448
    q = clone;
449
    return (*q) ? 0 : 1;
450
#endif
451
}
452
 
453
 
454
static ucl_bool strength_reduce_bug(int *x)
455
{
456
    return x[0] != -3 || x[1] != -2 || x[2] != -1;
457
}
458
 
459
 
460
/***********************************************************************
461
//
462
************************************************************************/
463
 
464
int __ucl_init_done = 0;
465
 
466
UCL_PUBLIC(int)
467
__ucl_init2(ucl_uint32 v, int s1, int s2, int s3, int s4, int s5,
468
                          int s6, int s7, int s8, int s9)
469
{
470
    int r;
471
 
472
    __ucl_init_done = 1;
473
 
474
    if (v == 0)
475
        return UCL_E_ERROR;
476
 
477
    r = (s1 == -1 || s1 == (int) sizeof(short)) &&
478
        (s2 == -1 || s2 == (int) sizeof(int)) &&
479
        (s3 == -1 || s3 == (int) sizeof(long)) &&
480
        (s4 == -1 || s4 == (int) sizeof(ucl_uint32)) &&
481
        (s5 == -1 || s5 == (int) sizeof(ucl_uint)) &&
482
        (s6 == -1 || s6 > 0) &&
483
        (s7 == -1 || s7 == (int) sizeof(char *)) &&
484
        (s8 == -1 || s8 == (int) sizeof(ucl_voidp)) &&
485
        (s9 == -1 || s9 == (int) sizeof(ucl_compress_t));
486
    if (!r)
487
        return UCL_E_ERROR;
488
 
489
    r = _ucl_config_check();
490
    if (r != UCL_E_OK)
491
        return r;
492
 
493
    return r;
494
}
495
 
496
 
497
/*
498
vi:ts=4:et
499
*/