Index: configure =================================================================== --- configure (revision 76311) +++ configure (working copy) @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 76030 . +# From configure.in Revision: 76301 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 3.2. # @@ -26314,6 +26314,104 @@ echo "${ECHO_T}no" >&6; } fi +if test "$have_long_long" = yes +then + { echo "$as_me:$LINENO: checking for %lld and %llu printf() format support" >&5 +echo $ECHO_N "checking for %lld and %llu printf() format support... $ECHO_C" >&6; } + if test "${ac_cv_have_long_long_format+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_have_long_long_format=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + #include + #include + + #ifdef HAVE_SYS_TYPES_H + #include + #endif + + int main() + { + char buffer[256]; + + if (sprintf(buffer, "%lld", (long long)123) < 0) + return 1; + if (strcmp(buffer, "123")) + return 1; + + if (sprintf(buffer, "%lld", (long long)-123) < 0) + return 1; + if (strcmp(buffer, "-123")) + return 1; + + if (sprintf(buffer, "%llu", (unsigned long long)123) < 0) + return 1; + if (strcmp(buffer, "123")) + return 1; + + return 0; + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_long_long_format=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_have_long_long_format=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + { echo "$as_me:$LINENO: result: $ac_cv_have_long_long_format" >&5 +echo "${ECHO_T}$ac_cv_have_long_long_format" >&6; } +fi + +if test $ac_cv_have_long_long_format = yes +then + +cat >>confdefs.h <<\_ACEOF +#define PY_FORMAT_LONG_LONG "ll" +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for %zd printf() format support" >&5 echo $ECHO_N "checking for %zd printf() format support... $ECHO_C" >&6; } if test "${ac_cv_have_size_t_format+set}" = set; then Index: Include/pyport.h =================================================================== --- Include/pyport.h (revision 76311) +++ Include/pyport.h (working copy) @@ -219,6 +219,22 @@ # endif #endif +/* PY_FORMAT_LONG_LONG is analogous to PY_FORMAT_SIZE_T above, but for + * the long long type instead of the size_t type. It's only available + * when HAVE_LONG_LONG is defined. The "high level" Python format + * functions listed above will interpret "lld" or "llu" correctly on + * all platforms. + */ +#ifdef HAVE_LONG_LONG +# ifndef PY_FORMAT_LONG_LONG +# if defined(MS_WIN64) || defined(MS_WINDOWS) +# define PY_FORMAT_LONG_LONG "I64" +# else +# error "This platform's pyconfig.h needs to define PY_FORMAT_LONG_LONG" +# endif +# endif +#endif + /* Py_LOCAL can be used instead of static to get the fastest possible calling * convention for functions that are local to a given module. * Index: configure.in =================================================================== --- configure.in (revision 76311) +++ configure.in (working copy) @@ -3806,6 +3806,54 @@ AC_MSG_RESULT(no) fi +if test "$have_long_long" = yes +then + AC_MSG_CHECKING(for %lld and %llu printf() format support) + AC_CACHE_VAL(ac_cv_have_long_long_format, + AC_TRY_RUN([[ + #include + #include + #include + + #ifdef HAVE_SYS_TYPES_H + #include + #endif + + int main() + { + char buffer[256]; + + if (sprintf(buffer, "%lld", (long long)123) < 0) + return 1; + if (strcmp(buffer, "123")) + return 1; + + if (sprintf(buffer, "%lld", (long long)-123) < 0) + return 1; + if (strcmp(buffer, "-123")) + return 1; + + if (sprintf(buffer, "%llu", (unsigned long long)123) < 0) + return 1; + if (strcmp(buffer, "123")) + return 1; + + return 0; + } + ]], ac_cv_have_long_long_format=yes, + ac_cv_have_long_long_format=no, + ac_cv_have_long_long_format=no) + ) + AC_MSG_RESULT($ac_cv_have_long_long_format) +fi + +if test $ac_cv_have_long_long_format = yes +then + AC_DEFINE(PY_FORMAT_LONG_LONG, "ll", + [Define to printf format modifier for long long type]) +fi + + AC_MSG_CHECKING(for %zd printf() format support) AC_CACHE_VAL(ac_cv_have_size_t_format, AC_TRY_RUN([[ Index: Objects/unicodeobject.c =================================================================== --- Objects/unicodeobject.c (revision 76311) +++ Objects/unicodeobject.c (working copy) @@ -667,7 +667,8 @@ #undef CONVERT_WCHAR_TO_SURROGATES static void -makefmt(char *fmt, int longflag, int size_tflag, int zeropad, int width, int precision, char c) +makefmt(char *fmt, int longflag, int longlongflag, int size_tflag, + int zeropad, int width, int precision, char c) { *fmt++ = '%'; if (width) { @@ -679,6 +680,15 @@ fmt += sprintf(fmt, ".%d", precision); if (longflag) *fmt++ = 'l'; + else if (longlongflag) { +#ifdef HAVE_LONG_LONG + char *f = PY_FORMAT_LONG_LONG; + while (*f) + *fmt++ = *f++; +#else + PyErr_BadArgument(); +#endif + } else if (size_tflag) { char *f = PY_FORMAT_SIZE_T; while (*f) @@ -705,13 +715,13 @@ Py_UNICODE *s; PyObject *string; /* used by sprintf */ - char buffer[21]; + char buffer[21+1]; /* use abuffer instead of buffer, if we need more space * (which can happen if there's a format specifier with width). */ char *abuffer = NULL; char *realbuffer; Py_ssize_t abuffersize = 0; - char fmt[60]; /* should be enough for %0width.precisionld */ + char fmt[61]; /* should be enough for %0width.precisionlld */ const char *copy; #ifdef VA_LIST_IS_ARRAY @@ -754,6 +764,9 @@ /* step 3: figure out how large a buffer we need */ for (f = format; *f; f++) { if (*f == '%') { +#ifdef HAVE_LONG_LONG + int longlongflag = 0; +#endif const char* p = f; width = 0; while (ISDIGIT((unsigned)*f)) @@ -764,9 +777,21 @@ /* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since * they don't affect the amount of space we reserve. */ - if ((*f == 'l' || *f == 'z') && - (f[1] == 'd' || f[1] == 'u')) + if (*f == 'l') { + if (f[1] == 'd' || f[1] == 'u') { + ++f; + } +#ifdef HAVE_LONG_LONG + else if (f[1] == 'l' && + (f[2] == 'd' || f[2] == 'u')) { + longlongflag = 1; + f += 2; + } +#endif + } + else if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) { ++f; + } switch (*f) { case 'c': @@ -777,13 +802,25 @@ break; case 'd': case 'u': case 'i': case 'x': (void) va_arg(count, int); - /* 20 bytes is enough to hold a 64-bit - integer. Decimal takes the most space. - This isn't enough for octal. - If a width is specified we need more - (which we allocate later). */ - if (width < 20) - width = 20; +#ifdef HAVE_LONG_LONG + /* Need at most + ceil(log10(256)*SIZEOF_LONG_LONG) digits, + plus 1 for the sign. 53/22 is an upper + bound for log10(256). */ + if (longlongflag) { + int minwidth = 2 + (SIZEOF_LONG_LONG*53-1) / 22; + if (width < minwidth) + width = minwidth; + } + else +#endif + /* 21 bytes is enough to hold a 64-bit + integer, including sign. Decimal takes the most space. + This isn't enough for octal. + If a width is specified we need more + (which we allocate later). */ + if (width < 21) + width = 21; n += width; if (abuffersize < width) abuffersize = width; @@ -881,7 +918,7 @@ n++; } expand: - if (abuffersize > 20) { + if (abuffersize > 21) { abuffer = PyObject_Malloc(abuffersize); if (!abuffer) { PyErr_NoMemory(); @@ -906,6 +943,7 @@ if (*f == '%') { const char* p = f++; int longflag = 0; + int longlongflag = 0; int size_tflag = 0; zeropad = (*f == '0'); /* parse the width.precision part */ @@ -918,11 +956,19 @@ while (ISDIGIT((unsigned)*f)) precision = (precision*10) + *f++ - '0'; } - /* handle the long flag, but only for %ld and %lu. - others can be added when necessary. */ - if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) { - longflag = 1; - ++f; + /* Handle %ld, %lu, %lld and %llu. */ + if (*f == 'l') { + if (f[1] == 'd' || f[1] == 'u') { + longflag = 1; + ++f; + } +#ifdef HAVE_LONG_LONG + else if (f[1] == 'l' && + (f[2] == 'd' || f[2] == 'u')) { + longlongflag = 1; + f += 2; + } +#endif } /* handle the size_t flag. */ if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) { @@ -935,9 +981,14 @@ *s++ = va_arg(vargs, int); break; case 'd': - makefmt(fmt, longflag, size_tflag, zeropad, width, precision, 'd'); + makefmt(fmt, longflag, longlongflag, size_tflag, zeropad, + width, precision, 'd'); if (longflag) sprintf(realbuffer, fmt, va_arg(vargs, long)); +#ifdef HAVE_LONG_LONG + else if (longlongflag) + sprintf(realbuffer, fmt, va_arg(vargs, PY_LONG_LONG)); +#endif else if (size_tflag) sprintf(realbuffer, fmt, va_arg(vargs, Py_ssize_t)); else @@ -945,9 +996,13 @@ appendstring(realbuffer); break; case 'u': - makefmt(fmt, longflag, size_tflag, zeropad, width, precision, 'u'); + makefmt(fmt, longflag, longlongflag, size_tflag, zeropad, width, precision, 'u'); if (longflag) sprintf(realbuffer, fmt, va_arg(vargs, unsigned long)); +#ifdef HAVE_LONG_LONG + else if (longlongflag) + sprintf(realbuffer, fmt, va_arg(vargs, unsigned PY_LONG_LONG)); +#endif else if (size_tflag) sprintf(realbuffer, fmt, va_arg(vargs, size_t)); else @@ -955,12 +1010,12 @@ appendstring(realbuffer); break; case 'i': - makefmt(fmt, 0, 0, zeropad, width, precision, 'i'); + makefmt(fmt, 0, 0, 0, zeropad, width, precision, 'i'); sprintf(realbuffer, fmt, va_arg(vargs, int)); appendstring(realbuffer); break; case 'x': - makefmt(fmt, 0, 0, zeropad, width, precision, 'x'); + makefmt(fmt, 0, 0, 0, zeropad, width, precision, 'x'); sprintf(realbuffer, fmt, va_arg(vargs, int)); appendstring(realbuffer); break; Index: Misc/NEWS =================================================================== --- Misc/NEWS (revision 76311) +++ Misc/NEWS (working copy) @@ -110,6 +110,9 @@ C-API ----- +- Issue #Add '%lld' and '%llu' support to PyString_FromFormat(V) + and PyErr_Format, on machines with HAVE_LONG_LONG defined. + - Issue #6151: Made PyDescr_COMMON conform to standard C (like PyObject_HEAD in PEP 3123). The PyDescr_TYPE and PyDescr_NAME macros should be should used for accessing the d_type and d_name members of structures Index: Doc/c-api/exceptions.rst =================================================================== --- Doc/c-api/exceptions.rst (revision 76311) +++ Doc/c-api/exceptions.rst (working copy) @@ -155,6 +155,8 @@ .. % The descriptions for %zd and %zu are wrong, but the truth is complicated .. % because not all compilers support the %z width modifier -- we fake it .. % when necessary via interpolating PY_FORMAT_SIZE_T. + .. % Similar comments apply to the %ll width modifier and + .. % PY_FORMAT_LONG_LONG. +-------------------+---------------+--------------------------------+ | Format Characters | Type | Comment | @@ -176,6 +178,12 @@ | :attr:`%lu` | unsigned long | Exactly equivalent to | | | | ``printf("%lu")``. | +-------------------+---------------+--------------------------------+ + | :attr:`%lld` | long long | Exactly equivalent to | + | | | ``printf("%lld")``. | + +-------------------+---------------+--------------------------------+ + | :attr:`%llu` | unsigned | Exactly equivalent to | + | | long long | ``printf("%llu")``. | + +-------------------+---------------+--------------------------------+ | :attr:`%zd` | Py_ssize_t | Exactly equivalent to | | | | ``printf("%zd")``. | +-------------------+---------------+--------------------------------+ @@ -203,7 +211,15 @@ An unrecognized format character causes all the rest of the format string to be copied as-is to the result string, and any extra arguments discarded. + .. note:: + The `"%lld"` and `"%llu"` format specifiers are only available + when `HAVE_LONG_LONG` is defined. + + .. versionchanged:: 3.2 + Support for `"%lld"` and `"%llu"` added. + + .. cfunction:: void PyErr_SetNone(PyObject *type) This is a shorthand for ``PyErr_SetObject(type, Py_None)``. Index: Doc/c-api/unicode.rst =================================================================== --- Doc/c-api/unicode.rst (revision 76311) +++ Doc/c-api/unicode.rst (working copy) @@ -232,9 +232,12 @@ types and must correspond exactly to the format characters in the *format* string. The following format characters are allowed: + .. % This should be exactly the same as the table in PyErr_Format. .. % The descriptions for %zd and %zu are wrong, but the truth is complicated .. % because not all compilers support the %z width modifier -- we fake it .. % when necessary via interpolating PY_FORMAT_SIZE_T. + .. % Similar comments apply to the %ll width modifier and + .. % PY_FORMAT_LONG_LONG. +-------------------+---------------------+--------------------------------+ | Format Characters | Type | Comment | @@ -256,6 +259,12 @@ | :attr:`%lu` | unsigned long | Exactly equivalent to | | | | ``printf("%lu")``. | +-------------------+---------------------+--------------------------------+ + | :attr:`%lld` | long long | Exactly equivalent to | + | | | ``printf("%lld")``. | + +-------------------+---------------------+--------------------------------+ + | :attr:`%llu` | unsigned long long | Exactly equivalent to | + | | | ``printf("%llu")``. | + +-------------------+---------------------+--------------------------------+ | :attr:`%zd` | Py_ssize_t | Exactly equivalent to | | | | ``printf("%zd")``. | +-------------------+---------------------+--------------------------------+ @@ -301,7 +310,16 @@ An unrecognized format character causes all the rest of the format string to be copied as-is to the result string, and any extra arguments discarded. + .. note:: + The `"%lld"` and `"%llu"` format specifiers are only available + when `HAVE_LONG_LONG` is defined. + + .. versionchanged:: 3.2 + Support for `"%lld"` and `"%llu"` added. + + + .. cfunction:: PyObject* PyUnicode_FromFormatV(const char *format, va_list vargs) Identical to :func:`PyUnicode_FromFormat` except that it takes exactly two Index: Modules/_testcapimodule.c =================================================================== --- Modules/_testcapimodule.c (revision 76311) +++ Modules/_testcapimodule.c (working copy) @@ -1037,6 +1037,12 @@ CHECK_1_FORMAT("%lu", unsigned long); CHECK_1_FORMAT("%zu", size_t); + /* "%lld" and "%llu" support added in Python 2.7. */ +#ifdef HAVE_LONG_LONG + CHECK_1_FORMAT("%llu", unsigned PY_LONG_LONG); + CHECK_1_FORMAT("%lld", PY_LONG_LONG); +#endif + Py_RETURN_NONE; Fail: Index: pyconfig.h.in =================================================================== --- pyconfig.h.in (revision 76311) +++ pyconfig.h.in (working copy) @@ -910,6 +910,9 @@ /* Define as the preferred size in bits of long digits */ #undef PYLONG_BITS_IN_DIGIT +/* Define to printf format modifier for long long type */ +#undef PY_FORMAT_LONG_LONG + /* Define to printf format modifier for Py_ssize_t */ #undef PY_FORMAT_SIZE_T