summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorAndrew MacIntyre <andymac@bullseye.apana.org.au>2002-02-28 11:38:24 (GMT)
committerAndrew MacIntyre <andymac@bullseye.apana.org.au>2002-02-28 11:38:24 (GMT)
commit5e9c80d906446f3fc53c4da36e88d937d5c1593d (patch)
tree0750dab1203278f39a50b5ed3bdc6ee88c6b43b2 /Objects
parentbbea4717bcef2c6409a04263d4a8cfeecebd831e (diff)
downloadcpython-5e9c80d906446f3fc53c4da36e88d937d5c1593d.zip
cpython-5e9c80d906446f3fc53c4da36e88d937d5c1593d.tar.gz
cpython-5e9c80d906446f3fc53c4da36e88d937d5c1593d.tar.bz2
%#x/%#X format conversion cleanup (see patch #450267):
Objects/ stringobject.c unicodeobject.c
Diffstat (limited to 'Objects')
-rw-r--r--Objects/stringobject.c64
-rw-r--r--Objects/unicodeobject.c73
2 files changed, 74 insertions, 63 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 2824857..4fb5e93 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -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);
}
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index f214c20..c318bd6 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -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);
}