Changeset 439 for EcnlProtoTool/trunk/mruby-2.1.1/src/backtrace.c
- Timestamp:
- Jul 9, 2020, 8:51:43 AM (4 years ago)
- Location:
- EcnlProtoTool/trunk/mruby-2.1.1
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/mruby-2.1.1/src/backtrace.c
r331 r439 17 17 18 18 struct backtrace_location { 19 int lineno; 19 int32_t lineno; 20 mrb_sym method_id; 20 21 const char *filename; 21 mrb_sym method_id;22 22 }; 23 23 24 typedef void (*each_backtrace_func)(mrb_state*, int i,struct backtrace_location*, void*);24 typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*, void*); 25 25 26 26 static const mrb_data_type bt_type = { "Backtrace", mrb_free }; 27 27 28 static void 29 each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func func, void *data) 30 { 31 int i, j; 28 mrb_value mrb_exc_inspect(mrb_state *mrb, mrb_value exc); 29 mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace); 30 31 static void 32 each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtrace_func func, void *data) 33 { 34 ptrdiff_t i; 32 35 33 36 if (ciidx >= mrb->c->ciend - mrb->c->cibase) 34 37 ciidx = 10; /* ciidx is broken... */ 35 38 36 for (i=ciidx , j=0; i >= 0; i--,j++) {39 for (i=ciidx; i >= 0; i--) { 37 40 struct backtrace_location loc; 38 41 mrb_callinfo *ci; 39 42 mrb_irep *irep; 40 mrb_code *pc;43 const mrb_code *pc; 41 44 42 45 ci = &mrb->c->cibase[i]; … … 52 55 } 53 56 else if (i+1 <= ciidx) { 54 pc = mrb->c->cibase[i+1].pc - 1; 57 if (!mrb->c->cibase[i + 1].pc) continue; 58 pc = &mrb->c->cibase[i+1].pc[-1]; 55 59 } 56 60 else { 57 61 pc = pc0; 58 62 } 59 loc.filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq)); 60 loc.lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq)); 61 63 64 loc.lineno = mrb_debug_get_line(mrb, irep, pc - irep->iseq); 62 65 if (loc.lineno == -1) continue; 63 66 67 loc.filename = mrb_debug_get_filename(mrb, irep, pc - irep->iseq); 64 68 if (!loc.filename) { 65 69 loc.filename = "(unknown)"; … … 67 71 68 72 loc.method_id = ci->mid; 69 func(mrb, j,&loc, data);73 func(mrb, &loc, data); 70 74 } 71 75 } … … 74 78 75 79 static void 76 print_backtrace(mrb_state *mrb, mrb_value backtrace) 77 { 78 int i, n; 80 print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace) 81 { 82 mrb_int i; 83 mrb_int n = RARRAY_LEN(backtrace); 84 mrb_value *loc, mesg; 79 85 FILE *stream = stderr; 80 86 81 if (!mrb_array_p(backtrace)) return; 82 fprintf(stream, "trace:\n"); 83 84 n = RARRAY_LEN(backtrace); 85 for (i=0; n--; i++) { 86 mrb_value entry = RARRAY_PTR(backtrace)[n]; 87 88 if (mrb_string_p(entry)) { 89 fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry)); 90 } 91 } 92 } 93 94 static void 95 print_packed_backtrace(mrb_state *mrb, mrb_value packed) 96 { 97 FILE *stream = stderr; 98 struct backtrace_location *bt; 99 int n, i; 100 101 bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, packed, &bt_type); 102 if (bt == NULL) { 103 mrb_raise(mrb, E_RUNTIME_ERROR, "broken backtrace"); 104 } 105 n = (mrb_int)RDATA(packed)->flags; 106 107 fprintf(stream, "trace:\n"); 108 for (i = 0; n--; i++) { 109 int ai = mrb_gc_arena_save(mrb); 110 struct backtrace_location *entry = &bt[n]; 111 if (entry->filename == NULL) continue; 112 fprintf(stream, "\t[%d] %s:%d", (int)i, entry->filename, entry->lineno); 113 if (entry->method_id != 0) { 114 const char *method_name; 115 116 method_name = mrb_sym2name(mrb, entry->method_id); 117 fprintf(stream, ":in %s", method_name); 118 mrb_gc_arena_restore(mrb, ai); 119 } 120 fprintf(stream, "\n"); 121 } 87 if (n != 0) { 88 fprintf(stream, "trace (most recent call last):\n"); 89 for (i=n-1,loc=&RARRAY_PTR(backtrace)[i]; i>0; i--,loc--) { 90 if (mrb_string_p(*loc)) { 91 fprintf(stream, "\t[%d] %.*s\n", 92 (int)i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc)); 93 } 94 } 95 if (mrb_string_p(*loc)) { 96 fprintf(stream, "%.*s: ", (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc)); 97 } 98 } 99 mesg = mrb_exc_inspect(mrb, mrb_obj_value(exc)); 100 fprintf(stream, "%.*s\n", (int)RSTRING_LEN(mesg), RSTRING_PTR(mesg)); 122 101 } 123 102 … … 138 117 backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace")); 139 118 if (mrb_nil_p(backtrace)) return; 140 if (mrb_array_p(backtrace)) { 141 print_backtrace(mrb, backtrace); 142 } 143 else { 144 print_packed_backtrace(mrb, backtrace); 145 } 119 if (!mrb_array_p(backtrace)) backtrace = mrb_unpack_backtrace(mrb, backtrace); 120 print_backtrace(mrb, mrb->exc, backtrace); 146 121 } 147 122 #else … … 155 130 156 131 static void 132 count_backtrace_i(mrb_state *mrb, 133 const struct backtrace_location *loc, 134 void *data) 135 { 136 int *lenp = (int*)data; 137 138 (*lenp)++; 139 } 140 141 static void 157 142 pack_backtrace_i(mrb_state *mrb, 158 int i, 159 struct backtrace_location *loc, 143 const struct backtrace_location *loc, 160 144 void *data) 161 145 { 162 struct backtrace_location *entry = (struct backtrace_location*)data; 163 164 entry[i] = *loc; 146 struct backtrace_location **pptr = (struct backtrace_location**)data; 147 struct backtrace_location *ptr = *pptr; 148 149 *ptr = *loc; 150 *pptr = ptr+1; 165 151 } 166 152 … … 170 156 struct RData *backtrace; 171 157 ptrdiff_t ciidx = mrb->c->ci - mrb->c->cibase; 172 mrb_int len = (ciidx+1)*sizeof(struct backtrace_location); 158 int len = 0; 159 int size; 173 160 void *ptr; 174 161 175 ptr = mrb_malloc(mrb, len); 176 memset(ptr, 0, len); 162 each_backtrace(mrb, ciidx, mrb->c->ci->pc, count_backtrace_i, &len); 163 size = len * sizeof(struct backtrace_location); 164 ptr = mrb_malloc(mrb, size); 177 165 backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type); 178 backtrace->flags = (u nsigned int)ciidx+1;179 each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, ptr);166 backtrace->flags = (uint32_t)len; 167 each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, &ptr); 180 168 return mrb_obj_value(backtrace); 181 169 } … … 184 172 mrb_keep_backtrace(mrb_state *mrb, mrb_value exc) 185 173 { 174 mrb_sym sym = mrb_intern_lit(mrb, "backtrace"); 186 175 mrb_value backtrace; 187 int ai = mrb_gc_arena_save(mrb); 188 176 int ai; 177 178 if (mrb_iv_defined(mrb, exc, sym)) return; 179 ai = mrb_gc_arena_save(mrb); 189 180 backtrace = packed_backtrace(mrb); 190 mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "backtrace"), backtrace);181 mrb_iv_set(mrb, exc, sym, backtrace); 191 182 mrb_gc_arena_restore(mrb, ai); 192 183 } … … 195 186 mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace) 196 187 { 197 struct backtrace_location *bt;188 const struct backtrace_location *bt; 198 189 mrb_int n, i; 199 200 if (mrb_nil_p(backtrace)) return mrb_ary_new_capa(mrb, 0); 190 int ai; 191 192 if (mrb_nil_p(backtrace)) { 193 empty_backtrace: 194 return mrb_ary_new_capa(mrb, 0); 195 } 201 196 if (mrb_array_p(backtrace)) return backtrace; 202 197 bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, backtrace, &bt_type); 203 if (bt == NULL) { 204 mrb_raise(mrb, E_RUNTIME_ERROR, "broken backtrace"); 205 } 198 if (bt == NULL) goto empty_backtrace; 206 199 n = (mrb_int)RDATA(backtrace)->flags; 207 200 backtrace = mrb_ary_new_capa(mrb, n); 201 ai = mrb_gc_arena_save(mrb); 208 202 for (i = 0; i < n; i++) { 209 int ai = mrb_gc_arena_save(mrb); 210 struct backtrace_location *entry = &bt[i]; 203 const struct backtrace_location *entry = &bt[i]; 211 204 mrb_value btline; 212 205 213 if (entry->filename == NULL) continue; 214 btline = mrb_format(mrb, "%S:%S", 215 mrb_str_new_cstr(mrb, entry->filename), 216 mrb_fixnum_value(entry->lineno)); 206 btline = mrb_format(mrb, "%s:%d", entry->filename, (int)entry->lineno); 217 207 if (entry->method_id != 0) { 218 208 mrb_str_cat_lit(mrb, btline, ":in "); 219 mrb_str_cat_cstr(mrb, btline, mrb_sym 2name(mrb, entry->method_id));209 mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id)); 220 210 } 221 211 mrb_ary_push(mrb, backtrace, btline);
Note:
See TracChangeset
for help on using the changeset viewer.