summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backtrace.c73
-rw-r--r--src/codegen.c8
-rw-r--r--src/load.c3
-rw-r--r--src/parse.y28
-rw-r--r--src/state.c1
5 files changed, 106 insertions, 7 deletions
diff --git a/src/backtrace.c b/src/backtrace.c
new file mode 100644
index 000000000..3fadb9552
--- /dev/null
+++ b/src/backtrace.c
@@ -0,0 +1,73 @@
+/*
+** backtrace.c -
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include "mruby.h"
+#include "mruby/variable.h"
+#include "mruby/proc.h"
+
+void
+mrb_print_backtrace(mrb_state *mrb)
+{
+#ifdef ENABLE_STDIO
+ mrb_callinfo *ci;
+ mrb_int ciidx;
+ const char *filename, *method, *sep;
+ int i, line;
+
+ printf("trace:\n");
+ ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "ciidx")));
+ if (ciidx >= mrb->ciend - mrb->cibase)
+ ciidx = 10; /* ciidx is broken... */
+
+ for (i = ciidx; i >= 0; i--) {
+ ci = &mrb->cibase[i];
+ filename = "(unknown)";
+ line = -1;
+
+ if (MRB_PROC_CFUNC_P(ci->proc)) {
+ continue;
+ }
+ else {
+ mrb_irep *irep = ci->proc->body.irep;
+ if (irep->filename != NULL)
+ filename = irep->filename;
+ if (irep->lines != NULL) {
+ mrb_code *pc;
+
+ if (i+1 <= ciidx) {
+ pc = mrb->cibase[i+1].pc;
+ }
+ else {
+ pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "lastpc")));
+ }
+ if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) {
+ line = irep->lines[pc - irep->iseq - 1];
+ }
+ }
+ }
+ if (line == -1) continue;
+ if (ci->target_class == ci->proc->target_class)
+ sep = ".";
+ else
+ sep = "#";
+
+ method = mrb_sym2name(mrb, ci->mid);
+ if (method) {
+ const char *cn = mrb_class_name(mrb, ci->proc->target_class);
+
+ if (cn) {
+ printf("\t[%d] %s:%d:in %s%s%s\n", i, filename, line, cn, sep, method);
+ }
+ else {
+ printf("\t[%d] %s:%d:in %s\n", i, filename, line, method);
+ }
+ }
+ else {
+ printf("\t[%d] %s:%d\n", i, filename, line);
+ }
+ }
+#endif
+}
diff --git a/src/codegen.c b/src/codegen.c
index 38328c669..f4617a570 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -2403,6 +2403,8 @@ scope_finish(codegen_scope *s)
{
mrb_state *mrb = s->mrb;
mrb_irep *irep = s->irep;
+ size_t fname_len;
+ char *fname;
irep->flags = 0;
if (s->iseq) {
@@ -2418,7 +2420,11 @@ scope_finish(codegen_scope *s)
irep->pool = (mrb_value *)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
irep->syms = (mrb_sym *)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
if (s->filename) {
- irep->filename = s->filename;
+ fname_len = strlen(s->filename);
+ fname = codegen_malloc(s, fname_len + 1);
+ memcpy(fname, s->filename, fname_len);
+ fname[fname_len] = '\0';
+ irep->filename = fname;
}
irep->nlocals = s->nlocals;
diff --git a/src/load.c b/src/load.c
index b3f13a8ef..81d47858a 100644
--- a/src/load.c
+++ b/src/load.c
@@ -267,9 +267,6 @@ read_rite_lineno_record(mrb_state *mrb, const uint8_t *bin, size_t irepno, uint3
mrb->irep[irepno]->lines = lines;
error_exit:
- if (fname) {
- mrb_free(mrb, fname);
- }
return ret;
}
diff --git a/src/parse.y b/src/parse.y
index fc2d09f23..54e8eafce 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -3232,14 +3232,14 @@ nextc(parser_state *p)
else {
#ifdef ENABLE_STDIO
if (p->f) {
- if (feof(p->f)) return -1;
+ if (feof(p->f)) goto end_retry;
c = fgetc(p->f);
- if (c == EOF) return -1;
+ if (c == EOF) goto end_retry;
}
else
#endif
if (!p->s || p->s >= p->send) {
- return -1;
+ goto end_retry;
}
else {
c = (unsigned char)*p->s++;
@@ -3247,6 +3247,18 @@ nextc(parser_state *p)
}
p->column++;
return c;
+
+ end_retry:
+ if (!p->cxt) return -1;
+ else {
+ mrbc_context *cxt = p->cxt;
+
+ if (cxt->partial_hook(p) < 0) return -1;
+ p->cxt = NULL;
+ c = nextc(p);
+ p->cxt = cxt;
+ return c;
+ }
}
static void
@@ -5023,6 +5035,9 @@ parser_init_cxt(parser_state *p, mrbc_context *cxt)
}
}
p->capture_errors = cxt->capture_errors;
+ if (cxt->partial_hook) {
+ p->cxt = cxt;
+ }
}
static void
@@ -5147,6 +5162,13 @@ mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
return c->filename;
}
+void
+mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*func)(struct mrb_parser_state*), void *data)
+{
+ c->partial_hook = func;
+ c->partial_data = data;
+}
+
#ifdef ENABLE_STDIO
parser_state*
mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
diff --git a/src/state.c b/src/state.c
index 9bf051c1a..b34fbd025 100644
--- a/src/state.c
+++ b/src/state.c
@@ -101,6 +101,7 @@ mrb_irep_free(mrb_state *mrb, struct mrb_irep *irep)
mrb_free(mrb, irep->iseq);
mrb_free(mrb, irep->pool);
mrb_free(mrb, irep->syms);
+ mrb_free(mrb, (void *)irep->filename);
mrb_free(mrb, irep->lines);
mrb_free(mrb, irep);
}