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 }