1c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* ------------------------------------------------------------------------
2c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
3c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   Python Codec Registry and support functions
4c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
5c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielWritten by Marc-Andre Lemburg (mal@lemburg.com).
6c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
7c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielCopyright (c) Corporation for National Research Initiatives.
8c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
9c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   ------------------------------------------------------------------------ */
10c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
11c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#include "Python.h"
12c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#include <ctype.h>
13c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
14c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* --- Codec Registry ----------------------------------------------------- */
15c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
16c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Import the standard encodings package which will register the first
17c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   codec search function.
18c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
19c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   This is done in a lazy way so that the Unicode implementation does
20c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   not downgrade startup time of scripts not needing it.
21c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
22c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   ImportErrors are silently ignored by this function. Only one try is
23c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   made.
24c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
25c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel*/
26c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
27c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic int _PyCodecRegistry_Init(void); /* Forward */
28c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
29c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielint PyCodec_Register(PyObject *search_function)
30c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
31c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyInterpreterState *interp = PyThreadState_GET()->interp;
32c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
33c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
34c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (search_function == NULL) {
35c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_BadArgument();
36c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
37c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
38c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (!PyCallable_Check(search_function)) {
39c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_SetString(PyExc_TypeError, "argument must be callable");
40c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
41c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
42c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return PyList_Append(interp->codec_search_path, search_function);
43c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
44c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel onError:
45c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return -1;
46c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
47c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
48c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Convert a string to a normalized Python string: all characters are
49c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   converted to lower case, spaces are replaced with underscores. */
50c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
51c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic
52c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *normalizestring(const char *string)
53c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
54c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    register size_t i;
55c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    size_t len = strlen(string);
56c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    char *p;
57c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *v;
58c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
59c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (len > PY_SSIZE_T_MAX) {
60c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_SetString(PyExc_OverflowError, "string is too large");
61c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
62c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
63c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
64c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    v = PyString_FromStringAndSize(NULL, len);
65c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (v == NULL)
66c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
67c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    p = PyString_AS_STRING(v);
68c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    for (i = 0; i < len; i++) {
69c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        register char ch = string[i];
70c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (ch == ' ')
71c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            ch = '-';
72c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        else
73c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            ch = Py_TOLOWER(Py_CHARMASK(ch));
74c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        p[i] = ch;
75c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
76c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return v;
77c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
78c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
79c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Lookup the given encoding and return a tuple providing the codec
80c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   facilities.
81c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
82c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   The encoding string is looked up converted to all lower-case
83c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   characters. This makes encodings looked up through this mechanism
84c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   effectively case-insensitive.
85c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
86c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   If no codec is found, a LookupError is set and NULL returned.
87c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
88c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   As side effect, this tries to load the encodings package, if not
89c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   yet done. This is part of the lazy load strategy for the encodings
90c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   package.
91c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
92c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel*/
93c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
94c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *_PyCodec_Lookup(const char *encoding)
95c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
96c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyInterpreterState *interp;
97c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *result, *args = NULL, *v;
98c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_ssize_t i, len;
99c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
100c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (encoding == NULL) {
101c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_BadArgument();
102c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
103c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
104c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
105c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    interp = PyThreadState_GET()->interp;
106c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
107c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
108c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
109c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /* Convert the encoding to a normalized Python string: all
110c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel       characters are converted to lower case, spaces and hyphens are
111c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel       replaced with underscores. */
112c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    v = normalizestring(encoding);
113c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (v == NULL)
114c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
115c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyString_InternInPlace(&v);
116c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
117c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /* First, try to lookup the name in the registry dictionary */
118c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    result = PyDict_GetItem(interp->codec_search_cache, v);
119c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (result != NULL) {
120c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_INCREF(result);
121c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_DECREF(v);
122c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return result;
123c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
124c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
125c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /* Next, scan the search functions in order of registration */
126c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    args = PyTuple_New(1);
127c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (args == NULL)
128c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
129c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyTuple_SET_ITEM(args,0,v);
130c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
131c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    len = PyList_Size(interp->codec_search_path);
132c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (len < 0)
133c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
134c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (len == 0) {
135c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_SetString(PyExc_LookupError,
136c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        "no codec search functions registered: "
137c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        "can't find encoding");
138c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
139c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
140c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
141c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    for (i = 0; i < len; i++) {
142c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *func;
143c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
144c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        func = PyList_GetItem(interp->codec_search_path, i);
145c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (func == NULL)
146c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            goto onError;
147c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        result = PyEval_CallObject(func, args);
148c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (result == NULL)
149c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            goto onError;
150c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (result == Py_None) {
151c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_DECREF(result);
152c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            continue;
153c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
154c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 4) {
155c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            PyErr_SetString(PyExc_TypeError,
156c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                            "codec search functions must return 4-tuples");
157c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_DECREF(result);
158c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            goto onError;
159c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
160c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        break;
161c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
162c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (i == len) {
163c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /* XXX Perhaps we should cache misses too ? */
164c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_Format(PyExc_LookupError,
165c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                     "unknown encoding: %s", encoding);
166c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
167c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
168c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
169c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /* Cache and return the result */
170c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyDict_SetItem(interp->codec_search_cache, v, result);
171c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(args);
172c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return result;
173c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
174c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel onError:
175c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_XDECREF(args);
176c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return NULL;
177c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
178c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
179c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic
180c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *args_tuple(PyObject *object,
181c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                     const char *errors)
182c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
183c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *args;
184c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
185c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    args = PyTuple_New(1 + (errors != NULL));
186c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (args == NULL)
187c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
188c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_INCREF(object);
189c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyTuple_SET_ITEM(args,0,object);
190c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (errors) {
191c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *v;
192c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
193c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        v = PyString_FromString(errors);
194c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (v == NULL) {
195c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_DECREF(args);
196c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
197c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
198c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyTuple_SET_ITEM(args, 1, v);
199c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
200c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return args;
201c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
202c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
203c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Helper function to get a codec item */
204c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
205c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic
206c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *codec_getitem(const char *encoding, int index)
207c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
208c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *codecs;
209c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *v;
210c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
211c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    codecs = _PyCodec_Lookup(encoding);
212c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (codecs == NULL)
213c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
214c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    v = PyTuple_GET_ITEM(codecs, index);
215c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(codecs);
216c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_INCREF(v);
217c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return v;
218c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
219c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
220c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Helper function to create an incremental codec. */
221c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
222c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic
223c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *codec_getincrementalcodec(const char *encoding,
224c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                                    const char *errors,
225c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                                    const char *attrname)
226c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
227c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *codecs, *ret, *inccodec;
228c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
229c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    codecs = _PyCodec_Lookup(encoding);
230c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (codecs == NULL)
231c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
232c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    inccodec = PyObject_GetAttrString(codecs, attrname);
233c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(codecs);
234c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (inccodec == NULL)
235c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
236c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (errors)
237c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        ret = PyObject_CallFunction(inccodec, "s", errors);
238c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else
239c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        ret = PyObject_CallFunction(inccodec, NULL);
240c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(inccodec);
241c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return ret;
242c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
243c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
244c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Helper function to create a stream codec. */
245c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
246c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic
247c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *codec_getstreamcodec(const char *encoding,
248c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                               PyObject *stream,
249c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                               const char *errors,
250c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                               const int index)
251c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
252c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *codecs, *streamcodec, *codeccls;
253c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
254c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    codecs = _PyCodec_Lookup(encoding);
255c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (codecs == NULL)
256c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
257c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
258c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    codeccls = PyTuple_GET_ITEM(codecs, index);
259c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (errors != NULL)
260c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        streamcodec = PyObject_CallFunction(codeccls, "Os", stream, errors);
261c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else
262c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        streamcodec = PyObject_CallFunction(codeccls, "O", stream);
263c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(codecs);
264c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return streamcodec;
265c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
266c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
267c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Convenience APIs to query the Codec registry.
268c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
269c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   All APIs return a codec object with incremented refcount.
270c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
271c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel */
272c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
273c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_Encoder(const char *encoding)
274c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
275c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return codec_getitem(encoding, 0);
276c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
277c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
278c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_Decoder(const char *encoding)
279c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
280c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return codec_getitem(encoding, 1);
281c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
282c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
283c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_IncrementalEncoder(const char *encoding,
284c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                                     const char *errors)
285c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
286c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return codec_getincrementalcodec(encoding, errors, "incrementalencoder");
287c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
288c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
289c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_IncrementalDecoder(const char *encoding,
290c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                                     const char *errors)
291c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
292c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return codec_getincrementalcodec(encoding, errors, "incrementaldecoder");
293c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
294c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
295c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_StreamReader(const char *encoding,
296c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                               PyObject *stream,
297c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                               const char *errors)
298c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
299c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return codec_getstreamcodec(encoding, stream, errors, 2);
300c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
301c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
302c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_StreamWriter(const char *encoding,
303c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                               PyObject *stream,
304c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                               const char *errors)
305c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
306c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return codec_getstreamcodec(encoding, stream, errors, 3);
307c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
308c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
309c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Encode an object (e.g. an Unicode object) using the given encoding
310c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   and return the resulting encoded object (usually a Python string).
311c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
312c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   errors is passed to the encoder factory as argument if non-NULL. */
313c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
314c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_Encode(PyObject *object,
315c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                         const char *encoding,
316c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                         const char *errors)
317c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
318c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *encoder = NULL;
319c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *args = NULL, *result = NULL;
320c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *v;
321c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
322c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    encoder = PyCodec_Encoder(encoding);
323c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (encoder == NULL)
324c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
325c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
326c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    args = args_tuple(object, errors);
327c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (args == NULL)
328c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
329c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
330c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    result = PyEval_CallObject(encoder,args);
331c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (result == NULL)
332c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
333c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
334c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (!PyTuple_Check(result) ||
335c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyTuple_GET_SIZE(result) != 2) {
336c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_SetString(PyExc_TypeError,
337c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        "encoder must return a tuple (object,integer)");
338c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
339c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
340c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    v = PyTuple_GET_ITEM(result,0);
341c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_INCREF(v);
342c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /* We don't check or use the second (integer) entry. */
343c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
344c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(args);
345c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(encoder);
346c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(result);
347c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return v;
348c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
349c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel onError:
350c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_XDECREF(result);
351c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_XDECREF(args);
352c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_XDECREF(encoder);
353c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return NULL;
354c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
355c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
356c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Decode an object (usually a Python string) using the given encoding
357c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   and return an equivalent object (e.g. an Unicode object).
358c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
359c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   errors is passed to the decoder factory as argument if non-NULL. */
360c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
361c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_Decode(PyObject *object,
362c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                         const char *encoding,
363c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                         const char *errors)
364c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
365c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *decoder = NULL;
366c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *args = NULL, *result = NULL;
367c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *v;
368c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
369c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    decoder = PyCodec_Decoder(encoding);
370c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (decoder == NULL)
371c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
372c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
373c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    args = args_tuple(object, errors);
374c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (args == NULL)
375c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
376c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
377c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    result = PyEval_CallObject(decoder,args);
378c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (result == NULL)
379c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
380c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (!PyTuple_Check(result) ||
381c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyTuple_GET_SIZE(result) != 2) {
382c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_SetString(PyExc_TypeError,
383c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        "decoder must return a tuple (object,integer)");
384c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        goto onError;
385c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
386c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    v = PyTuple_GET_ITEM(result,0);
387c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_INCREF(v);
388c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /* We don't check or use the second (integer) entry. */
389c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
390c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(args);
391c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(decoder);
392c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(result);
393c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return v;
394c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
395c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel onError:
396c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_XDECREF(args);
397c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_XDECREF(decoder);
398c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_XDECREF(result);
399c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return NULL;
400c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
401c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
402c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Register the error handling callback function error under the name
403c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   name. This function will be called by the codec when it encounters
404c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   an unencodable characters/undecodable bytes and doesn't know the
405c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   callback name, when name is specified as the error parameter
406c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   in the call to the encode/decode function.
407c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   Return 0 on success, -1 on error */
408c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielint PyCodec_RegisterError(const char *name, PyObject *error)
409c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
410c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyInterpreterState *interp = PyThreadState_GET()->interp;
411c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
412c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return -1;
413c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (!PyCallable_Check(error)) {
414c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_SetString(PyExc_TypeError, "handler must be callable");
415c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return -1;
416c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
417c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return PyDict_SetItemString(interp->codec_error_registry,
418c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                                (char *)name, error);
419c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
420c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
421c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/* Lookup the error handling callback function registered under the
422c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   name error. As a special case NULL can be passed, in which case
423c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel   the error handling callback for strict encoding will be returned. */
424c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_LookupError(const char *name)
425c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
426c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *handler = NULL;
427c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
428c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyInterpreterState *interp = PyThreadState_GET()->interp;
429c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
430c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
431c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
432c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (name==NULL)
433c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        name = "strict";
434c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    handler = PyDict_GetItemString(interp->codec_error_registry, (char *)name);
435c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (!handler)
436c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_Format(PyExc_LookupError, "unknown error handler name '%.400s'", name);
437c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else
438c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_INCREF(handler);
439c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return handler;
440c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
441c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
442c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic void wrong_exception_type(PyObject *exc)
443c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
444c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *type = PyObject_GetAttrString(exc, "__class__");
445c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (type != NULL) {
446c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *name = PyObject_GetAttrString(type, "__name__");
447c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_DECREF(type);
448c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (name != NULL) {
449c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            PyObject *string = PyObject_Str(name);
450c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_DECREF(name);
451c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (string != NULL) {
452c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                PyErr_Format(PyExc_TypeError,
453c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    "don't know how to handle %.400s in error callback",
454c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    PyString_AS_STRING(string));
455c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Py_DECREF(string);
456c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
457c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
458c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
459c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
460c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
461c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_StrictErrors(PyObject *exc)
462c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
463c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (PyExceptionInstance_Check(exc))
464c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
465c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else
466c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyErr_SetString(PyExc_TypeError, "codec must pass exception instance");
467c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return NULL;
468c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
469c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
470c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
471c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#ifdef Py_USING_UNICODE
472c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_IgnoreErrors(PyObject *exc)
473c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
474c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_ssize_t end;
475c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) {
476c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeEncodeError_GetEnd(exc, &end))
477c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
478c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
479c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) {
480c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeDecodeError_GetEnd(exc, &end))
481c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
482c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
483c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) {
484c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeTranslateError_GetEnd(exc, &end))
485c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
486c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
487c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else {
488c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        wrong_exception_type(exc);
489c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
490c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
491c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /* ouch: passing NULL, 0, pos gives None instead of u'' */
492c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return Py_BuildValue("(u#n)", &end, 0, end);
493c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
494c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
495c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
496c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_ReplaceErrors(PyObject *exc)
497c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
498c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *restuple;
499c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_ssize_t start;
500c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_ssize_t end;
501c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_ssize_t i;
502c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
503c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) {
504c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *res;
505c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE *p;
506c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeEncodeError_GetStart(exc, &start))
507c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
508c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeEncodeError_GetEnd(exc, &end))
509c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
510c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        res = PyUnicode_FromUnicode(NULL, end-start);
511c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (res == NULL)
512c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
513c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        for (p = PyUnicode_AS_UNICODE(res), i = start;
514c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            i<end; ++p, ++i)
515c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            *p = '?';
516c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        restuple = Py_BuildValue("(On)", res, end);
517c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_DECREF(res);
518c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return restuple;
519c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
520c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) {
521c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE res = Py_UNICODE_REPLACEMENT_CHARACTER;
522c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeDecodeError_GetEnd(exc, &end))
523c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
524c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return Py_BuildValue("(u#n)", &res, (Py_ssize_t)1, end);
525c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
526c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) {
527c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *res;
528c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE *p;
529c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeTranslateError_GetStart(exc, &start))
530c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
531c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeTranslateError_GetEnd(exc, &end))
532c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
533c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        res = PyUnicode_FromUnicode(NULL, end-start);
534c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (res == NULL)
535c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
536c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        for (p = PyUnicode_AS_UNICODE(res), i = start;
537c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            i<end; ++p, ++i)
538c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            *p = Py_UNICODE_REPLACEMENT_CHARACTER;
539c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        restuple = Py_BuildValue("(On)", res, end);
540c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_DECREF(res);
541c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return restuple;
542c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
543c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else {
544c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        wrong_exception_type(exc);
545c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
546c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
547c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
548c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
549c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc)
550c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
551c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) {
552c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *restuple;
553c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *object;
554c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_ssize_t start;
555c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_ssize_t end;
556c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *res;
557c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE *p;
558c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE *startp;
559c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE *e;
560c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE *outp;
561c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_ssize_t ressize;
562c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeEncodeError_GetStart(exc, &start))
563c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
564c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeEncodeError_GetEnd(exc, &end))
565c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
566c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (!(object = PyUnicodeEncodeError_GetObject(exc)))
567c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
568c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        startp = PyUnicode_AS_UNICODE(object);
569c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (end - start > PY_SSIZE_T_MAX / (2+7+1)) {
570c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            end = start + PY_SSIZE_T_MAX / (2+7+1);
571c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#ifndef Py_UNICODE_WIDE
572c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (0xD800 <= startp[end - 1] && startp[end - 1] <= 0xDBFF)
573c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                end--;
574c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#endif
575c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
576c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        e = startp + end;
577c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        for (p = startp+start, ressize = 0; p < e;) {
578c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_UCS4 ch = *p++;
579c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#ifndef Py_UNICODE_WIDE
580c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if ((0xD800 <= ch && ch <= 0xDBFF) &&
581c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                (p < e) &&
582c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                (0xDC00 <= *p && *p <= 0xDFFF)) {
583c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ch = ((((ch & 0x03FF) << 10) |
584c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                       ((Py_UCS4)*p++ & 0x03FF)) + 0x10000);
585c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
586c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#endif
587c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (ch < 10)
588c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 2+1+1;
589c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 100)
590c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 2+2+1;
591c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 1000)
592c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 2+3+1;
593c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 10000)
594c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 2+4+1;
595c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 100000)
596c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 2+5+1;
597c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 1000000)
598c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 2+6+1;
599c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else
600c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 2+7+1;
601c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
602c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /* allocate replacement */
603c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        res = PyUnicode_FromUnicode(NULL, ressize);
604c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (res == NULL) {
605c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_DECREF(object);
606c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
607c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
608c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /* generate replacement */
609c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        for (p = startp+start, outp = PyUnicode_AS_UNICODE(res); p < e;) {
610c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            int digits;
611c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            int base;
612c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_UCS4 ch = *p++;
613c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#ifndef Py_UNICODE_WIDE
614c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if ((0xD800 <= ch && ch <= 0xDBFF) &&
615c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                (p < startp+end) &&
616c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                (0xDC00 <= *p && *p <= 0xDFFF)) {
617c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ch = ((((ch & 0x03FF) << 10) |
618c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                       ((Py_UCS4)*p++ & 0x03FF)) + 0x10000);
619c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
620c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#endif
621c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            *outp++ = '&';
622c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            *outp++ = '#';
623c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (ch < 10) {
624c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                digits = 1;
625c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                base = 1;
626c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
627c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 100) {
628c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                digits = 2;
629c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                base = 10;
630c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
631c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 1000) {
632c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                digits = 3;
633c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                base = 100;
634c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
635c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 10000) {
636c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                digits = 4;
637c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                base = 1000;
638c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
639c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 100000) {
640c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                digits = 5;
641c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                base = 10000;
642c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
643c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else if (ch < 1000000) {
644c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                digits = 6;
645c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                base = 100000;
646c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
647c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else {
648c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                digits = 7;
649c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                base = 1000000;
650c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
651c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            while (digits-->0) {
652c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = '0' + ch/base;
653c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ch %= base;
654c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                base /= 10;
655c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
656c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            *outp++ = ';';
657c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
658c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        restuple = Py_BuildValue("(On)", res, end);
659c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_DECREF(res);
660c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_DECREF(object);
661c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return restuple;
662c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
663c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else {
664c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        wrong_exception_type(exc);
665c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
666c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
667c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
668c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
669c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic Py_UNICODE hexdigits[] = {
670c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    '0', '1', '2', '3', '4', '5', '6', '7',
671c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
672c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel};
673c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
674c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielPyObject *PyCodec_BackslashReplaceErrors(PyObject *exc)
675c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
676c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) {
677c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *restuple;
678c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *object;
679c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_ssize_t start;
680c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_ssize_t end;
681c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyObject *res;
682c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE *p;
683c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE *startp;
684c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_UNICODE *outp;
685c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_ssize_t ressize;
686c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeEncodeError_GetStart(exc, &start))
687c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
688c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyUnicodeEncodeError_GetEnd(exc, &end))
689c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
690c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (!(object = PyUnicodeEncodeError_GetObject(exc)))
691c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
692c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (end - start > PY_SSIZE_T_MAX / (1+1+8))
693c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            end = start + PY_SSIZE_T_MAX / (1+1+8);
694c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        startp = PyUnicode_AS_UNICODE(object);
695c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        for (p = startp+start, ressize = 0; p < startp+end; ++p) {
696c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#ifdef Py_UNICODE_WIDE
697c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (*p >= 0x00010000)
698c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 1+1+8;
699c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else
700c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#endif
701c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (*p >= 0x100) {
702c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 1+1+4;
703c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
704c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else
705c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ressize += 1+1+2;
706c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
707c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        res = PyUnicode_FromUnicode(NULL, ressize);
708c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (res == NULL) {
709c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_DECREF(object);
710c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return NULL;
711c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
712c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        for (p = startp+start, outp = PyUnicode_AS_UNICODE(res);
713c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            p < startp+end; ++p) {
714c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_UNICODE c = *p;
715c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            *outp++ = '\\';
716c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#ifdef Py_UNICODE_WIDE
717c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (c >= 0x00010000) {
718c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = 'U';
719c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = hexdigits[(c>>28)&0xf];
720c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = hexdigits[(c>>24)&0xf];
721c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = hexdigits[(c>>20)&0xf];
722c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = hexdigits[(c>>16)&0xf];
723c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = hexdigits[(c>>12)&0xf];
724c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = hexdigits[(c>>8)&0xf];
725c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
726c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else
727c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#endif
728c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (c >= 0x100) {
729c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = 'u';
730c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = hexdigits[(c>>12)&0xf];
731c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = hexdigits[(c>>8)&0xf];
732c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
733c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            else
734c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                *outp++ = 'x';
735c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            *outp++ = hexdigits[(c>>4)&0xf];
736c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            *outp++ = hexdigits[c&0xf];
737c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
738c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
739c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        restuple = Py_BuildValue("(On)", res, end);
740c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_DECREF(res);
741c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_DECREF(object);
742c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return restuple;
743c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
744c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    else {
745c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        wrong_exception_type(exc);
746c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return NULL;
747c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
748c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
749c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#endif
750c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
751c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic PyObject *strict_errors(PyObject *self, PyObject *exc)
752c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
753c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return PyCodec_StrictErrors(exc);
754c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
755c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
756c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
757c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#ifdef Py_USING_UNICODE
758c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic PyObject *ignore_errors(PyObject *self, PyObject *exc)
759c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
760c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return PyCodec_IgnoreErrors(exc);
761c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
762c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
763c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
764c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic PyObject *replace_errors(PyObject *self, PyObject *exc)
765c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
766c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return PyCodec_ReplaceErrors(exc);
767c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
768c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
769c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
770c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic PyObject *xmlcharrefreplace_errors(PyObject *self, PyObject *exc)
771c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
772c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return PyCodec_XMLCharRefReplaceErrors(exc);
773c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
774c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
775c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
776c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic PyObject *backslashreplace_errors(PyObject *self, PyObject *exc)
777c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
778c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return PyCodec_BackslashReplaceErrors(exc);
779c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
780c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#endif
781c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
782c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielstatic int _PyCodecRegistry_Init(void)
783c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel{
784c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static struct {
785c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        char *name;
786c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PyMethodDef def;
787c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    } methods[] =
788c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    {
789c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        {
790c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "strict",
791c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            {
792c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                "strict_errors",
793c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                strict_errors,
794c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                METH_O,
795c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                PyDoc_STR("Implements the 'strict' error handling, which "
796c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                          "raises a UnicodeError on coding errors.")
797c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
798c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        },
799c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#ifdef Py_USING_UNICODE
800c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        {
801c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "ignore",
802c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            {
803c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                "ignore_errors",
804c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ignore_errors,
805c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                METH_O,
806c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                PyDoc_STR("Implements the 'ignore' error handling, which "
807c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                          "ignores malformed data and continues.")
808c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
809c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        },
810c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        {
811c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "replace",
812c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            {
813c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                "replace_errors",
814c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                replace_errors,
815c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                METH_O,
816c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                PyDoc_STR("Implements the 'replace' error handling, which "
817c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                          "replaces malformed data with a replacement marker.")
818c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
819c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        },
820c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        {
821c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "xmlcharrefreplace",
822c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            {
823c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                "xmlcharrefreplace_errors",
824c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                xmlcharrefreplace_errors,
825c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                METH_O,
826c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                PyDoc_STR("Implements the 'xmlcharrefreplace' error handling, "
827c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                          "which replaces an unencodable character with the "
828c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                          "appropriate XML character reference.")
829c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
830c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        },
831c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        {
832c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "backslashreplace",
833c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            {
834c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                "backslashreplace_errors",
835c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                backslashreplace_errors,
836c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                METH_O,
837c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                PyDoc_STR("Implements the 'backslashreplace' error handling, "
838c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                          "which replaces an unencodable character with a "
839c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                          "backslashed escape sequence.")
840c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
841c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
842c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel#endif
843c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    };
844c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
845c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyInterpreterState *interp = PyThreadState_GET()->interp;
846c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    PyObject *mod;
847c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    unsigned i;
848c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
849c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (interp->codec_search_path != NULL)
850c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return 0;
851c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
852c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    interp->codec_search_path = PyList_New(0);
853c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    interp->codec_search_cache = PyDict_New();
854c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    interp->codec_error_registry = PyDict_New();
855c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
856c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (interp->codec_error_registry) {
857c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        for (i = 0; i < sizeof(methods)/sizeof(methods[0]); ++i) {
858c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            PyObject *func = PyCFunction_New(&methods[i].def, NULL);
859c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            int res;
860c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (!func)
861c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Py_FatalError("can't initialize codec error registry");
862c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            res = PyCodec_RegisterError(methods[i].name, func);
863c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Py_DECREF(func);
864c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (res)
865c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Py_FatalError("can't initialize codec error registry");
866c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
867c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
868c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
869c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (interp->codec_search_path == NULL ||
870c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        interp->codec_search_cache == NULL ||
871c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        interp->codec_error_registry == NULL)
872c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Py_FatalError("can't initialize codec registry");
873c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
874c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    mod = PyImport_ImportModuleLevel("encodings", NULL, NULL, NULL, 0);
875c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    if (mod == NULL) {
876c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (PyErr_ExceptionMatches(PyExc_ImportError)) {
877c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            /* Ignore ImportErrors... this is done so that
878c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel               distributions can disable the encodings package. Note
879c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel               that other errors are not masked, e.g. SystemErrors
880c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel               raised to inform the user of an error in the Python
881c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel               configuration are still reported back to the user. */
882c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            PyErr_Clear();
883c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return 0;
884c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
885c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return -1;
886c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
887c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    Py_DECREF(mod);
888c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    return 0;
889c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel}
890