mirror of
https://github.com/python/cpython.git
synced 2025-09-03 15:31:08 +00:00
code part of patch #100895 by Fredrik Lundh
PyErr_Format computes size of buffer needed rather than relying on static buffer.
This commit is contained in:
parent
51ee09b995
commit
b69a27e5b2
1 changed files with 124 additions and 4 deletions
128
Python/errors.c
128
Python/errors.c
|
@ -29,6 +29,8 @@ extern char *strerror(int);
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
|
PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
|
||||||
{
|
{
|
||||||
|
@ -364,7 +366,6 @@ PyObject *PyErr_SetFromWindowsErrWithFilename(
|
||||||
PyObject *PyErr_SetFromWindowsErr(int ierr)
|
PyObject *PyErr_SetFromWindowsErr(int ierr)
|
||||||
{
|
{
|
||||||
return PyErr_SetFromWindowsErrWithFilename(ierr, NULL);
|
return PyErr_SetFromWindowsErrWithFilename(ierr, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* MS_WINDOWS */
|
#endif /* MS_WINDOWS */
|
||||||
|
|
||||||
|
@ -393,12 +394,131 @@ PyObject *
|
||||||
PyErr_Format(PyObject *exception, const char *format, ...)
|
PyErr_Format(PyObject *exception, const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list vargs;
|
va_list vargs;
|
||||||
char buffer[500]; /* Caller is responsible for limiting the format */
|
int n, i;
|
||||||
|
const char* f;
|
||||||
|
char* s;
|
||||||
|
PyObject* string;
|
||||||
|
|
||||||
|
/* step 1: figure out how large a buffer we need */
|
||||||
|
|
||||||
|
#ifdef HAVE_STDARG_PROTOTYPES
|
||||||
va_start(vargs, format);
|
va_start(vargs, format);
|
||||||
|
#else
|
||||||
|
va_start(vargs);
|
||||||
|
#endif
|
||||||
|
|
||||||
vsprintf(buffer, format, vargs);
|
n = 0;
|
||||||
PyErr_SetString(exception, buffer);
|
for (f = format; *f; f++) {
|
||||||
|
if (*f == '%') {
|
||||||
|
const char* p = f;
|
||||||
|
while (*++f && *f != '%' && !isalpha(*f))
|
||||||
|
;
|
||||||
|
switch (*f) {
|
||||||
|
case 'c':
|
||||||
|
va_arg(vargs, int);
|
||||||
|
/* fall through... */
|
||||||
|
case '%':
|
||||||
|
n++;
|
||||||
|
break;
|
||||||
|
case 'd': case 'i': case 'x':
|
||||||
|
va_arg(vargs, int);
|
||||||
|
/* 20 bytes should be enough to hold a 64-bit
|
||||||
|
integer */
|
||||||
|
n = n + 20;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
s = va_arg(vargs, char*);
|
||||||
|
n = n + strlen(s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* if we stumble upon an unknown
|
||||||
|
formatting code, copy the rest of
|
||||||
|
the format string to the output
|
||||||
|
string. (we cannot just skip the
|
||||||
|
code, since there's no way to know
|
||||||
|
what's in the argument list) */
|
||||||
|
n = n + strlen(p);
|
||||||
|
goto expand;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
n = n + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
expand:
|
||||||
|
|
||||||
|
string = PyString_FromStringAndSize(NULL, n);
|
||||||
|
if (!string)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_STDARG_PROTOTYPES
|
||||||
|
va_start(vargs, format);
|
||||||
|
#else
|
||||||
|
va_start(vargs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* step 2: fill the buffer */
|
||||||
|
|
||||||
|
s = PyString_AsString(string);
|
||||||
|
|
||||||
|
for (f = format; *f; f++) {
|
||||||
|
if (*f == '%') {
|
||||||
|
const char* p = f++;
|
||||||
|
/* parse the width.precision part (we're only
|
||||||
|
interested in the precision value, if any) */
|
||||||
|
n = 0;
|
||||||
|
while (isdigit(*f))
|
||||||
|
n = (n*10) + *f++ - '0';
|
||||||
|
if (*f == '.') {
|
||||||
|
f++;
|
||||||
|
n = 0;
|
||||||
|
while (isdigit(*f))
|
||||||
|
n = (n*10) + *f++ - '0';
|
||||||
|
}
|
||||||
|
while (*f && *f != '%' && !isalpha(*f))
|
||||||
|
f++;
|
||||||
|
switch (*f) {
|
||||||
|
case 'c':
|
||||||
|
*s++ = va_arg(vargs, int);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
sprintf(s, "%d", va_arg(vargs, int));
|
||||||
|
s = s + strlen(s);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
sprintf(s, "%i", va_arg(vargs, int));
|
||||||
|
s = s + strlen(s);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
sprintf(s, "%x", va_arg(vargs, int));
|
||||||
|
s = s + strlen(s);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
p = va_arg(vargs, char*);
|
||||||
|
i = strlen(p);
|
||||||
|
if (n > 0 && i > n)
|
||||||
|
i = n;
|
||||||
|
memcpy(s, p, i);
|
||||||
|
s = s + i;
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
*s++ = '%';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strcpy(s, p);
|
||||||
|
s = s + strlen(s);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
*s++ = *f;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
|
||||||
|
_PyString_Resize(&string, s - PyString_AsString(string));
|
||||||
|
|
||||||
|
PyErr_SetObject(exception, string);
|
||||||
|
Py_XDECREF(string);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue