Mercurial > cpython-lru_cache-weakref
comparison Python/errors.c @ 14335:951eb3af3494 legacy-trunk
code part of patch #100895 by Fredrik Lundh
PyErr_Format computes size of buffer needed rather than relying on
static buffer.
| author | Jeremy Hylton <jeremy@alum.mit.edu> |
|---|---|
| date | Fri, 01 Sep 2000 03:49:47 +0000 |
| parents | 6dee1985c681 |
| children | 6f6f965c5e2d |
comparison
equal
deleted
inserted
replaced
| 14334:bea8f14e7d61 | 14335:951eb3af3494 |
|---|---|
| 26 | 26 |
| 27 #ifdef MS_WIN32 | 27 #ifdef MS_WIN32 |
| 28 #include "windows.h" | 28 #include "windows.h" |
| 29 #include "winbase.h" | 29 #include "winbase.h" |
| 30 #endif | 30 #endif |
| 31 | |
| 32 #include <ctype.h> | |
| 31 | 33 |
| 32 void | 34 void |
| 33 PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback) | 35 PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback) |
| 34 { | 36 { |
| 35 PyThreadState *tstate = PyThreadState_GET(); | 37 PyThreadState *tstate = PyThreadState_GET(); |
| 362 } | 364 } |
| 363 | 365 |
| 364 PyObject *PyErr_SetFromWindowsErr(int ierr) | 366 PyObject *PyErr_SetFromWindowsErr(int ierr) |
| 365 { | 367 { |
| 366 return PyErr_SetFromWindowsErrWithFilename(ierr, NULL); | 368 return PyErr_SetFromWindowsErrWithFilename(ierr, NULL); |
| 367 | |
| 368 } | 369 } |
| 369 #endif /* MS_WINDOWS */ | 370 #endif /* MS_WINDOWS */ |
| 370 | 371 |
| 371 void | 372 void |
| 372 _PyErr_BadInternalCall(char *filename, int lineno) | 373 _PyErr_BadInternalCall(char *filename, int lineno) |
| 391 | 392 |
| 392 PyObject * | 393 PyObject * |
| 393 PyErr_Format(PyObject *exception, const char *format, ...) | 394 PyErr_Format(PyObject *exception, const char *format, ...) |
| 394 { | 395 { |
| 395 va_list vargs; | 396 va_list vargs; |
| 396 char buffer[500]; /* Caller is responsible for limiting the format */ | 397 int n, i; |
| 397 | 398 const char* f; |
| 399 char* s; | |
| 400 PyObject* string; | |
| 401 | |
| 402 /* step 1: figure out how large a buffer we need */ | |
| 403 | |
| 404 #ifdef HAVE_STDARG_PROTOTYPES | |
| 398 va_start(vargs, format); | 405 va_start(vargs, format); |
| 399 | 406 #else |
| 400 vsprintf(buffer, format, vargs); | 407 va_start(vargs); |
| 401 PyErr_SetString(exception, buffer); | 408 #endif |
| 409 | |
| 410 n = 0; | |
| 411 for (f = format; *f; f++) { | |
| 412 if (*f == '%') { | |
| 413 const char* p = f; | |
| 414 while (*++f && *f != '%' && !isalpha(*f)) | |
| 415 ; | |
| 416 switch (*f) { | |
| 417 case 'c': | |
| 418 va_arg(vargs, int); | |
| 419 /* fall through... */ | |
| 420 case '%': | |
| 421 n++; | |
| 422 break; | |
| 423 case 'd': case 'i': case 'x': | |
| 424 va_arg(vargs, int); | |
| 425 /* 20 bytes should be enough to hold a 64-bit | |
| 426 integer */ | |
| 427 n = n + 20; | |
| 428 break; | |
| 429 case 's': | |
| 430 s = va_arg(vargs, char*); | |
| 431 n = n + strlen(s); | |
| 432 break; | |
| 433 default: | |
| 434 /* if we stumble upon an unknown | |
| 435 formatting code, copy the rest of | |
| 436 the format string to the output | |
| 437 string. (we cannot just skip the | |
| 438 code, since there's no way to know | |
| 439 what's in the argument list) */ | |
| 440 n = n + strlen(p); | |
| 441 goto expand; | |
| 442 } | |
| 443 } else | |
| 444 n = n + 1; | |
| 445 } | |
| 446 | |
| 447 expand: | |
| 448 | |
| 449 string = PyString_FromStringAndSize(NULL, n); | |
| 450 if (!string) | |
| 451 return NULL; | |
| 452 | |
| 453 #ifdef HAVE_STDARG_PROTOTYPES | |
| 454 va_start(vargs, format); | |
| 455 #else | |
| 456 va_start(vargs); | |
| 457 #endif | |
| 458 | |
| 459 /* step 2: fill the buffer */ | |
| 460 | |
| 461 s = PyString_AsString(string); | |
| 462 | |
| 463 for (f = format; *f; f++) { | |
| 464 if (*f == '%') { | |
| 465 const char* p = f++; | |
| 466 /* parse the width.precision part (we're only | |
| 467 interested in the precision value, if any) */ | |
| 468 n = 0; | |
| 469 while (isdigit(*f)) | |
| 470 n = (n*10) + *f++ - '0'; | |
| 471 if (*f == '.') { | |
| 472 f++; | |
| 473 n = 0; | |
| 474 while (isdigit(*f)) | |
| 475 n = (n*10) + *f++ - '0'; | |
| 476 } | |
| 477 while (*f && *f != '%' && !isalpha(*f)) | |
| 478 f++; | |
| 479 switch (*f) { | |
| 480 case 'c': | |
| 481 *s++ = va_arg(vargs, int); | |
| 482 break; | |
| 483 case 'd': | |
| 484 sprintf(s, "%d", va_arg(vargs, int)); | |
| 485 s = s + strlen(s); | |
| 486 break; | |
| 487 case 'i': | |
| 488 sprintf(s, "%i", va_arg(vargs, int)); | |
| 489 s = s + strlen(s); | |
| 490 break; | |
| 491 case 'x': | |
| 492 sprintf(s, "%x", va_arg(vargs, int)); | |
| 493 s = s + strlen(s); | |
| 494 break; | |
| 495 case 's': | |
| 496 p = va_arg(vargs, char*); | |
| 497 i = strlen(p); | |
| 498 if (n > 0 && i > n) | |
| 499 i = n; | |
| 500 memcpy(s, p, i); | |
| 501 s = s + i; | |
| 502 break; | |
| 503 case '%': | |
| 504 *s++ = '%'; | |
| 505 break; | |
| 506 default: | |
| 507 strcpy(s, p); | |
| 508 s = s + strlen(s); | |
| 509 goto end; | |
| 510 } | |
| 511 } else | |
| 512 *s++ = *f; | |
| 513 } | |
| 514 | |
| 515 end: | |
| 516 | |
| 517 _PyString_Resize(&string, s - PyString_AsString(string)); | |
| 518 | |
| 519 PyErr_SetObject(exception, string); | |
| 520 Py_XDECREF(string); | |
| 521 | |
| 402 return NULL; | 522 return NULL; |
| 403 } | 523 } |
| 404 | 524 |
| 405 | 525 |
| 406 PyObject * | 526 PyObject * |
