Ruby  2.0.0p451(2014-02-24revision45167)
eval_error.c
Go to the documentation of this file.
1 /* -*-c-*- */
2 /*
3  * included by eval.c
4  */
5 
6 static void
7 warn_printf(const char *fmt, ...)
8 {
9  char buf[BUFSIZ];
10  va_list args;
11 
12  va_init_list(args, fmt);
13  vsnprintf(buf, BUFSIZ, fmt, args);
14  va_end(args);
15  rb_write_error(buf);
16 }
17 
18 #define warn_print(x) rb_write_error(x)
19 #define warn_print2(x,l) rb_write_error2((x),(l))
20 
21 static void
22 error_pos(void)
23 {
24  const char *sourcefile = rb_sourcefile();
25  int sourceline = rb_sourceline();
26 
27  if (sourcefile) {
28  if (sourceline == 0) {
29  warn_printf("%s", sourcefile);
30  }
31  else if (rb_frame_callee()) {
32  warn_printf("%s:%d:in `%s'", sourcefile, sourceline,
34  }
35  else {
36  warn_printf("%s:%d", sourcefile, sourceline);
37  }
38  }
39 }
40 
41 static VALUE
43 {
44  if (NIL_P(info))
45  return Qnil;
46  info = rb_funcall(info, rb_intern("backtrace"), 0);
47  if (NIL_P(info))
48  return Qnil;
49  return rb_check_backtrace(info);
50 }
51 
52 VALUE
54 {
55  return get_backtrace(info);
56 }
57 
59 
60 static void
62 {
63  ID set_backtrace = rb_intern("set_backtrace");
64 
65  if (rb_backtrace_p(bt)) {
66  if (rb_method_basic_definition_p(CLASS_OF(info), set_backtrace)) {
67  rb_exc_set_backtrace(info, bt);
68  return;
69  }
70  else {
71  bt = rb_backtrace_to_str_ary(bt);
72  }
73  }
74  rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
75 }
76 
77 static void
79 {
80  volatile VALUE errat = Qnil; /* OK */
81  rb_thread_t *th = GET_THREAD();
82  VALUE errinfo = th->errinfo;
83  int raised_flag = th->raised_flag;
84  volatile VALUE eclass, e;
85  const char *volatile einfo;
86  volatile long elen;
87 
88  if (NIL_P(errinfo))
89  return;
91 
92  TH_PUSH_TAG(th);
93  if (TH_EXEC_TAG() == 0) {
94  errat = get_backtrace(errinfo);
95  }
96  else {
97  errat = Qnil;
98  }
99  if (TH_EXEC_TAG())
100  goto error;
101  if (NIL_P(errat)) {
102  const char *file = rb_sourcefile();
103  int line = rb_sourceline();
104  if (!file)
105  warn_printf("%d", line);
106  else if (!line)
107  warn_printf("%s", file);
108  else
109  warn_printf("%s:%d", file, line);
110  }
111  else if (RARRAY_LEN(errat) == 0) {
112  error_pos();
113  }
114  else {
115  VALUE mesg = RARRAY_PTR(errat)[0];
116 
117  if (NIL_P(mesg))
118  error_pos();
119  else {
120  warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
121  }
122  }
123 
124  eclass = CLASS_OF(errinfo);
125  if (TH_EXEC_TAG() == 0) {
126  e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
127  StringValue(e);
128  einfo = RSTRING_PTR(e);
129  elen = RSTRING_LEN(e);
130  }
131  else {
132  einfo = "";
133  elen = 0;
134  }
135  if (TH_EXEC_TAG())
136  goto error;
137  if (eclass == rb_eRuntimeError && elen == 0) {
138  warn_print(": unhandled exception\n");
139  }
140  else {
141  VALUE epath;
142 
143  epath = rb_class_name(eclass);
144  if (elen == 0) {
145  warn_print(": ");
146  warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
147  warn_print("\n");
148  }
149  else {
150  char *tail = 0;
151  long len = elen;
152 
153  if (RSTRING_PTR(epath)[0] == '#')
154  epath = 0;
155  if ((tail = memchr(einfo, '\n', elen)) != 0) {
156  len = tail - einfo;
157  tail++; /* skip newline */
158  }
159  warn_print(": ");
160  warn_print2(einfo, len);
161  if (epath) {
162  warn_print(" (");
163  warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
164  warn_print(")\n");
165  }
166  if (tail) {
167  warn_print2(tail, elen - len - 1);
168  if (einfo[elen-1] != '\n') warn_print2("\n", 1);
169  }
170  }
171  }
172 
173  if (!NIL_P(errat)) {
174  long i;
175  long len = RARRAY_LEN(errat);
176  VALUE *ptr = RARRAY_PTR(errat);
177  int skip = eclass == rb_eSysStackError;
178 
179 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
180 #define TRACE_HEAD 8
181 #define TRACE_TAIL 5
182 
183  for (i = 1; i < len; i++) {
184  if (RB_TYPE_P(ptr[i], T_STRING)) {
185  warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
186  }
187  if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
188  warn_printf("\t ... %ld levels...\n",
189  len - TRACE_HEAD - TRACE_TAIL);
190  i = len - TRACE_TAIL;
191  }
192  }
193  }
194  error:
195  TH_POP_TAG();
196  rb_thread_raised_set(th, raised_flag);
197 }
198 
199 void
201 {
202  error_print();
203 }
204 
205 void
206 rb_print_undef(VALUE klass, ID id, int scope)
207 {
208  const char *v;
209 
210  switch (scope) {
211  default:
212  case NOEX_PUBLIC: v = ""; break;
213  case NOEX_PRIVATE: v = " private"; break;
214  case NOEX_PROTECTED: v = " protected"; break;
215  }
216  rb_name_error(id, "undefined%s method `%"PRIsVALUE"' for %s `%"PRIsVALUE"'", v,
217  QUOTE_ID(id),
218  (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class",
219  rb_class_name(klass));
220 }
221 
222 void
224 {
225  rb_name_error_str(name, "undefined method `%"PRIsVALUE"' for %s `%"PRIsVALUE"'",
226  QUOTE(name),
227  (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class",
228  rb_class_name(klass));
229 }
230 
231 static int
233 {
234  VALUE st = rb_iv_get(err, "status");
235  return NUM2INT(st);
236 }
237 
238 static int
240 {
241  int status = EXIT_FAILURE;
242  rb_thread_t *th = GET_THREAD();
243 
244  if (rb_threadptr_set_raised(th))
245  return EXIT_FAILURE;
246  switch (ex & TAG_MASK) {
247  case 0:
248  status = EXIT_SUCCESS;
249  break;
250 
251  case TAG_RETURN:
252  error_pos();
253  warn_print(": unexpected return\n");
254  break;
255  case TAG_NEXT:
256  error_pos();
257  warn_print(": unexpected next\n");
258  break;
259  case TAG_BREAK:
260  error_pos();
261  warn_print(": unexpected break\n");
262  break;
263  case TAG_REDO:
264  error_pos();
265  warn_print(": unexpected redo\n");
266  break;
267  case TAG_RETRY:
268  error_pos();
269  warn_print(": retry outside of rescue clause\n");
270  break;
271  case TAG_THROW:
272  /* TODO: fix me */
273  error_pos();
274  warn_printf(": unexpected throw\n");
275  break;
276  case TAG_RAISE: {
277  VALUE errinfo = GET_THREAD()->errinfo;
278  if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
279  status = sysexit_status(errinfo);
280  }
281  else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
282  /* no message when exiting by signal */
283  }
284  else {
285  error_print();
286  }
287  break;
288  }
289  case TAG_FATAL:
290  error_print();
291  break;
292  default:
293  rb_bug("Unknown longjmp status %d", ex);
294  break;
295  }
297  return status;
298 }
#define RB_TYPE_P(obj, type)
#define warn_print2(x, l)
Definition: eval_error.c:19
void rb_bug(const char *fmt,...)
Definition: error.c:290
#define tail
Definition: st.c:108
#define TAG_NEXT
Definition: eval_intern.h:137
int i
Definition: win32ole.c:784
unsigned long VALUE
Definition: ripper.y:104
VALUE rb_eSignal
Definition: error.c:507
#define TAG_THROW
Definition: eval_intern.h:141
#define TAG_BREAK
Definition: eval_intern.h:136
static void error_pos(void)
Definition: eval_error.c:22
static void set_backtrace(VALUE info, VALUE bt)
Definition: eval_error.c:61
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2584
static int sysexit_status(VALUE err)
Definition: eval_error.c:232
#define QUOTE_ID(id)
#define RSTRING_PTR(str)
#define CLASS_OF(v)
void rb_print_undef_str(VALUE klass, VALUE name)
Definition: eval_error.c:223
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:773
#define Qnil
#define TH_EXEC_TAG()
Definition: eval_intern.h:111
VALUE rb_class_name(VALUE)
Definition: variable.c:383
VALUE rb_backtrace_to_str_ary(VALUE obj)
Definition: vm_backtrace.c:586
#define vsnprintf
#define TAG_RAISE
Definition: eval_intern.h:140
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:914
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:899
#define TAG_FATAL
Definition: eval_intern.h:142
int args
Definition: win32ole.c:785
#define TH_POP_TAG()
Definition: eval_intern.h:101
VALUE rb_obj_is_instance_of(VALUE, VALUE)
Definition: object.c:545
static VALUE get_backtrace(VALUE info)
Definition: eval_error.c:42
static int error_handle(int ex)
Definition: eval_error.c:239
int rb_threadptr_set_raised(rb_thread_t *th)
Definition: thread.c:2045
#define RARRAY_LEN(a)
VALUE rb_eRuntimeError
Definition: error.c:510
VALUE rb_eSysStackError
Definition: eval.c:30
unsigned long ID
Definition: ripper.y:105
#define RSTRING_LEN(str)
VALUE rb_get_backtrace(VALUE info)
Definition: eval_error.c:53
#define T_STRING
#define TRACE_MAX
#define NIL_P(v)
#define rb_sourcefile()
Definition: tcltklib.c:97
#define TAG_REDO
Definition: eval_intern.h:139
int err
Definition: win32.c:87
#define EXIT_FAILURE
Definition: eval_intern.h:24
#define TAG_MASK
Definition: eval_intern.h:143
#define rb_thread_raised_clear(th)
Definition: eval_intern.h:173
#define TAG_RETURN
Definition: eval_intern.h:135
#define EXIT_SUCCESS
Definition: error.c:31
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt)
Definition: error.c:747
#define StringValue(v)
#define QUOTE(str)
#define TRACE_HEAD
#define rb_thread_raised_set(th, f)
Definition: eval_intern.h:170
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
#define RARRAY_PTR(a)
#define TRACE_TAIL
int rb_threadptr_reset_raised(rb_thread_t *th)
Definition: thread.c:2055
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:94
int rb_sourceline(void)
Definition: vm.c:816
void ruby_error_print(void)
Definition: eval_error.c:200
#define va_init_list(a, b)
Definition: tcltklib.c:61
static void warn_printf(const char *fmt,...)
Definition: eval_error.c:7
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:582
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1517
ID rb_frame_callee(void)
Definition: eval.c:919
v
Definition: win32ole.c:798
VALUE rb_check_backtrace(VALUE bt)
Definition: error.c:710
void rb_write_error(const char *)
Definition: io.c:7065
#define T_MODULE
int rb_backtrace_p(VALUE obj)
Definition: vm_backtrace.c:413
const char * name
Definition: nkf.c:208
#define NUM2INT(x)
const char * rb_id2name(ID id)
Definition: ripper.c:17058
#define PRIsVALUE
#define warn_print(x)
Definition: eval_error.c:18
void rb_print_undef(VALUE klass, ID id, int scope)
Definition: eval_error.c:206
static void error_print(void)
Definition: eval_error.c:78
#define rb_intern(str)
VALUE rb_eSystemExit
Definition: error.c:505
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:883
#define TAG_RETRY
Definition: eval_intern.h:138