mruby/c VM Source Code master (2026/08/06)
Loading...
Searching...
No Matches
error.c
Go to the documentation of this file.
1
14
15/***** Feature test switches ************************************************/
16/***** System headers *******************************************************/
17//@cond
18#include "vm_config.h"
19#include <string.h>
20#include <stdarg.h>
21//@endcond
22
23/***** Local headers ********************************************************/
24#include "mrubyc.h"
25
26/***** Constat values *******************************************************/
27/***** Macros ***************************************************************/
28/***** Typedefs *************************************************************/
29/***** Function prototypes **************************************************/
30/***** Local variables ******************************************************/
31/***** Global variables *****************************************************/
32/***** Local functions ******************************************************/
33static mrbc_exception * sub_exception_new(struct VM *vm, struct RClass *exc_cls)
34{
35 // allocate memory for instance.
36 mrbc_exception *ex = mrbc_alloc( vm, sizeof(mrbc_exception) );
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
69 // in case of no message.
70 if( !message ) {
71 ex->message = 0;
72 ex->message_size = 0;
73 goto RETURN;
74 }
75
76 // in case of message is ""
77 if( *(const char *)message == 0 ) {
78 ex->message = (const uint8_t *)"";
79 ex->message_size = 0;
80 goto RETURN;
81 }
82
83 // in case of message in ROM.
84 if( len == 0 ) {
85 ex->message = message;
86 ex->message_size = 0;
87 goto RETURN;
88 }
89
90 // else, copy the message.
91 uint8_t *buf = mrbc_alloc( vm, len+1 );
92
93 memcpy( buf, message, len );
94 buf[len] = 0;
95 ex->message_size = len;
96 ex->message = buf;
97
98 RETURN:
99 return mrbc_immediate_value(MRBC_TT_EXCEPTION, .exception = ex);
100}
101
102
103//================================================================
112mrbc_value mrbc_exception_new_alloc(struct VM *vm, struct RClass *exc_cls, const void *message, int len )
113{
114 mrbc_exception *ex = sub_exception_new( vm, exc_cls );
115
116 ex->message_size = len;
117 ex->message = message;
118
119 return mrbc_immediate_value(MRBC_TT_EXCEPTION, .exception = ex);
120}
121
122
123//================================================================
129{
130 if( value->exception->message_size ) {
131 mrbc_raw_free( (void *)value->exception->message );
132 }
133 mrbc_raw_free( value->exception );
134}
135
136
137//================================================================
145void mrbc_raise( struct VM *vm, struct RClass *exc_cls, const char *msg )
146{
147 if( vm ) {
148 struct RClass *cls = exc_cls ? exc_cls : MRBC_CLASS(RuntimeError);
149 const char msg_len = msg ? strlen(msg) : 0;
150
152 vm->exception = mrbc_exception_new( vm, cls, msg, msg_len );
153 vm->flag_preemption = 2;
154
155 } else {
156 mrbc_printf("Exception: %s (%s)\n", msg ? msg : mrbc_symid_to_str(exc_cls->sym_id), mrbc_symid_to_str(exc_cls->sym_id));
157 }
158}
159
160
161//================================================================
168void mrbc_raisef( struct VM *vm, struct RClass *exc_cls, const char *fstr, ... )
169{
170 static const int MESSAGE_INI_LEN = 32;
171 va_list ap;
172 va_start( ap, fstr );
173
174 char *buf = 0;
175 if( vm ) buf = mrbc_alloc( vm, MESSAGE_INI_LEN );
176
177 if( buf ) {
178 mrbc_vasprintf( &buf, MESSAGE_INI_LEN, fstr, ap );
181 exc_cls ? exc_cls : MRBC_CLASS(RuntimeError),
182 buf, strlen(buf) );
183 vm->flag_preemption = 2;
184
185 } else {
186 // VM == NULL or ENOMEM
187 mrbc_printf("Exception: ");
188 mrbc_vprintf( fstr, ap );
189 mrbc_printf(" (%s)\n", exc_cls ? mrbc_symid_to_str(exc_cls->sym_id) : "RuntimeError");
190 }
191
192 va_end( ap );
193}
194
195
196//================================================================
201void mrbc_clear_exception( struct VM *vm )
202{
205 vm->flag_preemption = 0;
206}
207
208
209//================================================================
215{
216 if( mrbc_type(*v) != MRBC_TT_EXCEPTION ) return;
217
218 const mrbc_exception *exc = v->exception;
219 const char *clsname = mrbc_symid_to_str(exc->cls->sym_id);
220
221 mrbc_printf("Exception: %s (%s)\n",
222 exc->message ? (const char *)exc->message : clsname, clsname );
223}
224
225
226//================================================================
231void mrbc_print_vm_exception( const struct VM *vm )
232{
233 if( mrbc_type(vm->exception) != MRBC_TT_EXCEPTION ) return;
234
235 const mrbc_exception *exc = vm->exception.exception;
236 const char *clsname = mrbc_symid_to_str(exc->cls->sym_id);
237
238 mrbc_printf("Exception(vm_id=%d):", vm->vm_id );
239 if( exc->method_id ) {
240 mrbc_printf(" in `%s':", mrbc_symid_to_str(exc->method_id) );
241 }
242 mrbc_printf(" %s (%s)\n",
243 exc->message ? (const char *)exc->message : clsname, clsname );
244
245 for( int i = 0; i < MRBC_EXCEPTION_CALL_NEST_LEVEL; i++ ) {
246 if( !exc->call_nest[i] ) return;
247 mrbc_printf("\tin `%s'\n", mrbc_symid_to_str(exc->call_nest[i]));
248 }
249 mrbc_printf("\tin ...\n");
250}
251
252
253
254/***** Exception class ******************************************************/
255//================================================================
258static void c_exception_new(struct VM *vm, mrbc_value v[], int argc)
259{
260 assert( mrbc_type(v[0]) == MRBC_TT_CLASS );
261
262 mrbc_value value;
263#if MRBC_USE_STRING
264 if( argc == 1 && mrbc_type(v[1]) == MRBC_TT_STRING ) {
265 value = mrbc_exception_new(vm, v[0].cls, mrbc_string_cstr(&v[1]), mrbc_string_size(&v[1]));
266 } else {
267#endif
268 value = mrbc_exception_new(vm, v[0].cls, NULL, 0);
269#if MRBC_USE_STRING
270 }
271#endif
272
273 SET_RETURN(value);
274}
275
276
277#if MRBC_USE_STRING
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#endif
295
296
297/* mruby/c Exception class hierarchy.
298
299 Exception
300 NoMemoryError
301 NotImplementedError
302 StandardError
303 ArgumentError
304 IndexError
305 IOError
306 NameError
307 NoMethodError
308 NoMatchingPatternError
309 RangeError
310 RuntimeError
311 TypeError
312 ZeroDivisionError
313*/
314
315/* MRBC_AUTOGEN_METHOD_TABLE
316 FILE("_autogen_class_exception.h")
317
318 CLASS("Exception")
319 METHOD("new", c_exception_new )
320#if MRBC_USE_STRING
321 METHOD("message", c_exception_message )
322#endif
323
324 CLASS("NoMemoryError")
325 SUPER("Exception")
326
327 CLASS("NotImplementedError")
328 SUPER("Exception")
329
330 CLASS("StandardError")
331 SUPER("Exception")
332
333 CLASS("ArgumentError")
334 SUPER("StandardError")
335
336 CLASS("IndexError")
337 SUPER("StandardError")
338
339 CLASS("IOError")
340 SUPER("StandardError")
341
342 CLASS("NameError")
343 SUPER("StandardError")
344
345 CLASS("NoMethodError")
346 SUPER("NameError")
347
348 CLASS("NoMatchingPatternError")
349 SUPER("StandardError")
350
351 CLASS("RangeError")
352 SUPER("StandardError")
353
354 CLASS("RuntimeError")
355 SUPER("StandardError")
356
357 CLASS("TypeError")
358 SUPER("StandardError")
359
360 CLASS("ZeroDivisionError")
361 SUPER("StandardError")
362*/
363#include "_autogen_class_exception.h"
void mrbc_raw_free(void *ptr)
Definition alloc.c:707
static void mrbc_set_nil(mrbc_value *p)
Definition boxing_no.h:99
#define mrbc_immediate_value(...)
Definition boxing_no.h:75
#define mrbc_type(o)
Definition boxing_no.h:57
struct RObject mrbc_value
Value object. Default version.
mrbc_value mrbc_string_new(mrbc_vm *vm, const void *src, int len)
Definition c_string.c:64
static char * mrbc_string_cstr(const mrbc_value *v)
Definition c_string.h:122
static mrbc_value mrbc_string_new_cstr(mrbc_vm *vm, const char *src)
Definition c_string.h:91
static int mrbc_string_size(const mrbc_value *str)
Definition c_string.h:114
#define MRBC_CLASS(cls)
Definition class.h:55
void mrbc_printf(const char *fstr,...)
Definition console.c:205
void mrbc_vprintf(const char *fstr, va_list ap)
Definition console.c:266
void mrbc_vasprintf(char **buf, int bufsiz, const char *fstr, va_list ap)
Definition console.c:301
void mrbc_print_exception(const mrbc_value *v)
Definition error.c:214
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:145
void mrbc_print_vm_exception(const struct VM *vm)
Definition error.c:231
void mrbc_exception_delete(mrbc_value *value)
Definition error.c:128
static mrbc_exception * sub_exception_new(struct VM *vm, struct RClass *exc_cls)
Definition error.c:33
mrbc_value mrbc_exception_new_alloc(struct VM *vm, struct RClass *exc_cls, const void *message, int len)
Definition error.c:112
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:168
void mrbc_clear_exception(struct VM *vm)
Definition error.c:201
#define MRBC_EXCEPTION_CALL_NEST_LEVEL
Definition error.h:33
struct RException mrbc_exception
Exception object.
Include at once the necessary header files.
mrbc_sym method_id
called method ID.
Definition vm.h:134
struct CALLINFO * prev
previous linked list.
Definition vm.h:130
Class object.
Definition class.h:87
mrbc_sym sym_id
class name's symbol ID
Definition class.h:97
mrbc_sym call_nest[MRBC_EXCEPTION_CALL_NEST_LEVEL]
Definition error.h:55
struct RClass * cls
exception class.
Definition error.h:51
const uint8_t * message
to heap or ROM.
Definition error.h:54
mrbc_sym method_id
raised method, if it is known.
Definition error.h:52
uint16_t message_size
message length.
Definition error.h:53
struct RException * exception
Definition boxing_no.h:35
Virtual Machine.
Definition vm.h:150
mrbc_callinfo * callinfo_tail
Last point of CALLINFO link.
Definition vm.h:166
uint8_t vm_id
vm_id : 1..MAX_VM_COUNT
Definition vm.h:154
volatile int8_t flag_preemption
Definition vm.h:155
mrbc_value exception
Raised exception or nil.
Definition vm.h:169
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:239
static void mrbc_decref(mrbc_value *v)
Definition value.h:572
#define MRBC_INIT_OBJECT_HEADER(p, t)
Definition value.h:146
@ MRBC_TT_STRING
String.
Definition value.h:98
@ MRBC_TT_EXCEPTION
Exception.
Definition value.h:101
@ MRBC_TT_CLASS
Class.
Definition value.h:90
#define SET_RETURN(n)
Definition value.h:221
struct CALLINFO mrbc_callinfo
Call information.
Global configuration of mruby/c VM's.