comparison src/doprnt.c @ 4329:d9eb5ea14f65

Provide %b in #'format; use it for converting between ints and bit vectors. lisp/ChangeLog addition: 2007-12-17 Aidan Kehoe <kehoea@parhasard.net> * subr.el (integer-to-bit-vector): New. * subr.el (bit-vector-to-integer): New. Provide naive implementations using the Lisp reader for these. src/ChangeLog addition: 2007-12-17 Aidan Kehoe <kehoea@parhasard.net> * doprnt.c (emacs_doprnt_1): Add support for formatted printing of both longs and bignums as base 2. * editfns.c (Fformat): Document the new %b escape for #'format. * lisp.h: Make ulong_to_bit_string available beside long_to_string. * lread.c: Fix a bug where the integer base was being ignored in certain contexts; thank you Sebastian Freundt. This is necessary for correct behaviour of #'integer-to-bit-vector and #'bit-vector-to-integer, just added to subr.el * print.c (ulong_to_bit_string): New. Analagous to long_to_string, but used all the time when %b is encountered, since we can't pass that to sprintf. man/ChangeLog addition: 2007-12-17 Aidan Kehoe <kehoea@parhasard.net> * lispref/strings.texi (Formatting Strings): Document %b for binary output.
author Aidan Kehoe <kehoea@parhasard.net>
date Mon, 17 Dec 2007 08:44:14 +0100
parents 89e64783d068
children 3483b381b0a9
comparison
equal deleted inserted replaced
4328:dfd878799ef0 4329:d9eb5ea14f65
32 32
33 #include "buffer.h" 33 #include "buffer.h"
34 #include "lstream.h" 34 #include "lstream.h"
35 35
36 static const char * const valid_flags = "-+ #0"; 36 static const char * const valid_flags = "-+ #0";
37 static const char * const valid_converters = "dic" "ouxX" "feEgG" "sS" 37 static const char * const valid_converters = "dic" "ouxX" "feEgG" "sS" "b"
38 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) 38 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO)
39 "npyY" 39 "npyY"
40 #endif 40 #endif
41 #ifdef HAVE_BIGFLOAT 41 #ifdef HAVE_BIGFLOAT
42 "FhHkK" 42 "FhHkK"
43 #endif 43 #endif
44 ; 44 ;
45 static const char * const int_converters = "dic"; 45 static const char * const int_converters = "dic";
46 static const char * const unsigned_int_converters = "ouxX"; 46 static const char * const unsigned_int_converters = "ouxXb";
47 static const char * const double_converters = "feEgG"; 47 static const char * const double_converters = "feEgG";
48 static const char * const string_converters = "sS"; 48 static const char * const string_converters = "sS";
49 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) 49 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO)
50 static const char * const bignum_converters = "npyY"; 50 static const char * const bignum_converters = "npyY\337";
51 #endif 51 #endif
52 #ifdef HAVE_BIGFLOAT 52 #ifdef HAVE_BIGFLOAT
53 static const char * const bigfloat_converters = "FhHkK"; 53 static const char * const bigfloat_converters = "FhHkK";
54 #endif 54 #endif
55 55
663 { 663 {
664 case 'i': case 'd': ch = 'n'; break; 664 case 'i': case 'd': ch = 'n'; break;
665 case 'o': ch = 'p'; break; 665 case 'o': ch = 'p'; break;
666 case 'x': ch = 'y'; break; 666 case 'x': ch = 'y'; break;
667 case 'X': ch = 'Y'; break; 667 case 'X': ch = 'Y'; break;
668 case 'b': ch = 'b'; break;
668 default: /* ch == 'u' */ 669 default: /* ch == 'u' */
669 if (strchr (unsigned_int_converters, ch) && 670 if (strchr (unsigned_int_converters, ch) &&
670 ratio_sign (XRATIO_DATA (obj)) < 0) 671 ratio_sign (XRATIO_DATA (obj)) < 0)
671 dead_wrong_type_argument (Qnonnegativep, obj); 672 dead_wrong_type_argument (Qnonnegativep, obj);
672 else 673 else
682 { 683 {
683 case 'i': case 'd': ch = 'n'; break; 684 case 'i': case 'd': ch = 'n'; break;
684 case 'o': ch = 'p'; break; 685 case 'o': ch = 'p'; break;
685 case 'x': ch = 'y'; break; 686 case 'x': ch = 'y'; break;
686 case 'X': ch = 'Y'; break; 687 case 'X': ch = 'Y'; break;
688 case 'b': ch = '\337'; break;
687 default: /* ch == 'u' */ 689 default: /* ch == 'u' */
688 if (strchr (unsigned_int_converters, ch) && 690 if (strchr (unsigned_int_converters, ch) &&
689 bignum_sign (XBIGNUM_DATA (obj)) < 0) 691 bignum_sign (XBIGNUM_DATA (obj)) < 0)
690 dead_wrong_type_argument (Qnatnump, obj); 692 dead_wrong_type_argument (Qnatnump, obj);
691 else 693 else
731 -1, spec->minus_flag, spec->zero_flag); 733 -1, spec->minus_flag, spec->zero_flag);
732 } 734 }
733 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) 735 #if defined(HAVE_BIGNUM) || defined(HAVE_RATIO)
734 else if (strchr (bignum_converters, ch)) 736 else if (strchr (bignum_converters, ch))
735 { 737 {
738 int base = 16;
739
740 if (ch == 'n')
741 base = 10;
742 else if (ch == 'p')
743 base = 8;
744 else if (ch == '\337')
745 base = 2;
746
736 #ifdef HAVE_BIGNUM 747 #ifdef HAVE_BIGNUM
737 if (BIGNUMP (arg.obj)) 748 if (BIGNUMP (arg.obj))
738 { 749 {
750 bignum *d = XBIGNUM_DATA (arg.obj);
739 Ibyte *text_to_print = 751 Ibyte *text_to_print =
740 (Ibyte *) bignum_to_string (XBIGNUM_DATA (arg.obj), 752 (Ibyte *) bignum_to_string (XBIGNUM_DATA (arg.obj),
741 ch == 'n' ? 10 : 753 base);
742 (ch == 'p' ? 8 : 16));
743 doprnt_2 (stream, text_to_print, 754 doprnt_2 (stream, text_to_print,
744 strlen ((const char *) text_to_print), 755 strlen ((const char *) text_to_print),
745 spec->minwidth, -1, spec->minus_flag, 756 spec->minwidth, -1, spec->minus_flag,
746 spec->zero_flag); 757 spec->zero_flag);
747 xfree (text_to_print, Ibyte *); 758 xfree (text_to_print, Ibyte *);
749 #endif 760 #endif
750 #ifdef HAVE_RATIO 761 #ifdef HAVE_RATIO
751 if (RATIOP (arg.obj)) 762 if (RATIOP (arg.obj))
752 { 763 {
753 Ibyte *text_to_print = 764 Ibyte *text_to_print =
754 (Ibyte *) ratio_to_string (XRATIO_DATA (arg.obj), 765 (Ibyte *) ratio_to_string (XRATIO_DATA (arg.obj), base);
755 ch == 'n' ? 10 :
756 (ch == 'p' ? 8 : 16));
757 doprnt_2 (stream, text_to_print, 766 doprnt_2 (stream, text_to_print,
758 strlen ((const char *) text_to_print), 767 strlen ((const char *) text_to_print),
759 spec->minwidth, -1, spec->minus_flag, 768 spec->minwidth, -1, spec->minus_flag,
760 spec->zero_flag); 769 spec->zero_flag);
761 xfree (text_to_print, Ibyte *); 770 xfree (text_to_print, Ibyte *);
772 strlen ((const char *) text_to_print), 781 strlen ((const char *) text_to_print),
773 spec->minwidth, -1, spec->minus_flag, spec->zero_flag); 782 spec->minwidth, -1, spec->minus_flag, spec->zero_flag);
774 xfree (text_to_print, Ibyte *); 783 xfree (text_to_print, Ibyte *);
775 } 784 }
776 #endif /* HAVE_BIGFLOAT */ 785 #endif /* HAVE_BIGFLOAT */
786 else if (ch == 'b')
787 {
788 Ascbyte *text_to_print = alloca_array (char, SIZEOF_LONG * 8 + 1);
789
790 ulong_to_bit_string (text_to_print, arg.ul);
791 doprnt_2 (stream, (Ibyte *)text_to_print,
792 qxestrlen ((Ibyte *)text_to_print),
793 spec->minwidth, -1, spec->minus_flag, spec->zero_flag);
794 }
777 else 795 else
778 { 796 {
779 Ascbyte *text_to_print; 797 Ascbyte *text_to_print;
780 Ascbyte constructed_spec[100]; 798 Ascbyte constructed_spec[100];
781 Ascbyte *p = constructed_spec; 799 Ascbyte *p = constructed_spec;