]> granicus.if.org Git - python/commitdiff
%#x/%#X format conversion cleanup (see patch #450267):
authorAndrew MacIntyre <andymac@bullseye.apana.org.au>
Thu, 28 Feb 2002 11:38:24 +0000 (11:38 +0000)
committerAndrew MacIntyre <andymac@bullseye.apana.org.au>
Thu, 28 Feb 2002 11:38:24 +0000 (11:38 +0000)
  Objects/
    stringobject.c
    unicodeobject.c

Objects/stringobject.c
Objects/unicodeobject.c

index 2824857186a59f4215e8fd4608b651cccc3980a1..4fb5e9361bfc8325ad25cb4af5ad810ee567941f 100644 (file)
@@ -3069,46 +3069,52 @@ formatint(char *buf, size_t buflen, int flags,
           + 1 + 1 = 24 */
        char fmt[64];   /* plenty big enough! */
        long x;
+
        if (!PyArg_Parse(v, "l;int argument required", &x))
                return -1;
        if (prec < 0)
                prec = 1;
-       PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%dl%c",
-                     (flags&F_ALT) ? "#" : "", 
-                     prec, type);
+
+       if ((flags & F_ALT) &&
+           (type == 'x' || type == 'X')) {
+               /* When converting under %#x or %#X, there are a number 
+                * of issues that cause pain:
+                * - when 0 is being converted, the C standard leaves off
+                *   the '0x' or '0X', which is inconsistent with other
+                *   %#x/%#X conversions and inconsistent with Python's
+                *   hex() function
+                * - there are platforms that violate the standard and
+                *   convert 0 with the '0x' or '0X'
+                *   (Metrowerks, Compaq Tru64)
+                * - there are platforms that give '0x' when converting
+                *   under %#X, but convert 0 in accordance with the 
+                *   standard (OS/2 EMX)
+                * 
+                * We can achieve the desired consistency by inserting our
+                * own '0x' or '0X' prefix, and substituting %x/%X in place
+                * of %#x/%#X.
+                *
+                * Note that this is the same approach as used in
+                * formatint() in unicodeobject.c
+                */
+               PyOS_snprintf(fmt, sizeof(fmt), "0%c%%.%dl%c", 
+                             type, prec, type);
+       }
+       else {
+               PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%dl%c",
+                             (flags&F_ALT) ? "#" : "", 
+                             prec, type);
+       }
+
        /* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec, len(x in octal))
-          worst case buf = '0x' + [0-9]*prec, where prec >= 11 */
+        * worst case buf = '0x' + [0-9]*prec, where prec >= 11
+        */
        if (buflen <= 13 || buflen <= (size_t)2 + (size_t)prec) {
                PyErr_SetString(PyExc_OverflowError,
                        "formatted integer is too long (precision too large?)");
                return -1;
        }
        PyOS_snprintf(buf, buflen, fmt, x);
-       /* When converting 0 under %#x or %#X, C leaves off the base marker,
-        * but we want it (for consistency with other %#x conversions, and
-        * for consistency with Python's hex() function).
-        * BUG 28-Apr-2001 tim:  At least two platform Cs (Metrowerks &
-        * Compaq Tru64) violate the std by converting 0 w/ leading 0x anyway.
-        * So add it only if the platform didn't already.
-        */
-       if (x == 0 &&
-          (flags & F_ALT) &&
-          (type == 'x' || type == 'X') &&
-           buf[1] != (char)type)  /* this last always true under std C */
-               {
-               memmove(buf+2, buf, strlen(buf) + 1);
-               buf[0] = '0';
-               buf[1] = (char)type;
-       }
-#if defined(PYOS_OS2) && defined(PYCC_GCC)
-       /* unfortunately, the EMX C runtime gives us '0x' as the base
-        * marker for %X when we expect/want '0X'
-        */
-       else if ((flags & F_ALT) && (type == 'X')) {
-               assert(buf[1] == 'x');
-               buf[1] = (char)type;
-       }
-#endif
        return strlen(buf);
 }
 
