The pixie no longer needs to be setuid-root.
[u/mdw/catacomb] / mptext.c
index 3eb58cf..8c00e34 100644 (file)
--- a/mptext.c
+++ b/mptext.c
@@ -1,13 +1,13 @@
 /* -*-c-*-
  *
- * $Id: mptext.c,v 1.17 2002/10/19 11:59:04 mdw Exp $
+ * $Id$
  *
  * Textual representation of multiprecision numbers
  *
  * (c) 1999 Straylight/Edgeware
  */
 
-/*----- Licensing notice --------------------------------------------------* 
+/*----- Licensing notice --------------------------------------------------*
  *
  * This file is part of Catacomb.
  *
  * it under the terms of the GNU Library General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
- * 
+ *
  * Catacomb is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Library General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Library General Public
  * License along with Catacomb; if not, write to the Free
  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA 02111-1307, USA.
  */
 
-/*----- Revision history --------------------------------------------------* 
- *
- * $Log: mptext.c,v $
- * Revision 1.17  2002/10/19 11:59:04  mdw
- * Fix leftovers bug in reading.
- *
- * Revision 1.16  2002/10/15 22:57:43  mdw
- * Bug fix: prevent negative zero.
- *
- * Revision 1.15  2002/10/15 19:18:15  mdw
- * Fix fencepost bugs in binary radix writing.
- *
- * Revision 1.14  2002/10/09 00:33:44  mdw
- * Allow `0o' and `0b' prefixes for octal and binary (from Haskell)
- *
- * Revision 1.13  2002/10/09 00:21:06  mdw
- * Allow user-specified `r_xx' bases to be up to 62.
- *
- * Revision 1.12  2002/01/13 19:51:18  mdw
- * Extend the textual format to bases up to 62 by distinguishing case.
- *
- * Revision 1.11  2001/06/16 23:42:17  mdw
- * Typesetting fixes.
- *
- * Revision 1.10  2001/06/16 13:22:39  mdw
- * Added fast-track code for binary output bases, and tests.
- *
- * Revision 1.9  2001/02/03 16:05:17  mdw
- * Make flags be unsigned.  Improve the write algorithm: recurse until the
- * parts are one word long and use single-precision arithmetic from there.
- * Fix off-by-one bug when breaking the number apart.
- *
- * Revision 1.8  2000/12/06 20:32:42  mdw
- * Reduce binary bytes (to allow marker bits to be ignored).  Fix error
- * message string a bit.  Allow leading `+' signs.
- *
- * Revision 1.7  2000/07/15 10:01:08  mdw
- * Bug fix in binary input.
- *
- * Revision 1.6  2000/06/25 12:58:23  mdw
- * Fix the derivation of `depth' commentary.
- *
- * Revision 1.5  2000/06/17 11:46:19  mdw
- * New and much faster stack-based algorithm for reading integers.  Support
- * reading and writing binary integers in bases between 2 and 256.
- *
- * Revision 1.4  1999/12/22 15:56:56  mdw
- * Use clever recursive algorithm for writing numbers out.
- *
- * Revision 1.3  1999/12/10 23:23:26  mdw
- * Allocate slightly less memory.
- *
- * Revision 1.2  1999/11/20 22:24:15  mdw
- * Use function versions of MPX_UMULN and MPX_UADDN.
- *
- * Revision 1.1  1999/11/17 18:02:16  mdw
- * New multiprecision integer arithmetic suite.
- *
- */
-
 /*----- Header files ------------------------------------------------------*/
 
 #include <ctype.h>
 
 /* --- Maximum recursion depth --- *
  *
- * This is the number of bits in a @size_t@ object.  Why? 
+ * This is the number of bits in a @size_t@ object.  Why?
  *
  * To see this, let %$b = \textit{MPW\_MAX} + 1$% and let %$Z$% be the
  * largest @size_t@ value.  Then the largest possible @mp@ is %$M - 1$% where
@@ -183,7 +123,7 @@ mp *mp_read(mp *m, int radix, const mptext_ops *ops, void *p)
   /* --- Initialize the stacks --- */
 
   mp_build(&rr, &rd, &rd + 1);
-  pow[0] = &rr;  
+  pow[0] = &rr;
   pows = 1;
 
   sp = 0;
@@ -196,8 +136,10 @@ mp *mp_read(mp *m, int radix, const mptext_ops *ops, void *p)
   /* --- Read an initial character --- */
 
   ch = ops->get(p);
-  while (isspace(ch))
-    ch = ops->get(p);
+  if (radix >= 0) {
+    while (isspace(ch))
+      ch = ops->get(p);
+  }
 
   /* --- Handle an initial sign --- */
 
