|
6
|
1 /* Error handling -- see also run.c */
|
|
|
2
|
|
|
3 /* New error handling interface.
|
|
|
4
|
|
|
5 The following problem exists (existed): methods of built-in modules
|
|
|
6 are called with 'self' and 'args' arguments, but without a context
|
|
|
7 argument, so they have no way to raise a specific exception.
|
|
|
8 The same is true for the object implementations: no context argument.
|
|
|
9 The old convention was to set 'errno' and to return NULL.
|
|
|
10 The caller (usually call_function() in eval.c) detects the NULL
|
|
|
11 return value and then calls puterrno(ctx) to turn the errno value
|
|
|
12 into a true exception. Problems with this approach are:
|
|
|
13 - it used standard errno values to indicate Python-specific errors,
|
|
|
14 but this means that when such an error code is reported by UNIX the
|
|
|
15 user gets a confusing message
|
|
|
16 - errno is a global variable, which makes extensions to a multi-
|
|
|
17 threading environment difficult; e.g., in IRIX, multi-threaded
|
|
|
18 programs must use the function getoserror() (sp.?) instead of
|
|
|
19 looking in errno
|
|
|
20 - there is no portable way to add new error numbers for specic
|
|
|
21 situations -- the value space for errno is reserved to the OS, yet
|
|
|
22 the way to turn module-specific errors into a module-specific
|
|
|
23 exception requires module-specific values for errno
|
|
|
24 - there is no way to add a more situation-specific message to an
|
|
|
25 error.
|
|
|
26
|
|
|
27 The new interface solves all these problems. To return an error, a
|
|
|
28 built-in function calls err_set(exception), err_set(valexception,
|
|
|
29 value) or err_setstr(exception, string), and returns NULL. These
|
|
|
30 functions save the value for later use by puterrno(). To adapt this
|
|
|
31 scheme to a multi-threaded environment, only the implementation of
|
|
|
32 err_setval() has to be changed.
|
|
|
33 */
|
|
|
34
|
|
|
35 #include <stdio.h>
|
|
|
36
|
|
|
37 #include "PROTO.h"
|
|
|
38 #include "object.h"
|
|
|
39 #include "stringobject.h"
|
|
|
40 #include "errors.h"
|
|
|
41
|
|
|
42 /* Last exception stored by err_setval() */
|
|
|
43
|
|
|
44 static object *last_exception;
|
|
|
45 static object *last_exc_val;
|
|
|
46
|
|
|
47 void
|
|
|
48 err_setval(exception, value)
|
|
|
49 object *exception;
|
|
|
50 object *value;
|
|
|
51 {
|
|
|
52 if (last_exception != NULL)
|
|
|
53 DECREF(last_exception);
|
|
|
54 if (exception != NULL)
|
|
|
55 INCREF(exception);
|
|
|
56 last_exception = exception;
|
|
|
57
|
|
|
58 if (last_exc_val != NULL)
|
|
|
59 DECREF(last_exc_val);
|
|
|
60 if (value != NULL)
|
|
|
61 INCREF(value);
|
|
|
62 last_exc_val = value;
|
|
|
63 }
|
|
|
64
|
|
|
65 void
|
|
|
66 err_set(exception)
|
|
|
67 object *exception;
|
|
|
68 {
|
|
|
69 err_setval(exception, (object *)NULL);
|
|
|
70 }
|
|
|
71
|
|
|
72 void
|
|
|
73 err_setstr(exception, string)
|
|
|
74 object *exception;
|
|
|
75 char *string;
|
|
|
76 {
|
|
|
77 object *value = newstringobject(string);
|
|
|
78 err_setval(exception, value);
|
|
|
79 if (value != NULL)
|
|
|
80 DECREF(value);
|
|
|
81 }
|
|
|
82
|
|
|
83 int
|
|
|
84 err_occurred()
|
|
|
85 {
|
|
|
86 return last_exception != NULL;
|
|
|
87 }
|
|
|
88
|
|
|
89 void
|
|
|
90 err_get(p_exc, p_val)
|
|
|
91 object **p_exc;
|
|
|
92 object **p_val;
|
|
|
93 {
|
|
|
94 *p_exc = last_exception;
|
|
|
95 last_exception = NULL;
|
|
|
96 *p_val = last_exc_val;
|
|
|
97 last_exc_val = NULL;
|
|
|
98 }
|
|
|
99
|
|
|
100 void
|
|
|
101 err_clear()
|
|
|
102 {
|
|
|
103 if (last_exception != NULL) {
|
|
|
104 DECREF(last_exception);
|
|
|
105 last_exception = NULL;
|
|
|
106 }
|
|
|
107 if (last_exc_val != NULL) {
|
|
|
108 DECREF(last_exc_val);
|
|
|
109 last_exc_val = NULL;
|
|
|
110 }
|
|
|
111 }
|