From: Tim Peters Date: Fri, 17 Mar 2006 03:29:34 +0000 (+0000) Subject: Introduced symbol PY_FORMAT_SIZE_T. See the new comments X-Git-Tag: v2.5a0~205 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ae1d0c978dbf8327f1193ab2f36323393efd5eb6;p=python Introduced symbol PY_FORMAT_SIZE_T. See the new comments in pyport.h. Changed PyString_FromFormatV() to use it instead of inlining its own maze of #if'ery. --- diff --git a/Include/pyport.h b/Include/pyport.h index 9111d86228..046516852b 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -85,6 +85,10 @@ typedef PY_LONG_LONG Py_intptr_t; # error "Python needs a typedef for Py_uintptr_t in pyport.h." #endif /* HAVE_UINTPTR_T */ +/* Py_ssize_t is a signed integral type such that sizeof(Py_ssize_t) == + * sizeof(size_t). C99 doesn't define such a thing directly (size_t is an + * unsigned integral type). See PEP 353 for details. + */ #ifdef HAVE_SSIZE_T typedef ssize_t Py_ssize_t; #elif SIZEOF_VOID_P == SIZEOF_SIZE_T @@ -92,8 +96,43 @@ typedef Py_intptr_t Py_ssize_t; #else # error "Python needs a typedef for Py_ssize_t in pyport.h." #endif + +/* Largest positive value of type Py_ssize_t. */ #define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1)) +/* PY_FORMAT_SIZE_T is a platform-specific modifier for use in a printf + * format to convert an argument with the width of a size_t or Py_ssize_t. + * C99 introduced "z" for this purpose, but not all platforms support that; + * e.g., MS compilers use "I" instead. + * + * These "high level" Python format functions interpret "z" correctly on + * all platforms (Python interprets the format string itself, and does whatever + * the platform C requires to convert a size_t/Py_ssize_t argument): + * + * PyString_FromFormat + * PyErr_Format + * PyString_FromFormatV + * + * Lower-level uses require that you interpolate the correct format modifier + * yourself (e.g., calling printf, fprintf, sprintf, PyOS_snprintf); for + * example, + * + * Py_ssize_t index; + * fprintf(stderr, "index %" PY_FORMAT_SIZE_T "d sucks\n", index); + * + * That will expand to %ld, or %Id, or to something else correct for a + * Py_ssize_t on the platform. + */ +#ifndef PY_FORMAT_SIZE_T +# if SIZEOF_SIZE_T == SIZEOF_LONG +# define PY_FORMAT_SIZE_T "l" +# elif defined(MS_WINDOWS) +# define PY_FORMAT_SIZE_T "I" +# else +# error "This platform's pyconfig.h needs to define PY_FORMAT_SIZE_T" +# endif +#endif + #include #include /* Moved here from the math section, before extern "C" */ diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 16d542ae07..d23c97332e 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -16,7 +16,7 @@ static PyStringObject *nullstring; When the interned string reaches a refcnt of 0 the string deallocation function will delete the reference from this dictionary. - Another way to look at this is that to say that the actual reference + Another way to look at this is that to say that the actual reference count of a string is: s->ob_refcnt + (s->ob_sstate?2:0) */ static PyObject *interned; @@ -183,7 +183,7 @@ PyString_FromFormatV(const char *format, va_list vargs) ++f; /* likewise for %zd */ if (*f == 'z' && *(f+1) == 'd') - ++f; + ++f; switch (*f) { case 'c': @@ -273,18 +273,9 @@ PyString_FromFormatV(const char *format, va_list vargs) case 'd': if (longflag) sprintf(s, "%ld", va_arg(vargs, long)); - else if (size_tflag) { - /* Instead of checking whether the C - library supports %zd, handle the - common cases. */ - #if SIZEOF_SIZE_T == SIZEOF_LONG - sprintf(s, "%ld", va_arg(vargs, long)); - #elif defined(MS_WINDOWS) - sprintf(s, "%Id", va_arg(vargs, size_t)); - #else - #error Cannot print size_t values - #endif - } + else if (size_tflag) + sprintf(s, "%" PY_FORMAT_SIZE_T "d", + va_arg(vargs, size_t)); else sprintf(s, "%d", va_arg(vargs, int)); s += strlen(s); @@ -622,7 +613,7 @@ PyObject *PyString_DecodeEscape(const char *s, *p++ = c; break; case 'x': - if (isxdigit(Py_CHARMASK(s[0])) + if (isxdigit(Py_CHARMASK(s[0])) && isxdigit(Py_CHARMASK(s[1]))) { unsigned int x = 0; c = Py_CHARMASK(*s); @@ -646,7 +637,7 @@ PyObject *PyString_DecodeEscape(const char *s, break; } if (!errors || strcmp(errors, "strict") == 0) { - PyErr_SetString(PyExc_ValueError, + PyErr_SetString(PyExc_ValueError, "invalid \\x escape"); goto failed; } @@ -838,7 +829,7 @@ PyString_Repr(PyObject *obj, int smartquotes) /* figure out which quote to use; single is preferred */ quote = '\''; - if (smartquotes && + if (smartquotes && memchr(op->ob_sval, '\'', op->ob_size) && !memchr(op->ob_sval, '"', op->ob_size)) quote = '"'; @@ -1003,7 +994,7 @@ string_repeat(register PyStringObject *a, register Py_ssize_t n) /* String slice a[i:j] consists of characters a[i] ... a[j-1] */ static PyObject * -string_slice(register PyStringObject *a, register Py_ssize_t i, +string_slice(register PyStringObject *a, register Py_ssize_t i, register Py_ssize_t j) /* j -- may be negative! */ { @@ -1047,7 +1038,7 @@ string_contains(PyObject *a, PyObject *el) if (len_sub == 0) return 1; - /* last points to one char beyond the start of the rightmost + /* last points to one char beyond the start of the rightmost substring. When s