mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

mbed-mruby

How to use

Class

Committer:
mzta
Date:
Mon Apr 13 05:20:15 2015 +0000
Revision:
1:8ccd1d494a4b
Parent:
0:158c61bb030f
- code refactoring.; - add SPI, SPISlave, I2C class to mruby-mbed (Incomplete).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mzta 0:158c61bb030f 1 /*
mzta 0:158c61bb030f 2 ** backtrace.c -
mzta 0:158c61bb030f 3 **
mzta 0:158c61bb030f 4 ** See Copyright Notice in mruby.h
mzta 0:158c61bb030f 5 */
mzta 0:158c61bb030f 6
mzta 0:158c61bb030f 7 #include <stdarg.h>
mzta 0:158c61bb030f 8 #include "mruby.h"
mzta 0:158c61bb030f 9 #include "mruby/variable.h"
mzta 0:158c61bb030f 10 #include "mruby/proc.h"
mzta 0:158c61bb030f 11 #include "mruby/array.h"
mzta 0:158c61bb030f 12 #include "mruby/string.h"
mzta 0:158c61bb030f 13 #include "mruby/class.h"
mzta 0:158c61bb030f 14 #include "mruby/debug.h"
mzta 0:158c61bb030f 15 #include "mruby/error.h"
mzta 0:158c61bb030f 16
mzta 0:158c61bb030f 17 #ifdef ENABLE_STDIO
mzta 0:158c61bb030f 18
mzta 0:158c61bb030f 19 typedef void (*output_stream_func)(mrb_state*, void*, int, const char*, ...);
mzta 0:158c61bb030f 20
mzta 0:158c61bb030f 21 static void
mzta 0:158c61bb030f 22 print_backtrace_i(mrb_state *mrb, void *stream, int level, const char *format, ...)
mzta 0:158c61bb030f 23 {
mzta 0:158c61bb030f 24 va_list ap;
mzta 0:158c61bb030f 25
mzta 0:158c61bb030f 26 va_start(ap, format);
mzta 0:158c61bb030f 27 vfprintf((FILE*)stream, format, ap);
mzta 0:158c61bb030f 28 va_end(ap);
mzta 0:158c61bb030f 29 }
mzta 0:158c61bb030f 30
mzta 0:158c61bb030f 31
mzta 0:158c61bb030f 32 #define MIN_BUFSIZE 127
mzta 0:158c61bb030f 33
mzta 0:158c61bb030f 34 static void
mzta 0:158c61bb030f 35 get_backtrace_i(mrb_state *mrb, void *stream, int level, const char *format, ...)
mzta 0:158c61bb030f 36 {
mzta 0:158c61bb030f 37 va_list ap;
mzta 0:158c61bb030f 38 mrb_value ary, str;
mzta 0:158c61bb030f 39 int ai;
mzta 0:158c61bb030f 40
mzta 0:158c61bb030f 41 if (level > 0) {
mzta 0:158c61bb030f 42 return;
mzta 0:158c61bb030f 43 }
mzta 0:158c61bb030f 44
mzta 0:158c61bb030f 45 ai = mrb_gc_arena_save(mrb);
mzta 0:158c61bb030f 46 ary = mrb_obj_value((struct RArray*)stream);
mzta 0:158c61bb030f 47
mzta 0:158c61bb030f 48 va_start(ap, format);
mzta 0:158c61bb030f 49 str = mrb_str_new(mrb, 0, vsnprintf(NULL, 0, format, ap) + 1);
mzta 0:158c61bb030f 50 va_end(ap);
mzta 0:158c61bb030f 51
mzta 0:158c61bb030f 52 va_start(ap, format);
mzta 0:158c61bb030f 53 vsnprintf(RSTRING_PTR(str), RSTRING_LEN(str), format, ap);
mzta 0:158c61bb030f 54 va_end(ap);
mzta 0:158c61bb030f 55
mzta 0:158c61bb030f 56 mrb_str_resize(mrb, str, RSTRING_LEN(str) - 1);
mzta 0:158c61bb030f 57 mrb_ary_push(mrb, ary, str);
mzta 0:158c61bb030f 58 mrb_gc_arena_restore(mrb, ai);
mzta 0:158c61bb030f 59 }
mzta 0:158c61bb030f 60
mzta 0:158c61bb030f 61 static void
mzta 0:158c61bb030f 62 output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *stream)
mzta 0:158c61bb030f 63 {
mzta 0:158c61bb030f 64 mrb_callinfo *ci;
mzta 0:158c61bb030f 65 const char *filename, *method, *sep;
mzta 0:158c61bb030f 66 int i, lineno, tracehead = 1;
mzta 0:158c61bb030f 67
mzta 0:158c61bb030f 68 if (ciidx >= mrb->c->ciend - mrb->c->cibase)
mzta 0:158c61bb030f 69 ciidx = 10; /* ciidx is broken... */
mzta 0:158c61bb030f 70
mzta 0:158c61bb030f 71 for (i = ciidx; i >= 0; i--) {
mzta 0:158c61bb030f 72 ci = &mrb->c->cibase[i];
mzta 0:158c61bb030f 73 filename = NULL;
mzta 0:158c61bb030f 74
mzta 0:158c61bb030f 75 if (!ci->proc) continue;
mzta 0:158c61bb030f 76 if (MRB_PROC_CFUNC_P(ci->proc)) {
mzta 0:158c61bb030f 77 continue;
mzta 0:158c61bb030f 78 }
mzta 0:158c61bb030f 79 else {
mzta 0:158c61bb030f 80 mrb_irep *irep = ci->proc->body.irep;
mzta 0:158c61bb030f 81 mrb_code *pc;
mzta 0:158c61bb030f 82
mzta 0:158c61bb030f 83 if (mrb->c->cibase[i].err) {
mzta 0:158c61bb030f 84 pc = mrb->c->cibase[i].err;
mzta 0:158c61bb030f 85 }
mzta 0:158c61bb030f 86 else if (i+1 <= ciidx) {
mzta 0:158c61bb030f 87 pc = mrb->c->cibase[i+1].pc - 1;
mzta 0:158c61bb030f 88 }
mzta 0:158c61bb030f 89 else {
mzta 0:158c61bb030f 90 pc = pc0;
mzta 0:158c61bb030f 91 }
mzta 0:158c61bb030f 92 filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq));
mzta 0:158c61bb030f 93 lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq));
mzta 0:158c61bb030f 94 }
mzta 0:158c61bb030f 95 if (lineno == -1) continue;
mzta 0:158c61bb030f 96 if (ci->target_class == ci->proc->target_class)
mzta 0:158c61bb030f 97 sep = ".";
mzta 0:158c61bb030f 98 else
mzta 0:158c61bb030f 99 sep = "#";
mzta 0:158c61bb030f 100
mzta 0:158c61bb030f 101 if (!filename) {
mzta 0:158c61bb030f 102 filename = "(unknown)";
mzta 0:158c61bb030f 103 }
mzta 0:158c61bb030f 104
mzta 0:158c61bb030f 105 if (tracehead) {
mzta 0:158c61bb030f 106 func(mrb, stream, 1, "trace:\n");
mzta 0:158c61bb030f 107 tracehead = 0;
mzta 0:158c61bb030f 108 }
mzta 0:158c61bb030f 109 method = mrb_sym2name(mrb, ci->mid);
mzta 0:158c61bb030f 110 if (method) {
mzta 0:158c61bb030f 111 const char *cn = mrb_class_name(mrb, ci->proc->target_class);
mzta 0:158c61bb030f 112
mzta 0:158c61bb030f 113 if (cn) {
mzta 0:158c61bb030f 114 func(mrb, stream, 1, "\t[%d] ", i);
mzta 0:158c61bb030f 115 func(mrb, stream, 0, "%s:%d:in %s%s%s", filename, lineno, cn, sep, method);
mzta 0:158c61bb030f 116 func(mrb, stream, 1, "\n");
mzta 0:158c61bb030f 117 }
mzta 0:158c61bb030f 118 else {
mzta 0:158c61bb030f 119 func(mrb, stream, 1, "\t[%d] ", i);
mzta 0:158c61bb030f 120 func(mrb, stream, 0, "%s:%d:in %s", filename, lineno, method);
mzta 0:158c61bb030f 121 func(mrb, stream, 1, "\n");
mzta 0:158c61bb030f 122 }
mzta 0:158c61bb030f 123 }
mzta 0:158c61bb030f 124 else {
mzta 0:158c61bb030f 125 func(mrb, stream, 1, "\t[%d] ", i);
mzta 0:158c61bb030f 126 func(mrb, stream, 0, "%s:%d", filename, lineno);
mzta 0:158c61bb030f 127 func(mrb, stream, 1, "\n");
mzta 0:158c61bb030f 128 }
mzta 0:158c61bb030f 129 }
mzta 0:158c61bb030f 130 }
mzta 0:158c61bb030f 131
mzta 0:158c61bb030f 132 static void
mzta 0:158c61bb030f 133 exc_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func func, void *stream)
mzta 0:158c61bb030f 134 {
mzta 0:158c61bb030f 135 output_backtrace(mrb, mrb_fixnum(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "ciidx"))),
mzta 0:158c61bb030f 136 (mrb_code*)mrb_cptr(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "lastpc"))),
mzta 0:158c61bb030f 137 func, stream);
mzta 0:158c61bb030f 138 }
mzta 0:158c61bb030f 139
mzta 0:158c61bb030f 140 /* mrb_print_backtrace/mrb_get_backtrace:
mzta 0:158c61bb030f 141
mzta 0:158c61bb030f 142 function to retrieve backtrace information from the exception.
mzta 0:158c61bb030f 143 note that if you call method after the exception, call stack will be
mzta 0:158c61bb030f 144 overwritten. So invoke these functions just after detecting exceptions.
mzta 0:158c61bb030f 145 */
mzta 0:158c61bb030f 146
mzta 0:158c61bb030f 147 MRB_API void
mzta 0:158c61bb030f 148 mrb_print_backtrace(mrb_state *mrb)
mzta 0:158c61bb030f 149 {
mzta 0:158c61bb030f 150 if (!mrb->exc || mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), E_SYSSTACK_ERROR)) {
mzta 0:158c61bb030f 151 return;
mzta 0:158c61bb030f 152 }
mzta 0:158c61bb030f 153 exc_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)stderr);
mzta 0:158c61bb030f 154 }
mzta 0:158c61bb030f 155
mzta 0:158c61bb030f 156 MRB_API mrb_value
mzta 0:158c61bb030f 157 mrb_exc_backtrace(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 158 {
mzta 0:158c61bb030f 159 mrb_value ary;
mzta 0:158c61bb030f 160
mzta 0:158c61bb030f 161 ary = mrb_ary_new(mrb);
mzta 0:158c61bb030f 162 exc_output_backtrace(mrb, mrb_obj_ptr(self), get_backtrace_i, (void*)mrb_ary_ptr(ary));
mzta 0:158c61bb030f 163
mzta 0:158c61bb030f 164 return ary;
mzta 0:158c61bb030f 165 }
mzta 0:158c61bb030f 166
mzta 0:158c61bb030f 167 MRB_API mrb_value
mzta 0:158c61bb030f 168 mrb_get_backtrace(mrb_state *mrb)
mzta 0:158c61bb030f 169 {
mzta 0:158c61bb030f 170 mrb_value ary;
mzta 0:158c61bb030f 171 mrb_callinfo *ci = mrb->c->ci;
mzta 0:158c61bb030f 172 mrb_code *pc = ci->pc;
mzta 0:158c61bb030f 173 mrb_int ciidx = (mrb_int)(ci - mrb->c->cibase - 1);
mzta 0:158c61bb030f 174
mzta 0:158c61bb030f 175 if (ciidx < 0) ciidx = 0;
mzta 0:158c61bb030f 176 ary = mrb_ary_new(mrb);
mzta 0:158c61bb030f 177 output_backtrace(mrb, ciidx, pc, get_backtrace_i, (void*)mrb_ary_ptr(ary));
mzta 0:158c61bb030f 178
mzta 0:158c61bb030f 179 return ary;
mzta 0:158c61bb030f 180 }
mzta 0:158c61bb030f 181
mzta 0:158c61bb030f 182 #else
mzta 0:158c61bb030f 183
mzta 0:158c61bb030f 184 MRB_API void
mzta 0:158c61bb030f 185 mrb_print_backtrace(mrb_state *mrb)
mzta 0:158c61bb030f 186 {
mzta 0:158c61bb030f 187 }
mzta 0:158c61bb030f 188
mzta 0:158c61bb030f 189 MRB_API mrb_value
mzta 0:158c61bb030f 190 mrb_exc_backtrace(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 191 {
mzta 0:158c61bb030f 192 return mrb_ary_new(mrb);
mzta 0:158c61bb030f 193 }
mzta 0:158c61bb030f 194
mzta 0:158c61bb030f 195 MRB_API mrb_value
mzta 0:158c61bb030f 196 mrb_get_backtrace(mrb_state *mrb)
mzta 0:158c61bb030f 197 {
mzta 0:158c61bb030f 198 return mrb_ary_new(mrb);
mzta 0:158c61bb030f 199 }
mzta 0:158c61bb030f 200
mzta 0:158c61bb030f 201 #endif
mzta 0:158c61bb030f 202