Mercurial > cpython-lru_cache-weakref
comparison Python/errors.c @ 19477:e1c91ac55cca legacy-trunk
PyErr_Format(): Factor out most of this code into
PyString_FromFormat() since it's much more generally useful than
just for exceptions.
| author | Barry Warsaw <barry@python.org> |
|---|---|
| date | Fri, 24 Aug 2001 18:35:23 +0000 |
| parents | 6a2e2548e6cf |
| children | 55874d8e0dfb |
comparison
equal
deleted
inserted
replaced
| 19476:0e70df98424e | 19477:e1c91ac55cca |
|---|---|
| 383 | 383 |
| 384 PyObject * | 384 PyObject * |
| 385 PyErr_Format(PyObject *exception, const char *format, ...) | 385 PyErr_Format(PyObject *exception, const char *format, ...) |
| 386 { | 386 { |
| 387 va_list vargs; | 387 va_list vargs; |
| 388 int n, i; | |
| 389 const char* f; | |
| 390 char* s; | |
| 391 PyObject* string; | 388 PyObject* string; |
| 392 | |
| 393 /* step 1: figure out how large a buffer we need */ | |
| 394 | 389 |
| 395 #ifdef HAVE_STDARG_PROTOTYPES | 390 #ifdef HAVE_STDARG_PROTOTYPES |
| 396 va_start(vargs, format); | 391 va_start(vargs, format); |
| 397 #else | 392 #else |
| 398 va_start(vargs); | 393 va_start(vargs); |
| 399 #endif | 394 #endif |
| 400 | 395 |
| 401 n = 0; | 396 string = PyString_FromFormatV(format, vargs); |
| 402 for (f = format; *f; f++) { | |
| 403 if (*f == '%') { | |
| 404 const char* p = f; | |
| 405 while (*++f && *f != '%' && !isalpha(Py_CHARMASK(*f))) | |
| 406 ; | |
| 407 switch (*f) { | |
| 408 case 'c': | |
| 409 (void) va_arg(vargs, int); | |
| 410 /* fall through... */ | |
| 411 case '%': | |
| 412 n++; | |
| 413 break; | |
| 414 case 'd': case 'i': case 'x': | |
| 415 (void) va_arg(vargs, int); | |
| 416 /* 20 bytes should be enough to hold a 64-bit | |
| 417 integer */ | |
| 418 n = n + 20; | |
| 419 break; | |
| 420 case 's': | |
| 421 s = va_arg(vargs, char*); | |
| 422 n = n + strlen(s); | |
| 423 break; | |
| 424 default: | |
| 425 /* if we stumble upon an unknown | |
| 426 formatting code, copy the rest of | |
| 427 the format string to the output | |
| 428 string. (we cannot just skip the | |
| 429 code, since there's no way to know | |
| 430 what's in the argument list) */ | |
| 431 n = n + strlen(p); | |
| 432 goto expand; | |
| 433 } | |
| 434 } else | |
| 435 n = n + 1; | |
| 436 } | |
| 437 | |
| 438 expand: | |
| 439 | |
| 440 string = PyString_FromStringAndSize(NULL, n); | |
| 441 if (!string) | |
| 442 return NULL; | |
| 443 | |
| 444 #ifdef HAVE_STDARG_PROTOTYPES | |
| 445 va_start(vargs, format); | |
| 446 #else | |
| 447 va_start(vargs); | |
| 448 #endif | |
| 449 | |
| 450 /* step 2: fill the buffer */ | |
| 451 | |
| 452 s = PyString_AsString(string); | |
| 453 | |
| 454 for (f = format; *f; f++) { | |
| 455 if (*f == '%') { | |
| 456 const char* p = f++; | |
| 457 /* parse the width.precision part (we're only | |
| 458 interested in the precision value, if any) */ | |
| 459 n = 0; | |
| 460 while (isdigit(Py_CHARMASK(*f))) | |
| 461 n = (n*10) + *f++ - '0'; | |
| 462 if (*f == '.') { | |
| 463 f++; | |
| 464 n = 0; | |
| 465 while (isdigit(Py_CHARMASK(*f))) | |
| 466 n = (n*10) + *f++ - '0'; | |
| 467 } | |
| 468 while (*f && *f != '%' && !isalpha(Py_CHARMASK(*f))) | |
| 469 f++; | |
| 470 switch (*f) { | |
| 471 case 'c': | |
| 472 *s++ = va_arg(vargs, int); | |
| 473 break; | |
| 474 case 'd': | |
| 475 sprintf(s, "%d", va_arg(vargs, int)); | |
| 476 s = s + strlen(s); | |
| 477 break; | |
| 478 case 'i': | |
| 479 sprintf(s, "%i", va_arg(vargs, int)); | |
| 480 s = s + strlen(s); | |
| 481 break; | |
| 482 case 'x': | |
| 483 sprintf(s, "%x", va_arg(vargs, int)); | |
| 484 s = s + strlen(s); | |
| 485 break; | |
| 486 case 's': | |
| 487 p = va_arg(vargs, char*); | |
| 488 i = strlen(p); | |
| 489 if (n > 0 && i > n) | |
| 490 i = n; | |
| 491 memcpy(s, p, i); | |
| 492 s = s + i; | |
| 493 break; | |
| 494 case '%': | |
| 495 *s++ = '%'; | |
| 496 break; | |
| 497 default: | |
| 498 strcpy(s, p); | |
| 499 s = s + strlen(s); | |
| 500 goto end; | |
| 501 } | |
| 502 } else | |
| 503 *s++ = *f; | |
| 504 } | |
| 505 | |
| 506 end: | |
| 507 | |
| 508 _PyString_Resize(&string, s - PyString_AsString(string)); | |
| 509 | |
| 510 PyErr_SetObject(exception, string); | 397 PyErr_SetObject(exception, string); |
| 511 Py_XDECREF(string); | 398 Py_XDECREF(string); |
| 512 | 399 |
| 513 return NULL; | 400 return NULL; |
| 514 } | 401 } |
