#include "bzlib_private.h"Go to the source code of this file.
Compounds | |
| struct | bzFile |
Defines | |
| #define | ADD_CHAR_TO_BLOCK(zs, zchh0) |
| #define | BZ_SETERR(eee) |
| #define | SET_BINARY_MODE(file) |
Functions | |
| void | bz__AssertH__fail (int errcode) |
| void * | default_bzalloc (void *opaque, Int32 items, Int32 size) |
| void | default_bzfree (void *opaque, void *addr) |
| void | prepare_new_block (EState *s) |
| void | init_RL (EState *s) |
| Bool | isempty_RL (EState *s) |
| int | BZ_API (bzCompressInit)(bz_stream *strm, int blockSize100k, int verbosity, int workFactor) |
| void | add_pair_to_block (EState *s) |
| void | flush_RL (EState *s) |
| Bool | copy_input_until_stop (EState *s) |
| Bool | copy_output_until_stop (EState *s) |
| Bool | handle_compress (bz_stream *strm) |
| void | unRLE_obuf_to_output_FAST (DState *s) |
| __inline__ Int32 | indexIntoF (Int32 indx, Int32 *cftab) |
| void | unRLE_obuf_to_output_SMALL (DState *s) |
| Bool | myfeof (FILE *f) |
| BZFILE * | bzopen_or_bzdopen (const char *path, int fd, const char *mode, int open_mode) |
| BZFILE * | BZ_API (bzopen)(const char *path, const char *mode) |
Variables | |
| char * | bzerrorstrings [] |
|
|
Value: { \
UInt32 zchh = (UInt32)(zchh0); \
\
if (zchh != zs->state_in_ch && \
zs->state_in_len == 1) { \
UChar ch = (UChar)(zs->state_in_ch); \
BZ_UPDATE_CRC( zs->blockCRC, ch ); \
zs->inUse[zs->state_in_ch] = True; \
zs->block[zs->nblock] = (UInt16)ch; \
zs->nblock++; \
zs->state_in_ch = zchh; \
} \
else \
\
if (zchh != zs->state_in_ch || \
zs->state_in_len == 255) { \
if (zs->state_in_ch < 256) \
add_pair_to_block ( zs ); \
zs->state_in_ch = zchh; \
zs->state_in_len = 1; \
} else { \
zs->state_in_len++; \
} \
}Definition at line 260 of file bzlib.c. Referenced by copy_input_until_stop().
|
|
|
Value: { \
if (bzerror != NULL) *bzerror = eee; \
if (bzf != NULL) bzf->lastErr = eee; \
} |
|
|
|
|
|
Definition at line 1398 of file bzlib.c. 01401 {
01402 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
01403 }
|
|
|
Definition at line 152 of file bzlib.c. 00157 {
00158 Int32 n;
00159 EState* s;
00160
00161 if (strm == NULL ||
00162 blockSize100k < 1 || blockSize100k > 9 ||
00163 workFactor < 0 || workFactor > 250)
00164 return BZ_PARAM_ERROR;
00165
00166 if (workFactor == 0) workFactor = 30;
00167 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
00168 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
00169
00170 s = BZALLOC( sizeof(EState) );
00171 if (s == NULL) return BZ_MEM_ERROR;
00172 s->strm = strm;
00173
00174 s->arr1 = NULL;
00175 s->arr2 = NULL;
00176 s->ftab = NULL;
00177
00178 n = 100000 * blockSize100k;
00179 s->arr1 = BZALLOC( n * sizeof(UInt32) );
00180 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
00181 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
00182
00183 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
00184 if (s->arr1 != NULL) BZFREE(s->arr1);
00185 if (s->arr2 != NULL) BZFREE(s->arr2);
00186 if (s->ftab != NULL) BZFREE(s->ftab);
00187 if (s != NULL) BZFREE(s);
00188 return BZ_MEM_ERROR;
00189 }
00190
00191 s->blockNo = 0;
00192 s->state = BZ_S_INPUT;
00193 s->mode = BZ_M_RUNNING;
00194 s->combinedCRC = 0;
00195 s->blockSize100k = blockSize100k;
00196 s->nblockMAX = 100000 * blockSize100k - 19;
00197 s->verbosity = verbosity;
00198 s->workFactor = workFactor;
00199
00200 s->block = (UInt16*)s->arr2;
00201 s->mtfv = (UInt16*)s->arr1;
00202 s->zbits = NULL;
00203 s->ptr = (UInt32*)s->arr1;
00204
00205 strm->state = s;
00206 strm->total_in = 0;
00207 strm->total_out = 0;
00208 init_RL ( s );
00209 prepare_new_block ( s );
00210 return BZ_OK;
00211 }
|
|
|
Definition at line 216 of file bzlib.c. Referenced by flush_RL().
00217 {
00218 Int32 i;
00219 UChar ch = (UChar)(s->state_in_ch);
00220 for (i = 0; i < s->state_in_len; i++) {
00221 BZ_UPDATE_CRC( s->blockCRC, ch );
00222 }
00223 s->inUse[s->state_in_ch] = True;
00224 switch (s->state_in_len) {
00225 case 1:
00226 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00227 break;
00228 case 2:
00229 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00230 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00231 break;
00232 case 3:
00233 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00234 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00235 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00236 break;
00237 default:
00238 s->inUse[s->state_in_len-4] = True;
00239 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00240 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00241 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00242 s->block[s->nblock] = (UInt16)ch; s->nblock++;
00243 s->block[s->nblock] = ((UInt16)(s->state_in_len-4));
00244 s->nblock++;
00245 break;
00246 }
00247 }
|
|
|
Definition at line 86 of file bzlib.c. 00087 {
00088 fprintf(stderr,
00089 "\n\nbzip2/libbzip2, v0.9.5a: internal error number %d.\n"
00090 "This is a bug in bzip2/libbzip2, v0.9.5a. Please report\n"
00091 "it to me at: jseward@acm.org. If this happened when\n"
00092 "you were using some program which uses libbzip2 as a\n"
00093 "component, you should also report this bug to the author(s)\n"
00094 "of that program. Please make an effort to report this bug;\n"
00095 "timely and accurate bug reports eventually lead to higher\n"
00096 "quality software. Thanks. Julian Seward, 24 May 1999.\n\n",
00097 errcode
00098 );
00099 exit(3);
00100 }
|
|
||||||||||||||||||||
|
Definition at line 1324 of file bzlib.c. Referenced by BZ_API().
01327 : 0, bzdopen:1 */
01328 {
01329 int bzerr;
01330 char unused[BZ_MAX_UNUSED];
01331 int blockSize100k = 9;
01332 int writing = 0;
01333 char mode2[10] = "";
01334 FILE *fp = NULL;
01335 BZFILE *bzfp = NULL;
01336 int verbosity = 0;
01337 int workFactor = 30;
01338 int smallMode = 0;
01339 int nUnused = 0;
01340
01341 if (mode == NULL) return NULL;
01342 while (*mode) {
01343 switch (*mode) {
01344 case 'r':
01345 writing = 0; break;
01346 case 'w':
01347 writing = 1; break;
01348 case 's':
01349 smallMode = 1; break;
01350 default:
01351 if (isdigit((int)(*mode))) {
01352 blockSize100k = *mode-'0';
01353 }
01354 }
01355 mode++;
01356 }
01357 strcat(mode2, writing ? "w" : "r" );
01358 strcat(mode2,"b"); /* binary mode */
01359
01360 if (open_mode==0) {
01361 if (path==NULL || strcmp(path,"")==0) {
01362 fp = (writing ? stdout : stdin);
01363 SET_BINARY_MODE(fp);
01364 } else {
01365 fp = fopen(path,mode2);
01366 }
01367 } else {
01368 #ifdef BZ_STRICT_ANSI
01369 fp = NULL;
01370 #else
01371 fp = fdopen(fd,mode2);
01372 #endif
01373 }
01374 if (fp == NULL) return NULL;
01375
01376 if (writing) {
01377 /* Guard against total chaos and anarchy -- JRS */
01378 if (blockSize100k < 1) blockSize100k = 1;
01379 if (blockSize100k > 9) blockSize100k = 9;
01380 bzfp = bzWriteOpen(&bzerr,fp,blockSize100k,verbosity,workFactor);
01381 } else {
01382 bzfp = bzReadOpen(&bzerr,fp,verbosity,smallMode,unused,nUnused);
01383 }
01384 if (bzfp == NULL) {
01385 if (fp != stdin && fp != stdout) fclose(fp);
01386 return NULL;
01387 }
01388 return bzfp;
01389 }
|
|
|
Definition at line 289 of file bzlib.c. Referenced by handle_compress().
00290 {
00291 Bool progress_in = False;
00292
00293 if (s->mode == BZ_M_RUNNING) {
00294
00295 /*-- fast track the common case --*/
00296 while (True) {
00297 /*-- block full? --*/
00298 if (s->nblock >= s->nblockMAX) break;
00299 /*-- no input? --*/
00300 if (s->strm->avail_in == 0) break;
00301 progress_in = True;
00302 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
00303 s->strm->next_in++;
00304 s->strm->avail_in--;
00305 s->strm->total_in++;
00306 }
00307
00308 } else {
00309
00310 /*-- general, uncommon case --*/
00311 while (True) {
00312 /*-- block full? --*/
00313 if (s->nblock >= s->nblockMAX) break;
00314 /*-- no input? --*/
00315 if (s->strm->avail_in == 0) break;
00316 /*-- flush/finish end? --*/
00317 if (s->avail_in_expect == 0) break;
00318 progress_in = True;
00319 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
00320 s->strm->next_in++;
00321 s->strm->avail_in--;
00322 s->strm->total_in++;
00323 s->avail_in_expect--;
00324 }
00325 }
00326 return progress_in;
00327 }
|
|
|
Definition at line 332 of file bzlib.c. Referenced by handle_compress().
00333 {
00334 Bool progress_out = False;
00335
00336 while (True) {
00337
00338 /*-- no output space? --*/
00339 if (s->strm->avail_out == 0) break;
00340
00341 /*-- block done? --*/
00342 if (s->state_out_pos >= s->numZ) break;
00343
00344 progress_out = True;
00345 *(s->strm->next_out) = s->zbits[s->state_out_pos];
00346 s->state_out_pos++;
00347 s->strm->avail_out--;
00348 s->strm->next_out++;
00349 s->strm->total_out++;
00350
00351 }
00352
00353 return progress_out;
00354 }
|
|
||||||||||||||||
|
|
|
||||||||||||
|
Definition at line 113 of file bzlib.c. 00114 {
00115 if (addr != NULL) free ( addr );
00116 }
|
|
|
Definition at line 252 of file bzlib.c. Referenced by handle_compress().
00253 {
00254 if (s->state_in_ch < 256) add_pair_to_block ( s );
00255 init_RL ( s );
00256 }
|
|
|
Definition at line 359 of file bzlib.c. 00360 {
00361 Bool progress_in = False;
00362 Bool progress_out = False;
00363 EState* s = strm->state;
00364
00365 while (True) {
00366
00367 if (s->state == BZ_S_OUTPUT) {
00368 progress_out |= copy_output_until_stop ( s );
00369 if (s->state_out_pos < s->numZ) break;
00370 if (s->mode == BZ_M_FINISHING &&
00371 s->avail_in_expect == 0 &&
00372 isempty_RL(s)) break;
00373 prepare_new_block ( s );
00374 s->state = BZ_S_INPUT;
00375 if (s->mode == BZ_M_FLUSHING &&
00376 s->avail_in_expect == 0 &&
00377 isempty_RL(s)) break;
00378 }
00379
00380 if (s->state == BZ_S_INPUT) {
00381 progress_in |= copy_input_until_stop ( s );
00382 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
00383 flush_RL ( s );
00384 compressBlock ( s, s->mode == BZ_M_FINISHING );
00385 s->state = BZ_S_OUTPUT;
00386 }
00387 else
00388 if (s->nblock >= s->nblockMAX) {
00389 compressBlock ( s, False );
00390 s->state = BZ_S_OUTPUT;
00391 }
00392 else
00393 if (s->strm->avail_in == 0) {
00394 break;
00395 }
00396 }
00397
00398 }
00399
00400 return progress_in || progress_out;
00401 }
|
|
||||||||||||
|
Definition at line 662 of file bzlib.c. 00663 {
00664 Int32 nb, na, mid;
00665 nb = 0;
00666 na = 256;
00667 do {
00668 mid = (nb + na) >> 1;
00669 if (indx >= cftab[mid]) nb = mid; else na = mid;
00670 }
00671 while (na - nb != 1);
00672 return nb;
00673 }
|
|
|
Definition at line 135 of file bzlib.c. Referenced by BZ_API(), and flush_RL().
00136 {
00137 s->state_in_ch = 256;
00138 s->state_in_len = 0;
00139 }
|
|
|
Definition at line 143 of file bzlib.c. Referenced by handle_compress().
00144 {
00145 if (s->state_in_ch < 256 && s->state_in_len > 0)
00146 return False; else
00147 return True;
00148 }
|
|
|
Definition at line 867 of file bzlib.c. Referenced by compressStream(), testStream(), and uncompressStream().
|
|
|
Definition at line 121 of file bzlib.c. Referenced by BZ_API(), and handle_compress().
00122 {
00123 Int32 i;
00124 s->nblock = 0;
00125 s->numZ = 0;
00126 s->state_out_pos = 0;
00127 BZ_INITIALISE_CRC ( s->blockCRC );
00128 for (i = 0; i < 256; i++) s->inUse[i] = False;
00129 s->blockNo++;
00130 }
|
|
|
Definition at line 525 of file bzlib.c. 00526 {
00527 UChar k1;
00528
00529 if (s->blockRandomised) {
00530
00531 while (True) {
00532 /* try to finish existing run */
00533 while (True) {
00534 if (s->strm->avail_out == 0) return;
00535 if (s->state_out_len == 0) break;
00536 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
00537 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
00538 s->state_out_len--;
00539 s->strm->next_out++;
00540 s->strm->avail_out--;
00541 s->strm->total_out++;
00542 }
00543
00544 /* can a new run be started? */
00545 if (s->nblock_used == s->save_nblock+1) return;
00546
00547
00548 s->state_out_len = 1;
00549 s->state_out_ch = s->k0;
00550 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
00551 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00552 if (s->nblock_used == s->save_nblock+1) continue;
00553 if (k1 != s->k0) { s->k0 = k1; continue; };
00554
00555 s->state_out_len = 2;
00556 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
00557 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00558 if (s->nblock_used == s->save_nblock+1) continue;
00559 if (k1 != s->k0) { s->k0 = k1; continue; };
00560
00561 s->state_out_len = 3;
00562 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
00563 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00564 if (s->nblock_used == s->save_nblock+1) continue;
00565 if (k1 != s->k0) { s->k0 = k1; continue; };
00566
00567 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
00568 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00569 s->state_out_len = ((Int32)k1) + 4;
00570 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
00571 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
00572 }
00573
00574 } else {
00575
00576 /* restore */
00577 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
00578 UChar c_state_out_ch = s->state_out_ch;
00579 Int32 c_state_out_len = s->state_out_len;
00580 Int32 c_nblock_used = s->nblock_used;
00581 Int32 c_k0 = s->k0;
00582 UInt32* c_tt = s->tt;
00583 UInt32 c_tPos = s->tPos;
00584 char* cs_next_out = s->strm->next_out;
00585 unsigned int cs_avail_out = s->strm->avail_out;
00586 /* end restore */
00587
00588 UInt32 avail_out_INIT = cs_avail_out;
00589 Int32 s_save_nblockPP = s->save_nblock+1;
00590
00591 while (True) {
00592
00593 /* try to finish existing run */
00594 if (c_state_out_len > 0) {
00595 while (True) {
00596 if (cs_avail_out == 0) goto return_notr;
00597 if (c_state_out_len == 1) break;
00598 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
00599 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
00600 c_state_out_len--;
00601 cs_next_out++;
00602 cs_avail_out--;
00603 }
00604 s_state_out_len_eq_one:
00605 {
00606 if (cs_avail_out == 0) {
00607 c_state_out_len = 1; goto return_notr;
00608 };
00609 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
00610 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
00611 cs_next_out++;
00612 cs_avail_out--;
00613 }
00614 }
00615 /* can a new run be started? */
00616 if (c_nblock_used == s_save_nblockPP) {
00617 c_state_out_len = 0; goto return_notr;
00618 };
00619 c_state_out_ch = c_k0;
00620 BZ_GET_FAST_C(k1); c_nblock_used++;
00621 if (k1 != c_k0) {
00622 c_k0 = k1; goto s_state_out_len_eq_one;
00623 };
00624 if (c_nblock_used == s_save_nblockPP)
00625 goto s_state_out_len_eq_one;
00626
00627 c_state_out_len = 2;
00628 BZ_GET_FAST_C(k1); c_nblock_used++;
00629 if (c_nblock_used == s_save_nblockPP) continue;
00630 if (k1 != c_k0) { c_k0 = k1; continue; };
00631
00632 c_state_out_len = 3;
00633 BZ_GET_FAST_C(k1); c_nblock_used++;
00634 if (c_nblock_used == s_save_nblockPP) continue;
00635 if (k1 != c_k0) { c_k0 = k1; continue; };
00636
00637 BZ_GET_FAST_C(k1); c_nblock_used++;
00638 c_state_out_len = ((Int32)k1) + 4;
00639 BZ_GET_FAST_C(c_k0); c_nblock_used++;
00640 }
00641
00642 return_notr:
00643 s->strm->total_out += (avail_out_INIT - cs_avail_out);
00644
00645 /* save */
00646 s->calculatedBlockCRC = c_calculatedBlockCRC;
00647 s->state_out_ch = c_state_out_ch;
00648 s->state_out_len = c_state_out_len;
00649 s->nblock_used = c_nblock_used;
00650 s->k0 = c_k0;
00651 s->tt = c_tt;
00652 s->tPos = c_tPos;
00653 s->strm->next_out = cs_next_out;
00654 s->strm->avail_out = cs_avail_out;
00655 /* end save */
00656 }
00657 }
|
|
|
Definition at line 678 of file bzlib.c. 00679 {
00680 UChar k1;
00681
00682 if (s->blockRandomised) {
00683
00684 while (True) {
00685 /* try to finish existing run */
00686 while (True) {
00687 if (s->strm->avail_out == 0) return;
00688 if (s->state_out_len == 0) break;
00689 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
00690 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
00691 s->state_out_len--;
00692 s->strm->next_out++;
00693 s->strm->avail_out--;
00694 s->strm->total_out++;
00695 }
00696
00697 /* can a new run be started? */
00698 if (s->nblock_used == s->save_nblock+1) return;
00699
00700
00701 s->state_out_len = 1;
00702 s->state_out_ch = s->k0;
00703 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
00704 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00705 if (s->nblock_used == s->save_nblock+1) continue;
00706 if (k1 != s->k0) { s->k0 = k1; continue; };
00707
00708 s->state_out_len = 2;
00709 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
00710 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00711 if (s->nblock_used == s->save_nblock+1) continue;
00712 if (k1 != s->k0) { s->k0 = k1; continue; };
00713
00714 s->state_out_len = 3;
00715 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
00716 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00717 if (s->nblock_used == s->save_nblock+1) continue;
00718 if (k1 != s->k0) { s->k0 = k1; continue; };
00719
00720 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
00721 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00722 s->state_out_len = ((Int32)k1) + 4;
00723 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
00724 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
00725 }
00726
00727 } else {
00728
00729 while (True) {
00730 /* try to finish existing run */
00731 while (True) {
00732 if (s->strm->avail_out == 0) return;
00733 if (s->state_out_len == 0) break;
00734 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
00735 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
00736 s->state_out_len--;
00737 s->strm->next_out++;
00738 s->strm->avail_out--;
00739 s->strm->total_out++;
00740 }
00741
00742 /* can a new run be started? */
00743 if (s->nblock_used == s->save_nblock+1) return;
00744
00745 s->state_out_len = 1;
00746 s->state_out_ch = s->k0;
00747 BZ_GET_SMALL(k1); s->nblock_used++;
00748 if (s->nblock_used == s->save_nblock+1) continue;
00749 if (k1 != s->k0) { s->k0 = k1; continue; };
00750
00751 s->state_out_len = 2;
00752 BZ_GET_SMALL(k1); s->nblock_used++;
00753 if (s->nblock_used == s->save_nblock+1) continue;
00754 if (k1 != s->k0) { s->k0 = k1; continue; };
00755
00756 s->state_out_len = 3;
00757 BZ_GET_SMALL(k1); s->nblock_used++;
00758 if (s->nblock_used == s->save_nblock+1) continue;
00759 if (k1 != s->k0) { s->k0 = k1; continue; };
00760
00761 BZ_GET_SMALL(k1); s->nblock_used++;
00762 s->state_out_len = ((Int32)k1) + 4;
00763 BZ_GET_SMALL(s->k0); s->nblock_used++;
00764 }
00765
00766 }
00767 }
|
|
|
Initial value: {
"OK"
,"SEQUENCE_ERROR"
,"PARAM_ERROR"
,"MEM_ERROR"
,"DATA_ERROR"
,"DATA_ERROR_MAGIC"
,"IO_ERROR"
,"UNEXPECTED_EOF"
,"OUTBUFF_FULL"
,"???"
,"???"
,"???"
,"???"
,"???"
,"???"
} |
1.2.11.1 written by Dimitri van Heesch,
© 1997-2001