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 *