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