PageRenderTime 142ms CodeModel.GetById 25ms app.highlight 105ms RepoModel.GetById 1ms app.codeStats 1ms

/Objects/exceptions.c

http://unladen-swallow.googlecode.com/
C | 2196 lines | 1629 code | 341 blank | 226 comment | 195 complexity | 684115965b3b5151fa86ff432969f265 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * New exceptions.c written in Iceland by Richard Jones and Georg Brandl.
   3 *
   4 * Thanks go to Tim Peters and Michael Hudson for debugging.
   5 */
   6
   7#define PY_SSIZE_T_CLEAN
   8#include <Python.h>
   9#include "structmember.h"
  10#include "osdefs.h"
  11
  12#define MAKE_IT_NONE(x) (x) = Py_None; Py_INCREF(Py_None);
  13#define EXC_MODULE_NAME "exceptions."
  14
  15/* NOTE: If the exception class hierarchy changes, don't forget to update
  16 * Lib/test/exception_hierarchy.txt
  17 */
  18
  19PyDoc_STRVAR(exceptions_doc, "Python's standard exception class hierarchy.\n\
  20\n\
  21Exceptions found here are defined both in the exceptions module and the\n\
  22built-in namespace.  It is recommended that user-defined exceptions\n\
  23inherit from Exception.  See the documentation for the exception\n\
  24inheritance hierarchy.\n\
  25");
  26
  27/*
  28 *    BaseException
  29 */
  30static PyObject *
  31BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  32{
  33    PyBaseExceptionObject *self;
  34
  35    self = (PyBaseExceptionObject *)type->tp_alloc(type, 0);
  36    if (!self)
  37        return NULL;
  38    /* the dict is created on the fly in PyObject_GenericSetAttr */
  39    self->message = self->dict = NULL;
  40
  41    self->args = PyTuple_New(0);
  42    if (!self->args) {
  43        Py_DECREF(self);
  44        return NULL;
  45    }
  46
  47    self->message = PyString_FromString("");
  48    if (!self->message) {
  49        Py_DECREF(self);
  50        return NULL;
  51    }
  52
  53    return (PyObject *)self;
  54}
  55
  56static int
  57BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds)
  58{
  59    if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
  60        return -1;
  61
  62    Py_DECREF(self->args);
  63    self->args = args;
  64    Py_INCREF(self->args);
  65
  66    if (PyTuple_GET_SIZE(self->args) == 1) {
  67        Py_CLEAR(self->message);
  68        self->message = PyTuple_GET_ITEM(self->args, 0);
  69        Py_INCREF(self->message);
  70    }
  71    return 0;
  72}
  73
  74static int
  75BaseException_clear(PyBaseExceptionObject *self)
  76{
  77    Py_CLEAR(self->dict);
  78    Py_CLEAR(self->args);
  79    Py_CLEAR(self->message);
  80    return 0;
  81}
  82
  83static void
  84BaseException_dealloc(PyBaseExceptionObject *self)
  85{
  86    _PyObject_GC_UNTRACK(self);
  87    BaseException_clear(self);
  88    Py_TYPE(self)->tp_free((PyObject *)self);
  89}
  90
  91static int
  92BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg)
  93{
  94    Py_VISIT(self->dict);
  95    Py_VISIT(self->args);
  96    Py_VISIT(self->message);
  97    return 0;
  98}
  99
 100static PyObject *
 101BaseException_str(PyBaseExceptionObject *self)
 102{
 103    PyObject *out;
 104
 105    switch (PyTuple_GET_SIZE(self->args)) {
 106    case 0:
 107        out = PyString_FromString("");
 108        break;
 109    case 1:
 110        out = PyObject_Str(PyTuple_GET_ITEM(self->args, 0));
 111        break;
 112    default:
 113        out = PyObject_Str(self->args);
 114        break;
 115    }
 116
 117    return out;
 118}
 119
 120#ifdef Py_USING_UNICODE
 121static PyObject *
 122BaseException_unicode(PyBaseExceptionObject *self)
 123{
 124    PyObject *out;
 125
 126    switch (PyTuple_GET_SIZE(self->args)) {
 127    case 0:
 128        out = PyUnicode_FromString("");
 129        break;
 130    case 1:
 131        out = PyObject_Unicode(PyTuple_GET_ITEM(self->args, 0));
 132        break;
 133    default:
 134        out = PyObject_Unicode(self->args);
 135        break;
 136    }
 137
 138    return out;
 139}
 140#endif
 141
 142static PyObject *
 143BaseException_repr(PyBaseExceptionObject *self)
 144{
 145    PyObject *repr_suffix;
 146    PyObject *repr;
 147    char *name;
 148    char *dot;
 149
 150    repr_suffix = PyObject_Repr(self->args);
 151    if (!repr_suffix)
 152        return NULL;
 153
 154    name = (char *)Py_TYPE(self)->tp_name;
 155    dot = strrchr(name, '.');
 156    if (dot != NULL) name = dot+1;
 157
 158    repr = PyString_FromString(name);
 159    if (!repr) {
 160        Py_DECREF(repr_suffix);
 161        return NULL;
 162    }
 163
 164    PyString_ConcatAndDel(&repr, repr_suffix);
 165    return repr;
 166}
 167
 168/* Pickling support */
 169static PyObject *
 170BaseException_reduce(PyBaseExceptionObject *self)
 171{
 172    if (self->args && self->dict)
 173        return PyTuple_Pack(3, Py_TYPE(self), self->args, self->dict);
 174    else
 175        return PyTuple_Pack(2, Py_TYPE(self), self->args);
 176}
 177
 178/*
 179 * Needed for backward compatibility, since exceptions used to store
 180 * all their attributes in the __dict__. Code is taken from cPickle's
 181 * load_build function.
 182 */
 183static PyObject *
 184BaseException_setstate(PyObject *self, PyObject *state)
 185{
 186    PyObject *d_key, *d_value;
 187    Py_ssize_t i = 0;
 188
 189    if (state != Py_None) {
 190        if (!PyDict_Check(state)) {
 191            PyErr_SetString(PyExc_TypeError, "state is not a dictionary");
 192            return NULL;
 193        }
 194        while (PyDict_Next(state, &i, &d_key, &d_value)) {
 195            if (PyObject_SetAttr(self, d_key, d_value) < 0)
 196                return NULL;
 197        }
 198    }
 199    Py_RETURN_NONE;
 200}
 201
 202
 203static PyMethodDef BaseException_methods[] = {
 204   {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS },
 205   {"__setstate__", (PyCFunction)BaseException_setstate, METH_O },
 206#ifdef Py_USING_UNICODE   
 207   {"__unicode__", (PyCFunction)BaseException_unicode, METH_NOARGS },
 208#endif
 209   {NULL, NULL, 0, NULL},
 210};
 211
 212
 213
 214static PyObject *
 215BaseException_getitem(PyBaseExceptionObject *self, Py_ssize_t index)
 216{
 217    if (PyErr_WarnPy3k("__getitem__ not supported for exception "
 218                       "classes in 3.x; use args attribute", 1) < 0)
 219        return NULL;
 220    return PySequence_GetItem(self->args, index);
 221}
 222
 223static PyObject *
 224BaseException_getslice(PyBaseExceptionObject *self,
 225			Py_ssize_t start, Py_ssize_t stop)
 226{
 227    if (PyErr_WarnPy3k("__getslice__ not supported for exception "
 228                       "classes in 3.x; use args attribute", 1) < 0)
 229        return NULL;
 230    return PySequence_GetSlice(self->args, start, stop);
 231}
 232
 233static PySequenceMethods BaseException_as_sequence = {
 234    0,                      /* sq_length; */
 235    0,                      /* sq_concat; */
 236    0,                      /* sq_repeat; */
 237    (ssizeargfunc)BaseException_getitem,  /* sq_item; */
 238    (ssizessizeargfunc)BaseException_getslice,  /* sq_slice; */
 239    0,                      /* sq_ass_item; */
 240    0,                      /* sq_ass_slice; */
 241    0,                      /* sq_contains; */
 242    0,                      /* sq_inplace_concat; */
 243    0                       /* sq_inplace_repeat; */
 244};
 245
 246static PyObject *
 247BaseException_get_dict(PyBaseExceptionObject *self)
 248{
 249    if (self->dict == NULL) {
 250        self->dict = PyDict_New();
 251        if (!self->dict)
 252            return NULL;
 253    }
 254    Py_INCREF(self->dict);
 255    return self->dict;
 256}
 257
 258static int
 259BaseException_set_dict(PyBaseExceptionObject *self, PyObject *val)
 260{
 261    if (val == NULL) {
 262        PyErr_SetString(PyExc_TypeError, "__dict__ may not be deleted");
 263        return -1;
 264    }
 265    if (!PyDict_Check(val)) {
 266        PyErr_SetString(PyExc_TypeError, "__dict__ must be a dictionary");
 267        return -1;
 268    }
 269    Py_CLEAR(self->dict);
 270    Py_INCREF(val);
 271    self->dict = val;
 272    return 0;
 273}
 274
 275static PyObject *
 276BaseException_get_args(PyBaseExceptionObject *self)
 277{
 278    if (self->args == NULL) {
 279        Py_INCREF(Py_None);
 280        return Py_None;
 281    }
 282    Py_INCREF(self->args);
 283    return self->args;
 284}
 285
 286static int
 287BaseException_set_args(PyBaseExceptionObject *self, PyObject *val)
 288{
 289    PyObject *seq;
 290    if (val == NULL) {
 291        PyErr_SetString(PyExc_TypeError, "args may not be deleted");
 292        return -1;
 293    }
 294    seq = PySequence_Tuple(val);
 295    if (!seq) return -1;
 296    Py_CLEAR(self->args);
 297    self->args = seq;
 298    return 0;
 299}
 300
 301static PyObject *
 302BaseException_get_message(PyBaseExceptionObject *self)
 303{
 304    PyObject *msg;
 305    
 306    /* if "message" is in self->dict, accessing a user-set message attribute */
 307    if (self->dict &&
 308        (msg = PyDict_GetItemString(self->dict, "message"))) {
 309        Py_INCREF(msg);
 310        return msg;
 311    }
 312
 313    if (self->message == NULL) {
 314        PyErr_SetString(PyExc_AttributeError, "message attribute was deleted");
 315        return NULL;
 316    }
 317
 318    /* accessing the deprecated "builtin" message attribute of Exception */
 319    if (PyErr_WarnEx(PyExc_DeprecationWarning,
 320                     "BaseException.message has been deprecated as "
 321                     "of Python 2.6", 1) < 0)
 322        return NULL;
 323
 324    Py_INCREF(self->message);
 325    return self->message;
 326}
 327
 328static int
 329BaseException_set_message(PyBaseExceptionObject *self, PyObject *val)
 330{
 331    /* if val is NULL, delete the message attribute */
 332    if (val == NULL) {
 333        if (self->dict && PyDict_GetItemString(self->dict, "message")) {
 334            if (PyDict_DelItemString(self->dict, "message") < 0)
 335                return -1;
 336        }
 337        Py_XDECREF(self->message);
 338        self->message = NULL;
 339        return 0;
 340    }
 341    
 342    /* else set it in __dict__, but may need to create the dict first */
 343    if (self->dict == NULL) {
 344        self->dict = PyDict_New();
 345        if (!self->dict)
 346            return -1;
 347    }
 348    return PyDict_SetItemString(self->dict, "message", val);
 349}
 350
 351static PyGetSetDef BaseException_getset[] = {
 352    {"__dict__", (getter)BaseException_get_dict, (setter)BaseException_set_dict},
 353    {"args", (getter)BaseException_get_args, (setter)BaseException_set_args},
 354    {"message", (getter)BaseException_get_message,
 355	    (setter)BaseException_set_message},
 356    {NULL},
 357};
 358
 359
 360static PyTypeObject _PyExc_BaseException = {
 361    PyObject_HEAD_INIT(NULL)
 362    0,                          /*ob_size*/
 363    EXC_MODULE_NAME "BaseException", /*tp_name*/
 364    sizeof(PyBaseExceptionObject), /*tp_basicsize*/
 365    0,                          /*tp_itemsize*/
 366    (destructor)BaseException_dealloc, /*tp_dealloc*/
 367    0,                          /*tp_print*/
 368    0,                          /*tp_getattr*/
 369    0,                          /*tp_setattr*/
 370    0,                          /* tp_compare; */
 371    (reprfunc)BaseException_repr, /*tp_repr*/
 372    0,                          /*tp_as_number*/
 373    &BaseException_as_sequence, /*tp_as_sequence*/
 374    0,                          /*tp_as_mapping*/
 375    0,                          /*tp_hash */
 376    0,                          /*tp_call*/
 377    (reprfunc)BaseException_str,  /*tp_str*/
 378    PyObject_GenericGetAttr,    /*tp_getattro*/
 379    PyObject_GenericSetAttr,    /*tp_setattro*/
 380    0,                          /*tp_as_buffer*/
 381    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
 382    	Py_TPFLAGS_BASE_EXC_SUBCLASS,  /*tp_flags*/
 383    PyDoc_STR("Common base class for all exceptions"), /* tp_doc */
 384    (traverseproc)BaseException_traverse, /* tp_traverse */
 385    (inquiry)BaseException_clear, /* tp_clear */
 386    0,                          /* tp_richcompare */
 387    0,                          /* tp_weaklistoffset */
 388    0,                          /* tp_iter */
 389    0,                          /* tp_iternext */
 390    BaseException_methods,      /* tp_methods */
 391    0,                          /* tp_members */
 392    BaseException_getset,       /* tp_getset */
 393    0,                          /* tp_base */
 394    0,                          /* tp_dict */
 395    0,                          /* tp_descr_get */
 396    0,                          /* tp_descr_set */
 397    offsetof(PyBaseExceptionObject, dict), /* tp_dictoffset */
 398    (initproc)BaseException_init, /* tp_init */
 399    0,                          /* tp_alloc */
 400    BaseException_new,          /* tp_new */
 401};
 402/* the CPython API expects exceptions to be (PyObject *) - both a hold-over
 403from the previous implmentation and also allowing Python objects to be used
 404in the API */
 405PyObject *PyExc_BaseException = (PyObject *)&_PyExc_BaseException;
 406
 407/* note these macros omit the last semicolon so the macro invocation may
 408 * include it and not look strange.
 409 */
 410#define SimpleExtendsException(EXCBASE, EXCNAME, EXCDOC) \
 411static PyTypeObject _PyExc_ ## EXCNAME = { \
 412    PyObject_HEAD_INIT(NULL) \
 413    0, \
 414    EXC_MODULE_NAME # EXCNAME, \
 415    sizeof(PyBaseExceptionObject), \
 416    0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, \
 417    0, 0, 0, 0, 0, 0, 0, \
 418    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
 419    PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \
 420    (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \
 421    0, 0, 0, offsetof(PyBaseExceptionObject, dict), \
 422    (initproc)BaseException_init, 0, BaseException_new,\
 423}; \
 424PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
 425
 426#define MiddlingExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDOC) \
 427static PyTypeObject _PyExc_ ## EXCNAME = { \
 428    PyObject_HEAD_INIT(NULL) \
 429    0, \
 430    EXC_MODULE_NAME # EXCNAME, \
 431    sizeof(Py ## EXCSTORE ## Object), \
 432    0, (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
 433    0, 0, 0, 0, 0, \
 434    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
 435    PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
 436    (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \
 437    0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \
 438    (initproc)EXCSTORE ## _init, 0, BaseException_new,\
 439}; \
 440PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
 441
 442#define ComplexExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDEALLOC, EXCMETHODS, EXCMEMBERS, EXCSTR, EXCDOC) \
 443static PyTypeObject _PyExc_ ## EXCNAME = { \
 444    PyObject_HEAD_INIT(NULL) \
 445    0, \
 446    EXC_MODULE_NAME # EXCNAME, \
 447    sizeof(Py ## EXCSTORE ## Object), 0, \
 448    (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
 449    (reprfunc)EXCSTR, 0, 0, 0, \
 450    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
 451    PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
 452    (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \
 453    EXCMEMBERS, 0, &_ ## EXCBASE, \
 454    0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \
 455    (initproc)EXCSTORE ## _init, 0, BaseException_new,\
 456}; \
 457PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
 458
 459
 460/*
 461 *    Exception extends BaseException
 462 */
 463SimpleExtendsException(PyExc_BaseException, Exception,
 464                       "Common base class for all non-exit exceptions.");
 465
 466
 467/*
 468 *    StandardError extends Exception
 469 */
 470SimpleExtendsException(PyExc_Exception, StandardError,
 471    "Base class for all standard Python exceptions that do not represent\n"
 472    "interpreter exiting.");
 473
 474
 475/*
 476 *    TypeError extends StandardError
 477 */
 478SimpleExtendsException(PyExc_StandardError, TypeError,
 479                       "Inappropriate argument type.");
 480
 481
 482/*
 483 *    StopIteration extends Exception
 484 */
 485SimpleExtendsException(PyExc_Exception, StopIteration,
 486                       "Signal the end from iterator.next().");
 487
 488
 489/*
 490 *    GeneratorExit extends BaseException
 491 */
 492SimpleExtendsException(PyExc_BaseException, GeneratorExit,
 493                       "Request that a generator exit.");
 494
 495
 496/*
 497 *    SystemExit extends BaseException
 498 */
 499
 500static int
 501SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds)
 502{
 503    Py_ssize_t size = PyTuple_GET_SIZE(args);
 504
 505    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
 506        return -1;
 507
 508    if (size == 0)
 509        return 0;
 510    Py_CLEAR(self->code);
 511    if (size == 1)
 512        self->code = PyTuple_GET_ITEM(args, 0);
 513    else if (size > 1)
 514        self->code = args;
 515    Py_INCREF(self->code);
 516    return 0;
 517}
 518
 519static int
 520SystemExit_clear(PySystemExitObject *self)
 521{
 522    Py_CLEAR(self->code);
 523    return BaseException_clear((PyBaseExceptionObject *)self);
 524}
 525
 526static void
 527SystemExit_dealloc(PySystemExitObject *self)
 528{
 529    _PyObject_GC_UNTRACK(self);
 530    SystemExit_clear(self);
 531    Py_TYPE(self)->tp_free((PyObject *)self);
 532}
 533
 534static int
 535SystemExit_traverse(PySystemExitObject *self, visitproc visit, void *arg)
 536{
 537    Py_VISIT(self->code);
 538    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
 539}
 540
 541static PyMemberDef SystemExit_members[] = {
 542    {"code", T_OBJECT, offsetof(PySystemExitObject, code), 0,
 543        PyDoc_STR("exception code")},
 544    {NULL}  /* Sentinel */
 545};
 546
 547ComplexExtendsException(PyExc_BaseException, SystemExit, SystemExit,
 548                        SystemExit_dealloc, 0, SystemExit_members, 0,
 549                        "Request to exit from the interpreter.");
 550
 551/*
 552 *    KeyboardInterrupt extends BaseException
 553 */
 554SimpleExtendsException(PyExc_BaseException, KeyboardInterrupt,
 555                       "Program interrupted by user.");
 556
 557
 558/*
 559 *    ImportError extends StandardError
 560 */
 561SimpleExtendsException(PyExc_StandardError, ImportError,
 562          "Import can't find module, or can't find name in module.");
 563
 564
 565/*
 566 *    EnvironmentError extends StandardError
 567 */
 568
 569/* Where a function has a single filename, such as open() or some
 570 * of the os module functions, PyErr_SetFromErrnoWithFilename() is
 571 * called, giving a third argument which is the filename.  But, so
 572 * that old code using in-place unpacking doesn't break, e.g.:
 573 *
 574 * except IOError, (errno, strerror):
 575 *
 576 * we hack args so that it only contains two items.  This also
 577 * means we need our own __str__() which prints out the filename
 578 * when it was supplied.
 579 */
 580static int
 581EnvironmentError_init(PyEnvironmentErrorObject *self, PyObject *args,
 582    PyObject *kwds)
 583{
 584    PyObject *myerrno = NULL, *strerror = NULL, *filename = NULL;
 585    PyObject *subslice = NULL;
 586
 587    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
 588        return -1;
 589
 590    if (PyTuple_GET_SIZE(args) <= 1 || PyTuple_GET_SIZE(args) > 3) {
 591        return 0;
 592    }
 593
 594    if (!PyArg_UnpackTuple(args, "EnvironmentError", 2, 3,
 595                           &myerrno, &strerror, &filename)) {
 596        return -1;
 597    }
 598    Py_CLEAR(self->myerrno);       /* replacing */
 599    self->myerrno = myerrno;
 600    Py_INCREF(self->myerrno);
 601
 602    Py_CLEAR(self->strerror);      /* replacing */
 603    self->strerror = strerror;
 604    Py_INCREF(self->strerror);
 605
 606    /* self->filename will remain Py_None otherwise */
 607    if (filename != NULL) {
 608        Py_CLEAR(self->filename);      /* replacing */
 609        self->filename = filename;
 610        Py_INCREF(self->filename);
 611
 612        subslice = PyTuple_GetSlice(args, 0, 2);
 613        if (!subslice)
 614            return -1;
 615
 616        Py_DECREF(self->args);  /* replacing args */
 617        self->args = subslice;
 618    }
 619    return 0;
 620}
 621
 622static int
 623EnvironmentError_clear(PyEnvironmentErrorObject *self)
 624{
 625    Py_CLEAR(self->myerrno);
 626    Py_CLEAR(self->strerror);
 627    Py_CLEAR(self->filename);
 628    return BaseException_clear((PyBaseExceptionObject *)self);
 629}
 630
 631static void
 632EnvironmentError_dealloc(PyEnvironmentErrorObject *self)
 633{
 634    _PyObject_GC_UNTRACK(self);
 635    EnvironmentError_clear(self);
 636    Py_TYPE(self)->tp_free((PyObject *)self);
 637}
 638
 639static int
 640EnvironmentError_traverse(PyEnvironmentErrorObject *self, visitproc visit,
 641        void *arg)
 642{
 643    Py_VISIT(self->myerrno);
 644    Py_VISIT(self->strerror);
 645    Py_VISIT(self->filename);
 646    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
 647}
 648
 649static PyObject *
 650EnvironmentError_str(PyEnvironmentErrorObject *self)
 651{
 652    PyObject *rtnval = NULL;
 653
 654    if (self->filename) {
 655        PyObject *fmt;
 656        PyObject *repr;
 657        PyObject *tuple;
 658
 659        fmt = PyString_FromString("[Errno %s] %s: %s");
 660        if (!fmt)
 661            return NULL;
 662
 663        repr = PyObject_Repr(self->filename);
 664        if (!repr) {
 665            Py_DECREF(fmt);
 666            return NULL;
 667        }
 668        tuple = PyTuple_New(3);
 669        if (!tuple) {
 670            Py_DECREF(repr);
 671            Py_DECREF(fmt);
 672            return NULL;
 673        }
 674
 675        if (self->myerrno) {
 676            Py_INCREF(self->myerrno);
 677            PyTuple_SET_ITEM(tuple, 0, self->myerrno);
 678        }
 679        else {
 680            Py_INCREF(Py_None);
 681            PyTuple_SET_ITEM(tuple, 0, Py_None);
 682        }
 683        if (self->strerror) {
 684            Py_INCREF(self->strerror);
 685            PyTuple_SET_ITEM(tuple, 1, self->strerror);
 686        }
 687        else {
 688            Py_INCREF(Py_None);
 689            PyTuple_SET_ITEM(tuple, 1, Py_None);
 690        }
 691
 692        PyTuple_SET_ITEM(tuple, 2, repr);
 693
 694        rtnval = PyString_Format(fmt, tuple);
 695
 696        Py_DECREF(fmt);
 697        Py_DECREF(tuple);
 698    }
 699    else if (self->myerrno && self->strerror) {
 700        PyObject *fmt;
 701        PyObject *tuple;
 702
 703        fmt = PyString_FromString("[Errno %s] %s");
 704        if (!fmt)
 705            return NULL;
 706
 707        tuple = PyTuple_New(2);
 708        if (!tuple) {
 709            Py_DECREF(fmt);
 710            return NULL;
 711        }
 712
 713        if (self->myerrno) {
 714            Py_INCREF(self->myerrno);
 715            PyTuple_SET_ITEM(tuple, 0, self->myerrno);
 716        }
 717        else {
 718            Py_INCREF(Py_None);
 719            PyTuple_SET_ITEM(tuple, 0, Py_None);
 720        }
 721        if (self->strerror) {
 722            Py_INCREF(self->strerror);
 723            PyTuple_SET_ITEM(tuple, 1, self->strerror);
 724        }
 725        else {
 726            Py_INCREF(Py_None);
 727            PyTuple_SET_ITEM(tuple, 1, Py_None);
 728        }
 729
 730        rtnval = PyString_Format(fmt, tuple);
 731
 732        Py_DECREF(fmt);
 733        Py_DECREF(tuple);
 734    }
 735    else
 736        rtnval = BaseException_str((PyBaseExceptionObject *)self);
 737
 738    return rtnval;
 739}
 740
 741static PyMemberDef EnvironmentError_members[] = {
 742    {"errno", T_OBJECT, offsetof(PyEnvironmentErrorObject, myerrno), 0,
 743        PyDoc_STR("exception errno")},
 744    {"strerror", T_OBJECT, offsetof(PyEnvironmentErrorObject, strerror), 0,
 745        PyDoc_STR("exception strerror")},
 746    {"filename", T_OBJECT, offsetof(PyEnvironmentErrorObject, filename), 0,
 747        PyDoc_STR("exception filename")},
 748    {NULL}  /* Sentinel */
 749};
 750
 751
 752static PyObject *
 753EnvironmentError_reduce(PyEnvironmentErrorObject *self)
 754{
 755    PyObject *args = self->args;
 756    PyObject *res = NULL, *tmp;
 757
 758    /* self->args is only the first two real arguments if there was a
 759     * file name given to EnvironmentError. */
 760    if (PyTuple_GET_SIZE(args) == 2 && self->filename) {
 761        args = PyTuple_New(3);
 762        if (!args) return NULL;
 763
 764        tmp = PyTuple_GET_ITEM(self->args, 0);
 765        Py_INCREF(tmp);
 766        PyTuple_SET_ITEM(args, 0, tmp);
 767
 768        tmp = PyTuple_GET_ITEM(self->args, 1);
 769        Py_INCREF(tmp);
 770        PyTuple_SET_ITEM(args, 1, tmp);
 771
 772        Py_INCREF(self->filename);
 773        PyTuple_SET_ITEM(args, 2, self->filename);
 774    } else
 775        Py_INCREF(args);
 776
 777    if (self->dict)
 778        res = PyTuple_Pack(3, Py_TYPE(self), args, self->dict);
 779    else
 780        res = PyTuple_Pack(2, Py_TYPE(self), args);
 781    Py_DECREF(args);
 782    return res;
 783}
 784
 785
 786static PyMethodDef EnvironmentError_methods[] = {
 787    {"__reduce__", (PyCFunction)EnvironmentError_reduce, METH_NOARGS},
 788    {NULL}
 789};
 790
 791ComplexExtendsException(PyExc_StandardError, EnvironmentError,
 792                        EnvironmentError, EnvironmentError_dealloc,
 793                        EnvironmentError_methods, EnvironmentError_members,
 794                        EnvironmentError_str,
 795                        "Base class for I/O related errors.");
 796
 797
 798/*
 799 *    IOError extends EnvironmentError
 800 */
 801MiddlingExtendsException(PyExc_EnvironmentError, IOError,
 802                         EnvironmentError, "I/O operation failed.");
 803
 804
 805/*
 806 *    OSError extends EnvironmentError
 807 */
 808MiddlingExtendsException(PyExc_EnvironmentError, OSError,
 809                         EnvironmentError, "OS system call failed.");
 810
 811
 812/*
 813 *    WindowsError extends OSError
 814 */
 815#ifdef MS_WINDOWS
 816#include "errmap.h"
 817
 818static int
 819WindowsError_clear(PyWindowsErrorObject *self)
 820{
 821    Py_CLEAR(self->myerrno);
 822    Py_CLEAR(self->strerror);
 823    Py_CLEAR(self->filename);
 824    Py_CLEAR(self->winerror);
 825    return BaseException_clear((PyBaseExceptionObject *)self);
 826}
 827
 828static void
 829WindowsError_dealloc(PyWindowsErrorObject *self)
 830{
 831    _PyObject_GC_UNTRACK(self);
 832    WindowsError_clear(self);
 833    Py_TYPE(self)->tp_free((PyObject *)self);
 834}
 835
 836static int
 837WindowsError_traverse(PyWindowsErrorObject *self, visitproc visit, void *arg)
 838{
 839    Py_VISIT(self->myerrno);
 840    Py_VISIT(self->strerror);
 841    Py_VISIT(self->filename);
 842    Py_VISIT(self->winerror);
 843    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
 844}
 845
 846static int
 847WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds)
 848{
 849    PyObject *o_errcode = NULL;
 850    long errcode;
 851    long posix_errno;
 852
 853    if (EnvironmentError_init((PyEnvironmentErrorObject *)self, args, kwds)
 854            == -1)
 855        return -1;
 856
 857    if (self->myerrno == NULL)
 858        return 0;
 859
 860    /* Set errno to the POSIX errno, and winerror to the Win32
 861       error code. */
 862    errcode = PyInt_AsLong(self->myerrno);
 863    if (errcode == -1 && PyErr_Occurred())
 864        return -1;
 865    posix_errno = winerror_to_errno(errcode);
 866
 867    Py_CLEAR(self->winerror);
 868    self->winerror = self->myerrno;
 869
 870    o_errcode = PyInt_FromLong(posix_errno);
 871    if (!o_errcode)
 872        return -1;
 873
 874    self->myerrno = o_errcode;
 875
 876    return 0;
 877}
 878
 879
 880static PyObject *
 881WindowsError_str(PyWindowsErrorObject *self)
 882{
 883    PyObject *rtnval = NULL;
 884
 885    if (self->filename) {
 886        PyObject *fmt;
 887        PyObject *repr;
 888        PyObject *tuple;
 889
 890        fmt = PyString_FromString("[Error %s] %s: %s");
 891        if (!fmt)
 892            return NULL;
 893
 894        repr = PyObject_Repr(self->filename);
 895        if (!repr) {
 896            Py_DECREF(fmt);
 897            return NULL;
 898        }
 899        tuple = PyTuple_New(3);
 900        if (!tuple) {
 901            Py_DECREF(repr);
 902            Py_DECREF(fmt);
 903            return NULL;
 904        }
 905
 906        if (self->winerror) {
 907            Py_INCREF(self->winerror);
 908            PyTuple_SET_ITEM(tuple, 0, self->winerror);
 909        }
 910        else {
 911            Py_INCREF(Py_None);
 912            PyTuple_SET_ITEM(tuple, 0, Py_None);
 913        }
 914        if (self->strerror) {
 915            Py_INCREF(self->strerror);
 916            PyTuple_SET_ITEM(tuple, 1, self->strerror);
 917        }
 918        else {
 919            Py_INCREF(Py_None);
 920            PyTuple_SET_ITEM(tuple, 1, Py_None);
 921        }
 922
 923        PyTuple_SET_ITEM(tuple, 2, repr);
 924
 925        rtnval = PyString_Format(fmt, tuple);
 926
 927        Py_DECREF(fmt);
 928        Py_DECREF(tuple);
 929    }
 930    else if (self->winerror && self->strerror) {
 931        PyObject *fmt;
 932        PyObject *tuple;
 933
 934        fmt = PyString_FromString("[Error %s] %s");
 935        if (!fmt)
 936            return NULL;
 937
 938        tuple = PyTuple_New(2);
 939        if (!tuple) {
 940            Py_DECREF(fmt);
 941            return NULL;
 942        }
 943
 944        if (self->winerror) {
 945            Py_INCREF(self->winerror);
 946            PyTuple_SET_ITEM(tuple, 0, self->winerror);
 947        }
 948        else {
 949            Py_INCREF(Py_None);
 950            PyTuple_SET_ITEM(tuple, 0, Py_None);
 951        }
 952        if (self->strerror) {
 953            Py_INCREF(self->strerror);
 954            PyTuple_SET_ITEM(tuple, 1, self->strerror);
 955        }
 956        else {
 957            Py_INCREF(Py_None);
 958            PyTuple_SET_ITEM(tuple, 1, Py_None);
 959        }
 960
 961        rtnval = PyString_Format(fmt, tuple);
 962
 963        Py_DECREF(fmt);
 964        Py_DECREF(tuple);
 965    }
 966    else
 967        rtnval = EnvironmentError_str((PyEnvironmentErrorObject *)self);
 968
 969    return rtnval;
 970}
 971
 972static PyMemberDef WindowsError_members[] = {
 973    {"errno", T_OBJECT, offsetof(PyWindowsErrorObject, myerrno), 0,
 974        PyDoc_STR("POSIX exception code")},
 975    {"strerror", T_OBJECT, offsetof(PyWindowsErrorObject, strerror), 0,
 976        PyDoc_STR("exception strerror")},
 977    {"filename", T_OBJECT, offsetof(PyWindowsErrorObject, filename), 0,
 978        PyDoc_STR("exception filename")},
 979    {"winerror", T_OBJECT, offsetof(PyWindowsErrorObject, winerror), 0,
 980        PyDoc_STR("Win32 exception code")},
 981    {NULL}  /* Sentinel */
 982};
 983
 984ComplexExtendsException(PyExc_OSError, WindowsError, WindowsError,
 985                        WindowsError_dealloc, 0, WindowsError_members,
 986                        WindowsError_str, "MS-Windows OS system call failed.");
 987
 988#endif /* MS_WINDOWS */
 989
 990
 991/*
 992 *    VMSError extends OSError (I think)
 993 */
 994#ifdef __VMS
 995MiddlingExtendsException(PyExc_OSError, VMSError, EnvironmentError,
 996                         "OpenVMS OS system call failed.");
 997#endif
 998
 999
1000/*
1001 *    EOFError extends StandardError
1002 */
1003SimpleExtendsException(PyExc_StandardError, EOFError,
1004                       "Read beyond end of file.");
1005
1006
1007/*
1008 *    RuntimeError extends StandardError
1009 */
1010SimpleExtendsException(PyExc_StandardError, RuntimeError,
1011                       "Unspecified run-time error.");
1012
1013
1014/*
1015 *    NotImplementedError extends RuntimeError
1016 */
1017SimpleExtendsException(PyExc_RuntimeError, NotImplementedError,
1018                       "Method or function hasn't been implemented yet.");
1019
1020/*
1021 *    NameError extends StandardError
1022 */
1023SimpleExtendsException(PyExc_StandardError, NameError,
1024                       "Name not found globally.");
1025
1026/*
1027 *    UnboundLocalError extends NameError
1028 */
1029SimpleExtendsException(PyExc_NameError, UnboundLocalError,
1030                       "Local name referenced but not bound to a value.");
1031
1032/*
1033 *    AttributeError extends StandardError
1034 */
1035SimpleExtendsException(PyExc_StandardError, AttributeError,
1036                       "Attribute not found.");
1037
1038
1039/*
1040 *    SyntaxError extends StandardError
1041 */
1042
1043static int
1044SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
1045{
1046    PyObject *info = NULL;
1047    Py_ssize_t lenargs = PyTuple_GET_SIZE(args);
1048
1049    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
1050        return -1;
1051
1052    if (lenargs >= 1) {
1053        Py_CLEAR(self->msg);
1054        self->msg = PyTuple_GET_ITEM(args, 0);
1055        Py_INCREF(self->msg);
1056    }
1057    if (lenargs == 2) {
1058        info = PyTuple_GET_ITEM(args, 1);
1059        info = PySequence_Tuple(info);
1060        if (!info) return -1;
1061
1062        if (PyTuple_GET_SIZE(info) != 4) {
1063            /* not a very good error message, but it's what Python 2.4 gives */
1064            PyErr_SetString(PyExc_IndexError, "tuple index out of range");
1065            Py_DECREF(info);
1066            return -1;
1067        }
1068
1069        Py_CLEAR(self->filename);
1070        self->filename = PyTuple_GET_ITEM(info, 0);
1071        Py_INCREF(self->filename);
1072
1073        Py_CLEAR(self->lineno);
1074        self->lineno = PyTuple_GET_ITEM(info, 1);
1075        Py_INCREF(self->lineno);
1076
1077        Py_CLEAR(self->offset);
1078        self->offset = PyTuple_GET_ITEM(info, 2);
1079        Py_INCREF(self->offset);
1080
1081        Py_CLEAR(self->text);
1082        self->text = PyTuple_GET_ITEM(info, 3);
1083        Py_INCREF(self->text);
1084
1085        Py_DECREF(info);
1086    }
1087    return 0;
1088}
1089
1090static int
1091SyntaxError_clear(PySyntaxErrorObject *self)
1092{
1093    Py_CLEAR(self->msg);
1094    Py_CLEAR(self->filename);
1095    Py_CLEAR(self->lineno);
1096    Py_CLEAR(self->offset);
1097    Py_CLEAR(self->text);
1098    Py_CLEAR(self->print_file_and_line);
1099    return BaseException_clear((PyBaseExceptionObject *)self);
1100}
1101
1102static void
1103SyntaxError_dealloc(PySyntaxErrorObject *self)
1104{
1105    _PyObject_GC_UNTRACK(self);
1106    SyntaxError_clear(self);
1107    Py_TYPE(self)->tp_free((PyObject *)self);
1108}
1109
1110static int
1111SyntaxError_traverse(PySyntaxErrorObject *self, visitproc visit, void *arg)
1112{
1113    Py_VISIT(self->msg);
1114    Py_VISIT(self->filename);
1115    Py_VISIT(self->lineno);
1116    Py_VISIT(self->offset);
1117    Py_VISIT(self->text);
1118    Py_VISIT(self->print_file_and_line);
1119    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
1120}
1121
1122/* This is called "my_basename" instead of just "basename" to avoid name
1123   conflicts with glibc; basename is already prototyped if _GNU_SOURCE is
1124   defined, and Python does define that. */
1125static char *
1126my_basename(char *name)
1127{
1128    char *cp = name;
1129    char *result = name;
1130
1131    if (name == NULL)
1132        return "???";
1133    while (*cp != '\0') {
1134        if (*cp == SEP)
1135            result = cp + 1;
1136        ++cp;
1137    }
1138    return result;
1139}
1140
1141
1142static PyObject *
1143SyntaxError_str(PySyntaxErrorObject *self)
1144{
1145    PyObject *str;
1146    PyObject *result;
1147    int have_filename = 0;
1148    int have_lineno = 0;
1149    char *buffer = NULL;
1150    Py_ssize_t bufsize;
1151
1152    if (self->msg)
1153        str = PyObject_Str(self->msg);
1154    else
1155        str = PyObject_Str(Py_None);
1156    if (!str) return NULL;
1157    /* Don't fiddle with non-string return (shouldn't happen anyway) */
1158    if (!PyString_Check(str)) return str;
1159
1160    /* XXX -- do all the additional formatting with filename and
1161       lineno here */
1162
1163    have_filename = (self->filename != NULL) &&
1164        PyString_Check(self->filename);
1165    have_lineno = (self->lineno != NULL) && PyInt_Check(self->lineno);
1166
1167    if (!have_filename && !have_lineno)
1168        return str;
1169
1170    bufsize = PyString_GET_SIZE(str) + 64;
1171    if (have_filename)
1172        bufsize += PyString_GET_SIZE(self->filename);
1173
1174    buffer = PyMem_MALLOC(bufsize);
1175    if (buffer == NULL)
1176        return str;
1177
1178    if (have_filename && have_lineno)
1179        PyOS_snprintf(buffer, bufsize, "%s (%s, line %ld)",
1180            PyString_AS_STRING(str),
1181            my_basename(PyString_AS_STRING(self->filename)),
1182            PyInt_AsLong(self->lineno));
1183    else if (have_filename)
1184        PyOS_snprintf(buffer, bufsize, "%s (%s)",
1185            PyString_AS_STRING(str),
1186            my_basename(PyString_AS_STRING(self->filename)));
1187    else /* only have_lineno */
1188        PyOS_snprintf(buffer, bufsize, "%s (line %ld)",
1189            PyString_AS_STRING(str),
1190            PyInt_AsLong(self->lineno));
1191
1192    result = PyString_FromString(buffer);
1193    PyMem_FREE(buffer);
1194
1195    if (result == NULL)
1196        result = str;
1197    else
1198        Py_DECREF(str);
1199    return result;
1200}
1201
1202static PyMemberDef SyntaxError_members[] = {
1203    {"msg", T_OBJECT, offsetof(PySyntaxErrorObject, msg), 0,
1204        PyDoc_STR("exception msg")},
1205    {"filename", T_OBJECT, offsetof(PySyntaxErrorObject, filename), 0,
1206        PyDoc_STR("exception filename")},
1207    {"lineno", T_OBJECT, offsetof(PySyntaxErrorObject, lineno), 0,
1208        PyDoc_STR("exception lineno")},
1209    {"offset", T_OBJECT, offsetof(PySyntaxErrorObject, offset), 0,
1210        PyDoc_STR("exception offset")},
1211    {"text", T_OBJECT, offsetof(PySyntaxErrorObject, text), 0,
1212        PyDoc_STR("exception text")},
1213    {"print_file_and_line", T_OBJECT,
1214        offsetof(PySyntaxErrorObject, print_file_and_line), 0,
1215        PyDoc_STR("exception print_file_and_line")},
1216    {NULL}  /* Sentinel */
1217};
1218
1219ComplexExtendsException(PyExc_StandardError, SyntaxError, SyntaxError,
1220                        SyntaxError_dealloc, 0, SyntaxError_members,
1221                        SyntaxError_str, "Invalid syntax.");
1222
1223
1224/*
1225 *    IndentationError extends SyntaxError
1226 */
1227MiddlingExtendsException(PyExc_SyntaxError, IndentationError, SyntaxError,
1228                         "Improper indentation.");
1229
1230
1231/*
1232 *    TabError extends IndentationError
1233 */
1234MiddlingExtendsException(PyExc_IndentationError, TabError, SyntaxError,
1235                         "Improper mixture of spaces and tabs.");
1236
1237
1238/*
1239 *    LookupError extends StandardError
1240 */
1241SimpleExtendsException(PyExc_StandardError, LookupError,
1242                       "Base class for lookup errors.");
1243
1244
1245/*
1246 *    IndexError extends LookupError
1247 */
1248SimpleExtendsException(PyExc_LookupError, IndexError,
1249                       "Sequence index out of range.");
1250
1251
1252/*
1253 *    KeyError extends LookupError
1254 */
1255static PyObject *
1256KeyError_str(PyBaseExceptionObject *self)
1257{
1258    /* If args is a tuple of exactly one item, apply repr to args[0].
1259       This is done so that e.g. the exception raised by {}[''] prints
1260         KeyError: ''
1261       rather than the confusing
1262         KeyError
1263       alone.  The downside is that if KeyError is raised with an explanatory
1264       string, that string will be displayed in quotes.  Too bad.
1265       If args is anything else, use the default BaseException__str__().
1266    */
1267    if (PyTuple_GET_SIZE(self->args) == 1) {
1268        return PyObject_Repr(PyTuple_GET_ITEM(self->args, 0));
1269    }
1270    return BaseException_str(self);
1271}
1272
1273ComplexExtendsException(PyExc_LookupError, KeyError, BaseException,
1274                        0, 0, 0, KeyError_str, "Mapping key not found.");
1275
1276
1277/*
1278 *    ValueError extends StandardError
1279 */
1280SimpleExtendsException(PyExc_StandardError, ValueError,
1281                       "Inappropriate argument value (of correct type).");
1282
1283/*
1284 *    UnicodeError extends ValueError
1285 */
1286
1287SimpleExtendsException(PyExc_ValueError, UnicodeError,
1288                       "Unicode related error.");
1289
1290#ifdef Py_USING_UNICODE
1291static PyObject *
1292get_string(PyObject *attr, const char *name)
1293{
1294    if (!attr) {
1295        PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);
1296        return NULL;
1297    }
1298
1299    if (!PyString_Check(attr)) {
1300        PyErr_Format(PyExc_TypeError, "%.200s attribute must be str", name);
1301        return NULL;
1302    }
1303    Py_INCREF(attr);
1304    return attr;
1305}
1306
1307
1308static int
1309set_string(PyObject **attr, const char *value)
1310{
1311    PyObject *obj = PyString_FromString(value);
1312    if (!obj)
1313        return -1;
1314    Py_CLEAR(*attr);
1315    *attr = obj;
1316    return 0;
1317}
1318
1319
1320static PyObject *
1321get_unicode(PyObject *attr, const char *name)
1322{
1323    if (!attr) {
1324        PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);
1325        return NULL;
1326    }
1327
1328    if (!PyUnicode_Check(attr)) {
1329        PyErr_Format(PyExc_TypeError,
1330                     "%.200s attribute must be unicode", name);
1331        return NULL;
1332    }
1333    Py_INCREF(attr);
1334    return attr;
1335}
1336
1337PyObject *
1338PyUnicodeEncodeError_GetEncoding(PyObject *exc)
1339{
1340    return get_string(((PyUnicodeErrorObject *)exc)->encoding, "encoding");
1341}
1342
1343PyObject *
1344PyUnicodeDecodeError_GetEncoding(PyObject *exc)
1345{
1346    return get_string(((PyUnicodeErrorObject *)exc)->encoding, "encoding");
1347}
1348
1349PyObject *
1350PyUnicodeEncodeError_GetObject(PyObject *exc)
1351{
1352    return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object");
1353}
1354
1355PyObject *
1356PyUnicodeDecodeError_GetObject(PyObject *exc)
1357{
1358    return get_string(((PyUnicodeErrorObject *)exc)->object, "object");
1359}
1360
1361PyObject *
1362PyUnicodeTranslateError_GetObject(PyObject *exc)
1363{
1364    return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object");
1365}
1366
1367int
1368PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start)
1369{
1370    Py_ssize_t size;
1371    PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object,
1372                                "object");
1373    if (!obj)
1374        return -1;
1375    *start = ((PyUnicodeErrorObject *)exc)->start;
1376    size = PyUnicode_GET_SIZE(obj);
1377    if (*start<0)
1378        *start = 0; /*XXX check for values <0*/
1379    if (*start>=size)
1380        *start = size-1;
1381    Py_DECREF(obj);
1382    return 0;
1383}
1384
1385
1386int
1387PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start)
1388{
1389    Py_ssize_t size;
1390    PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object,
1391                               "object");
1392    if (!obj)
1393        return -1;
1394    size = PyString_GET_SIZE(obj);
1395    *start = ((PyUnicodeErrorObject *)exc)->start;
1396    if (*start<0)
1397        *start = 0;
1398    if (*start>=size)
1399        *start = size-1;
1400    Py_DECREF(obj);
1401    return 0;
1402}
1403
1404
1405int
1406PyUnicodeTranslateError_GetStart(PyObject *exc, Py_ssize_t *start)
1407{
1408    return PyUnicodeEncodeError_GetStart(exc, start);
1409}
1410
1411
1412int
1413PyUnicodeEncodeError_SetStart(PyObject *exc, Py_ssize_t start)
1414{
1415    ((PyUnicodeErrorObject *)exc)->start = start;
1416    return 0;
1417}
1418
1419
1420int
1421PyUnicodeDecodeError_SetStart(PyObject *exc, Py_ssize_t start)
1422{
1423    ((PyUnicodeErrorObject *)exc)->start = start;
1424    return 0;
1425}
1426
1427
1428int
1429PyUnicodeTranslateError_SetStart(PyObject *exc, Py_ssize_t start)
1430{
1431    ((PyUnicodeErrorObject *)exc)->start = start;
1432    return 0;
1433}
1434
1435
1436int
1437PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end)
1438{
1439    Py_ssize_t size;
1440    PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object,
1441                                "object");
1442    if (!obj)
1443        return -1;
1444    *end = ((PyUnicodeErrorObject *)exc)->end;
1445    size = PyUnicode_GET_SIZE(obj);
1446    if (*end<1)
1447        *end = 1;
1448    if (*end>size)
1449        *end = size;
1450    Py_DECREF(obj);
1451    return 0;
1452}
1453
1454
1455int
1456PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end)
1457{
1458    Py_ssize_t size;
1459    PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object,
1460                               "object");
1461    if (!obj)
1462        return -1;
1463    *end = ((PyUnicodeErrorObject *)exc)->end;
1464    size = PyString_GET_SIZE(obj);
1465    if (*end<1)
1466        *end = 1;
1467    if (*end>size)
1468        *end = size;
1469    Py_DECREF(obj);
1470    return 0;
1471}
1472
1473
1474int
1475PyUnicodeTranslateError_GetEnd(PyObject *exc, Py_ssize_t *start)
1476{
1477    return PyUnicodeEncodeError_GetEnd(exc, start);
1478}
1479
1480
1481int
1482PyUnicodeEncodeError_SetEnd(PyObject *exc, Py_ssize_t end)
1483{
1484    ((PyUnicodeErrorObject *)exc)->end = end;
1485    return 0;
1486}
1487
1488
1489int
1490PyUnicodeDecodeError_SetEnd(PyObject *exc, Py_ssize_t end)
1491{
1492    ((PyUnicodeErrorObject *)exc)->end = end;
1493    return 0;
1494}
1495
1496
1497int
1498PyUnicodeTranslateError_SetEnd(PyObject *exc, Py_ssize_t end)
1499{
1500    ((PyUnicodeErrorObject *)exc)->end = end;
1501    return 0;
1502}
1503
1504PyObject *
1505PyUnicodeEncodeError_GetReason(PyObject *exc)
1506{
1507    return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason");
1508}
1509
1510
1511PyObject *
1512PyUnicodeDecodeError_GetReason(PyObject *exc)
1513{
1514    return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason");
1515}
1516
1517
1518PyObject *
1519PyUnicodeTranslateError_GetReason(PyObject *exc)
1520{
1521    return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason");
1522}
1523
1524
1525int
1526PyUnicodeEncodeError_SetReason(PyObject *exc, const char *reason)
1527{
1528    return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason);
1529}
1530
1531
1532int
1533PyUnicodeDecodeError_SetReason(PyObject *exc, const char *reason)
1534{
1535    return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason);
1536}
1537
1538
1539int
1540PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason)
1541{
1542    return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason);
1543}
1544
1545
1546static int
1547UnicodeError_init(PyUnicodeErrorObject *self, PyObject *args, PyObject *kwds,
1548                  PyTypeObject *objecttype)
1549{
1550    Py_CLEAR(self->encoding);
1551    Py_CLEAR(self->object);
1552    Py_CLEAR(self->reason);
1553
1554    if (!PyArg_ParseTuple(args, "O!O!nnO!",
1555        &PyString_Type, &self->encoding,
1556        objecttype, &self->object,
1557        &self->start,
1558        &self->end,
1559        &PyString_Type, &self->reason)) {
1560        self->encoding = self->object = self->reason = NULL;
1561        return -1;
1562    }
1563
1564    Py_INCREF(self->encoding);
1565    Py_INCREF(self->object);
1566    Py_INCREF(self->reason);
1567
1568    return 0;
1569}
1570
1571static int
1572UnicodeError_clear(PyUnicodeErrorObject *self)
1573{
1574    Py_CLEAR(self->encoding);
1575    Py_CLEAR(self->object);
1576    Py_CLEAR(self->reason);
1577    return BaseException_clear((PyBaseExceptionObject *)self);
1578}
1579
1580static void
1581UnicodeError_dealloc(PyUnicodeErrorObject *self)
1582{
1583    _PyObject_GC_UNTRACK(self);
1584    UnicodeError_clear(self);
1585    Py_TYPE(self)->tp_free((PyObject *)self);
1586}
1587
1588static int
1589UnicodeError_traverse(PyUnicodeErrorObject *self, visitproc visit, void *arg)
1590{
1591    Py_VISIT(self->encoding);
1592    Py_VISIT(self->object);
1593    Py_VISIT(self->reason);
1594    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
1595}
1596
1597static PyMemberDef UnicodeError_members[] = {
1598    {"encoding", T_OBJECT, offsetof(PyUnicodeErrorObject, encoding), 0,
1599        PyDoc_STR("exception encoding")},
1600    {"object", T_OBJECT, offsetof(PyUnicodeErrorObject, object), 0,
1601        PyDoc_STR("exception object")},
1602    {"start", T_PYSSIZET, offsetof(PyUnicodeErrorObject, start), 0,
1603        PyDoc_STR("exception start")},
1604    {"end", T_PYSSIZET, offsetof(PyUnicodeErrorObject, end), 0,
1605        PyDoc_STR("exception end")},
1606    {"reason", T_OBJECT, offsetof(PyUnicodeErrorObject, reason), 0,
1607        PyDoc_STR("exception reason")},
1608    {NULL}  /* Sentinel */
1609};
1610
1611
1612/*
1613 *    UnicodeEncodeError extends UnicodeError
1614 */
1615
1616static int
1617UnicodeEncodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
1618{
1619    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
1620        return -1;
1621    return UnicodeError_init((PyUnicodeErrorObject *)self, args,
1622                             kwds, &PyUnicode_Type);
1623}
1624
1625static PyObject *
1626UnicodeEncodeError_str(PyObject *self)
1627{
1628    PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;
1629
1630    if (uself->end==uself->start+1) {
1631        int badchar = (int)PyUnicode_AS_UNICODE(uself->object)[uself->start];
1632        char badchar_str[20];
1633        if (badchar <= 0xff)
1634            PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar);
1635        else if (badchar <= 0xffff)
1636            PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar);
1637        else
1638            PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar);
1639        return PyString_FromFormat(
1640            "'%.400s' codec can't encode character u'\\%s' in position %zd: %.400s",
1641            PyString_AS_STRING(uself->encoding),
1642            badchar_str,
1643            uself->start,
1644            PyString_AS_STRING(uself->reason)
1645        );
1646    }
1647    return PyString_FromFormat(
1648        "'%.400s' codec can't encode characters in position %zd-%zd: %.400s",
1649        PyString_AS_STRING(uself->encoding),
1650        uself->start,
1651        uself->end-1,
1652        PyString_AS_STRING(uself->reason)
1653    );
1654}
1655
1656static PyTypeObject _PyExc_UnicodeEncodeError = {
1657    PyObject_HEAD_INIT(NULL)
1658    0,
1659    EXC_MODULE_NAME "UnicodeEncodeError",
1660    sizeof(PyUnicodeErrorObject), 0,
1661    (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1662    (reprfunc)UnicodeEncodeError_str, 0, 0, 0,
1663    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
1664    PyDoc_STR("Unicode encoding error."), (traverseproc)UnicodeError_traverse,
1665    (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
1666    0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
1667    (initproc)UnicodeEncodeError_init, 0, BaseException_new,
1668};
1669PyObject *PyExc_UnicodeEncodeError = (PyObject *)&_PyExc_UnicodeEncodeError;
1670
1671PyObject *
1672PyUnicodeEncodeError_Create(
1673    const char *encoding, const Py_UNICODE *object, Py_ssize_t length,
1674    Py_ssize_t start, Py_ssize_t end, const char *reason)
1675{
1676    return PyObject_CallFunction(PyExc_UnicodeEncodeError, "su#nns",
1677                                 encoding, object, length, start, end, reason);
1678}
1679
1680
1681/*
1682 *    UnicodeDecodeError extends UnicodeError
1683 */
1684
1685static int
1686UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
1687{
1688    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
1689        return -1;
1690    return UnicodeError_init((PyUnicodeErrorObject *)self, args,
1691                             kwds, &PyString_Type);
1692}
1693
1694static PyObject *
1695UnicodeDecodeError_str(PyObject *self)
1696{
1697    PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;
1698
1699    if (uself->end==uself->start+1) {
1700        /* FromFormat does not support %02x, so format that separately */
1701        char byte[4];
1702        PyOS_snprintf(byte, sizeof(byte), "%02x",
1703                      ((int)PyString_AS_STRING(uself->object)[uself->start])&0xff);
1704        return PyString_FromFormat(
1705            "'%.400s' codec can't decode byte 0x%s in position %zd: %.400s",
1706            PyString_AS_STRING(uself->encoding),
1707            byte,
1708            uself->start,
1709            PyString_AS_STRING(uself->reason)
1710        );
1711    }
1712    return PyString_FromFormat(
1713        "'%.400s' codec can't decode bytes in position %zd-%zd: %.400s",
1714        PyString_AS_STRING(uself->encoding),
1715        uself->start,
1716        uself->end-1,
1717        PyString_AS_STRING(uself->reason)
1718    );
1719}
1720
1721static PyTypeObject _PyExc_UnicodeDecodeError = {
1722    PyObject_HEAD_INIT(NULL)
1723    0,
1724    EXC_MODULE_NAME "UnicodeDecodeError",
1725    sizeof(PyUnicodeErrorObject), 0,
1726    (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1727    (reprfunc)UnicodeDecodeError_str, 0, 0, 0,
1728    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
1729    PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse,
1730    (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
1731    0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
1732    (initproc)UnicodeDecodeError_init, 0, BaseException_new,
1733};
1734PyObject *PyExc_UnicodeDecodeError = (PyObject *)&_PyExc_UnicodeDecodeError;
1735
1736PyObject *
1737PyUnicodeDecodeError_Create(
1738    const char *encoding, const char *object, Py_ssize_t length,
1739    Py_ssize_t start, Py_ssize_t end, const char *reason)
1740{
1741    assert(length < INT_MAX);
1742    assert(start < INT_MAX);
1743    assert(end < INT_MAX);
1744    return PyObject_CallFunction(PyExc_UnicodeDecodeError, "ss#nns",
1745                                 encoding, object, length, start, end, reason);
1746}
1747
1748
1749/*
1750 *    UnicodeTranslateError extends UnicodeError
1751 */
1752
1753static int
1754UnicodeTranslateError_init(PyUnicodeErrorObject *self, PyObject *args,
1755                           PyObject *kwds)
1756{
1757    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
1758        return -1;
1759
1760    Py_CLEAR(self->object);
1761    Py_CLEAR(self->reason);
1762
1763    if (!PyArg_ParseTuple(args, "O!nnO!",
1764        &PyUnicode_Type, &self->object,
1765        &self->start,
1766        &self->end,
1767        &PyString_Type, &self->reason)) {
1768        self->object = self->reason = NULL;
1769        return -1;
1770    }
1771
1772    Py_INCREF(self->object);
1773    Py_INCREF(self->reason);
1774
1775    return 0;
1776}
1777
1778
1779static PyObject *
1780UnicodeTranslateError_str(PyObject *self)
1781{
1782    PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;
1783
1784    if (uself->end==uself->start+1) {
1785        int badchar = (int)PyUnicode_AS_UNICODE(uself->object)[uself->start];
1786        char badchar_str[20];
1787        if (badchar <= 0xff)
1788            PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar);
1789        else if (badchar <= 0xffff)
1790            PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar);
1791        else
1792            PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar);
1793        return PyString_FromFormat(
1794            "can't translate character u'\\%s' in position %zd: %.400s",
1795            badchar_str,
1796            uself->start,
1797            PyString_AS_STRING(uself->reason)
1798        );
1799    }
1800    return PyString_FromFormat(
1801        "can't translate characters in position %zd-%zd: %.400s",
1802        uself->start,
1803        uself->end-1,
1804        PyString_AS_STRING(uself->reason)
1805    );
1806}
1807
1808static PyTypeObject _PyExc_UnicodeTranslateError = {
1809    PyObject_HEAD_INIT(NULL)
1810    0,
1811    EXC_MODULE_NAME "UnicodeTranslateError",
1812    sizeof(PyUnicodeErrorObject), 0,
1813    (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1814    (reprfunc)UnicodeTranslateError_str, 0, 0, 0,
1815    Py_TPFLAGS_DEFAULT | 

Large files files are truncated, but you can click here to view the full file