Mercurial > hg > xemacs-beta
comparison src/doprnt.c @ 1983:9c872f33ecbe
[xemacs-hg @ 2004-04-05 22:49:31 by james]
Add bignum, ratio, and bigfloat support.
author | james |
---|---|
date | Mon, 05 Apr 2004 22:50:11 +0000 |
parents | b531bf8658e9 |
children | 4e6a63799f08 |
comparison
equal
deleted
inserted
replaced
1982:a748951fd4fb | 1983:9c872f33ecbe |
---|---|
4 Copyright (C) 1995 Free Software Foundation, Inc. | 4 Copyright (C) 1995 Free Software Foundation, Inc. |
5 Copyright (C) 2001, 2002 Ben Wing. | 5 Copyright (C) 2001, 2002 Ben Wing. |
6 Rewritten by mly to use varargs.h. | 6 Rewritten by mly to use varargs.h. |
7 Rewritten from scratch by Ben Wing (February 1995) for Mule; expanded | 7 Rewritten from scratch by Ben Wing (February 1995) for Mule; expanded |
8 to full printf spec. | 8 to full printf spec. |
9 Support for bignums, ratios, and bigfloats added April 2004 by Jerry James. | |
9 | 10 |
10 This file is part of XEmacs. | 11 This file is part of XEmacs. |
11 | 12 |
12 XEmacs is free software; you can redistribute it and/or modify it | 13 XEmacs is free software; you can redistribute it and/or modify it |
13 under the terms of the GNU General Public License as published by the | 14 under the terms of the GNU General Public License as published by the |
31 | 32 |
32 #include "buffer.h" | 33 #include "buffer.h" |
33 #include "lstream.h" | 34 #include "lstream.h" |
34 | 35 |
35 static const char * const valid_flags = "-+ #0"; | 36 static const char * const valid_flags = "-+ #0"; |
36 static const char * const valid_converters = "dic" "ouxX" "feEgG" "sS"; | 37 static const char * const valid_converters = "dic" "ouxX" "feEgG" "sS" |
38 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) | |
39 "npyY" | |
40 #endif | |
41 #ifdef HAVE_BIGFLOAT | |
42 "FhHkK" | |
43 #endif | |
44 ; | |
37 static const char * const int_converters = "dic"; | 45 static const char * const int_converters = "dic"; |
38 static const char * const unsigned_int_converters = "ouxX"; | 46 static const char * const unsigned_int_converters = "ouxX"; |
39 static const char * const double_converters = "feEgG"; | 47 static const char * const double_converters = "feEgG"; |
40 static const char * const string_converters = "sS"; | 48 static const char * const string_converters = "sS"; |
49 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) | |
50 static const char * const bignum_converters = "npyY"; | |
51 #endif | |
52 #ifdef HAVE_BIGFLOAT | |
53 static const char * const bigfloat_converters = "FhHkK"; | |
54 #endif | |
41 | 55 |
42 typedef struct printf_spec printf_spec; | 56 typedef struct printf_spec printf_spec; |
43 struct printf_spec | 57 struct printf_spec |
44 { | 58 { |
45 int argnum; /* which argument does this spec want? This is one-based: | 59 int argnum; /* which argument does this spec want? This is one-based: |
68 { | 82 { |
69 long l; | 83 long l; |
70 unsigned long ul; | 84 unsigned long ul; |
71 double d; | 85 double d; |
72 Ibyte *bp; | 86 Ibyte *bp; |
87 Lisp_Object obj; | |
73 }; | 88 }; |
74 | 89 |
75 /* We maintain a list of all the % specs in the specification, | 90 /* We maintain a list of all the % specs in the specification, |
76 along with the offset and length of the block of literal text | 91 along with the offset and length of the block of literal text |
77 before each spec. In addition, we have a "dummy" spec that | 92 before each spec. In addition, we have a "dummy" spec that |
383 } | 398 } |
384 else if (strchr (double_converters, ch)) | 399 else if (strchr (double_converters, ch)) |
385 arg.d = va_arg (vargs, double); | 400 arg.d = va_arg (vargs, double); |
386 else if (strchr (string_converters, ch)) | 401 else if (strchr (string_converters, ch)) |
387 arg.bp = va_arg (vargs, Ibyte *); | 402 arg.bp = va_arg (vargs, Ibyte *); |
403 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) | |
404 else if (strchr (bignum_converters, ch)) | |
405 arg.obj = va_arg (vargs, Lisp_Object); | |
406 #endif | |
407 #ifdef HAVE_BIGFLOAT | |
408 else if (strchr (bigfloat_converters, ch)) | |
409 arg.obj = va_arg (vargs, Lisp_Object); | |
410 #endif | |
388 else abort (); | 411 else abort (); |
389 | 412 |
390 Dynarr_add (args, arg); | 413 Dynarr_add (args, arg); |
391 } | 414 } |
392 | 415 |
566 else | 589 else |
567 { | 590 { |
568 Lisp_Object obj = largs[spec->argnum - 1]; | 591 Lisp_Object obj = largs[spec->argnum - 1]; |
569 if (CHARP (obj)) | 592 if (CHARP (obj)) |
570 obj = make_int (XCHAR (obj)); | 593 obj = make_int (XCHAR (obj)); |
594 #ifdef WITH_NUMBER_TYPES | |
595 if (!NUMBERP (obj)) | |
596 #else | |
571 if (!INT_OR_FLOATP (obj)) | 597 if (!INT_OR_FLOATP (obj)) |
598 #endif | |
572 { | 599 { |
573 syntax_error | 600 syntax_error |
574 ("format specifier %%%c doesn't match argument type", | 601 ("format specifier %%%c doesn't match argument type", |
575 make_char (ch)); | 602 make_char (ch)); |
576 } | 603 } |
577 else if (strchr (double_converters, ch)) | 604 else if (strchr (double_converters, ch)) |
578 arg.d = XFLOATINT (obj); | 605 { |
606 #ifdef WITH_NUMBER_TYPES | |
607 if (INTP (obj) || FLOATP (obj)) | |
608 arg.d = XFLOATINT (obj); | |
609 #ifdef HAVE_BIGNUM | |
610 else if (BIGNUMP (obj)) | |
611 arg.d = bignum_to_double (XBIGNUM_DATA (obj)); | |
612 #endif | |
613 #ifdef HAVE_RATIO | |
614 else if (RATIOP (obj)) | |
615 arg.d = ratio_to_double (XRATIO_DATA (obj)); | |
616 #endif | |
617 #ifdef HAVE_BIGFLOAT | |
618 else if (BIGFLOATP (obj)) | |
619 { | |
620 arg.obj = obj; | |
621 switch (ch) | |
622 { | |
623 case 'f': ch = 'F'; break; | |
624 case 'e': ch = 'h'; break; | |
625 case 'E': ch = 'H'; break; | |
626 case 'g': ch = 'k'; break; | |
627 case 'G': ch = 'K'; break; | |
628 } | |
629 } | |
630 #endif | |
631 #else /* !WITH_NUMBER_TYPES */ | |
632 arg.d = XFLOATINT (obj); | |
633 #endif /* WITH_NUMBER_TYPES */ | |
634 } | |
579 else | 635 else |
580 { | 636 { |
581 if (FLOATP (obj)) | 637 if (FLOATP (obj)) |
582 obj = Ftruncate (obj); | 638 obj = Ftruncate (obj); |
583 | 639 #ifdef HAVE_BIGFLOAT |
584 if (strchr (unsigned_int_converters, ch)) | 640 else if (BIGFLOATP (obj)) |
585 arg.ul = (unsigned long) XINT (obj); | 641 { |
586 else | 642 #ifdef HAVE_BIGNUM |
587 arg.l = XINT (obj); | 643 bignum_set_bigfloat (scratch_bignum, |
588 } | 644 XBIGFLOAT_DATA (obj)); |
589 } | 645 if (strchr (unsigned_int_converters, ch) && |
590 | 646 bignum_sign (scratch_bignum) < 0) |
647 dead_wrong_type_argument (Qnonnegativep, obj); | |
648 obj = | |
649 Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
650 #else /* !HAVE_BIGNUM */ | |
651 obj = make_int (bigfloat_to_long (XBIGFLOAT_DATA (obj))); | |
652 #endif /* HAVE_BIGNUM */ | |
653 } | |
654 #endif /* HAVE_BIGFLOAT */ | |
655 #ifdef HAVE_RATIO | |
656 else if (RATIOP (obj)) | |
657 { | |
658 arg.obj = obj; | |
659 switch (ch) | |
660 { | |
661 case 'i': case 'd': ch = 'n'; break; | |
662 case 'o': ch = 'p'; break; | |
663 case 'x': ch = 'y'; break; | |
664 case 'X': ch = 'Y'; break; | |
665 default: /* ch == 'u' */ | |
666 if (strchr (unsigned_int_converters, ch) && | |
667 ratio_sign (XRATIO_DATA (obj)) < 0) | |
668 dead_wrong_type_argument (Qnonnegativep, obj); | |
669 else | |
670 ch = 'n'; | |
671 } | |
672 } | |
673 #endif | |
674 #ifdef HAVE_BIGNUM | |
675 if (BIGNUMP (obj)) | |
676 { | |
677 arg.obj = obj; | |
678 switch (ch) | |
679 { | |
680 case 'i': case 'd': ch = 'n'; break; | |
681 case 'o': ch = 'p'; break; | |
682 case 'x': ch = 'y'; break; | |
683 case 'X': ch = 'Y'; break; | |
684 default: /* ch == 'u' */ | |
685 if (strchr (unsigned_int_converters, ch) && | |
686 bignum_sign (XBIGNUM_DATA (obj)) < 0) | |
687 dead_wrong_type_argument (Qnatnump, obj); | |
688 else | |
689 ch = 'n'; | |
690 } | |
691 } | |
692 #endif | |
693 if (INTP (obj)) | |
694 { | |
695 if (strchr (unsigned_int_converters, ch)) | |
696 { | |
697 #ifdef HAVE_BIGNUM | |
698 if (XINT (obj) < 0) | |
699 dead_wrong_type_argument (Qnatnump, obj); | |
700 #endif | |
701 arg.ul = (unsigned long) XUINT (obj); | |
702 } | |
703 else | |
704 arg.l = XINT (obj); | |
705 } | |
706 } | |
707 } | |
591 | 708 |
592 if (ch == 'c') | 709 if (ch == 'c') |
593 { | 710 { |
594 Ichar a; | 711 Ichar a; |
595 Bytecount charlen; | 712 Bytecount charlen; |
603 | 720 |
604 charlen = set_itext_ichar (charbuf, a); | 721 charlen = set_itext_ichar (charbuf, a); |
605 doprnt_2 (stream, charbuf, charlen, spec->minwidth, | 722 doprnt_2 (stream, charbuf, charlen, spec->minwidth, |
606 -1, spec->minus_flag, spec->zero_flag); | 723 -1, spec->minus_flag, spec->zero_flag); |
607 } | 724 } |
725 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) | |
726 else if (strchr (bignum_converters, ch)) | |
727 { | |
728 #ifdef HAVE_BIGNUM | |
729 if (BIGNUMP (arg.obj)) | |
730 { | |
731 char *text_to_print = | |
732 bignum_to_string (XBIGNUM_DATA (arg.obj), | |
733 ch == 'n' ? 10 : | |
734 (ch == 'p' ? 8 : 16)); | |
735 doprnt_2 (stream, text_to_print, strlen (text_to_print), | |
736 spec->minwidth, -1, spec->minus_flag, | |
737 spec->zero_flag); | |
738 } | |
739 #endif | |
740 #ifdef HAVE_RATIO | |
741 if (RATIOP (arg.obj)) | |
742 { | |
743 char *text_to_print = | |
744 ratio_to_string (XRATIO_DATA (arg.obj), | |
745 ch == 'n' ? 10 : | |
746 (ch == 'p' ? 8 : 16)); | |
747 doprnt_2 (stream, text_to_print, strlen (text_to_print), | |
748 spec->minwidth, -1, spec->minus_flag, | |
749 spec->zero_flag); | |
750 } | |
751 #endif | |
752 } | |
753 #endif /* HAVE_BIGNUM || HAVE_RATIO */ | |
754 #ifdef HAVE_BIGFLOAT | |
755 else if (strchr (bigfloat_converters, ch)) | |
756 { | |
757 char *text_to_print = | |
758 bigfloat_to_string (XBIGFLOAT_DATA (arg.obj), 10); | |
759 doprnt_2 (stream, text_to_print, strlen (text_to_print), | |
760 spec->minwidth, -1, spec->minus_flag, spec->zero_flag); | |
761 } | |
762 #endif /* HAVE_BIGFLOAT */ | |
608 else | 763 else |
609 { | 764 { |
610 /* ASCII Decimal representation uses 2.4 times as many | 765 /* ASCII Decimal representation uses 2.4 times as many |
611 bits as machine binary. */ | 766 bits as machine binary. */ |
612 char *text_to_print = | 767 char *text_to_print = |