[Python-Dev] PyErr_SafeFormat

Fredrik Lundh Fredrik Lundh" <effbot@telia.com
Thu, 13 Jul 2000 19:29:30 +0200


greg wrote:
> We don't care about anything except for %d, %s, possibly %c and %x.

how about:

PyObject *
PyErr_SafeFormat(PyObject *exception, const char *format, ...)
{
    va_list vargs;
    int n;
    const char* p;
    char* s;
    PyObject* string;

    /* figure out how large buffer we need */

    va_start(vargs, format);

    n =3D 0;

    for (p =3D format; *p; p++) {
        if (*p =3D=3D '%') {
            while (*++p && *p !=3D '%' && !isalpha(*p))
                ;
            switch (*p) {
            case 'c':
                va_arg(vargs, int);
                /* fall through... */
            case '%':
                n++;
                break;
            case 'd': case 'i': case 'x':
                va_arg(vargs, int);
                n =3D n + 20;
                break;
            case 's':
                s =3D va_arg(vargs, char*);
                n =3D n + strlen(s);
                break;
            default:
                n =3D n + strlen(p);
                goto expand;
            }
        } else
            n =3D n + 1;
    }

  expand:

    string =3D PyString_FromStringAndSize(NULL, n);
    if (!string)
        return NULL;

    /* fill it in */

    va_start(vargs, format);

    s =3D PyString_AsString(string);
    p =3D format;

    for (p =3D format; *p; p++) {
        if (*p =3D=3D '%') {
            while (*++p && *p !=3D '%' && !isalpha(*p))
                ;
            switch (*p) {
            case 'c':
                *s++ =3D va_arg(vargs, int);
                break;
            case 'd': case 'i':
                itoa(va_arg(vargs, int), s, 10);
                s =3D s + strlen(s);
                break;
            case 'x':
                itoa(va_arg(vargs, int), s, 16);
                s =3D s + strlen(s);
                break;
            case 's':
                strcpy(s, va_arg(vargs, char*));
                s =3D s + strlen(s);
                break;
            case '%':
                *s++ =3D '%';
                break;
            default:
                strcpy(s, p-1);
                s =3D s + strlen(s);
                goto end;
            }
        } else
            *s++ =3D *p;
    }

  end:

    _PyString_Resize(&string, s - PyString_AsString(string));

    PyErr_SetObject(exception, string);
    Py_XDECREF(string);

    return NULL;
}

</F>