blob: ef035f0ab3c47326c5d1c4ea390001d6509d83c1 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001
Guido van Rossum373c8691997-04-29 18:22:47 +00002/* Error handling */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00003
Guido van Rossum373c8691997-04-29 18:22:47 +00004#include "Python.h"
Guido van Rossumf22120a1990-12-20 23:05:40 +00005
Guido van Rossum53e8d441995-03-09 12:11:31 +00006#ifndef __STDC__
Guido van Rossum7844e381997-04-11 20:44:04 +00007#ifndef MS_WINDOWS
Tim Petersdbd9ba62000-07-09 03:09:57 +00008extern char *strerror(int);
Guido van Rossum53e8d441995-03-09 12:11:31 +00009#endif
Guido van Rossum7844e381997-04-11 20:44:04 +000010#endif
Guido van Rossumf5401bd1990-11-02 17:50:28 +000011
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000012#ifdef MS_WINDOWS
Martin v. Löwis5d12abe2007-09-03 07:40:24 +000013#include <windows.h>
14#include <winbase.h>
Guido van Rossum743007d1999-04-21 15:27:31 +000015#endif
16
Jeremy Hyltonb69a27e2000-09-01 03:49:47 +000017#include <ctype.h>
18
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000019#ifdef __cplusplus
20extern "C" {
21#endif
22
23
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000024void
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000025PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
Guido van Rossum1ae940a1995-01-02 19:04:15 +000026{
Guido van Rossum885553e1998-12-21 18:33:30 +000027 PyThreadState *tstate = PyThreadState_GET();
Guido van Rossuma027efa1997-05-05 20:56:21 +000028 PyObject *oldtype, *oldvalue, *oldtraceback;
Guido van Rossum1ae940a1995-01-02 19:04:15 +000029
Guido van Rossuma027efa1997-05-05 20:56:21 +000030 if (traceback != NULL && !PyTraceBack_Check(traceback)) {
31 /* XXX Should never happen -- fatal error instead? */
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000032 /* Well, it could be None. */
Guido van Rossuma027efa1997-05-05 20:56:21 +000033 Py_DECREF(traceback);
34 traceback = NULL;
35 }
36
37 /* Save these in locals to safeguard against recursive
38 invocation through Py_XDECREF */
39 oldtype = tstate->curexc_type;
40 oldvalue = tstate->curexc_value;
41 oldtraceback = tstate->curexc_traceback;
42
43 tstate->curexc_type = type;
44 tstate->curexc_value = value;
45 tstate->curexc_traceback = traceback;
46
47 Py_XDECREF(oldtype);
48 Py_XDECREF(oldvalue);
49 Py_XDECREF(oldtraceback);
Guido van Rossum1ae940a1995-01-02 19:04:15 +000050}
51
52void
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000053PyErr_SetObject(PyObject *exception, PyObject *value)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000054{
Thomas Wouters303de6a2006-04-20 22:42:37 +000055 if (exception != NULL &&
56 !PyExceptionClass_Check(exception)) {
Thomas Wouters303de6a2006-04-20 22:42:37 +000057 PyErr_Format(PyExc_SystemError,
Walter Dörwald573c08c2007-05-25 15:46:59 +000058 "exception %R not a BaseException subclass",
59 exception);
Thomas Wouters303de6a2006-04-20 22:42:37 +000060 return;
61 }
Guido van Rossum373c8691997-04-29 18:22:47 +000062 Py_XINCREF(exception);
63 Py_XINCREF(value);
64 PyErr_Restore(exception, value, (PyObject *)NULL);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000065}
66
67void
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000068PyErr_SetNone(PyObject *exception)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000069{
Guido van Rossum373c8691997-04-29 18:22:47 +000070 PyErr_SetObject(exception, (PyObject *)NULL);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000071}
72
73void
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000074PyErr_SetString(PyObject *exception, const char *string)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000075{
Walter Dörwald573c08c2007-05-25 15:46:59 +000076 PyObject *value = PyUnicode_FromString(string);
Guido van Rossum373c8691997-04-29 18:22:47 +000077 PyErr_SetObject(exception, value);
78 Py_XDECREF(value);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000079}
80
Guido van Rossum3a241811994-08-29 12:14:12 +000081
Guido van Rossum373c8691997-04-29 18:22:47 +000082PyObject *
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000083PyErr_Occurred(void)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000084{
Tim Peters024da352001-05-30 06:09:50 +000085 PyThreadState *tstate = PyThreadState_GET();
Guido van Rossuma027efa1997-05-05 20:56:21 +000086
87 return tstate->curexc_type;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000088}
89
Barry Warsawc0dc92a1997-08-22 21:22:58 +000090
91int
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000092PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
Barry Warsawc0dc92a1997-08-22 21:22:58 +000093{
Barry Warsawfa5c3152000-05-02 19:27:51 +000094 if (err == NULL || exc == NULL) {
95 /* maybe caused by "import exceptions" that failed early on */
96 return 0;
97 }
Barry Warsawc0dc92a1997-08-22 21:22:58 +000098 if (PyTuple_Check(exc)) {
Martin v. Löwisd96ee902006-02-16 14:37:16 +000099 Py_ssize_t i, n;
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000100 n = PyTuple_Size(exc);
101 for (i = 0; i < n; i++) {
102 /* Test recursively */
103 if (PyErr_GivenExceptionMatches(
104 err, PyTuple_GET_ITEM(exc, i)))
105 {
106 return 1;
107 }
108 }
109 return 0;
110 }
111 /* err might be an instance, so check its class. */
Brett Cannonbf364092006-03-01 04:25:17 +0000112 if (PyExceptionInstance_Check(err))
113 err = PyExceptionInstance_Class(err);
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000114
Brett Cannonbf364092006-03-01 04:25:17 +0000115 if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {
116 /* problems here!? not sure PyObject_IsSubclass expects to
117 be called with an exception pending... */
118 return PyObject_IsSubclass(err, exc);
119 }
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000120
121 return err == exc;
122}
Guido van Rossum743007d1999-04-21 15:27:31 +0000123
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000124
125int
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000126PyErr_ExceptionMatches(PyObject *exc)
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000127{
128 return PyErr_GivenExceptionMatches(PyErr_Occurred(), exc);
129}
130
131
132/* Used in many places to normalize a raised exception, including in
133 eval_code2(), do_raise(), and PyErr_Print()
134*/
135void
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000136PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000137{
138 PyObject *type = *exc;
139 PyObject *value = *val;
140 PyObject *inclass = NULL;
Jeremy Hyltone2e2c9f2001-09-26 19:58:38 +0000141 PyObject *initial_tb = NULL;
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000142
Guido van Rossumed473a42000-08-07 19:18:27 +0000143 if (type == NULL) {
Guido van Rossum6b3fffa2003-04-10 20:29:48 +0000144 /* There was no exception, so nothing to do. */
145 return;
Guido van Rossumed473a42000-08-07 19:18:27 +0000146 }
147
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000148 /* If PyErr_SetNone() was used, the value will have been actually
149 set to NULL.
150 */
151 if (!value) {
152 value = Py_None;
153 Py_INCREF(value);
154 }
155
Brett Cannonbf364092006-03-01 04:25:17 +0000156 if (PyExceptionInstance_Check(value))
157 inclass = PyExceptionInstance_Class(value);
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000158
159 /* Normalize the exception so that if the type is a class, the
160 value will be an instance.
161 */
Brett Cannonbf364092006-03-01 04:25:17 +0000162 if (PyExceptionClass_Check(type)) {
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000163 /* if the value was not an instance, or is not an instance
164 whose class is (or is derived from) type, then use the
165 value as an argument to instantiation of the type
166 class.
167 */
Brett Cannonbf364092006-03-01 04:25:17 +0000168 if (!inclass || !PyObject_IsSubclass(inclass, type)) {
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000169 PyObject *args, *res;
170
171 if (value == Py_None)
Raymond Hettinger8ae46892003-10-12 19:09:37 +0000172 args = PyTuple_New(0);
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000173 else if (PyTuple_Check(value)) {
174 Py_INCREF(value);
175 args = value;
176 }
177 else
Raymond Hettinger8ae46892003-10-12 19:09:37 +0000178 args = PyTuple_Pack(1, value);
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000179
180 if (args == NULL)
181 goto finally;
182 res = PyEval_CallObject(type, args);
183 Py_DECREF(args);
184 if (res == NULL)
185 goto finally;
186 Py_DECREF(value);
187 value = res;
188 }
Barry Warsaw3a749931997-09-30 15:00:18 +0000189 /* if the class of the instance doesn't exactly match the
190 class of the type, believe the instance
191 */
192 else if (inclass != type) {
193 Py_DECREF(type);
194 type = inclass;
195 Py_INCREF(type);
196 }
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000197 }
198 *exc = type;
199 *val = value;
200 return;
201finally:
Guido van Rossum19b55f21997-12-09 14:11:39 +0000202 Py_DECREF(type);
203 Py_DECREF(value);
Jeremy Hyltone2e2c9f2001-09-26 19:58:38 +0000204 /* If the new exception doesn't set a traceback and the old
205 exception had a traceback, use the old traceback for the
206 new exception. It's better than nothing.
207 */
208 initial_tb = *tb;
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000209 PyErr_Fetch(exc, val, tb);
Jeremy Hyltone2e2c9f2001-09-26 19:58:38 +0000210 if (initial_tb != NULL) {
211 if (*tb == NULL)
212 *tb = initial_tb;
213 else
214 Py_DECREF(initial_tb);
215 }
Barry Warsawc0dc92a1997-08-22 21:22:58 +0000216 /* normalize recursively */
217 PyErr_NormalizeException(exc, val, tb);
218}
219
220
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000221void
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000222PyErr_Fetch(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000223{
Nicholas Bastine5662ae2004-03-24 22:22:12 +0000224 PyThreadState *tstate = PyThreadState_GET();
Guido van Rossuma027efa1997-05-05 20:56:21 +0000225
226 *p_type = tstate->curexc_type;
227 *p_value = tstate->curexc_value;
228 *p_traceback = tstate->curexc_traceback;
229
230 tstate->curexc_type = NULL;
231 tstate->curexc_value = NULL;
232 tstate->curexc_traceback = NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000233}
234
235void
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000236PyErr_Clear(void)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000237{
Guido van Rossuma027efa1997-05-05 20:56:21 +0000238 PyErr_Restore(NULL, NULL, NULL);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000239}
Guido van Rossum7d310eb1990-10-14 20:00:05 +0000240
241/* Convenience functions to set a type error exception and return 0 */
242
243int
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000244PyErr_BadArgument(void)
Guido van Rossum7d310eb1990-10-14 20:00:05 +0000245{
Guido van Rossuma027efa1997-05-05 20:56:21 +0000246 PyErr_SetString(PyExc_TypeError,
Fred Drake661ea262000-10-24 19:57:45 +0000247 "bad argument type for built-in operation");
Guido van Rossum7d310eb1990-10-14 20:00:05 +0000248 return 0;
249}
250
Guido van Rossum373c8691997-04-29 18:22:47 +0000251PyObject *
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000252PyErr_NoMemory(void)
Guido van Rossum7d310eb1990-10-14 20:00:05 +0000253{
Vladimir Marangozov0888ff12000-08-18 18:01:06 +0000254 if (PyErr_ExceptionMatches(PyExc_MemoryError))
255 /* already current */
256 return NULL;
257
Barry Warsaw2d8adff1997-08-29 21:54:35 +0000258 /* raise the pre-allocated instance if it still exists */
259 if (PyExc_MemoryErrorInst)
260 PyErr_SetObject(PyExc_MemoryError, PyExc_MemoryErrorInst);
261 else
262 /* this will probably fail since there's no memory and hee,
263 hee, we have to instantiate this class
264 */
265 PyErr_SetNone(PyExc_MemoryError);
266
Guido van Rossum7d310eb1990-10-14 20:00:05 +0000267 return NULL;
268}
269
Guido van Rossum373c8691997-04-29 18:22:47 +0000270PyObject *
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000271PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
Guido van Rossum7d310eb1990-10-14 20:00:05 +0000272{
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000273 PyObject *message;
Guido van Rossum373c8691997-04-29 18:22:47 +0000274 PyObject *v;
Guido van Rossum3a241811994-08-29 12:14:12 +0000275 int i = errno;
Martin v. Löwis3484a182002-03-09 12:07:51 +0000276#ifdef PLAN9
277 char errbuf[ERRMAX];
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000278#else
279#ifndef MS_WINDOWS
280 char *s;
281#else
282 WCHAR *s_buf = NULL;
283#endif /* Unix/Windows */
284#endif /* PLAN 9*/
285
Guido van Rossume9fbc091995-02-18 14:52:19 +0000286#ifdef EINTR
Guido van Rossum373c8691997-04-29 18:22:47 +0000287 if (i == EINTR && PyErr_CheckSignals())
Guido van Rossum5063bab1991-10-20 20:14:56 +0000288 return NULL;
Guido van Rossume9fbc091995-02-18 14:52:19 +0000289#endif
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000290
Martin v. Löwis3484a182002-03-09 12:07:51 +0000291#ifdef PLAN9
292 rerrstr(errbuf, sizeof errbuf);
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000293 message = PyUnicode_DecodeUTF8(errbuf, strlen(errbuf), "ignore");
Martin v. Löwis3484a182002-03-09 12:07:51 +0000294#else
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000295#ifndef MS_WINDOWS
Guido van Rossume0e59821998-10-14 20:38:13 +0000296 if (i == 0)
297 s = "Error"; /* Sometimes errno didn't get set */
Barry Warsaw97d95151998-07-23 16:05:56 +0000298 else
Guido van Rossume0e59821998-10-14 20:38:13 +0000299 s = strerror(i);
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000300 message = PyUnicode_DecodeUTF8(s, strlen(s), "ignore");
Guido van Rossum743007d1999-04-21 15:27:31 +0000301#else
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000302 if (i == 0)
303 message = PyUnicode_FromString("Error"); /* Sometimes errno didn't get set */
304 else
Guido van Rossum743007d1999-04-21 15:27:31 +0000305 {
Guido van Rossum795e1892000-02-17 15:19:15 +0000306 /* Note that the Win32 errors do not lineup with the
307 errno error. So if the error is in the MSVC error
Brett Cannonbf364092006-03-01 04:25:17 +0000308 table, we use it, otherwise we assume it really _is_
Guido van Rossum795e1892000-02-17 15:19:15 +0000309 a Win32 error code
310 */
Guido van Rossum584b16a2000-02-21 16:50:31 +0000311 if (i > 0 && i < _sys_nerr) {
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000312 message = PyUnicode_FromString(_sys_errlist[i]);
Guido van Rossum795e1892000-02-17 15:19:15 +0000313 }
314 else {
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000315 int len = FormatMessageW(
Guido van Rossum795e1892000-02-17 15:19:15 +0000316 FORMAT_MESSAGE_ALLOCATE_BUFFER |
317 FORMAT_MESSAGE_FROM_SYSTEM |
318 FORMAT_MESSAGE_IGNORE_INSERTS,
319 NULL, /* no message source */
320 i,
321 MAKELANGID(LANG_NEUTRAL,
322 SUBLANG_DEFAULT),
323 /* Default language */
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000324 (LPWSTR) &s_buf,
Guido van Rossum795e1892000-02-17 15:19:15 +0000325 0, /* size not used */
326 NULL); /* no args */
Mark Hammond3d61a062002-10-04 00:13:02 +0000327 if (len==0) {
Brett Cannonbf364092006-03-01 04:25:17 +0000328 /* Only ever seen this in out-of-mem
Mark Hammond3d61a062002-10-04 00:13:02 +0000329 situations */
Mark Hammond3d61a062002-10-04 00:13:02 +0000330 s_buf = NULL;
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000331 message = PyUnicode_FromFormat("Windows Error 0x%X", i);
Mark Hammond3d61a062002-10-04 00:13:02 +0000332 } else {
Mark Hammond3d61a062002-10-04 00:13:02 +0000333 /* remove trailing cr/lf and dots */
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000334 while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
335 s_buf[--len] = L'\0';
336 message = PyUnicode_FromUnicode(s_buf, len);
Mark Hammond3d61a062002-10-04 00:13:02 +0000337 }
Guido van Rossum795e1892000-02-17 15:19:15 +0000338 }
Guido van Rossum743007d1999-04-21 15:27:31 +0000339 }
Martin v. Löwis3484a182002-03-09 12:07:51 +0000340#endif /* Unix/Windows */
341#endif /* PLAN 9*/
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000342
343 if (message == NULL)
344 {
345#ifdef MS_WINDOWS
346 LocalFree(s_buf);
347#endif
348 return NULL;
349 }
350
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000351 if (filenameObject != NULL)
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000352 v = Py_BuildValue("(iOO)", i, message, filenameObject);
Guido van Rossume0e59821998-10-14 20:38:13 +0000353 else
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000354 v = Py_BuildValue("(iO)", i, message);
355 Py_DECREF(message);
356
Guido van Rossum7d310eb1990-10-14 20:00:05 +0000357 if (v != NULL) {
Guido van Rossum373c8691997-04-29 18:22:47 +0000358 PyErr_SetObject(exc, v);
359 Py_DECREF(v);
Guido van Rossum7d310eb1990-10-14 20:00:05 +0000360 }
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000361#ifdef MS_WINDOWS
Guido van Rossum795e1892000-02-17 15:19:15 +0000362 LocalFree(s_buf);
Guido van Rossum743007d1999-04-21 15:27:31 +0000363#endif
Guido van Rossum7d310eb1990-10-14 20:00:05 +0000364 return NULL;
365}
Guido van Rossum743007d1999-04-21 15:27:31 +0000366
Barry Warsaw97d95151998-07-23 16:05:56 +0000367
368PyObject *
Neal Norwitzb382b842007-08-24 20:00:37 +0000369PyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename)
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000370{
Neal Norwitzcd795962007-08-24 19:54:13 +0000371 PyObject *name = filename ? PyUnicode_FromString(filename) : NULL;
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000372 PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
Mark Hammondda7efaa2002-10-04 00:09:38 +0000373 Py_XDECREF(name);
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000374 return result;
375}
376
377#ifdef Py_WIN_WIDE_FILENAMES
378PyObject *
Neal Norwitzb382b842007-08-24 20:00:37 +0000379PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, const Py_UNICODE *filename)
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000380{
Brett Cannonbf364092006-03-01 04:25:17 +0000381 PyObject *name = filename ?
382 PyUnicode_FromUnicode(filename, wcslen(filename)) :
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000383 NULL;
384 PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
385 Py_XDECREF(name);
386 return result;
387}
388#endif /* Py_WIN_WIDE_FILENAMES */
389
390PyObject *
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000391PyErr_SetFromErrno(PyObject *exc)
Barry Warsaw97d95151998-07-23 16:05:56 +0000392{
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000393 return PyErr_SetFromErrnoWithFilenameObject(exc, NULL);
Barry Warsaw97d95151998-07-23 16:05:56 +0000394}
Guido van Rossum683a0721990-10-21 22:09:12 +0000395
Brett Cannonbf364092006-03-01 04:25:17 +0000396#ifdef MS_WINDOWS
Guido van Rossum795e1892000-02-17 15:19:15 +0000397/* Windows specific error code handling */
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000398PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
Thomas Heller085358a2002-07-29 14:27:41 +0000399 PyObject *exc,
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000400 int ierr,
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000401 PyObject *filenameObject)
Guido van Rossum795e1892000-02-17 15:19:15 +0000402{
403 int len;
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000404 WCHAR *s_buf = NULL; /* Free via LocalFree */
405 PyObject *message;
Guido van Rossum795e1892000-02-17 15:19:15 +0000406 PyObject *v;
407 DWORD err = (DWORD)ierr;
408 if (err==0) err = GetLastError();
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000409 len = FormatMessageW(
Guido van Rossum795e1892000-02-17 15:19:15 +0000410 /* Error API error */
411 FORMAT_MESSAGE_ALLOCATE_BUFFER |
412 FORMAT_MESSAGE_FROM_SYSTEM |
413 FORMAT_MESSAGE_IGNORE_INSERTS,
414 NULL, /* no message source */
415 err,
416 MAKELANGID(LANG_NEUTRAL,
417 SUBLANG_DEFAULT), /* Default language */
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000418 (LPWSTR) &s_buf,
Guido van Rossum795e1892000-02-17 15:19:15 +0000419 0, /* size not used */
420 NULL); /* no args */
Mark Hammond3d61a062002-10-04 00:13:02 +0000421 if (len==0) {
422 /* Only seen this in out of mem situations */
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000423 message = PyUnicode_FromFormat("Windows Error 0x%X", err);
Mark Hammond3d61a062002-10-04 00:13:02 +0000424 s_buf = NULL;
425 } else {
Mark Hammond3d61a062002-10-04 00:13:02 +0000426 /* remove trailing cr/lf and dots */
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000427 while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
428 s_buf[--len] = L'\0';
429 message = PyUnicode_FromUnicode(s_buf, len);
Mark Hammond3d61a062002-10-04 00:13:02 +0000430 }
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000431
432 if (message == NULL)
433 {
434 LocalFree(s_buf);
435 return NULL;
436 }
437
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000438 if (filenameObject != NULL)
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000439 v = Py_BuildValue("(iOO)", err, message, filenameObject);
Guido van Rossum795e1892000-02-17 15:19:15 +0000440 else
Martin v. Löwis5d12abe2007-09-03 07:40:24 +0000441 v = Py_BuildValue("(iO)", err, message);
442 Py_DECREF(message);
443
Guido van Rossum795e1892000-02-17 15:19:15 +0000444 if (v != NULL) {
Thomas Heller085358a2002-07-29 14:27:41 +0000445 PyErr_SetObject(exc, v);
Guido van Rossum795e1892000-02-17 15:19:15 +0000446 Py_DECREF(v);
447 }
Mark Hammond3d61a062002-10-04 00:13:02 +0000448 LocalFree(s_buf);
Guido van Rossum795e1892000-02-17 15:19:15 +0000449 return NULL;
450}
451
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000452PyObject *PyErr_SetExcFromWindowsErrWithFilename(
453 PyObject *exc,
454 int ierr,
455 const char *filename)
456{
Neal Norwitzcd795962007-08-24 19:54:13 +0000457 PyObject *name = filename ? PyUnicode_FromString(filename) : NULL;
Brett Cannonbf364092006-03-01 04:25:17 +0000458 PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
459 ierr,
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000460 name);
461 Py_XDECREF(name);
462 return ret;
463}
464
465#ifdef Py_WIN_WIDE_FILENAMES
466PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename(
467 PyObject *exc,
468 int ierr,
469 const Py_UNICODE *filename)
470{
Brett Cannonbf364092006-03-01 04:25:17 +0000471 PyObject *name = filename ?
472 PyUnicode_FromUnicode(filename, wcslen(filename)) :
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000473 NULL;
Brett Cannonbf364092006-03-01 04:25:17 +0000474 PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
475 ierr,
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000476 name);
477 Py_XDECREF(name);
478 return ret;
479}
480#endif /* Py_WIN_WIDE_FILENAMES */
481
Thomas Heller085358a2002-07-29 14:27:41 +0000482PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr)
483{
484 return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL);
485}
486
Guido van Rossum795e1892000-02-17 15:19:15 +0000487PyObject *PyErr_SetFromWindowsErr(int ierr)
488{
Thomas Heller085358a2002-07-29 14:27:41 +0000489 return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,
490 ierr, NULL);
491}
492PyObject *PyErr_SetFromWindowsErrWithFilename(
493 int ierr,
494 const char *filename)
495{
Neal Norwitzcd795962007-08-24 19:54:13 +0000496 PyObject *name = filename ? PyUnicode_FromString(filename) : NULL;
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000497 PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
498 PyExc_WindowsError,
499 ierr, name);
Mark Hammondda7efaa2002-10-04 00:09:38 +0000500 Py_XDECREF(name);
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000501 return result;
Guido van Rossum795e1892000-02-17 15:19:15 +0000502}
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000503
504#ifdef Py_WIN_WIDE_FILENAMES
505PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(
506 int ierr,
507 const Py_UNICODE *filename)
508{
Brett Cannonbf364092006-03-01 04:25:17 +0000509 PyObject *name = filename ?
510 PyUnicode_FromUnicode(filename, wcslen(filename)) :
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000511 NULL;
512 PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
513 PyExc_WindowsError,
514 ierr, name);
Mark Hammondda7efaa2002-10-04 00:09:38 +0000515 Py_XDECREF(name);
Mark Hammondc2e85bd2002-10-03 05:10:39 +0000516 return result;
517}
518#endif /* Py_WIN_WIDE_FILENAMES */
Guido van Rossum795e1892000-02-17 15:19:15 +0000519#endif /* MS_WINDOWS */
520
Guido van Rossum683a0721990-10-21 22:09:12 +0000521void
Neal Norwitzb382b842007-08-24 20:00:37 +0000522_PyErr_BadInternalCall(const char *filename, int lineno)
Fred Drake6d63adf2000-08-24 22:38:39 +0000523{
524 PyErr_Format(PyExc_SystemError,
525 "%s:%d: bad argument to internal function",
526 filename, lineno);
527}
528
529/* Remove the preprocessor macro for PyErr_BadInternalCall() so that we can
530 export the entry point for existing object code: */
531#undef PyErr_BadInternalCall
532void
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000533PyErr_BadInternalCall(void)
Guido van Rossum683a0721990-10-21 22:09:12 +0000534{
Fred Drake6d63adf2000-08-24 22:38:39 +0000535 PyErr_Format(PyExc_SystemError,
536 "bad argument to internal function");
Guido van Rossum683a0721990-10-21 22:09:12 +0000537}
Fred Drake6d63adf2000-08-24 22:38:39 +0000538#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)
539
Guido van Rossum1548bac1997-02-14 17:09:47 +0000540
541
Guido van Rossum1548bac1997-02-14 17:09:47 +0000542PyObject *
543PyErr_Format(PyObject *exception, const char *format, ...)
Guido van Rossum1548bac1997-02-14 17:09:47 +0000544{
545 va_list vargs;
Jeremy Hyltonb69a27e2000-09-01 03:49:47 +0000546 PyObject* string;
Guido van Rossum1548bac1997-02-14 17:09:47 +0000547
Jeremy Hyltonb69a27e2000-09-01 03:49:47 +0000548#ifdef HAVE_STDARG_PROTOTYPES
Guido van Rossum1548bac1997-02-14 17:09:47 +0000549 va_start(vargs, format);
Jeremy Hyltonb69a27e2000-09-01 03:49:47 +0000550#else
551 va_start(vargs);
552#endif
Guido van Rossum1548bac1997-02-14 17:09:47 +0000553
Walter Dörwald573c08c2007-05-25 15:46:59 +0000554 string = PyUnicode_FromFormatV(format, vargs);
Jeremy Hyltonb69a27e2000-09-01 03:49:47 +0000555 PyErr_SetObject(exception, string);
556 Py_XDECREF(string);
Tim Petersc15c4f12001-10-02 21:32:07 +0000557 va_end(vargs);
Guido van Rossum1548bac1997-02-14 17:09:47 +0000558 return NULL;
559}
Guido van Rossum7617e051997-09-16 18:43:50 +0000560
561
Thomas Wouters477c8d52006-05-27 19:21:47 +0000562
Guido van Rossum7617e051997-09-16 18:43:50 +0000563PyObject *
Neal Norwitzb382b842007-08-24 20:00:37 +0000564PyErr_NewException(const char *name, PyObject *base, PyObject *dict)
Guido van Rossum7617e051997-09-16 18:43:50 +0000565{
Neal Norwitzb382b842007-08-24 20:00:37 +0000566 const char *dot;
Guido van Rossum2ac650f1997-10-03 19:50:55 +0000567 PyObject *modulename = NULL;
568 PyObject *classname = NULL;
569 PyObject *mydict = NULL;
570 PyObject *bases = NULL;
Guido van Rossum7617e051997-09-16 18:43:50 +0000571 PyObject *result = NULL;
Guido van Rossum2ac650f1997-10-03 19:50:55 +0000572 dot = strrchr(name, '.');
573 if (dot == NULL) {
574 PyErr_SetString(PyExc_SystemError,
575 "PyErr_NewException: name must be module.class");
Guido van Rossum7617e051997-09-16 18:43:50 +0000576 return NULL;
Guido van Rossum7617e051997-09-16 18:43:50 +0000577 }
578 if (base == NULL)
579 base = PyExc_Exception;
Guido van Rossum2ac650f1997-10-03 19:50:55 +0000580 if (dict == NULL) {
581 dict = mydict = PyDict_New();
582 if (dict == NULL)
583 goto failure;
584 }
585 if (PyDict_GetItemString(dict, "__module__") == NULL) {
Neal Norwitzcd795962007-08-24 19:54:13 +0000586 modulename = PyUnicode_FromStringAndSize(name,
Thomas Wouters89f507f2006-12-13 04:49:30 +0000587 (Py_ssize_t)(dot-name));
Guido van Rossum2ac650f1997-10-03 19:50:55 +0000588 if (modulename == NULL)
589 goto failure;
590 if (PyDict_SetItemString(dict, "__module__", modulename) != 0)
591 goto failure;
592 }
Thomas Wouters477c8d52006-05-27 19:21:47 +0000593 if (PyTuple_Check(base)) {
594 bases = base;
595 /* INCREF as we create a new ref in the else branch */
596 Py_INCREF(bases);
597 } else {
598 bases = PyTuple_Pack(1, base);
599 if (bases == NULL)
600 goto failure;
601 }
602 /* Create a real new-style class. */
Thomas Hellerace8ba82007-07-11 20:01:43 +0000603 result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO",
Thomas Wouters477c8d52006-05-27 19:21:47 +0000604 dot+1, bases, dict);
Guido van Rossum7617e051997-09-16 18:43:50 +0000605 failure:
Guido van Rossum2ac650f1997-10-03 19:50:55 +0000606 Py_XDECREF(bases);
607 Py_XDECREF(mydict);
608 Py_XDECREF(classname);
609 Py_XDECREF(modulename);
Guido van Rossum7617e051997-09-16 18:43:50 +0000610 return result;
611}
Jeremy Hyltonb709df32000-09-01 02:47:25 +0000612
613/* Call when an exception has occurred but there is no way for Python
614 to handle it. Examples: exception in __del__ or during GC. */
615void
616PyErr_WriteUnraisable(PyObject *obj)
617{
618 PyObject *f, *t, *v, *tb;
619 PyErr_Fetch(&t, &v, &tb);
620 f = PySys_GetObject("stderr");
621 if (f != NULL) {
622 PyFile_WriteString("Exception ", f);
623 if (t) {
Thomas Wouters477c8d52006-05-27 19:21:47 +0000624 PyObject* moduleName;
Guido van Rossumd8faa362007-04-27 19:54:29 +0000625 char* className;
626 assert(PyExceptionClass_Check(t));
627 className = PyExceptionClass_Name(t);
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000628 if (className != NULL) {
629 char *dot = strrchr(className, '.');
630 if (dot != NULL)
631 className = dot+1;
632 }
633
634 moduleName = PyObject_GetAttrString(t, "__module__");
Brett Cannonbf364092006-03-01 04:25:17 +0000635 if (moduleName == NULL)
636 PyFile_WriteString("<unknown>", f);
637 else {
Neal Norwitzcd795962007-08-24 19:54:13 +0000638 char* modstr = PyUnicode_AsString(moduleName);
Neal Norwitz2633c692007-02-26 22:22:47 +0000639 if (modstr &&
640 strcmp(modstr, "__builtin__") != 0)
Brett Cannonbf364092006-03-01 04:25:17 +0000641 {
642 PyFile_WriteString(modstr, f);
643 PyFile_WriteString(".", f);
644 }
645 }
646 if (className == NULL)
647 PyFile_WriteString("<unknown>", f);
648 else
649 PyFile_WriteString(className, f);
Jeremy Hyltonb709df32000-09-01 02:47:25 +0000650 if (v && v != Py_None) {
651 PyFile_WriteString(": ", f);
652 PyFile_WriteObject(v, f, 0);
653 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000654 Py_XDECREF(moduleName);
Jeremy Hyltonb709df32000-09-01 02:47:25 +0000655 }
656 PyFile_WriteString(" in ", f);
657 PyFile_WriteObject(obj, f, 0);
658 PyFile_WriteString(" ignored\n", f);
659 PyErr_Clear(); /* Just in case */
660 }
661 Py_XDECREF(t);
662 Py_XDECREF(v);
663 Py_XDECREF(tb);
664}
Guido van Rossumcfd42b52000-12-15 21:58:52 +0000665
Armin Rigo092381a2003-10-25 14:29:27 +0000666extern PyObject *PyModule_GetWarningsModule(void);
Guido van Rossumcfd42b52000-12-15 21:58:52 +0000667
668/* Function to issue a warning message; may raise an exception. */
669int
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000670PyErr_WarnEx(PyObject *category, const char *message, Py_ssize_t stack_level)
Guido van Rossumcfd42b52000-12-15 21:58:52 +0000671{
Mark Hammonda43fd0c2003-02-19 00:33:33 +0000672 PyObject *dict, *func = NULL;
Mark Hammondedd07732003-07-15 23:03:55 +0000673 PyObject *warnings_module = PyModule_GetWarningsModule();
Guido van Rossumcfd42b52000-12-15 21:58:52 +0000674
Mark Hammondedd07732003-07-15 23:03:55 +0000675 if (warnings_module != NULL) {
676 dict = PyModule_GetDict(warnings_module);
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000677 if (dict != NULL)
678 func = PyDict_GetItemString(dict, "warn");
Guido van Rossumcfd42b52000-12-15 21:58:52 +0000679 }
680 if (func == NULL) {
681 PySys_WriteStderr("warning: %s\n", message);
682 return 0;
683 }
684 else {
Thomas Wouters477c8d52006-05-27 19:21:47 +0000685 PyObject *res;
Guido van Rossumcfd42b52000-12-15 21:58:52 +0000686
687 if (category == NULL)
688 category = PyExc_RuntimeWarning;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000689 res = PyObject_CallFunction(func, "sOn",
690 message, category, stack_level);
Guido van Rossumcfd42b52000-12-15 21:58:52 +0000691 if (res == NULL)
692 return -1;
693 Py_DECREF(res);
694 return 0;
695 }
696}
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000697
Guido van Rossum2fd45652001-02-28 21:46:24 +0000698/* Warning with explicit origin */
699int
Martin v. Löwis95292d62002-12-11 14:04:59 +0000700PyErr_WarnExplicit(PyObject *category, const char *message,
701 const char *filename, int lineno,
702 const char *module, PyObject *registry)
Guido van Rossum2fd45652001-02-28 21:46:24 +0000703{
704 PyObject *mod, *dict, *func = NULL;
705
706 mod = PyImport_ImportModule("warnings");
707 if (mod != NULL) {
708 dict = PyModule_GetDict(mod);
709 func = PyDict_GetItemString(dict, "warn_explicit");
710 Py_DECREF(mod);
711 }
712 if (func == NULL) {
713 PySys_WriteStderr("warning: %s\n", message);
714 return 0;
715 }
716 else {
Thomas Wouters477c8d52006-05-27 19:21:47 +0000717 PyObject *res;
Guido van Rossum2fd45652001-02-28 21:46:24 +0000718
719 if (category == NULL)
720 category = PyExc_RuntimeWarning;
721 if (registry == NULL)
722 registry = Py_None;
Thomas Wouters477c8d52006-05-27 19:21:47 +0000723 res = PyObject_CallFunction(func, "sOsizO", message, category,
724 filename, lineno, module, registry);
Guido van Rossum2fd45652001-02-28 21:46:24 +0000725 if (res == NULL)
726 return -1;
727 Py_DECREF(res);
728 return 0;
729 }
730}
731
732
Martin v. Löwiscfeb3b62002-03-03 21:30:27 +0000733/* Set file and line information for the current exception.
734 If the exception is not a SyntaxError, also sets additional attributes
735 to make printing of exceptions believe it is a syntax error. */
Guido van Rossum2fd45652001-02-28 21:46:24 +0000736
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000737void
Martin v. Löwis95292d62002-12-11 14:04:59 +0000738PyErr_SyntaxLocation(const char *filename, int lineno)
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000739{
740 PyObject *exc, *v, *tb, *tmp;
741
742 /* add attributes for the line number and filename for the error */
743 PyErr_Fetch(&exc, &v, &tb);
744 PyErr_NormalizeException(&exc, &v, &tb);
Thomas Wouters477c8d52006-05-27 19:21:47 +0000745 /* XXX check that it is, indeed, a syntax error. It might not
746 * be, though. */
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000747 tmp = PyInt_FromLong(lineno);
748 if (tmp == NULL)
749 PyErr_Clear();
750 else {
751 if (PyObject_SetAttrString(v, "lineno", tmp))
752 PyErr_Clear();
753 Py_DECREF(tmp);
754 }
755 if (filename != NULL) {
Neal Norwitzcd795962007-08-24 19:54:13 +0000756 tmp = PyUnicode_FromString(filename);
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000757 if (tmp == NULL)
758 PyErr_Clear();
759 else {
760 if (PyObject_SetAttrString(v, "filename", tmp))
761 PyErr_Clear();
762 Py_DECREF(tmp);
763 }
764
765 tmp = PyErr_ProgramText(filename, lineno);
766 if (tmp) {
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000767 if (PyObject_SetAttrString(v, "text", tmp))
768 PyErr_Clear();
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000769 Py_DECREF(tmp);
770 }
771 }
Martin v. Löwiscfeb3b62002-03-03 21:30:27 +0000772 if (PyObject_SetAttrString(v, "offset", Py_None)) {
773 PyErr_Clear();
774 }
775 if (exc != PyExc_SyntaxError) {
776 if (!PyObject_HasAttrString(v, "msg")) {
777 tmp = PyObject_Str(v);
778 if (tmp) {
779 if (PyObject_SetAttrString(v, "msg", tmp))
780 PyErr_Clear();
781 Py_DECREF(tmp);
782 } else {
783 PyErr_Clear();
784 }
785 }
786 if (!PyObject_HasAttrString(v, "print_file_and_line")) {
787 if (PyObject_SetAttrString(v, "print_file_and_line",
788 Py_None))
789 PyErr_Clear();
790 }
791 }
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000792 PyErr_Restore(exc, v, tb);
793}
794
795/* com_fetch_program_text will attempt to load the line of text that
796 the exception refers to. If it fails, it will return NULL but will
Brett Cannonbf364092006-03-01 04:25:17 +0000797 not set an exception.
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000798
799 XXX The functionality of this function is quite similar to the
800 functionality in tb_displayline() in traceback.c.
801*/
802
803PyObject *
Martin v. Löwis95292d62002-12-11 14:04:59 +0000804PyErr_ProgramText(const char *filename, int lineno)
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000805{
806 FILE *fp;
807 int i;
808 char linebuf[1000];
809
Tim Petersa7444f42006-02-27 23:29:46 +0000810 if (filename == NULL || *filename == '\0' || lineno <= 0)
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000811 return NULL;
Jack Jansen7b8c7542002-04-14 20:12:41 +0000812 fp = fopen(filename, "r" PY_STDIOTEXTMODE);
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000813 if (fp == NULL)
814 return NULL;
815 for (i = 0; i < lineno; i++) {
816 char *pLastChar = &linebuf[sizeof(linebuf) - 2];
817 do {
818 *pLastChar = '\0';
Jack Jansen7b8c7542002-04-14 20:12:41 +0000819 if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, fp, NULL) == NULL)
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000820 break;
821 /* fgets read *something*; if it didn't get as
822 far as pLastChar, it must have found a newline
Thomas Wouters477c8d52006-05-27 19:21:47 +0000823 or hit the end of the file; if pLastChar is \n,
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000824 it obviously found a newline; else we haven't
825 yet seen a newline, so must continue */
826 } while (*pLastChar != '\0' && *pLastChar != '\n');
827 }
828 fclose(fp);
829 if (i == lineno) {
830 char *p = linebuf;
831 while (*p == ' ' || *p == '\t' || *p == '\014')
832 p++;
Neal Norwitzcd795962007-08-24 19:54:13 +0000833 return PyUnicode_FromString(p);
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000834 }
835 return NULL;
836}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000837
838#ifdef __cplusplus
839}
840#endif