]> git.saurik.com Git - apple/libc.git/blob - gdtoa/FreeBSD/gdtoa-misc.c
Libc-391.2.3.tar.gz
[apple/libc.git] / gdtoa / FreeBSD / gdtoa-misc.c
1 /****************************************************************
2
3 The author of this software is David M. Gay.
4
5 Copyright (C) 1998, 1999 by Lucent Technologies
6 All Rights Reserved
7
8 Permission to use, copy, modify, and distribute this software and
9 its documentation for any purpose and without fee is hereby
10 granted, provided that the above copyright notice appear in all
11 copies and that both that the copyright notice and this
12 permission notice and warranty disclaimer appear in supporting
13 documentation, and that the name of Lucent or any of its entities
14 not be used in advertising or publicity pertaining to
15 distribution of the software without specific, written prior
16 permission.
17
18 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25 THIS SOFTWARE.
26
27 ****************************************************************/
28
29 /* Please send bug reports to David M. Gay (dmg at acm dot org,
30 * with " at " changed at "@" and " dot " changed to "."). */
31
32 #include "gdtoaimp.h"
33
34 static Bigint *freelist[Kmax+1];
35 #ifndef Omit_Private_Memory
36 #ifndef PRIVATE_MEM
37 #define PRIVATE_MEM 2304
38 #endif
39 #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
40 static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
41 #endif
42
43 Bigint *
44 Balloc
45 #ifdef KR_headers
46 (k) int k;
47 #else
48 (int k)
49 #endif
50 {
51 int x;
52 Bigint *rv;
53 #ifndef Omit_Private_Memory
54 unsigned int len;
55 #endif
56
57 ACQUIRE_DTOA_LOCK(0);
58 if ( (rv = freelist[k]) !=0) {
59 freelist[k] = rv->next;
60 }
61 else {
62 x = 1 << k;
63 #ifdef Omit_Private_Memory
64 rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
65 #else
66 len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
67 /sizeof(double);
68 if (pmem_next - private_mem + len <= PRIVATE_mem) {
69 rv = (Bigint*)pmem_next;
70 pmem_next += len;
71 }
72 else
73 rv = (Bigint*)MALLOC(len*sizeof(double));
74 #endif
75 rv->k = k;
76 rv->maxwds = x;
77 }
78 FREE_DTOA_LOCK(0);
79 rv->sign = rv->wds = 0;
80 return rv;
81 }
82
83 void
84 Bfree
85 #ifdef KR_headers
86 (v) Bigint *v;
87 #else
88 (Bigint *v)
89 #endif
90 {
91 if (v) {
92 ACQUIRE_DTOA_LOCK(0);
93 v->next = freelist[v->k];
94 freelist[v->k] = v;
95 FREE_DTOA_LOCK(0);
96 }
97 }
98
99 int
100 lo0bits
101 #ifdef KR_headers
102 (y) ULong *y;
103 #else
104 (ULong *y)
105 #endif
106 {
107 register int k;
108 register ULong x = *y;
109
110 if (x & 7) {
111 if (x & 1)
112 return 0;
113 if (x & 2) {
114 *y = x >> 1;
115 return 1;
116 }
117 *y = x >> 2;
118 return 2;
119 }
120 k = 0;
121 if (!(x & 0xffff)) {
122 k = 16;
123 x >>= 16;
124 }
125 if (!(x & 0xff)) {
126 k += 8;
127 x >>= 8;
128 }
129 if (!(x & 0xf)) {
130 k += 4;
131 x >>= 4;
132 }
133 if (!(x & 0x3)) {
134 k += 2;
135 x >>= 2;
136 }
137 if (!(x & 1)) {
138 k++;
139 x >>= 1;
140 if (!x)
141 return 32;
142 }
143 *y = x;
144 return k;
145 }
146
147 Bigint *
148 multadd
149 #ifdef KR_headers
150 (b, m, a) Bigint *b; int m, a;
151 #else
152 (Bigint *b, int m, int a) /* multiply by m and add a */
153 #endif
154 {
155 int i, wds;
156 #ifdef ULLong
157 ULong *x;
158 ULLong carry, y;
159 #else
160 ULong carry, *x, y;
161 #ifdef Pack_32
162 ULong xi, z;
163 #endif
164 #endif
165 Bigint *b1;
166
167 wds = b->wds;
168 x = b->x;
169 i = 0;
170 carry = a;
171 do {
172 #ifdef ULLong
173 y = *x * (ULLong)m + carry;
174 carry = y >> 32;
175 *x++ = y & 0xffffffffUL;
176 #else
177 #ifdef Pack_32
178 xi = *x;
179 y = (xi & 0xffff) * m + carry;
180 z = (xi >> 16) * m + (y >> 16);
181 carry = z >> 16;
182 *x++ = (z << 16) + (y & 0xffff);
183 #else
184 y = *x * m + carry;
185 carry = y >> 16;
186 *x++ = y & 0xffff;
187 #endif
188 #endif
189 }
190 while(++i < wds);
191 if (carry) {
192 if (wds >= b->maxwds) {
193 b1 = Balloc(b->k+1);
194 Bcopy(b1, b);
195 Bfree(b);
196 b = b1;
197 }
198 b->x[wds++] = carry;
199 b->wds = wds;
200 }
201 return b;
202 }
203
204 int
205 hi0bits_D2A
206 #ifdef KR_headers
207 (x) register ULong x;
208 #else
209 (register ULong x)
210 #endif
211 {
212 register int k = 0;
213
214 if (!(x & 0xffff0000)) {
215 k = 16;
216 x <<= 16;
217 }
218 if (!(x & 0xff000000)) {
219 k += 8;
220 x <<= 8;
221 }
222 if (!(x & 0xf0000000)) {
223 k += 4;
224 x <<= 4;
225 }
226 if (!(x & 0xc0000000)) {
227 k += 2;
228 x <<= 2;
229 }
230 if (!(x & 0x80000000)) {
231 k++;
232 if (!(x & 0x40000000))
233 return 32;
234 }
235 return k;
236 }
237
238 Bigint *
239 i2b
240 #ifdef KR_headers
241 (i) int i;
242 #else
243 (int i)
244 #endif
245 {
246 Bigint *b;
247
248 b = Balloc(1);
249 b->x[0] = i;
250 b->wds = 1;
251 return b;
252 }
253
254 Bigint *
255 mult
256 #ifdef KR_headers
257 (a, b) Bigint *a, *b;
258 #else
259 (Bigint *a, Bigint *b)
260 #endif
261 {
262 Bigint *c;
263 int k, wa, wb, wc;
264 ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
265 ULong y;
266 #ifdef ULLong
267 ULLong carry, z;
268 #else
269 ULong carry, z;
270 #ifdef Pack_32
271 ULong z2;
272 #endif
273 #endif
274
275 if (a->wds < b->wds) {
276 c = a;
277 a = b;
278 b = c;
279 }
280 k = a->k;
281 wa = a->wds;
282 wb = b->wds;
283 wc = wa + wb;
284 if (wc > a->maxwds)
285 k++;
286 c = Balloc(k);
287 for(x = c->x, xa = x + wc; x < xa; x++)
288 *x = 0;
289 xa = a->x;
290 xae = xa + wa;
291 xb = b->x;
292 xbe = xb + wb;
293 xc0 = c->x;
294 #ifdef ULLong
295 for(; xb < xbe; xc0++) {
296 if ( (y = *xb++) !=0) {
297 x = xa;
298 xc = xc0;
299 carry = 0;
300 do {
301 z = *x++ * (ULLong)y + *xc + carry;
302 carry = z >> 32;
303 *xc++ = z & 0xffffffffUL;
304 }
305 while(x < xae);
306 *xc = carry;
307 }
308 }
309 #else
310 #ifdef Pack_32
311 for(; xb < xbe; xb++, xc0++) {
312 if ( (y = *xb & 0xffff) !=0) {
313 x = xa;
314 xc = xc0;
315 carry = 0;
316 do {
317 z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
318 carry = z >> 16;
319 z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
320 carry = z2 >> 16;
321 Storeinc(xc, z2, z);
322 }
323 while(x < xae);
324 *xc = carry;
325 }
326 if ( (y = *xb >> 16) !=0) {
327 x = xa;
328 xc = xc0;
329 carry = 0;
330 z2 = *xc;
331 do {
332 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
333 carry = z >> 16;
334 Storeinc(xc, z, z2);
335 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
336 carry = z2 >> 16;
337 }
338 while(x < xae);
339 *xc = z2;
340 }
341 }
342 #else
343 for(; xb < xbe; xc0++) {
344 if ( (y = *xb++) !=0) {
345 x = xa;
346 xc = xc0;
347 carry = 0;
348 do {
349 z = *x++ * y + *xc + carry;
350 carry = z >> 16;
351 *xc++ = z & 0xffff;
352 }
353 while(x < xae);
354 *xc = carry;
355 }
356 }
357 #endif
358 #endif
359 for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
360 c->wds = wc;
361 return c;
362 }
363
364 static Bigint *p5s;
365
366 Bigint *
367 pow5mult
368 #ifdef KR_headers
369 (b, k) Bigint *b; int k;
370 #else
371 (Bigint *b, int k)
372 #endif
373 {
374 Bigint *b1, *p5, *p51;
375 int i;
376 static int p05[3] = { 5, 25, 125 };
377
378 if ( (i = k & 3) !=0)
379 b = multadd(b, p05[i-1], 0);
380
381 if (!(k >>= 2))
382 return b;
383 if ((p5 = p5s) == 0) {
384 /* first time */
385 #ifdef MULTIPLE_THREADS
386 ACQUIRE_DTOA_LOCK(1);
387 if (!(p5 = p5s)) {
388 p5 = p5s = i2b(625);
389 p5->next = 0;
390 }
391 FREE_DTOA_LOCK(1);
392 #else
393 p5 = p5s = i2b(625);
394 p5->next = 0;
395 #endif
396 }
397 for(;;) {
398 if (k & 1) {
399 b1 = mult(b, p5);
400 Bfree(b);
401 b = b1;
402 }
403 if (!(k >>= 1))
404 break;
405 if ((p51 = p5->next) == 0) {
406 #ifdef MULTIPLE_THREADS
407 ACQUIRE_DTOA_LOCK(1);
408 if (!(p51 = p5->next)) {
409 p51 = p5->next = mult(p5,p5);
410 p51->next = 0;
411 }
412 FREE_DTOA_LOCK(1);
413 #else
414 p51 = p5->next = mult(p5,p5);
415 p51->next = 0;
416 #endif
417 }
418 p5 = p51;
419 }
420 return b;
421 }
422
423 Bigint *
424 lshift
425 #ifdef KR_headers
426 (b, k) Bigint *b; int k;
427 #else
428 (Bigint *b, int k)
429 #endif
430 {
431 int i, k1, n, n1;
432 Bigint *b1;
433 ULong *x, *x1, *xe, z;
434
435 n = k >> kshift;
436 k1 = b->k;
437 n1 = n + b->wds + 1;
438 for(i = b->maxwds; n1 > i; i <<= 1)
439 k1++;
440 b1 = Balloc(k1);
441 x1 = b1->x;
442 for(i = 0; i < n; i++)
443 *x1++ = 0;
444 x = b->x;
445 xe = x + b->wds;
446 if (k &= kmask) {
447 #ifdef Pack_32
448 k1 = 32 - k;
449 z = 0;
450 do {
451 *x1++ = *x << k | z;
452 z = *x++ >> k1;
453 }
454 while(x < xe);
455 if ((*x1 = z) !=0)
456 ++n1;
457 #else
458 k1 = 16 - k;
459 z = 0;
460 do {
461 *x1++ = *x << k & 0xffff | z;
462 z = *x++ >> k1;
463 }
464 while(x < xe);
465 if (*x1 = z)
466 ++n1;
467 #endif
468 }
469 else do
470 *x1++ = *x++;
471 while(x < xe);
472 b1->wds = n1 - 1;
473 Bfree(b);
474 return b1;
475 }
476
477 int
478 cmp
479 #ifdef KR_headers
480 (a, b) Bigint *a, *b;
481 #else
482 (Bigint *a, Bigint *b)
483 #endif
484 {
485 ULong *xa, *xa0, *xb, *xb0;
486 int i, j;
487
488 i = a->wds;
489 j = b->wds;
490 #ifdef DEBUG
491 if (i > 1 && !a->x[i-1])
492 Bug("cmp called with a->x[a->wds-1] == 0");
493 if (j > 1 && !b->x[j-1])
494 Bug("cmp called with b->x[b->wds-1] == 0");
495 #endif
496 if (i -= j)
497 return i;
498 xa0 = a->x;
499 xa = xa0 + j;
500 xb0 = b->x;
501 xb = xb0 + j;
502 for(;;) {
503 if (*--xa != *--xb)
504 return *xa < *xb ? -1 : 1;
505 if (xa <= xa0)
506 break;
507 }
508 return 0;
509 }
510
511 Bigint *
512 diff
513 #ifdef KR_headers
514 (a, b) Bigint *a, *b;
515 #else
516 (Bigint *a, Bigint *b)
517 #endif
518 {
519 Bigint *c;
520 int i, wa, wb;
521 ULong *xa, *xae, *xb, *xbe, *xc;
522 #ifdef ULLong
523 ULLong borrow, y;
524 #else
525 ULong borrow, y;
526 #ifdef Pack_32
527 ULong z;
528 #endif
529 #endif
530
531 i = cmp(a,b);
532 if (!i) {
533 c = Balloc(0);
534 c->wds = 1;
535 c->x[0] = 0;
536 return c;
537 }
538 if (i < 0) {
539 c = a;
540 a = b;
541 b = c;
542 i = 1;
543 }
544 else
545 i = 0;
546 c = Balloc(a->k);
547 c->sign = i;
548 wa = a->wds;
549 xa = a->x;
550 xae = xa + wa;
551 wb = b->wds;
552 xb = b->x;
553 xbe = xb + wb;
554 xc = c->x;
555 borrow = 0;
556 #ifdef ULLong
557 do {
558 y = (ULLong)*xa++ - *xb++ - borrow;
559 borrow = y >> 32 & 1UL;
560 *xc++ = y & 0xffffffffUL;
561 }
562 while(xb < xbe);
563 while(xa < xae) {
564 y = *xa++ - borrow;
565 borrow = y >> 32 & 1UL;
566 *xc++ = y & 0xffffffffUL;
567 }
568 #else
569 #ifdef Pack_32
570 do {
571 y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
572 borrow = (y & 0x10000) >> 16;
573 z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
574 borrow = (z & 0x10000) >> 16;
575 Storeinc(xc, z, y);
576 }
577 while(xb < xbe);
578 while(xa < xae) {
579 y = (*xa & 0xffff) - borrow;
580 borrow = (y & 0x10000) >> 16;
581 z = (*xa++ >> 16) - borrow;
582 borrow = (z & 0x10000) >> 16;
583 Storeinc(xc, z, y);
584 }
585 #else
586 do {
587 y = *xa++ - *xb++ - borrow;
588 borrow = (y & 0x10000) >> 16;
589 *xc++ = y & 0xffff;
590 }
591 while(xb < xbe);
592 while(xa < xae) {
593 y = *xa++ - borrow;
594 borrow = (y & 0x10000) >> 16;
595 *xc++ = y & 0xffff;
596 }
597 #endif
598 #endif
599 while(!*--xc)
600 wa--;
601 c->wds = wa;
602 return c;
603 }
604
605 double
606 b2d
607 #ifdef KR_headers
608 (a, e) Bigint *a; int *e;
609 #else
610 (Bigint *a, int *e)
611 #endif
612 {
613 ULong *xa, *xa0, w, y, z;
614 int k;
615 double d;
616 #ifdef VAX
617 ULong d0, d1;
618 #else
619 #define d0 word0(d)
620 #define d1 word1(d)
621 #endif
622
623 xa0 = a->x;
624 xa = xa0 + a->wds;
625 y = *--xa;
626 #ifdef DEBUG
627 if (!y) Bug("zero y in b2d");
628 #endif
629 k = hi0bits(y);
630 *e = 32 - k;
631 #ifdef Pack_32
632 if (k < Ebits) {
633 d0 = Exp_1 | y >> Ebits - k;
634 w = xa > xa0 ? *--xa : 0;
635 d1 = y << (32-Ebits) + k | w >> Ebits - k;
636 goto ret_d;
637 }
638 z = xa > xa0 ? *--xa : 0;
639 if (k -= Ebits) {
640 d0 = Exp_1 | y << k | z >> 32 - k;
641 y = xa > xa0 ? *--xa : 0;
642 d1 = z << k | y >> 32 - k;
643 }
644 else {
645 d0 = Exp_1 | y;
646 d1 = z;
647 }
648 #else
649 if (k < Ebits + 16) {
650 z = xa > xa0 ? *--xa : 0;
651 d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
652 w = xa > xa0 ? *--xa : 0;
653 y = xa > xa0 ? *--xa : 0;
654 d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
655 goto ret_d;
656 }
657 z = xa > xa0 ? *--xa : 0;
658 w = xa > xa0 ? *--xa : 0;
659 k -= Ebits + 16;
660 d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
661 y = xa > xa0 ? *--xa : 0;
662 d1 = w << k + 16 | y << k;
663 #endif
664 ret_d:
665 #ifdef VAX
666 word0(d) = d0 >> 16 | d0 << 16;
667 word1(d) = d1 >> 16 | d1 << 16;
668 #endif
669 return dval(d);
670 }
671 #undef d0
672 #undef d1
673
674 Bigint *
675 d2b
676 #ifdef KR_headers
677 (d, e, bits) double d; int *e, *bits;
678 #else
679 (double d, int *e, int *bits)
680 #endif
681 {
682 Bigint *b;
683 #ifndef Sudden_Underflow
684 int i;
685 #endif
686 int de, k;
687 ULong *x, y, z;
688 #ifdef VAX
689 ULong d0, d1;
690 d0 = word0(d) >> 16 | word0(d) << 16;
691 d1 = word1(d) >> 16 | word1(d) << 16;
692 #else
693 #define d0 word0(d)
694 #define d1 word1(d)
695 #endif
696
697 #ifdef Pack_32
698 b = Balloc(1);
699 #else
700 b = Balloc(2);
701 #endif
702 x = b->x;
703
704 z = d0 & Frac_mask;
705 d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
706 #ifdef Sudden_Underflow
707 de = (int)(d0 >> Exp_shift);
708 #ifndef IBM
709 z |= Exp_msk11;
710 #endif
711 #else
712 if ( (de = (int)(d0 >> Exp_shift)) !=0)
713 z |= Exp_msk1;
714 #endif
715 #ifdef Pack_32
716 if ( (y = d1) !=0) {
717 if ( (k = lo0bits(&y)) !=0) {
718 x[0] = y | z << 32 - k;
719 z >>= k;
720 }
721 else
722 x[0] = y;
723 #ifndef Sudden_Underflow
724 i =
725 #endif
726 b->wds = (x[1] = z) !=0 ? 2 : 1;
727 }
728 else {
729 #ifdef DEBUG
730 if (!z)
731 Bug("Zero passed to d2b");
732 #endif
733 k = lo0bits(&z);
734 x[0] = z;
735 #ifndef Sudden_Underflow
736 i =
737 #endif
738 b->wds = 1;
739 k += 32;
740 }
741 #else
742 if ( (y = d1) !=0) {
743 if ( (k = lo0bits(&y)) !=0)
744 if (k >= 16) {
745 x[0] = y | z << 32 - k & 0xffff;
746 x[1] = z >> k - 16 & 0xffff;
747 x[2] = z >> k;
748 i = 2;
749 }
750 else {
751 x[0] = y & 0xffff;
752 x[1] = y >> 16 | z << 16 - k & 0xffff;
753 x[2] = z >> k & 0xffff;
754 x[3] = z >> k+16;
755 i = 3;
756 }
757 else {
758 x[0] = y & 0xffff;
759 x[1] = y >> 16;
760 x[2] = z & 0xffff;
761 x[3] = z >> 16;
762 i = 3;
763 }
764 }
765 else {
766 #ifdef DEBUG
767 if (!z)
768 Bug("Zero passed to d2b");
769 #endif
770 k = lo0bits(&z);
771 if (k >= 16) {
772 x[0] = z;
773 i = 0;
774 }
775 else {
776 x[0] = z & 0xffff;
777 x[1] = z >> 16;
778 i = 1;
779 }
780 k += 32;
781 }
782 while(!x[i])
783 --i;
784 b->wds = i + 1;
785 #endif
786 #ifndef Sudden_Underflow
787 if (de) {
788 #endif
789 #ifdef IBM
790 *e = (de - Bias - (P-1) << 2) + k;
791 *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
792 #else
793 *e = de - Bias - (P-1) + k;
794 *bits = P - k;
795 #endif
796 #ifndef Sudden_Underflow
797 }
798 else {
799 *e = de - Bias - (P-1) + 1 + k;
800 #ifdef Pack_32
801 *bits = 32*i - hi0bits(x[i-1]);
802 #else
803 *bits = (i+2)*16 - hi0bits(x[i]);
804 #endif
805 }
806 #endif
807 return b;
808 }
809 #undef d0
810 #undef d1
811
812 CONST double
813 #ifdef IEEE_Arith
814 bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
815 CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
816 };
817 #else
818 #ifdef IBM
819 bigtens[] = { 1e16, 1e32, 1e64 };
820 CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
821 #else
822 bigtens[] = { 1e16, 1e32 };
823 CONST double tinytens[] = { 1e-16, 1e-32 };
824 #endif
825 #endif
826
827 CONST double
828 tens[] = {
829 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
830 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
831 1e20, 1e21, 1e22
832 #ifdef VAX
833 , 1e23, 1e24
834 #endif
835 };
836
837 char *
838 #ifdef KR_headers
839 strcp_D2A(a, b) char *a; char *b;
840 #else
841 strcp_D2A(char *a, CONST char *b)
842 #endif
843 {
844 while(*a = *b++)
845 a++;
846 return a;
847 }
848
849 #ifdef NO_STRING_H
850
851 Char *
852 #ifdef KR_headers
853 memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
854 #else
855 memcpy_D2A(void *a1, void *b1, size_t len)
856 #endif
857 {
858 register char *a = (char*)a1, *ae = a + len;
859 register char *b = (char*)b1, *a0 = a;
860 while(a < ae)
861 *a++ = *b++;
862 return a0;
863 }
864
865 #endif /* NO_STRING_H */