Subversion Repositories QNX 8.QNX8 IFS tool

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
26 pmbaty 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
*/