blob: 4708a27bfc6d6e471872b2ddb94b38163476861e [file] [log] [blame]
Damiend99b0522013-12-21 18:17:45 +00001#include <stdlib.h>
2#include <stdint.h>
3#include <string.h>
Damien George6c73ca12014-01-08 18:11:23 +00004#include <stdarg.h>
Damiend99b0522013-12-21 18:17:45 +00005#include <assert.h>
6
7#include "nlr.h"
8#include "misc.h"
9#include "mpconfig.h"
10#include "obj.h"
11
12typedef struct mp_obj_exception_t {
13 mp_obj_base_t base;
14 qstr id;
15 int n_args;
16 const void *args[];
17} mp_obj_exception_t;
18
19void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
20 mp_obj_exception_t *o = o_in;
21 switch (o->n_args) {
22 case 0:
23 print(env, "%s", qstr_str(o->id));
24 break;
25 case 1:
26 print(env, "%s: %s", qstr_str(o->id), (const char*)o->args[0]);
27 break;
28 case 2:
29 print(env, "%s: ", qstr_str(o->id));
30 print(env, (const char*)o->args[0], o->args[1]);
31 break;
32 default: // here we just assume at least 3 args, but only use first 3
33 print(env, "%s: ", qstr_str(o->id));
34 print(env, (const char*)o->args[0], o->args[1], o->args[2]);
35 break;
36 }
37}
38
39const mp_obj_type_t exception_type = {
40 { &mp_const_type },
41 "exception",
Damien George97209d32014-01-07 15:58:30 +000042 .print = exception_print,
Damiend99b0522013-12-21 18:17:45 +000043};
44
45mp_obj_t mp_obj_new_exception(qstr id) {
46 mp_obj_exception_t *o = m_new_obj(mp_obj_exception_t);
47 o->base.type = &exception_type;
48 o->id = id;
49 o->n_args = 0;
50 return o;
51}
52
53mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg) {
54 mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 1);
55 o->base.type = &exception_type;
56 o->id = id;
57 o->n_args = 1;
58 o->args[0] = msg;
59 return o;
60}
61
62mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1) {
63 mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 2);
64 o->base.type = &exception_type;
65 o->id = id;
66 o->n_args = 2;
67 o->args[0] = fmt;
68 o->args[1] = a1;
69 return o;
70}
71
72mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2) {
73 mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 3);
74 o->base.type = &exception_type;
75 o->id = id;
76 o->n_args = 3;
77 o->args[0] = fmt;
78 o->args[1] = a1;
79 o->args[2] = a2;
80 return o;
81}
Damienb86e3f92013-12-29 17:17:43 +000082
Damien George6c73ca12014-01-08 18:11:23 +000083mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) {
84 // count number of arguments by number of % signs, excluding %%
85 int n_args = 1; // count fmt
86 for (const char *s = fmt; *s; s++) {
87 if (*s == '%') {
88 if (s[1] == '%') {
89 s += 1;
90 } else {
91 n_args += 1;
92 }
93 }
94 }
95
96 // make exception object
97 mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, n_args);
98 o->base.type = &exception_type;
99 o->id = id;
100 o->n_args = n_args;
101 o->args[0] = fmt;
102
103 // extract args and store them
104 va_list ap;
105 va_start(ap, fmt);
106 for (int i = 1; i < n_args; i++) {
107 o->args[i] = va_arg(ap, void*);
108 }
109 va_end(ap);
110
111 return o;
112}
113
Damienb86e3f92013-12-29 17:17:43 +0000114qstr mp_obj_exception_get_type(mp_obj_t self_in) {
115 assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
116 mp_obj_exception_t *self = self_in;
117 return self->id;
118}