Mercurial > hg > xemacs-beta
diff 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 |
line wrap: on
line diff
--- a/src/doprnt.c Mon Apr 05 21:50:47 2004 +0000 +++ b/src/doprnt.c Mon Apr 05 22:50:11 2004 +0000 @@ -6,6 +6,7 @@ Rewritten by mly to use varargs.h. Rewritten from scratch by Ben Wing (February 1995) for Mule; expanded to full printf spec. + Support for bignums, ratios, and bigfloats added April 2004 by Jerry James. This file is part of XEmacs. @@ -33,11 +34,24 @@ #include "lstream.h" static const char * const valid_flags = "-+ #0"; -static const char * const valid_converters = "dic" "ouxX" "feEgG" "sS"; +static const char * const valid_converters = "dic" "ouxX" "feEgG" "sS" +#if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) + "npyY" +#endif +#ifdef HAVE_BIGFLOAT + "FhHkK" +#endif + ; static const char * const int_converters = "dic"; static const char * const unsigned_int_converters = "ouxX"; static const char * const double_converters = "feEgG"; static const char * const string_converters = "sS"; +#if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) +static const char * const bignum_converters = "npyY"; +#endif +#ifdef HAVE_BIGFLOAT +static const char * const bigfloat_converters = "FhHkK"; +#endif typedef struct printf_spec printf_spec; struct printf_spec @@ -70,6 +84,7 @@ unsigned long ul; double d; Ibyte *bp; + Lisp_Object obj; }; /* We maintain a list of all the % specs in the specification, @@ -385,6 +400,14 @@ arg.d = va_arg (vargs, double); else if (strchr (string_converters, ch)) arg.bp = va_arg (vargs, Ibyte *); +#if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) + else if (strchr (bignum_converters, ch)) + arg.obj = va_arg (vargs, Lisp_Object); +#endif +#ifdef HAVE_BIGFLOAT + else if (strchr (bigfloat_converters, ch)) + arg.obj = va_arg (vargs, Lisp_Object); +#endif else abort (); Dynarr_add (args, arg); @@ -568,27 +591,121 @@ Lisp_Object obj = largs[spec->argnum - 1]; if (CHARP (obj)) obj = make_int (XCHAR (obj)); +#ifdef WITH_NUMBER_TYPES + if (!NUMBERP (obj)) +#else if (!INT_OR_FLOATP (obj)) +#endif { syntax_error ("format specifier %%%c doesn't match argument type", make_char (ch)); } else if (strchr (double_converters, ch)) - arg.d = XFLOATINT (obj); + { +#ifdef WITH_NUMBER_TYPES + if (INTP (obj) || FLOATP (obj)) + arg.d = XFLOATINT (obj); +#ifdef HAVE_BIGNUM + else if (BIGNUMP (obj)) + arg.d = bignum_to_double (XBIGNUM_DATA (obj)); +#endif +#ifdef HAVE_RATIO + else if (RATIOP (obj)) + arg.d = ratio_to_double (XRATIO_DATA (obj)); +#endif +#ifdef HAVE_BIGFLOAT + else if (BIGFLOATP (obj)) + { + arg.obj = obj; + switch (ch) + { + case 'f': ch = 'F'; break; + case 'e': ch = 'h'; break; + case 'E': ch = 'H'; break; + case 'g': ch = 'k'; break; + case 'G': ch = 'K'; break; + } + } +#endif +#else /* !WITH_NUMBER_TYPES */ + arg.d = XFLOATINT (obj); +#endif /* WITH_NUMBER_TYPES */ + } else { if (FLOATP (obj)) obj = Ftruncate (obj); - - if (strchr (unsigned_int_converters, ch)) - arg.ul = (unsigned long) XINT (obj); - else - arg.l = XINT (obj); +#ifdef HAVE_BIGFLOAT + else if (BIGFLOATP (obj)) + { +#ifdef HAVE_BIGNUM + bignum_set_bigfloat (scratch_bignum, + XBIGFLOAT_DATA (obj)); + if (strchr (unsigned_int_converters, ch) && + bignum_sign (scratch_bignum) < 0) + dead_wrong_type_argument (Qnonnegativep, obj); + obj = + Fcanonicalize_number (make_bignum_bg (scratch_bignum)); +#else /* !HAVE_BIGNUM */ + obj = make_int (bigfloat_to_long (XBIGFLOAT_DATA (obj))); +#endif /* HAVE_BIGNUM */ + } +#endif /* HAVE_BIGFLOAT */ +#ifdef HAVE_RATIO + else if (RATIOP (obj)) + { + arg.obj = obj; + switch (ch) + { + case 'i': case 'd': ch = 'n'; break; + case 'o': ch = 'p'; break; + case 'x': ch = 'y'; break; + case 'X': ch = 'Y'; break; + default: /* ch == 'u' */ + if (strchr (unsigned_int_converters, ch) && + ratio_sign (XRATIO_DATA (obj)) < 0) + dead_wrong_type_argument (Qnonnegativep, obj); + else + ch = 'n'; + } + } +#endif +#ifdef HAVE_BIGNUM + if (BIGNUMP (obj)) + { + arg.obj = obj; + switch (ch) + { + case 'i': case 'd': ch = 'n'; break; + case 'o': ch = 'p'; break; + case 'x': ch = 'y'; break; + case 'X': ch = 'Y'; break; + default: /* ch == 'u' */ + if (strchr (unsigned_int_converters, ch) && + bignum_sign (XBIGNUM_DATA (obj)) < 0) + dead_wrong_type_argument (Qnatnump, obj); + else + ch = 'n'; + } + } +#endif + if (INTP (obj)) + { + if (strchr (unsigned_int_converters, ch)) + { +#ifdef HAVE_BIGNUM + if (XINT (obj) < 0) + dead_wrong_type_argument (Qnatnump, obj); +#endif + arg.ul = (unsigned long) XUINT (obj); + } + else + arg.l = XINT (obj); + } } } - if (ch == 'c') { Ichar a; @@ -605,6 +722,44 @@ doprnt_2 (stream, charbuf, charlen, spec->minwidth, -1, spec->minus_flag, spec->zero_flag); } +#if defined(HAVE_BIGNUM) || defined(HAVE_RATIO) + else if (strchr (bignum_converters, ch)) + { +#ifdef HAVE_BIGNUM + if (BIGNUMP (arg.obj)) + { + char *text_to_print = + bignum_to_string (XBIGNUM_DATA (arg.obj), + ch == 'n' ? 10 : + (ch == 'p' ? 8 : 16)); + doprnt_2 (stream, text_to_print, strlen (text_to_print), + spec->minwidth, -1, spec->minus_flag, + spec->zero_flag); + } +#endif +#ifdef HAVE_RATIO + if (RATIOP (arg.obj)) + { + char *text_to_print = + ratio_to_string (XRATIO_DATA (arg.obj), + ch == 'n' ? 10 : + (ch == 'p' ? 8 : 16)); + doprnt_2 (stream, text_to_print, strlen (text_to_print), + spec->minwidth, -1, spec->minus_flag, + spec->zero_flag); + } +#endif + } +#endif /* HAVE_BIGNUM || HAVE_RATIO */ +#ifdef HAVE_BIGFLOAT + else if (strchr (bigfloat_converters, ch)) + { + char *text_to_print = + bigfloat_to_string (XBIGFLOAT_DATA (arg.obj), 10); + doprnt_2 (stream, text_to_print, strlen (text_to_print), + spec->minwidth, -1, spec->minus_flag, spec->zero_flag); + } +#endif /* HAVE_BIGFLOAT */ else { /* ASCII Decimal representation uses 2.4 times as many