mirror of
https://github.com/python/cpython.git
synced 2025-11-02 11:08:57 +00:00
Teach PyString_FromFormat, PyErr_Format, and PyString_FromFormatV
about "%u", "%lu" and "%zu" formats. Since PyString_FromFormat and PyErr_Format have exactly the same rules (both inherited from PyString_FromFormatV), it would be good if someone with more LaTeX Fu changed one of them to just point to the other. Their docs were way out of synch before this patch, and I just did a mass copy+paste to repair that. Not a backport candidate (this is a new feature).
This commit is contained in:
parent
822f34a848
commit
8931ff1f67
5 changed files with 127 additions and 40 deletions
|
|
@ -245,7 +245,7 @@ booleans. The following macros are available, however.
|
||||||
\end{csimplemacrodesc}
|
\end{csimplemacrodesc}
|
||||||
|
|
||||||
\begin{cfuncdesc}{PyObject*}{PyBool_FromLong}{long v}
|
\begin{cfuncdesc}{PyObject*}{PyBool_FromLong}{long v}
|
||||||
Return a new reference to \constant{Py_True} or \constant{Py_False}
|
Return a new reference to \constant{Py_True} or \constant{Py_False}
|
||||||
depending on the truth value of \var{v}.
|
depending on the truth value of \var{v}.
|
||||||
\versionadded{2.3}
|
\versionadded{2.3}
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
@ -618,12 +618,24 @@ parameter and are called with a non-string parameter.
|
||||||
exactly to the format characters in the \var{format} string. The
|
exactly to the format characters in the \var{format} string. The
|
||||||
following format characters are allowed:
|
following format characters are allowed:
|
||||||
|
|
||||||
|
% This should be exactly the same as the table in PyErr_Format.
|
||||||
|
% One should just refer to the other.
|
||||||
|
|
||||||
|
% 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.
|
||||||
|
|
||||||
|
% %u, %lu, %zu should have "new in Python 2.5" blurbs.
|
||||||
|
|
||||||
\begin{tableiii}{l|l|l}{member}{Format Characters}{Type}{Comment}
|
\begin{tableiii}{l|l|l}{member}{Format Characters}{Type}{Comment}
|
||||||
\lineiii{\%\%}{\emph{n/a}}{The literal \% character.}
|
\lineiii{\%\%}{\emph{n/a}}{The literal \% character.}
|
||||||
\lineiii{\%c}{int}{A single character, represented as an C int.}
|
\lineiii{\%c}{int}{A single character, represented as an C int.}
|
||||||
\lineiii{\%d}{int}{Exactly equivalent to \code{printf("\%d")}.}
|
\lineiii{\%d}{int}{Exactly equivalent to \code{printf("\%d")}.}
|
||||||
|
\lineiii{\%u}{unsigned int}{Exactly equivalent to \code{printf("\%u")}.}
|
||||||
\lineiii{\%ld}{long}{Exactly equivalent to \code{printf("\%ld")}.}
|
\lineiii{\%ld}{long}{Exactly equivalent to \code{printf("\%ld")}.}
|
||||||
\lineiii{\%zd}{long}{Exactly equivalent to \code{printf("\%zd")}.}
|
\lineiii{\%lu}{unsigned long}{Exactly equivalent to \code{printf("\%lu")}.}
|
||||||
|
\lineiii{\%zd}{Py_ssize_t}{Exactly equivalent to \code{printf("\%zd")}.}
|
||||||
|
\lineiii{\%zu}{ssize_t}{Exactly equivalent to \code{printf("\%zu")}.}
|
||||||
\lineiii{\%i}{int}{Exactly equivalent to \code{printf("\%i")}.}
|
\lineiii{\%i}{int}{Exactly equivalent to \code{printf("\%i")}.}
|
||||||
\lineiii{\%x}{int}{Exactly equivalent to \code{printf("\%x")}.}
|
\lineiii{\%x}{int}{Exactly equivalent to \code{printf("\%x")}.}
|
||||||
\lineiii{\%s}{char*}{A null-terminated C character array.}
|
\lineiii{\%s}{char*}{A null-terminated C character array.}
|
||||||
|
|
@ -632,6 +644,10 @@ parameter and are called with a non-string parameter.
|
||||||
guaranteed to start with the literal \code{0x} regardless of
|
guaranteed to start with the literal \code{0x} regardless of
|
||||||
what the platform's \code{printf} yields.}
|
what the platform's \code{printf} yields.}
|
||||||
\end{tableiii}
|
\end{tableiii}
|
||||||
|
|
||||||
|
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.
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
\begin{cfuncdesc}{PyObject*}{PyString_FromFormatV}{const char *format,
|
\begin{cfuncdesc}{PyObject*}{PyString_FromFormatV}{const char *format,
|
||||||
|
|
@ -687,7 +703,7 @@ parameter and are called with a non-string parameter.
|
||||||
\var{size})}. It must not be deallocated. If \var{string} is a
|
\var{size})}. It must not be deallocated. If \var{string} is a
|
||||||
Unicode object, this function computes the default encoding of
|
Unicode object, this function computes the default encoding of
|
||||||
\var{string} and operates on that. If \var{string} is not a string
|
\var{string} and operates on that. If \var{string} is not a string
|
||||||
object at all, \cfunction{PyString_AsStringAndSize()} returns
|
object at all, \cfunction{PyString_AsStringAndSize()} returns
|
||||||
\code{-1} and raises \exception{TypeError}.
|
\code{-1} and raises \exception{TypeError}.
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
|
|
@ -1494,7 +1510,7 @@ They all return \NULL{} or \code{-1} if an exception occurs.
|
||||||
Return 1 if \var{substr} matches \var{str}[\var{start}:\var{end}] at
|
Return 1 if \var{substr} matches \var{str}[\var{start}:\var{end}] at
|
||||||
the given tail end (\var{direction} == -1 means to do a prefix
|
the given tail end (\var{direction} == -1 means to do a prefix
|
||||||
match, \var{direction} == 1 a suffix match), 0 otherwise.
|
match, \var{direction} == 1 a suffix match), 0 otherwise.
|
||||||
Return \code{-1} if an error occurred.
|
Return \code{-1} if an error occurred.
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
\begin{cfuncdesc}{Py_ssize_t}{PyUnicode_Find}{PyObject *str,
|
\begin{cfuncdesc}{Py_ssize_t}{PyUnicode_Find}{PyObject *str,
|
||||||
|
|
@ -3013,7 +3029,7 @@ Macros for the convenience of modules implementing the DB API:
|
||||||
|
|
||||||
|
|
||||||
\subsection{Set Objects \label{setObjects}}
|
\subsection{Set Objects \label{setObjects}}
|
||||||
\sectionauthor{Raymond D. Hettinger}{python@rcn.com}
|
\sectionauthor{Raymond D. Hettinger}{python@rcn.com}
|
||||||
|
|
||||||
\obindex{set}
|
\obindex{set}
|
||||||
\obindex{frozenset}
|
\obindex{frozenset}
|
||||||
|
|
@ -3022,8 +3038,8 @@ Macros for the convenience of modules implementing the DB API:
|
||||||
This section details the public API for \class{set} and \class{frozenset}
|
This section details the public API for \class{set} and \class{frozenset}
|
||||||
objects. Any functionality not listed below is best accessed using the
|
objects. Any functionality not listed below is best accessed using the
|
||||||
either the abstract object protocol (including
|
either the abstract object protocol (including
|
||||||
\cfunction{PyObject_CallMethod()}, \cfunction{PyObject_RichCompareBool()},
|
\cfunction{PyObject_CallMethod()}, \cfunction{PyObject_RichCompareBool()},
|
||||||
\cfunction{PyObject_Hash()}, \cfunction{PyObject_Repr()},
|
\cfunction{PyObject_Hash()}, \cfunction{PyObject_Repr()},
|
||||||
\cfunction{PyObject_IsTrue()}, \cfunction{PyObject_Print()}, and
|
\cfunction{PyObject_IsTrue()}, \cfunction{PyObject_Print()}, and
|
||||||
\cfunction{PyObject_GetIter()})
|
\cfunction{PyObject_GetIter()})
|
||||||
or the abstract number protocol (including
|
or the abstract number protocol (including
|
||||||
|
|
@ -3040,7 +3056,7 @@ or the abstract number protocol (including
|
||||||
block of memory for medium and large sized sets (much like list storage).
|
block of memory for medium and large sized sets (much like list storage).
|
||||||
None of the fields of this structure should be considered public and
|
None of the fields of this structure should be considered public and
|
||||||
are subject to change. All access should be done through the
|
are subject to change. All access should be done through the
|
||||||
documented API rather than by manipulating the values in the structure.
|
documented API rather than by manipulating the values in the structure.
|
||||||
|
|
||||||
\end{ctypedesc}
|
\end{ctypedesc}
|
||||||
|
|
||||||
|
|
@ -3059,7 +3075,7 @@ The following type check macros work on pointers to any Python object.
|
||||||
Likewise, the constructor functions work with any iterable Python object.
|
Likewise, the constructor functions work with any iterable Python object.
|
||||||
|
|
||||||
\begin{cfuncdesc}{int}{PyAnySet_Check}{PyObject *p}
|
\begin{cfuncdesc}{int}{PyAnySet_Check}{PyObject *p}
|
||||||
Return true if \var{p} is a \class{set} object, a \class{frozenset}
|
Return true if \var{p} is a \class{set} object, a \class{frozenset}
|
||||||
object, or an instance of a subtype.
|
object, or an instance of a subtype.
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
|
|
@ -3112,7 +3128,7 @@ The following functions and macros are available for instances of
|
||||||
function does not automatically convert unhashable sets into temporary
|
function does not automatically convert unhashable sets into temporary
|
||||||
frozensets. Raise a \exception{TypeError} if the \var{key} is unhashable.
|
frozensets. Raise a \exception{TypeError} if the \var{key} is unhashable.
|
||||||
Raise \exception{PyExc_SystemError} if \var{anyset} is not a \class{set},
|
Raise \exception{PyExc_SystemError} if \var{anyset} is not a \class{set},
|
||||||
\class{frozenset}, or an instance of a subtype.
|
\class{frozenset}, or an instance of a subtype.
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
The following functions are available for instances of \class{set} or
|
The following functions are available for instances of \class{set} or
|
||||||
|
|
@ -3134,7 +3150,7 @@ its subtypes but not for instances of \class{frozenset} or its subtypes.
|
||||||
unhashable. Unlike the Python \method{discard()} method, this function
|
unhashable. Unlike the Python \method{discard()} method, this function
|
||||||
does not automatically convert unhashable sets into temporary frozensets.
|
does not automatically convert unhashable sets into temporary frozensets.
|
||||||
Raise \exception{PyExc_SystemError} if \var{set} is an not an instance
|
Raise \exception{PyExc_SystemError} if \var{set} is an not an instance
|
||||||
of \class{set} or its subtype.
|
of \class{set} or its subtype.
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
\begin{cfuncdesc}{PyObject*}{PySet_Pop}{PyObject *set}
|
\begin{cfuncdesc}{PyObject*}{PySet_Pop}{PyObject *set}
|
||||||
|
|
@ -3142,7 +3158,7 @@ its subtypes but not for instances of \class{frozenset} or its subtypes.
|
||||||
and removes the object from the \var{set}. Return \NULL{} on
|
and removes the object from the \var{set}. Return \NULL{} on
|
||||||
failure. Raise \exception{KeyError} if the set is empty.
|
failure. Raise \exception{KeyError} if the set is empty.
|
||||||
Raise a \exception{SystemError} if \var{set} is an not an instance
|
Raise a \exception{SystemError} if \var{set} is an not an instance
|
||||||
of \class{set} or its subtype.
|
of \class{set} or its subtype.
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
\begin{cfuncdesc}{int}{PySet_Clear}{PyObject *set}
|
\begin{cfuncdesc}{int}{PySet_Clear}{PyObject *set}
|
||||||
|
|
|
||||||
|
|
@ -135,13 +135,32 @@ for each thread.
|
||||||
codes, similar to \cfunction{printf()}. The \code{width.precision}
|
codes, similar to \cfunction{printf()}. The \code{width.precision}
|
||||||
before a format code is parsed, but the width part is ignored.
|
before a format code is parsed, but the width part is ignored.
|
||||||
|
|
||||||
\begin{tableii}{c|l}{character}{Character}{Meaning}
|
% This should be exactly the same as the table in PyString_FromFormat.
|
||||||
\lineii{c}{Character, as an \ctype{int} parameter}
|
% One should just refer to the other.
|
||||||
\lineii{d}{Number in decimal, as an \ctype{int} parameter}
|
|
||||||
\lineii{x}{Number in hexadecimal, as an \ctype{int} parameter}
|
% The descriptions for %zd and %zu are wrong, but the truth is complicated
|
||||||
\lineii{s}{A string, as a \ctype{char *} parameter}
|
% because not all compilers support the %z width modifier -- we fake it
|
||||||
\lineii{p}{A hex pointer, as a \ctype{void *} parameter}
|
% when necessary via interpolating PY_FORMAT_SIZE_T.
|
||||||
\end{tableii}
|
|
||||||
|
% %u, %lu, %zu should have "new in Python 2.5" blurbs.
|
||||||
|
|
||||||
|
\begin{tableiii}{l|l|l}{member}{Format Characters}{Type}{Comment}
|
||||||
|
\lineiii{\%\%}{\emph{n/a}}{The literal \% character.}
|
||||||
|
\lineiii{\%c}{int}{A single character, represented as an C int.}
|
||||||
|
\lineiii{\%d}{int}{Exactly equivalent to \code{printf("\%d")}.}
|
||||||
|
\lineiii{\%u}{unsigned int}{Exactly equivalent to \code{printf("\%u")}.}
|
||||||
|
\lineiii{\%ld}{long}{Exactly equivalent to \code{printf("\%ld")}.}
|
||||||
|
\lineiii{\%lu}{unsigned long}{Exactly equivalent to \code{printf("\%lu")}.}
|
||||||
|
\lineiii{\%zd}{Py_ssize_t}{Exactly equivalent to \code{printf("\%zd")}.}
|
||||||
|
\lineiii{\%zu}{ssize_t}{Exactly equivalent to \code{printf("\%zu")}.}
|
||||||
|
\lineiii{\%i}{int}{Exactly equivalent to \code{printf("\%i")}.}
|
||||||
|
\lineiii{\%x}{int}{Exactly equivalent to \code{printf("\%x")}.}
|
||||||
|
\lineiii{\%s}{char*}{A null-terminated C character array.}
|
||||||
|
\lineiii{\%p}{void*}{The hex representation of a C pointer.
|
||||||
|
Mostly equivalent to \code{printf("\%p")} except that it is
|
||||||
|
guaranteed to start with the literal \code{0x} regardless of
|
||||||
|
what the platform's \code{printf} yields.}
|
||||||
|
\end{tableiii}
|
||||||
|
|
||||||
An unrecognized format character causes all the rest of the format
|
An unrecognized format character causes all the rest of the format
|
||||||
string to be copied as-is to the result string, and any extra
|
string to be copied as-is to the result string, and any extra
|
||||||
|
|
@ -275,8 +294,8 @@ for each thread.
|
||||||
command line documentation. There is no C API for warning control.
|
command line documentation. There is no C API for warning control.
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
\begin{cfuncdesc}{int}{PyErr_WarnExplicit}{PyObject *category,
|
\begin{cfuncdesc}{int}{PyErr_WarnExplicit}{PyObject *category,
|
||||||
const char *message, const char *filename, int lineno,
|
const char *message, const char *filename, int lineno,
|
||||||
const char *module, PyObject *registry}
|
const char *module, PyObject *registry}
|
||||||
Issue a warning message with explicit control over all warning
|
Issue a warning message with explicit control over all warning
|
||||||
attributes. This is a straightforward wrapper around the Python
|
attributes. This is a straightforward wrapper around the Python
|
||||||
|
|
@ -402,5 +421,5 @@ are derived from \exception{BaseException}.
|
||||||
\withsubitem{(built-in exception)}{\ttindex{BaseException}}
|
\withsubitem{(built-in exception)}{\ttindex{BaseException}}
|
||||||
|
|
||||||
String exceptions are still supported in the interpreter to allow
|
String exceptions are still supported in the interpreter to allow
|
||||||
existing code to run unmodified, but this will also change in a future
|
existing code to run unmodified, but this will also change in a future
|
||||||
release.
|
release.
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ Core and builtins
|
||||||
Extension Modules
|
Extension Modules
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
- On Win32, os.listdir now supports arbitrarily-long Unicode path names
|
- On Win32, os.listdir now supports arbitrarily-long Unicode path names
|
||||||
(up to the system limit of 32K characters).
|
(up to the system limit of 32K characters).
|
||||||
|
|
||||||
- Use Win32 API to implement os.{access,chdir,chmod,mkdir,remove,rename,rmdir,utime}.
|
- Use Win32 API to implement os.{access,chdir,chmod,mkdir,remove,rename,rmdir,utime}.
|
||||||
|
|
@ -200,6 +200,10 @@ Build
|
||||||
C API
|
C API
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- ``PyString_FromFormat``, ``PyErr_Format``, and ``PyString_FromFormatV``
|
||||||
|
now accept formats "%u" for unsigned ints, "%lu" for unsigned longs,
|
||||||
|
and "%zu" for unsigned integers of type ``size_t``.
|
||||||
|
|
||||||
Tests
|
Tests
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -486,8 +486,8 @@ test_u_code(PyObject *self)
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static PyObject *
|
||||||
PyObject *codec_incrementalencoder(PyObject *self, PyObject *args)
|
codec_incrementalencoder(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
const char *encoding, *errors = NULL;
|
const char *encoding, *errors = NULL;
|
||||||
if (!PyArg_ParseTuple(args, "s|s:test_incrementalencoder",
|
if (!PyArg_ParseTuple(args, "s|s:test_incrementalencoder",
|
||||||
|
|
@ -496,8 +496,8 @@ PyObject *codec_incrementalencoder(PyObject *self, PyObject *args)
|
||||||
return PyCodec_IncrementalEncoder(encoding, errors);
|
return PyCodec_IncrementalEncoder(encoding, errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static PyObject *
|
||||||
PyObject *codec_incrementaldecoder(PyObject *self, PyObject *args)
|
codec_incrementaldecoder(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
const char *encoding, *errors = NULL;
|
const char *encoding, *errors = NULL;
|
||||||
if (!PyArg_ParseTuple(args, "s|s:test_incrementaldecoder",
|
if (!PyArg_ParseTuple(args, "s|s:test_incrementaldecoder",
|
||||||
|
|
@ -660,6 +660,44 @@ test_thread_state(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Some tests of PyString_FromFormat(). This needs more tests.
|
||||||
|
* PyString_FromFormat() also needs docs.
|
||||||
|
*/
|
||||||
|
static PyObject *
|
||||||
|
test_string_from_format(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *result;
|
||||||
|
char *msg;
|
||||||
|
|
||||||
|
#define CHECK_1_FORMAT(FORMAT, TYPE) \
|
||||||
|
result = PyString_FromFormat(FORMAT, (TYPE)1); \
|
||||||
|
if (result == NULL) \
|
||||||
|
return NULL; \
|
||||||
|
if (strcmp(PyString_AsString(result), "1")) { \
|
||||||
|
msg = FORMAT " failed at 1"; \
|
||||||
|
goto Fail; \
|
||||||
|
} \
|
||||||
|
Py_DECREF(result)
|
||||||
|
|
||||||
|
CHECK_1_FORMAT("%d", int);
|
||||||
|
CHECK_1_FORMAT("%ld", long);
|
||||||
|
/* The z width modifier was added in Python 2.5. */
|
||||||
|
CHECK_1_FORMAT("%zd", Py_ssize_t);
|
||||||
|
|
||||||
|
/* The u type code was added in Python 2.5. */
|
||||||
|
CHECK_1_FORMAT("%u", unsigned int);
|
||||||
|
CHECK_1_FORMAT("%lu", unsigned long);
|
||||||
|
CHECK_1_FORMAT("%zu", size_t);
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
|
||||||
|
Fail:
|
||||||
|
Py_XDECREF(result);
|
||||||
|
return raiseTestError("test_string_from_format", msg);
|
||||||
|
|
||||||
|
#undef CHECK_1_FORMAT
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef TestMethods[] = {
|
static PyMethodDef TestMethods[] = {
|
||||||
{"raise_exception", raise_exception, METH_VARARGS},
|
{"raise_exception", raise_exception, METH_VARARGS},
|
||||||
{"test_config", (PyCFunction)test_config, METH_NOARGS},
|
{"test_config", (PyCFunction)test_config, METH_NOARGS},
|
||||||
|
|
@ -669,6 +707,7 @@ static PyMethodDef TestMethods[] = {
|
||||||
{"test_long_numbits", (PyCFunction)test_long_numbits, METH_NOARGS},
|
{"test_long_numbits", (PyCFunction)test_long_numbits, METH_NOARGS},
|
||||||
{"test_k_code", (PyCFunction)test_k_code, METH_NOARGS},
|
{"test_k_code", (PyCFunction)test_k_code, METH_NOARGS},
|
||||||
{"test_null_strings", (PyCFunction)test_null_strings, METH_NOARGS},
|
{"test_null_strings", (PyCFunction)test_null_strings, METH_NOARGS},
|
||||||
|
{"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS},
|
||||||
|
|
||||||
{"getargs_b", getargs_b, METH_VARARGS},
|
{"getargs_b", getargs_b, METH_VARARGS},
|
||||||
{"getargs_B", getargs_B, METH_VARARGS},
|
{"getargs_B", getargs_B, METH_VARARGS},
|
||||||
|
|
|
||||||
|
|
@ -176,14 +176,11 @@ PyString_FromFormatV(const char *format, va_list vargs)
|
||||||
while (*++f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
|
while (*++f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
|
||||||
;
|
;
|
||||||
|
|
||||||
/* skip the 'l' in %ld, since it doesn't change the
|
/* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since
|
||||||
width. although only %d is supported (see
|
* they don't affect the amount of space we reserve.
|
||||||
"expand" section below), others can be easily
|
*/
|
||||||
added */
|
if ((*f == 'l' || *f == 'z') &&
|
||||||
if (*f == 'l' && *(f+1) == 'd')
|
(f[1] == 'd' || f[1] == 'u'))
|
||||||
++f;
|
|
||||||
/* likewise for %zd */
|
|
||||||
if (*f == 'z' && *(f+1) == 'd')
|
|
||||||
++f;
|
++f;
|
||||||
|
|
||||||
switch (*f) {
|
switch (*f) {
|
||||||
|
|
@ -193,7 +190,7 @@ PyString_FromFormatV(const char *format, va_list vargs)
|
||||||
case '%':
|
case '%':
|
||||||
n++;
|
n++;
|
||||||
break;
|
break;
|
||||||
case 'd': case 'i': case 'x':
|
case 'd': case 'u': case 'i': case 'x':
|
||||||
(void) va_arg(count, int);
|
(void) va_arg(count, int);
|
||||||
/* 20 bytes is enough to hold a 64-bit
|
/* 20 bytes is enough to hold a 64-bit
|
||||||
integer. Decimal takes the most space.
|
integer. Decimal takes the most space.
|
||||||
|
|
@ -255,14 +252,14 @@ PyString_FromFormatV(const char *format, va_list vargs)
|
||||||
}
|
}
|
||||||
while (*f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
|
while (*f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
|
||||||
f++;
|
f++;
|
||||||
/* handle the long flag, but only for %ld. others
|
/* handle the long flag, but only for %ld and %lu.
|
||||||
can be added when necessary. */
|
others can be added when necessary. */
|
||||||
if (*f == 'l' && *(f+1) == 'd') {
|
if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) {
|
||||||
longflag = 1;
|
longflag = 1;
|
||||||
++f;
|
++f;
|
||||||
}
|
}
|
||||||
/* handle the size_t flag. */
|
/* handle the size_t flag. */
|
||||||
if (*f == 'z' && *(f+1) == 'd') {
|
if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) {
|
||||||
size_tflag = 1;
|
size_tflag = 1;
|
||||||
++f;
|
++f;
|
||||||
}
|
}
|
||||||
|
|
@ -281,6 +278,18 @@ PyString_FromFormatV(const char *format, va_list vargs)
|
||||||
sprintf(s, "%d", va_arg(vargs, int));
|
sprintf(s, "%d", va_arg(vargs, int));
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
break;
|
break;
|
||||||
|
case 'u':
|
||||||
|
if (longflag)
|
||||||
|
sprintf(s, "%lu",
|
||||||
|
va_arg(vargs, unsigned long));
|
||||||
|
else if (size_tflag)
|
||||||
|
sprintf(s, "%" PY_FORMAT_SIZE_T "u",
|
||||||
|
va_arg(vargs, size_t));
|
||||||
|
else
|
||||||
|
sprintf(s, "%u",
|
||||||
|
va_arg(vargs, unsigned int));
|
||||||
|
s += strlen(s);
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
sprintf(s, "%i", va_arg(vargs, int));
|
sprintf(s, "%i", va_arg(vargs, int));
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue