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 | */ |