errors.c revision 87e7ea72a6ef9232be9db06038943044c747971b
1/*********************************************************** 2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The 3Netherlands. 4 5 All Rights Reserved 6 7Permission to use, copy, modify, and distribute this software and its 8documentation for any purpose and without fee is hereby granted, 9provided that the above copyright notice appear in all copies and that 10both that copyright notice and this permission notice appear in 11supporting documentation, and that the names of Stichting Mathematisch 12Centrum or CWI not be used in advertising or publicity pertaining to 13distribution of the software without specific, written prior permission. 14 15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO 16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE 18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 23******************************************************************/ 24 25/* Error handling -- see also run.c */ 26 27/* New error handling interface. 28 29 The following problem exists (existed): methods of built-in modules 30 are called with 'self' and 'args' arguments, but without a context 31 argument, so they have no way to raise a specific exception. 32 The same is true for the object implementations: no context argument. 33 The old convention was to set 'errno' and to return NULL. 34 The caller (usually call_function() in eval.c) detects the NULL 35 return value and then calls puterrno(ctx) to turn the errno value 36 into a true exception. Problems with this approach are: 37 - it used standard errno values to indicate Python-specific errors, 38 but this means that when such an error code is reported by a system 39 call (e.g., in module posix), the user gets a confusing message 40 - errno is a global variable, which makes extensions to a multi- 41 threading environment difficult; e.g., in IRIX, multi-threaded 42 programs must use the function oserror() instead of looking in errno 43 - there is no portable way to add new error numbers for specic 44 situations -- the value space for errno is reserved to the OS, yet 45 the way to turn module-specific errors into a module-specific 46 exception requires module-specific values for errno 47 - there is no way to add a more situation-specific message to an 48 error. 49 50 The new interface solves all these problems. To return an error, a 51 built-in function calls err_set(exception), err_setval(exception, 52 value) or err_setstr(exception, string), and returns NULL. These 53 functions save the value for later use by puterrno(). To adapt this 54 scheme to a multi-threaded environment, only the implementation of 55 err_setval() has to be changed. 56*/ 57 58#include "allobjects.h" 59 60#include <errno.h> 61#ifndef errno 62extern int errno; 63#endif 64 65#include "errcode.h" 66 67extern char *strerror PROTO((int)); 68 69/* Last exception stored by err_setval() */ 70 71static object *last_exception; 72static object *last_exc_val; 73 74void 75err_setval(exception, value) 76 object *exception; 77 object *value; 78{ 79 XDECREF(last_exception); 80 XINCREF(exception); 81 last_exception = exception; 82 83 XDECREF(last_exc_val); 84 XINCREF(value); 85 last_exc_val = value; 86} 87 88void 89err_set(exception) 90 object *exception; 91{ 92 err_setval(exception, (object *)NULL); 93} 94 95void 96err_setstr(exception, string) 97 object *exception; 98 char *string; 99{ 100 object *value = newstringobject(string); 101 err_setval(exception, value); 102 XDECREF(value); 103} 104 105int 106err_occurred() 107{ 108 return last_exception != NULL; 109} 110 111void 112err_get(p_exc, p_val) 113 object **p_exc; 114 object **p_val; 115{ 116 *p_exc = last_exception; 117 last_exception = NULL; 118 *p_val = last_exc_val; 119 last_exc_val = NULL; 120} 121 122void 123err_clear() 124{ 125 XDECREF(last_exception); 126 last_exception = NULL; 127 XDECREF(last_exc_val); 128 last_exc_val = NULL; 129} 130 131/* Convenience functions to set a type error exception and return 0 */ 132 133int 134err_badarg() 135{ 136 err_setstr(TypeError, "illegal argument type for built-in operation"); 137 return 0; 138} 139 140object * 141err_nomem() 142{ 143 err_set(MemoryError); 144 return NULL; 145} 146 147object * 148err_errno(exc) 149 object *exc; 150{ 151 object *v; 152 if (errno == EINTR && intrcheck()) { 153 err_set(KeyboardInterrupt); 154 return NULL; 155 } 156 v = newtupleobject(2); 157 if (v != NULL) { 158 settupleitem(v, 0, newintobject((long)errno)); 159 settupleitem(v, 1, newstringobject(strerror(errno))); 160 } 161 err_setval(exc, v); 162 XDECREF(v); 163 return NULL; 164} 165 166void 167err_badcall() 168{ 169 err_setstr(SystemError, "bad argument to internal function"); 170} 171 172/* Set the error appropriate to the given input error code (see errcode.h) */ 173 174void 175err_input(err) 176 int err; 177{ 178 switch (err) { 179 case E_DONE: 180 case E_OK: 181 break; 182 case E_SYNTAX: 183 err_setstr(ValueError, "syntax error"); 184 break; 185 case E_TOKEN: 186 err_setstr(ValueError, "illegal token"); 187 break; 188 case E_INTR: 189 err_set(KeyboardInterrupt); 190 break; 191 case E_NOMEM: 192 err_nomem(); 193 break; 194 case E_EOF: 195 err_set(EOFError); 196 break; 197 default: 198 err_setstr(SystemError, "unknown input error"); 199 break; 200 } 201} 202