Ruby  2.1.10p492(2016-04-01revision54464)
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  ID caller_name;
30  if (sourceline == 0) {
31  warn_printf("%s", sourcefile);
32  }
33  else if ((caller_name = rb_frame_callee()) != 0) {
34  warn_printf("%s:%d:in `%s'", sourcefile, sourceline,
35  rb_id2name(caller_name));
36  }
37  else {
38  warn_printf("%s:%d", sourcefile, sourceline);
39  }
40  }
41 }
42 
43 static VALUE
45 {
46  if (NIL_P(info))
47  return Qnil;
48  info = rb_funcall(info, rb_intern("backtrace"), 0);
49  if (NIL_P(info))
50  return Qnil;
51  return rb_check_backtrace(info);
52 }
53 
54 VALUE
56 {
57  return get_backtrace(info);
58 }
59 
61 
62 static void
64 {
65  ID set_backtrace = rb_intern("set_backtrace");
66 
67  if (rb_backtrace_p(bt)) {
68  if (rb_method_basic_definition_p(CLASS_OF(info), set_backtrace)) {
69  rb_exc_set_backtrace(info, bt);
70  return;
71  }
72  else {
73  bt = rb_backtrace_to_str_ary(bt);
74  }
75  }
76  rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
77 }
78 
79 static void
81 {
82  volatile VALUE errat = Qundef;
84  VALUE errinfo = th->errinfo;
85  int raised_flag = th->raised_flag;
86  volatile VALUE eclass = Qundef, e = Qundef;
87  const char *volatile einfo;
88  volatile long elen;
89 
90  if (NIL_P(errinfo))
91  return;
93 
94  TH_PUSH_TAG(th);
95  if (TH_EXEC_TAG() == 0) {
96  errat = get_backtrace(errinfo);
97  }
98  else if (errat == Qundef) {
99  errat = Qnil;
100  }
101  else if (eclass == Qundef || e != Qundef) {
102  goto error;
103  }
104  else {
105  goto no_message;
106  }
107  if (NIL_P(errat)) {
108  const char *file = rb_sourcefile();
109  int line = rb_sourceline();
110  if (!file)
111  warn_printf("%d", line);
112  else if (!line)
113  warn_printf("%s", file);
114  else
115  warn_printf("%s:%d", file, line);
116  }
117  else if (RARRAY_LEN(errat) == 0) {
118  error_pos();
119  }
120  else {
121  VALUE mesg = RARRAY_AREF(errat, 0);
122 
123  if (NIL_P(mesg))
124  error_pos();
125  else {
126  warn_print_str(mesg);
127  }
128  }
129 
130  eclass = CLASS_OF(errinfo);
131  if (eclass != Qundef &&
132  (e = rb_check_funcall(errinfo, rb_intern("message"), 0, 0)) != Qundef &&
133  (RB_TYPE_P(e, T_STRING) || !NIL_P(e = rb_check_string_type(e)))) {
134  einfo = RSTRING_PTR(e);
135  elen = RSTRING_LEN(e);
136  }
137  else {
138  no_message:
139  einfo = "";
140  elen = 0;
141  }
142  if (eclass == rb_eRuntimeError && elen == 0) {
143  warn_print(": unhandled exception\n");
144  }
145  else {
146  VALUE epath;
147 
148  epath = rb_class_name(eclass);
149  if (elen == 0) {
150  warn_print(": ");
151  warn_print_str(epath);
152  warn_print("\n");
153  }
154  else {
155  char *tail = 0;
156  long len = elen;
157 
158  if (RSTRING_PTR(epath)[0] == '#')
159  epath = 0;
160  if ((tail = memchr(einfo, '\n', elen)) != 0) {
161  len = tail - einfo;
162  tail++; /* skip newline */
163  }
164  warn_print(": ");
165  warn_print2(einfo, len);
166  if (epath) {
167  warn_print(" (");
168  warn_print_str(epath);
169  warn_print(")\n");
170  }
171  if (tail) {
172  warn_print2(tail, elen - len - 1);
173  if (einfo[elen-1] != '\n') warn_print2("\n", 1);
174  }
175  }
176  }
177 
178  if (!NIL_P(errat)) {
179  long i;
180  long len = RARRAY_LEN(errat);
181  int skip = eclass == rb_eSysStackError;
182 
183 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
184 #define TRACE_HEAD 8
185 #define TRACE_TAIL 5
186 
187  for (i = 1; i < len; i++) {
188  VALUE line = RARRAY_AREF(errat, i);
189  if (RB_TYPE_P(line, T_STRING)) {
190  warn_printf("\tfrom %"PRIsVALUE"\n", line);
191  }
192  if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
193  warn_printf("\t ... %ld levels...\n",
194  len - TRACE_HEAD - TRACE_TAIL);
195  i = len - TRACE_TAIL;
196  }
197  }
198  }
199  error:
200  TH_POP_TAG();
201  th->errinfo = errinfo;
202  rb_thread_raised_set(th, raised_flag);
203 }
204 
205 void
207 {
208  error_print();
209 }
210 
211 void
212 rb_print_undef(VALUE klass, ID id, int scope)
213 {
214  const char *v;
215 
216  switch (scope) {
217  default:
218  case NOEX_PUBLIC: v = ""; break;
219  case NOEX_PRIVATE: v = " private"; break;
220  case NOEX_PROTECTED: v = " protected"; break;
221  }
222  rb_name_error(id, "undefined%s method `%"PRIsVALUE"' for %s `%"PRIsVALUE"'", v,
223  QUOTE_ID(id),
224  (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class",
225  rb_class_name(klass));
226 }
227 
228 void
230 {
231  rb_name_error_str(name, "undefined method `%"PRIsVALUE"' for %s `%"PRIsVALUE"'",
232  QUOTE(name),
233  (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class",
234  rb_class_name(klass));
235 }
236 
237 static int
239 {
240  VALUE st = rb_iv_get(err, "status");
241  return NUM2INT(st);
242 }
243 
244 static int
246 {
247  int status = EXIT_FAILURE;
249 
250  if (rb_threadptr_set_raised(th))
251  return EXIT_FAILURE;
252  switch (ex & TAG_MASK) {
253  case 0:
254  status = EXIT_SUCCESS;
255  break;
256 
257  case TAG_RETURN:
258  error_pos();
259  warn_print(": unexpected return\n");
260  break;
261  case TAG_NEXT:
262  error_pos();
263  warn_print(": unexpected next\n");
264  break;
265  case TAG_BREAK:
266  error_pos();
267  warn_print(": unexpected break\n");
268  break;
269  case TAG_REDO:
270  error_pos();
271  warn_print(": unexpected redo\n");
272  break;
273  case TAG_RETRY:
274  error_pos();
275  warn_print(": retry outside of rescue clause\n");
276  break;
277  case TAG_THROW:
278  /* TODO: fix me */
279  error_pos();
280  warn_printf(": unexpected throw\n");
281  break;
282  case TAG_RAISE: {
283  VALUE errinfo = GET_THREAD()->errinfo;
284  if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
285  status = sysexit_status(errinfo);
286  }
287  else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
288  /* no message when exiting by signal */
289  }
290  else {
291  error_print();
292  }
293  break;
294  }
295  case TAG_FATAL:
296  error_print();
297  break;
298  default:
299  rb_bug("Unknown longjmp status %d", ex);
300  break;
301  }
303  return status;
304 }
#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:327
#define tail
Definition: st.c:108
#define TAG_NEXT
Definition: eval_intern.h:190
static VALUE VALUE th
Definition: tcltklib.c:2944
VALUE rb_eSignal
Definition: error.c:544
#define TAG_THROW
Definition: eval_intern.h:194
rb_funcall(memo->yielder, id_lshift, 1, rb_assoc_new(memo->prev_value, memo->prev_elts))
#define TAG_BREAK
Definition: eval_intern.h:189
Tcl_CmdInfo * info
Definition: tcltklib.c:1467
static void error_pos(void)
Definition: eval_error.c:23
static void set_backtrace(VALUE info, VALUE bt)
Definition: eval_error.c:63
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2604
int status
Definition: tcltklib.c:2197
static int sysexit_status(VALUE err)
Definition: eval_error.c:238
VALUE exc
Definition: tcltklib.c:3088
#define QUOTE_ID(id)
#define RSTRING_PTR(str)
#define CLASS_OF(v)
NIL_P(eventloop_thread)
Definition: tcltklib.c:4056
void rb_print_undef_str(VALUE klass, VALUE name)
Definition: eval_error.c:229
#define TH_EXEC_TAG()
Definition: eval_intern.h:165
VALUE rb_class_name(VALUE)
Definition: variable.c:391
VALUE rb_backtrace_to_str_ary(VALUE obj)
Definition: vm_backtrace.c:590
#define TAG_RAISE
Definition: eval_intern.h:193
VALUE einfo
Definition: tcltklib.c:852
i
Definition: enum.c:446
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:982
const char * fmt
Definition: tcltklib.c:846
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:967
#define TAG_FATAL
Definition: eval_intern.h:195
#define TH_POP_TAG()
Definition: eval_intern.h:128
VALUE rb_obj_is_instance_of(VALUE, VALUE)
Definition: object.c:609
static VALUE get_backtrace(VALUE info)
Definition: eval_error.c:44
static int error_handle(int ex)
Definition: eval_error.c:245
int rb_threadptr_set_raised(rb_thread_t *th)
Definition: thread.c:2100
#define RARRAY_LEN(a)
#define Qnil
Definition: enum.c:67
VALUE rb_eRuntimeError
Definition: error.c:547
VALUE rb_eSysStackError
Definition: eval.c:28
static VALUE char * str
Definition: tcltklib.c:3539
#define RARRAY_AREF(a, i)
unsigned long ID
Definition: ripper.y:89
va_end(args)
#define RSTRING_LEN(str)
VALUE rb_get_backtrace(VALUE info)
Definition: eval_error.c:55
#define warn_print_str(x)
Definition: eval_error.c:20
#define T_STRING
#define TRACE_MAX
#define rb_sourcefile()
Definition: tcltklib.c:98
#define TAG_REDO
Definition: eval_intern.h:192
int err
Definition: win32.c:114
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt)
Definition: error.c:807
#define EXIT_FAILURE
Definition: eval_intern.h:24
int len
Definition: enumerator.c:1332
#define TAG_MASK
Definition: eval_intern.h:196
#define rb_thread_raised_clear(th)
Definition: eval_intern.h:226
#define TAG_RETURN
Definition: eval_intern.h:188
#define EXIT_SUCCESS
Definition: error.c:29
VALUE v
Definition: enum.c:845
#define QUOTE(str)
#define TRACE_HEAD
#define rb_thread_raised_set(th, f)
Definition: eval_intern.h:223
#define TRACE_TAIL
ssize_t ex
Definition: bigdecimal.c:5211
int rb_threadptr_reset_raised(rb_thread_t *th)
Definition: thread.c:2110
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:122
int rb_sourceline(void)
Definition: vm.c:1001
void ruby_error_print(void)
Definition: eval_error.c:206
VALUE rb_vsprintf(const char *, va_list)
Definition: sprintf.c:1244
#define va_init_list(a, b)
Definition: tcltklib.c:62
static void warn_printf(const char *fmt,...)
Definition: eval_error.c:7
#define Qundef
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:646
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1585
ID rb_frame_callee(void)
Definition: eval.c:949
VALUE name
Definition: enum.c:572
args[0]
Definition: enum.c:585
klass
Definition: tcltklib.c:3496
VALUE rb_check_backtrace(VALUE bt)
Definition: error.c:769
#define T_MODULE
int rb_backtrace_p(VALUE obj)
Definition: vm_backtrace.c:417
#define NUM2INT(x)
const char * rb_id2name(ID id)
Definition: ripper.c:17271
#define PRIsVALUE
BDIGIT e
Definition: bigdecimal.c:5209
unsigned long VALUE
Definition: ripper.y:88
#define warn_print(x)
Definition: eval_error.c:18
void rb_print_undef(VALUE klass, ID id, int scope)
Definition: eval_error.c:212
static void error_print(void)
Definition: eval_error.c:80
#define rb_intern(str)
VALUE rb_eSystemExit
Definition: error.c:542
VALUE rb_check_string_type(VALUE)
Definition: string.c:1678
void rb_write_error_str(VALUE mesg)
Definition: io.c:7191
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:929
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:410
Tcl_Interp *int * st
Definition: stubs.c:510
#define TAG_RETRY
Definition: eval_intern.h:191