mruby/c VM Source Code release 3.4
Loading...
Searching...
No Matches
error.c
Go to the documentation of this file.
1
13
14/***** Feature test switches ************************************************/
15/***** System headers *******************************************************/
16//@cond
17#include "vm_config.h"
18#include <string.h>
19#include <stdarg.h>
20//@endcond
21
22/***** Local headers ********************************************************/
23#include "mrubyc.h"
24
25/***** Constat values *******************************************************/
26/***** Macros ***************************************************************/
27/***** Typedefs *************************************************************/
28/***** Function prototypes **************************************************/
29/***** Local variables ******************************************************/
30/***** Global variables *****************************************************/
31/***** Local functions ******************************************************/
32static mrbc_exception * sub_exception_new(struct VM *vm, struct RClass *exc_cls)
33{
34 // allocate memory for instance.
35 mrbc_exception *ex = mrbc_alloc( vm, sizeof(mrbc_exception) );
36 if( !ex ) return ex; // ENOMEM
37
38 MRBC_INIT_OBJECT_HEADER( ex, "EX" );
39 ex->cls = exc_cls;
40 ex->method_id = 0;
41
42 mrbc_callinfo *callinfo = vm->callinfo_tail;
43 for( int i = 0; i < MRBC_EXCEPTION_CALL_NEST_LEVEL; i++ ) {
44 if( callinfo ) {
45 ex->call_nest[i] = callinfo->method_id;
46 callinfo = callinfo->prev;
47 } else {
48 ex->call_nest[i] = 0;
49 }
50 }
51
52 return ex;
53}
54
55/***** Global functions *****************************************************/
56//================================================================
65mrbc_value mrbc_exception_new(struct VM *vm, struct RClass *exc_cls, const void *message, int len )
66{
67 mrbc_exception *ex = sub_exception_new( vm, exc_cls );
68 if( !ex ) return mrbc_nil_value();
69
70 // in case of no message.
71 if( !message ) {
72 ex->message = 0;
73 ex->message_size = 0;
74 goto RETURN;
75 }
76
77 // in case of message is ""
78 if( *(const char *)message == 0 ) {
79 ex->message = (const uint8_t *)"";
80 ex->message_size = 0;
81 goto RETURN;
82 }
83
84 // in case of message in ROM.
85 if( len == 0 ) {
86 ex->message = message;
87 ex->message_size = 0;
88 goto RETURN;
89 }
90
91 // else, copy the message.
92 uint8_t *buf = mrbc_alloc( vm, len+1 );
93 if( buf ) {
94 memcpy( buf, message, len );
95 buf[len] = 0;
96 ex->message_size = len;
97 } else {
98 ex->message_size = 0;
99 }
100 ex->message = buf;
101
102 RETURN:
103 return (mrbc_value){.tt = MRBC_TT_EXCEPTION, .exception = ex};
104}
105
106
107//================================================================
116mrbc_value mrbc_exception_new_alloc(struct VM *vm, struct RClass *exc_cls, const void *message, int len )
117{
118 mrbc_exception *ex = sub_exception_new( vm, exc_cls );
119 if( !ex ) return mrbc_nil_value();
120
121 ex->message_size = len;
122 ex->message = message;
123
124 return (mrbc_value){.tt = MRBC_TT_EXCEPTION, .exception = ex};
125}
126
127
128//================================================================
134{
135 if( value->exception->message_size ) {
136 mrbc_raw_free( (void *)value->exception->message );
137 }
138 mrbc_raw_free( value->exception );
139}
140
141
142//================================================================
150void mrbc_raise( struct VM *vm, struct RClass *exc_cls, const char *msg )
151{
152 if( vm ) {
153 struct RClass *cls = exc_cls ? exc_cls : MRBC_CLASS(RuntimeError);
154 const char msg_len = msg ? strlen(msg) : 0;
155
157 vm->exception = mrbc_exception_new( vm, cls, msg, msg_len );
158 vm->flag_preemption = 2;
159
160 } else {
161 mrbc_printf("Exception: %s (%s)\n", msg ? msg : mrbc_symid_to_str(exc_cls->sym_id), mrbc_symid_to_str(exc_cls->sym_id));
162 }
163}
164
165
166//================================================================
173void mrbc_raisef( struct VM *vm, struct RClass *exc_cls, const char *fstr, ... )
174{
175 static const int MESSAGE_INI_LEN = 32;
176 va_list ap;
177 va_start( ap, fstr );
178
179 char *buf = 0;
180 if( vm ) buf = mrbc_alloc( vm, MESSAGE_INI_LEN );
181
182 if( buf ) {
183 mrbc_vasprintf( &buf, MESSAGE_INI_LEN, fstr, ap );
186 exc_cls ? exc_cls : MRBC_CLASS(RuntimeError),
187 buf, strlen(buf) );
188 vm->flag_preemption = 2;
189
190 } else {
191 // VM == NULL or ENOMEM
192 mrbc_printf("Exception: ");
193 mrbc_vprintf( fstr, ap );
194 mrbc_printf(" (%s)\n", exc_cls ? mrbc_symid_to_str(exc_cls->sym_id) : "RuntimeError");
195 }
196
197 va_end( ap );
198}
199
200
201//================================================================
206void mrbc_clear_exception( struct VM *vm )
207{
210 vm->flag_preemption = 0;
211}
212
213
214//================================================================
220{
221 if( mrbc_type(*v) != MRBC_TT_EXCEPTION ) return;
222
223 const mrbc_exception *exc = v->exception;
224 const char *clsname = mrbc_symid_to_str(exc->cls->sym_id);
225
226 mrbc_printf("Exception: %s (%s)\n",
227 exc->message ? (const char *)exc->message : clsname, clsname );
228}
229
230
231//================================================================
236void mrbc_print_vm_exception( const struct VM *vm )
237{
238 if( mrbc_type(vm->exception) != MRBC_TT_EXCEPTION ) return;
239
240 const mrbc_exception *exc = vm->exception.exception;
241 const char *clsname = mrbc_symid_to_str(exc->cls->sym_id);
242
243 mrbc_printf("Exception(vm_id=%d):", vm->vm_id );
244 if( exc->method_id ) {
245 mrbc_printf(" in `%s':", mrbc_symid_to_str(exc->method_id) );
246 }
247 mrbc_printf(" %s (%s)\n",
248 exc->message ? (const char *)exc->message : clsname, clsname );
249
250 for( int i = 0; i < MRBC_EXCEPTION_CALL_NEST_LEVEL; i++ ) {
251 if( !exc->call_nest[i] ) return;
252 mrbc_printf("\tin `%s'\n", mrbc_symid_to_str(exc->call_nest[i]));
253 }
254 mrbc_printf("\tin ...\n");
255}
256
257
258
259/***** Exception class ******************************************************/
260//================================================================
263static void c_exception_new(struct VM *vm, mrbc_value v[], int argc)
264{
265 assert( mrbc_type(v[0]) == MRBC_TT_CLASS );
266
267 mrbc_value value;
268 if( argc == 1 && mrbc_type(v[1]) == MRBC_TT_STRING ) {
269 value = mrbc_exception_new(vm, v[0].cls, mrbc_string_cstr(&v[1]), mrbc_string_size(&v[1]));
270 } else {
271 value = mrbc_exception_new(vm, v[0].cls, NULL, 0);
272 }
273
274 SET_RETURN(value);
275}
276
277
278//================================================================
281static void c_exception_message(struct VM *vm, mrbc_value v[], int argc)
282{
283 mrbc_value value;
284
285 if( v[0].exception->message ) {
286 value = mrbc_string_new( vm, v[0].exception->message, v[0].exception->message_size );
287 } else {
289 }
290
291 mrbc_decref( &v[0] );
292 v[0] = value;
293}
294
295
296/* mruby/c Exception class hierarchy.
297
298 Exception
299 NoMemoryError
300 NotImplementedError
301 StandardError
302 ArgumentError
303 IndexError
304 IOError
305 NameError
306 NoMethodError
307 RangeError
308 RuntimeError
309 TypeError
310 ZeroDivisionError
311*/
312
313/* MRBC_AUTOGEN_METHOD_TABLE
314 FILE("_autogen_class_exception.h")
315
316 CLASS("Exception")
317 METHOD("new", c_exception_new )
318 METHOD("message", c_exception_message )
319
320 CLASS("NoMemoryError")
321 SUPER("Exception")
322
323 CLASS("NotImplementedError")
324 SUPER("Exception")
325
326 CLASS("StandardError")
327 SUPER("Exception")
328
329 CLASS("ArgumentError")
330 SUPER("StandardError")
331
332 CLASS("IndexError")
333 SUPER("StandardError")
334
335 CLASS("IOError")
336 SUPER("StandardError")
337
338 CLASS("NameError")
339 SUPER("StandardError")
340
341 CLASS("NoMethodError")
342 SUPER("NameError")
343
344 CLASS("RangeError")
345 SUPER("StandardError")
346
347 CLASS("RuntimeError")
348 SUPER("StandardError")
349
350 CLASS("TypeError")
351 SUPER("StandardError")
352
353 CLASS("ZeroDivisionError")
354 SUPER("StandardError")
355*/
356#include "_autogen_class_exception.h"
void mrbc_raw_free(void *ptr)
Definition alloc.c:695
mrbc_value mrbc_string_new(struct VM *vm, const void *src, int len)
Definition c_string.c:62
static char * mrbc_string_cstr(const mrbc_value *v)
Definition c_string.h:116
static mrbc_value mrbc_string_new_cstr(struct VM *vm, const char *src)
Definition c_string.h:85
static int mrbc_string_size(const mrbc_value *str)
Definition c_string.h:108
#define MRBC_CLASS(cls)
Definition class.h:51
void mrbc_printf(const char *fstr,...)
Definition console.c:180
void mrbc_vprintf(const char *fstr, va_list ap)
Definition console.c:241
void mrbc_vasprintf(char **buf, int bufsiz, const char *fstr, va_list ap)
Definition console.c:276
void mrbc_print_exception(const mrbc_value *v)
Definition error.c:219
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:150
void mrbc_print_vm_exception(const struct VM *vm)
Definition error.c:236
void mrbc_exception_delete(mrbc_value *value)
Definition error.c:133
static mrbc_exception * sub_exception_new(struct VM *vm, struct RClass *exc_cls)
Definition error.c:32
mrbc_value mrbc_exception_new_alloc(struct VM *vm, struct RClass *exc_cls, const void *message, int len)
Definition error.c:116
mrbc_value mrbc_exception_new(struct VM *vm, struct RClass *exc_cls, const void *message, int len)
Definition error.c:65
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:173
void mrbc_clear_exception(struct VM *vm)
Definition error.c:206
#define MRBC_EXCEPTION_CALL_NEST_LEVEL
Definition error.h:32
struct RException mrbc_exception
Exception object.
Include at once the necessary header files.
mrbc_sym method_id
called method ID.
Definition vm.h:127
struct CALLINFO * prev
previous linked list.
Definition vm.h:119
Class object.
Definition class.h:83
mrbc_sym sym_id
class name's symbol ID
Definition class.h:84
mrbc_sym call_nest[MRBC_EXCEPTION_CALL_NEST_LEVEL]
Definition error.h:54
struct RClass * cls
exception class.
Definition error.h:50
const uint8_t * message
to heap or ROM.
Definition error.h:53
mrbc_sym method_id
raised method, if it is known.
Definition error.h:51
uint16_t message_size
message length.
Definition error.h:52
struct RException * exception
Definition value.h:167
Virtual Machine.
Definition vm.h:140
mrbc_callinfo * callinfo_tail
Last point of CALLINFO link.
Definition vm.h:157
uint8_t vm_id
vm_id : 1..MAX_VM_COUNT
Definition vm.h:144
volatile int8_t flag_preemption
Definition vm.h:145
mrbc_value exception
Raised exception or nil.
Definition vm.h:160
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:238
static void mrbc_decref(mrbc_value *v)
Definition value.h:604
#define mrbc_set_nil(p)
Definition value.h:201
#define MRBC_INIT_OBJECT_HEADER(p, t)
Definition value.h:307
#define mrbc_nil_value()
Definition value.h:210
#define mrbc_type(o)
Definition value.h:193
@ MRBC_TT_STRING
String.
Definition value.h:95
@ MRBC_TT_EXCEPTION
Exception.
Definition value.h:98
@ MRBC_TT_CLASS
Class.
Definition value.h:87
struct RObject mrbc_value
Definition value.h:174
#define SET_RETURN(n)
Definition value.h:261
struct CALLINFO mrbc_callinfo
Call information.
Global configuration of mruby/c VM's.