Ruby  2.4.2p198(2017-09-14revision59899)
eval_error.c
Go to the documentation of this file.
1 /* -*-c-*- */
2 /*
3  * included by eval.c
4  */
5 
6 #ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P
7 #define warn_print(x) RB_GNUC_EXTENSION_BLOCK( \
8  (__builtin_constant_p(x)) ? \
9  rb_write_error2((x), (long)strlen(x)) : \
10  rb_write_error(x) \
11 )
12 #else
13 #define warn_print(x) rb_write_error(x)
14 #endif
15 #define warn_print2(x,l) rb_write_error2((x),(l))
16 #define warn_print_str(x) rb_write_error_str(x)
17 
18 static VALUE error_pos_str(void);
19 
20 static void
21 error_pos(void)
22 {
23  VALUE str = error_pos_str();
24  if (!NIL_P(str)) {
25  warn_print_str(str);
26  }
27 }
28 
29 static VALUE
31 {
32  int sourceline;
33  VALUE sourcefile = rb_source_location(&sourceline);
34 
35  if (sourcefile) {
36  ID caller_name;
37  if (sourceline == 0) {
38  return rb_sprintf("%"PRIsVALUE": ", sourcefile);
39  }
40  else if ((caller_name = rb_frame_callee()) != 0) {
41  return rb_sprintf("%"PRIsVALUE":%d:in `%"PRIsVALUE"': ",
42  sourcefile, sourceline,
43  rb_id2str(caller_name));
44  }
45  else {
46  return rb_sprintf("%"PRIsVALUE":%d: ", sourcefile, sourceline);
47  }
48  }
49  return Qnil;
50 }
51 
52 static void
54 {
55  ID set_backtrace = rb_intern("set_backtrace");
56 
57  if (rb_backtrace_p(bt)) {
58  if (rb_method_basic_definition_p(CLASS_OF(info), set_backtrace)) {
59  rb_exc_set_backtrace(info, bt);
60  return;
61  }
62  else {
63  bt = rb_backtrace_to_str_ary(bt);
64  }
65  }
66  rb_check_funcall(info, set_backtrace, 1, &bt);
67 }
68 
69 static void
71 {
73 }
74 
75 void
76 rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
77 {
78  volatile VALUE errat = Qundef;
79  volatile int raised_flag = th->raised_flag;
80  volatile VALUE eclass = Qundef, e = Qundef;
81  const char *volatile einfo;
82  volatile long elen;
83  VALUE mesg;
84 
85  if (NIL_P(errinfo))
86  return;
88 
89  TH_PUSH_TAG(th);
90  if (TH_EXEC_TAG() == 0) {
91  errat = rb_get_backtrace(errinfo);
92  }
93  else if (errat == Qundef) {
94  errat = Qnil;
95  }
96  else if (eclass == Qundef || e != Qundef) {
97  goto error;
98  }
99  else {
100  goto no_message;
101  }
102  if (NIL_P(errat) || RARRAY_LEN(errat) == 0 ||
103  NIL_P(mesg = RARRAY_AREF(errat, 0))) {
104  error_pos();
105  }
106  else {
107  warn_print_str(mesg);
108  warn_print(": ");
109  }
110 
111  eclass = CLASS_OF(errinfo);
112  if (eclass != Qundef &&
113  (e = rb_check_funcall(errinfo, rb_intern("message"), 0, 0)) != Qundef &&
114  (RB_TYPE_P(e, T_STRING) || !NIL_P(e = rb_check_string_type(e)))) {
115  einfo = RSTRING_PTR(e);
116  elen = RSTRING_LEN(e);
117  }
118  else {
119  no_message:
120  einfo = "";
121  elen = 0;
122  }
123  if (eclass == rb_eRuntimeError && elen == 0) {
124  warn_print("unhandled exception\n");
125  }
126  else {
127  VALUE epath;
128 
129  epath = rb_class_name(eclass);
130  if (elen == 0) {
131  warn_print_str(epath);
132  warn_print("\n");
133  }
134  else {
135  const char *tail = 0;
136  long len = elen;
137 
138  if (RSTRING_PTR(epath)[0] == '#')
139  epath = 0;
140  if ((tail = memchr(einfo, '\n', elen)) != 0) {
141  len = tail - einfo;
142  tail++; /* skip newline */
143  }
144  warn_print_str(tail ? rb_str_subseq(e, 0, len) : e);
145  if (epath) {
146  warn_print(" (");
147  warn_print_str(epath);
148  warn_print(")\n");
149  }
150  if (tail) {
151  warn_print_str(rb_str_subseq(e, tail - einfo, elen - len - 1));
152  }
153  if (tail ? einfo[elen-1] != '\n' : !epath) warn_print2("\n", 1);
154  }
155  }
156 
157  if (!NIL_P(errat)) {
158  long i;
159  long len = RARRAY_LEN(errat);
160  int skip = eclass == rb_eSysStackError;
161 
162 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
163 #define TRACE_HEAD 8
164 #define TRACE_TAIL 5
165 
166  for (i = 1; i < len; i++) {
167  VALUE line = RARRAY_AREF(errat, i);
168  if (RB_TYPE_P(line, T_STRING)) {
169  warn_print_str(rb_sprintf("\tfrom %"PRIsVALUE"\n", line));
170  }
171  if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
172  warn_print_str(rb_sprintf("\t ... %ld levels...\n",
173  len - TRACE_HEAD - TRACE_TAIL));
174  i = len - TRACE_TAIL;
175  }
176  }
177  }
178  error:
179  TH_POP_TAG();
180  th->errinfo = errinfo;
181  rb_thread_raised_set(th, raised_flag);
182 }
183 
184 void
186 {
188 }
189 
190 #define undef_mesg_for(v, k) rb_fstring_cstr("undefined"v" method `%1$s' for "k" `%2$s'")
191 #define undef_mesg(v) ( \
192  is_mod ? \
193  undef_mesg_for(v, "module") : \
194  undef_mesg_for(v, "class"))
195 
196 void
198 {
199  const int is_mod = RB_TYPE_P(klass, T_MODULE);
200  VALUE mesg;
201  switch (visi & METHOD_VISI_MASK) {
202  case METHOD_VISI_UNDEF:
203  case METHOD_VISI_PUBLIC: mesg = undef_mesg(""); break;
204  case METHOD_VISI_PRIVATE: mesg = undef_mesg(" private"); break;
205  case METHOD_VISI_PROTECTED: mesg = undef_mesg(" protected"); break;
206  default: UNREACHABLE;
207  }
208  rb_name_err_raise_str(mesg, klass, ID2SYM(id));
209 }
210 
211 void
213 {
214  const int is_mod = RB_TYPE_P(klass, T_MODULE);
215  rb_name_err_raise_str(undef_mesg(""), klass, name);
216 }
217 
218 #define inaccessible_mesg_for(v, k) rb_fstring_cstr("method `%1$s' for "k" `%2$s' is "v)
219 #define inaccessible_mesg(v) ( \
220  is_mod ? \
221  inaccessible_mesg_for(v, "module") : \
222  inaccessible_mesg_for(v, "class"))
223 
224 void
226 {
227  const int is_mod = RB_TYPE_P(klass, T_MODULE);
228  VALUE mesg;
229  switch (visi & METHOD_VISI_MASK) {
230  case METHOD_VISI_UNDEF:
231  case METHOD_VISI_PUBLIC: mesg = inaccessible_mesg(""); break;
232  case METHOD_VISI_PRIVATE: mesg = inaccessible_mesg(" private"); break;
233  case METHOD_VISI_PROTECTED: mesg = inaccessible_mesg(" protected"); break;
234  default: UNREACHABLE;
235  }
236  rb_name_err_raise_str(mesg, klass, ID2SYM(id));
237 }
238 
239 static int
241 {
242  VALUE st = rb_ivar_get(err, id_status);
243  return NUM2INT(st);
244 }
245 
246 #define unknown_longjmp_status(status) \
247  rb_bug("Unknown longjmp status %d", status)
248 
249 static int
251 {
252  int status = EXIT_FAILURE;
253  rb_thread_t *th = GET_THREAD();
254 
255  if (rb_threadptr_set_raised(th))
256  return EXIT_FAILURE;
257  switch (ex & TAG_MASK) {
258  case 0:
259  status = EXIT_SUCCESS;
260  break;
261 
262  case TAG_RETURN:
263  error_pos();
264  warn_print("unexpected return\n");
265  break;
266  case TAG_NEXT:
267  error_pos();
268  warn_print("unexpected next\n");
269  break;
270  case TAG_BREAK:
271  error_pos();
272  warn_print("unexpected break\n");
273  break;
274  case TAG_REDO:
275  error_pos();
276  warn_print("unexpected redo\n");
277  break;
278  case TAG_RETRY:
279  error_pos();
280  warn_print("retry outside of rescue clause\n");
281  break;
282  case TAG_THROW:
283  /* TODO: fix me */
284  error_pos();
285  warn_print("unexpected throw\n");
286  break;
287  case TAG_RAISE: {
288  VALUE errinfo = th->errinfo;
289  if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
290  status = sysexit_status(errinfo);
291  }
292  else if (rb_obj_is_instance_of(errinfo, rb_eSignal) &&
293  rb_ivar_get(errinfo, id_signo) != INT2FIX(SIGSEGV)) {
294  /* no message when exiting by signal */
295  }
296  else {
297  error_print(th);
298  }
299  break;
300  }
301  case TAG_FATAL:
302  error_print(th);
303  break;
304  default:
306  break;
307  }
309  return status;
310 }
#define warn_print2(x, l)
Definition: eval_error.c:15
#define RARRAY_LEN(a)
Definition: ruby.h:1026
void rb_print_undef(VALUE klass, ID id, rb_method_visibility_t visi)
Definition: eval_error.c:197
VALUE rb_eSignal
Definition: error.c:758
#define NUM2INT(x)
Definition: ruby.h:684
#define CLASS_OF(v)
Definition: ruby.h:453
#define rb_name_err_raise_str(mesg, recv, name)
Definition: internal.h:1022
#define T_MODULE
Definition: ruby.h:494
#define rb_id2str(id)
Definition: vm_backtrace.c:29
static void error_pos(void)
Definition: eval_error.c:21
static void set_backtrace(VALUE info, VALUE bt)
Definition: eval_error.c:53
static int sysexit_status(VALUE err)
Definition: eval_error.c:240
#define UNREACHABLE
Definition: ruby.h:46
void rb_print_undef_str(VALUE klass, VALUE name)
Definition: eval_error.c:212
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1260
#define TH_EXEC_TAG()
Definition: eval_intern.h:180
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:690
#define TAG_NEXT
Definition: vm_core.h:165
#define GET_THREAD()
Definition: vm_core.h:1513
#define id_signo
Definition: eval.c:29
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
#define TH_POP_TAG()
Definition: eval_intern.h:137
VALUE rb_class_name(VALUE)
Definition: variable.c:443
static int error_handle(int ex)
Definition: eval_error.c:250
int rb_threadptr_set_raised(rb_thread_t *th)
Definition: thread.c:2180
VALUE rb_eRuntimeError
Definition: error.c:761
VALUE rb_eSysStackError
Definition: eval.c:25
#define undef_mesg(v)
Definition: eval_error.c:191
#define NIL_P(v)
Definition: ruby.h:451
rb_method_visibility_t
Definition: method.h:26
void rb_print_inaccessible(VALUE klass, ID id, rb_method_visibility_t visi)
Definition: eval_error.c:225
#define warn_print_str(x)
Definition: eval_error.c:16
#define TRACE_MAX
int err
Definition: win32.c:135
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt)
Definition: error.c:1044
void rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
Definition: eval_error.c:76
#define EXIT_FAILURE
Definition: eval_intern.h:33
#define id_status
Definition: error.c:792
int rb_backtrace_p(VALUE obj)
Definition: vm_backtrace.c:410
#define TAG_MASK
Definition: vm_core.h:171
#define rb_thread_raised_clear(th)
Definition: eval_intern.h:270
static VALUE error_pos_str(void)
Definition: eval_error.c:30
VALUE rb_backtrace_to_str_ary(VALUE obj)
Definition: vm_backtrace.c:584
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2324
#define TAG_REDO
Definition: vm_core.h:167
#define RSTRING_LEN(str)
Definition: ruby.h:978
#define EXIT_SUCCESS
Definition: error.c:32
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1440
#define TRACE_HEAD
#define rb_thread_raised_set(th, f)
Definition: eval_intern.h:267
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
#define TAG_FATAL
Definition: vm_core.h:170
#define Qnil
Definition: ruby.h:438
#define TRACE_TAIL
unsigned long VALUE
Definition: ruby.h:85
int rb_threadptr_reset_raised(rb_thread_t *th)
Definition: thread.c:2190
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:131
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:439
static void error_print(rb_thread_t *th)
Definition: eval_error.c:70
void ruby_error_print(void)
Definition: eval_error.c:185
register unsigned int len
Definition: zonetab.h:51
#define RSTRING_PTR(str)
Definition: ruby.h:982
VALUE rb_obj_is_instance_of(VALUE, VALUE)
Definition: object.c:653
#define TAG_RETRY
Definition: vm_core.h:166
#define INT2FIX(i)
Definition: ruby.h:232
#define TAG_THROW
Definition: vm_core.h:169
#define RARRAY_AREF(a, i)
Definition: ruby.h:1040
ID rb_frame_callee(void)
Definition: eval.c:985
VALUE rb_check_string_type(VALUE)
Definition: string.c:2164
#define inaccessible_mesg(v)
Definition: eval_error.c:219
#define T_STRING
Definition: ruby.h:496
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1880
#define TAG_RETURN
Definition: vm_core.h:163
const char * name
Definition: nkf.c:208
#define ID2SYM(x)
Definition: ruby.h:383
VALUE rb_source_location(int *pline)
Definition: vm.c:1275
VALUE rb_get_backtrace(VALUE exc)
Definition: error.c:965
#define warn_print(x)
Definition: eval_error.c:13
#define TAG_BREAK
Definition: vm_core.h:164
#define rb_intern(str)
#define TAG_RAISE
Definition: vm_core.h:168
VALUE rb_eSystemExit
Definition: error.c:756
#define Qundef
Definition: ruby.h:439
#define unknown_longjmp_status(status)
Definition: eval_error.c:246