@@ -215,7 +157,7 @@ mp *mp_read(mp *m, int radix, const mptext_ops *ops, void *p)
     r = -1;
   } else if (radix < 0) {
     rd = -radix;
-    assert(((void)"binary radix must fit in a byte", rd < UCHAR_MAX));
+    assert(((void)"binary radix must fit in a byte", rd <= UCHAR_MAX));
     r = -1;
   } else if (ch != '0') {
     rd = 10;
@@ -322,7 +264,7 @@ restart:
        a |= MPW(x) << b;
       } else {
        a |= MPW(x) >> (bit - b);
-       b += MPW_BITS - bit;
+       b += MPW_BITS - bit;
        *--v = MPW(a);
        n--;
        if (!n) {
@@ -397,7 +339,7 @@ restart:
        x = ch - '0';
       else {
        if (rd <= 36)
-         ch = tolower(ch);       
+         ch = tolower(ch);
        if (ch >= 'a' && ch <= 'z')     /* ASCII dependent! */
          x = ch - 'a' + 10;
        else if (ch >= 'A' && ch <= 'Z')
@@ -501,7 +443,7 @@ restart:
   /* --- Bail out if the number was bad --- */
 
 done:
-  if (!(f & f_ok))    
+  if (!(f & f_ok))
     return (0);
 
   /* --- Set the sign and return --- */
@@ -602,7 +544,7 @@ static int complicated(mp *m, int radix, mp **pr, unsigned i, unsigned z,
 
   assert(i);
   mp_div(&q, &m, m, pr[i]);
-  if (!MP_LEN(q))
+  if (MP_ZEROP(q))
     d = z;
   else {
     if (z > d)
@@ -717,7 +659,7 @@ int mp_write(mp *m, int radix, const mptext_ops *ops, void *p)
   int rc;
 
   if (MP_EQ(m, MP_ZERO))
-    return (ops->put("0", 1, p));
+    return (ops->put(radix > 0 ? "0" : "\0", 1, p));
 
   /* --- Set various things up --- */
 
@@ -729,13 +671,14 @@ int mp_write(mp *m, int radix, const mptext_ops *ops, void *p)
   if (radix > 0)
     assert(((void)"ascii radix must be <= 62", radix <= 62));
   else if (radix < 0)
-    assert(((void)"binary radix must fit in a byte", -radix < UCHAR_MAX));
+    assert(((void)"binary radix must fit in a byte", -radix <= UCHAR_MAX));
   else
     assert(((void)"radix can't be zero in mp_write", 0));
 
   /* --- If the number is negative, sort that out --- */
 
-  if (m->f & MP_NEG) {
+  if (MP_NEGP(m)) {
+    assert(radix > 0);
     if (ops->put("-", 1, p))
       return (EOF);
     m->f &= ~MP_NEG;
@@ -749,8 +692,8 @@ int mp_write(mp *m, int radix, const mptext_ops *ops, void *p)
     case   8: case   -8: return (binary(m, 3, radix, ops, p));
     case  16: case  -16: return (binary(m, 4, radix, ops, p));
     case  32: case  -32: return (binary(m, 5, radix, ops, p));
-              case  -64: return (binary(m, 6, radix, ops, p));
-              case -128: return (binary(m, 7, radix, ops, p));
+             case  -64: return (binary(m, 6, radix, ops, p));
+             case -128: return (binary(m, 7, radix, ops, p));
   }
 
   /* --- If the number is small, do it the easy way --- */
@@ -817,7 +760,7 @@ static int verify(dstr *v)
   if (m) {
     if (!ob) {
       fprintf(stderr, "*** unexpected successful parse\n"
-                     "*** input [%2i] =     ", ib);
+                     "*** input [%2i] =     ", ib);
       if (ib < 0)
        type_hex.dump(&v[1], stderr);
       else
@@ -829,17 +772,17 @@ static int verify(dstr *v)
       mp_writedstr(m, &d, ob);
       if (d.len != v[3].len || memcmp(d.buf, v[3].buf, d.len) != 0) {
        fprintf(stderr, "*** failed read or write\n"
-                       "*** input [%2i]      = ", ib);
+                       "*** input [%2i]      = ", ib);
        if (ib < 0)
          type_hex.dump(&v[1], stderr);
        else
          fputs(v[1].buf, stderr);
-       fprintf(stderr, "\n*** output [%2i]     = ", ob);
+       fprintf(stderr, "\n*** output [%2i]     = ", ob);
        if (ob < 0)
          type_hex.dump(&d, stderr);
        else
          fputs(d.buf, stderr);
-       fprintf(stderr, "\n*** expected [%2i]   = ", ob);
+       fprintf(stderr, "\n*** expected [%2i]   = ", ob);
        if (ob < 0)
          type_hex.dump(&v[3], stderr);
        else
@@ -852,7 +795,7 @@ static int verify(dstr *v)
   } else {
     if (ob) {
       fprintf(stderr, "*** unexpected parse failure\n"
-                     "*** input [%2i]    = ", ib);
+                     "*** input [%2i]    = ", ib);
       if (ib < 0)
        type_hex.dump(&v[1], stderr);
       else
@@ -870,17 +813,17 @@ static int verify(dstr *v)
   if (v[1].len - off != v[4].len ||
       memcmp(v[1].buf + off, v[4].buf, v[4].len) != 0) {
     fprintf(stderr, "*** leftovers incorrect\n"
-                   "*** input [%2i]    = ", ib);
+                   "*** input [%2i]    = ", ib);
     if (ib < 0)
       type_hex.dump(&v[1], stderr);
     else
       fputs(v[1].buf, stderr);
     fprintf(stderr, "\n*** expected `%s'\n"
-                   "*** found `%s'\n",
+                   "*** found `%s'\n",
            v[4].buf, v[1].buf + off);
     ok = 0;
   }
-           
+
   dstr_destroy(&d);
   assert(mparena_count(MPARENA_GLOBAL) == 0);
   return (ok);