index f214c20749595d164d0beb876c6afe8a6164dc09..c318bd6437d8ca005d0ad8bdbfc9a82e80589c4b 100644 (file)
@@ -5137,53 +5137,58 @@ formatint(Py_UNICODE *buf,
          PyObject *v)
 {
     /* fmt = '%#.' + `prec` + 'l' + `type`
-       worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)
-       + 1 + 1 = 24*/
+     * worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)
+     *                     + 1 + 1
+     *                   = 24
+     */
     char fmt[64]; /* plenty big enough! */
     long x;
-    int use_native_c_format = 1;
 
     x = PyInt_AsLong(v);
     if (x == -1 && PyErr_Occurred())
-       return -1;
+        return -1;
     if (prec < 0)
-       prec = 1;
+        prec = 1;
+
     /* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec,len(x in octal))
-       worst case buf = '0x' + [0-9]*prec, where prec >= 11 */
-    if (buflen <= 13 || buflen <= (size_t)2+(size_t)prec) {
+     * worst case buf = '0x' + [0-9]*prec, where prec >= 11
+     */
+    if (buflen <= 13 || buflen <= (size_t)2 + (size_t)prec) {
         PyErr_SetString(PyExc_OverflowError,
-            "formatted integer is too long (precision too long?)");
+               "formatted integer is too long (precision too large?)");
         return -1;
     }
-    /* When converting 0 under %#x or %#X, C leaves off the base marker,
-     * but we want it (for consistency with other %#x conversions, and
-     * for consistency with Python's hex() function).
-     * BUG 28-Apr-2001 tim:  At least two platform Cs (Metrowerks &
-     * Compaq Tru64) violate the std by converting 0 w/ leading 0x anyway.
-     * So add it only if the platform doesn't already.
-     */
-#if defined(PYOS_OS2) && defined(PYCC_GCC)
-    if ((flags & F_ALT) && (type == 'x' || type == 'X')) {
-        /* the EMX runtime gives 0x as the base marker when we want 0X
-         * so we cover all bets by supplying our own for both cases.
+
+    if ((flags & F_ALT) &&
+        (type == 'x' || type == 'X')) {
+        /* When converting under %#x or %#X, there are a number 
+         * of issues that cause pain:
+         * - when 0 is being converted, the C standard leaves off
+         *   the '0x' or '0X', which is inconsistent with other
+         *   %#x/%#X conversions and inconsistent with Python's
+         *   hex() function
+         * - there are platforms that violate the standard and
+         *   convert 0 with the '0x' or '0X'
+         *   (Metrowerks, Compaq Tru64)
+         * - there are platforms that give '0x' when converting
+         *   under %#X, but convert 0 in accordance with the 
+         *   standard (OS/2 EMX)
+         * 
+         * We can achieve the desired consistency by inserting our
+         * own '0x' or '0X' prefix, and substituting %x/%X in place
+         * of %#x/%#X.
+         *
+         * Note that this is the same approach as used in
+         * formatint() in stringobject.c
          */
-        use_native_c_format = 0;
-        PyOS_snprintf(fmt, sizeof(fmt), "0%c%%.%dl%c", type, prec, type);
+        PyOS_snprintf(fmt, sizeof(fmt), "0%c%%.%dl%c", 
+                      type, prec, type);
     }
-#else
-    if (x == 0 && (flags & F_ALT) && (type == 'x' || type == 'X')) {
-        /* Only way to know what the platform does is to try it. */
-        PyOS_snprintf(fmt, sizeof(fmt), type == 'x' ? "%#x" : "%#X", 0);
-        if (fmt[1] != (char)type) {
-            /* Supply our own leading 0x/0X -- needed under std C */
-            use_native_c_format = 0;
-            PyOS_snprintf(fmt, sizeof(fmt), "0%c%%#.%dl%c", type, prec, type);
-        }
+    else {
+        PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%dl%c",
+                      (flags&F_ALT) ? "#" : "", 
+                      prec, type);
     }
-#endif
-    if (use_native_c_format)
-         PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%dl%c",
-                      (flags & F_ALT) ? "#" : "", prec, type);
     return usprintf(buf, fmt, x);
 }