Ruby  1.9.3p551(2014-11-13revision48407)
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 
58 static void
60 {
61  rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
62 }
63 
64 static void
66 {
67  volatile VALUE errat = Qnil; /* OK */
69  VALUE errinfo = th->errinfo;
70  int raised_flag = th->raised_flag;
71  volatile VALUE eclass, e;
72  const char *volatile einfo;
73  volatile long elen;
74 
75  if (NIL_P(errinfo))
76  return;
78 
79  PUSH_TAG();
80  if (EXEC_TAG() == 0) {
81  errat = get_backtrace(errinfo);
82  }
83  else {
84  errat = Qnil;
85  }
86  if (EXEC_TAG())
87  goto error;
88  if (NIL_P(errat)) {
89  const char *file = rb_sourcefile();
90  int line = rb_sourceline();
91  if (!file)
92  warn_printf("%d", line);
93  else if (!line)
94  warn_printf("%s", file);
95  else
96  warn_printf("%s:%d", file, line);
97  }
98  else if (RARRAY_LEN(errat) == 0) {
99  error_pos();
100  }
101  else {
102  VALUE mesg = RARRAY_PTR(errat)[0];
103 
104  if (NIL_P(mesg))
105  error_pos();
106  else {
107  warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
108  }
109  }
110 
111  eclass = CLASS_OF(errinfo);
112  if (EXEC_TAG() == 0) {
113  e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
114  StringValue(e);
115  einfo = RSTRING_PTR(e);
116  elen = RSTRING_LEN(e);
117  }
118  else {
119  einfo = "";
120  elen = 0;
121  }
122  if (EXEC_TAG())
123  goto error;
124  if (eclass == rb_eRuntimeError && elen == 0) {
125  warn_print(": unhandled exception\n");
126  }
127  else {
128  VALUE epath;
129 
130  epath = rb_class_name(eclass);
131  if (elen == 0) {
132  warn_print(": ");
133  warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
134  warn_print("\n");
135  }
136  else {
137  char *tail = 0;
138  long len = elen;
139 
140  if (RSTRING_PTR(epath)[0] == '#')
141  epath = 0;
142  if ((tail = memchr(einfo, '\n', elen)) != 0) {
143  len = tail - einfo;
144  tail++; /* skip newline */
145  }
146  warn_print(": ");
147  warn_print2(einfo, len);
148  if (epath) {
149  warn_print(" (");
150  warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
151  warn_print(")\n");
152  }
153  if (tail) {
154  warn_print2(tail, elen - len - 1);
155  if (einfo[elen-1] != '\n') warn_print2("\n", 1);
156  }
157  }
158  }
159 
160  if (!NIL_P(errat)) {
161  long i;
162  long len = RARRAY_LEN(errat);
163  VALUE *ptr = RARRAY_PTR(errat);
164  int skip = eclass == rb_eSysStackError;
165 
166 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
167 #define TRACE_HEAD 8
168 #define TRACE_TAIL 5
169 
170  for (i = 1; i < len; i++) {
171  if (TYPE(ptr[i]) == T_STRING) {
172  warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
173  }
174  if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
175  warn_printf("\t ... %ld levels...\n",
176  len - TRACE_HEAD - TRACE_TAIL);
177  i = len - TRACE_TAIL;
178  }
179  }
180  }
181  error:
182  POP_TAG();
183  rb_thread_raised_set(th, raised_flag);
184 }
185 
186 void
188 {
189  error_print();
190 }
191 
192 void
193 rb_print_undef(VALUE klass, ID id, int scope)
194 {
195  const char *v;
196 
197  switch (scope) {
198  default:
199  case NOEX_PUBLIC: v = ""; break;
200  case NOEX_PRIVATE: v = " private"; break;
201  case NOEX_PROTECTED: v = " protected"; break;
202  }
203  rb_name_error(id, "undefined%s method `%s' for %s `%s'", v,
204  rb_id2name(id),
205  (TYPE(klass) == T_MODULE) ? "module" : "class",
206  rb_class2name(klass));
207 }
208 
209 static int
211 {
212  VALUE st = rb_iv_get(err, "status");
213  return NUM2INT(st);
214 }
215 
216 static int
218 {
219  int status = EXIT_FAILURE;
221 
222  if (rb_threadptr_set_raised(th))
223  return EXIT_FAILURE;
224  switch (ex & TAG_MASK) {
225  case 0:
226  status = EXIT_SUCCESS;
227  break;
228 
229  case TAG_RETURN:
230  error_pos();
231  warn_print(": unexpected return\n");
232  break;
233  case TAG_NEXT:
234  error_pos();
235  warn_print(": unexpected next\n");
236  break;
237  case TAG_BREAK:
238  error_pos();
239  warn_print(": unexpected break\n");
240  break;
241  case TAG_REDO:
242  error_pos();
243  warn_print(": unexpected redo\n");
244  break;
245  case TAG_RETRY:
246  error_pos();
247  warn_print(": retry outside of rescue clause\n");
248  break;
249  case TAG_THROW:
250  /* TODO: fix me */
251  error_pos();
252  warn_printf(": unexpected throw\n");
253  break;
254  case TAG_RAISE: {
255  VALUE errinfo = GET_THREAD()->errinfo;
256  if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
257  status = sysexit_status(errinfo);
258  }
259  else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
260  /* no message when exiting by signal */
261  }
262  else {
263  error_print();
264  }
265  break;
266  }
267  case TAG_FATAL:
268  error_print();
269  break;
270  default:
271  rb_bug("Unknown longjmp status %d", ex);
272  break;
273  }
275  return status;
276 }
#define RSTRING_LEN(string)
Definition: generator.h:45
RARRAY_PTR(q->result)[0]
#define warn_print2(x, l)
Definition: eval_error.c:19
void rb_bug(const char *fmt,...)
Definition: error.c:265
#define TAG_NEXT
Definition: eval_intern.h:154
static VALUE VALUE th
Definition: tcltklib.c:2937
VALUE rb_eSignal
Definition: error.c:463
#define NUM2INT(x)
Definition: ruby.h:536
#define TAG_THROW
Definition: eval_intern.h:158
#define CLASS_OF(v)
Definition: ruby.h:376
#define T_MODULE
Definition: ruby.h:416
#define TAG_BREAK
Definition: eval_intern.h:153
Tcl_CmdInfo * info
Definition: tcltklib.c:1454
static void error_pos(void)
Definition: eval_error.c:22
static void set_backtrace(VALUE info, VALUE bt)
Definition: eval_error.c:59
int status
Definition: tcltklib.c:2186
static int sysexit_status(VALUE err)
Definition: eval_error.c:210
unsigned long VALUE
Definition: ruby.h:88
#define RSTRING_PTR(string)
Definition: generator.h:42
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:525
#define RARRAY_LEN(ARRAY)
Definition: generator.h:39
#define TAG_RAISE
Definition: eval_intern.h:157
#define PUSH_TAG()
Definition: eval_intern.h:125
VALUE VALUE args
Definition: tcltklib.c:2550
VALUE einfo
Definition: tcltklib.c:843
const char * fmt
Definition: tcltklib.c:837
#define GET_THREAD()
Definition: vm_core.h:690
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:793
#define TAG_FATAL
Definition: eval_intern.h:159
#define Qnil
Definition: ruby.h:367
void rb_write_error(const char *)
Definition: io.c:6698
static VALUE get_backtrace(VALUE info)
Definition: eval_error.c:42
VALUE rb_class_name(VALUE)
Definition: variable.c:305
static int error_handle(int ex)
Definition: eval_error.c:217
#define EXEC_TAG()
Definition: eval_intern.h:130
int rb_threadptr_set_raised(rb_thread_t *th)
Definition: thread.c:1433
VALUE rb_eRuntimeError
Definition: error.c:466
VALUE rb_eSysStackError
Definition: eval.c:27
va_end(args)
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2220
#define NIL_P(v)
Definition: ruby.h:374
VALUE rb_get_backtrace(VALUE info)
Definition: eval_error.c:53
#define TRACE_MAX
#define TYPE(x)
Definition: ruby.h:441
#define rb_sourcefile()
Definition: tcltklib.c:93
#define TAG_REDO
Definition: eval_intern.h:156
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:3913
int err
Definition: win32.c:78
#define EXIT_FAILURE
Definition: eval_intern.h:24
#define POP_TAG()
Definition: eval_intern.h:126
#define TAG_MASK
Definition: eval_intern.h:160
#define rb_thread_raised_clear(th)
Definition: eval_intern.h:196
#define TAG_RETURN
Definition: eval_intern.h:152
#define EXIT_SUCCESS
Definition: error.c:29
#define TRACE_HEAD
#define rb_thread_raised_set(th, f)
Definition: eval_intern.h:193
unsigned long ID
Definition: ruby.h:89
#define TRACE_TAIL
ssize_t ex
Definition: bigdecimal.c:4948
const char * rb_class2name(VALUE)
Definition: variable.c:311
int rb_threadptr_reset_raised(rb_thread_t *th)
Definition: thread.c:1443
register unsigned int len
Definition: name2ctype.h:22210
return ptr
Definition: tcltklib.c:780
void ruby_error_print(void)
Definition: eval_error.c:187
#define va_init_list(a, b)
Definition: tcltklib.c:57
static void warn_printf(const char *fmt,...)
Definition: eval_error.c:7
VALUE rb_obj_is_instance_of(VALUE, VALUE)
Definition: object.c:480
int rb_sourceline(void)
Definition: vm.c:888
ID rb_frame_callee(void)
Definition: eval.c:807
#define T_STRING
Definition: ruby.h:418
klass
Definition: tcltklib.c:3493
VALUE rb_check_backtrace(VALUE bt)
Definition: error.c:658
const char * rb_id2name(ID id)
Definition: ripper.c:16362
return rb_funcall(q->proc, ID_call, 0)
BDIGIT e
Definition: bigdecimal.c:4946
#define warn_print(x)
Definition: eval_error.c:18
void rb_print_undef(VALUE klass, ID id, int scope)
Definition: eval_error.c:193
#define vsnprintf
Definition: subst.h:7
static void error_print(void)
Definition: eval_error.c:65
ssize_t i
Definition: bigdecimal.c:5519
#define rb_intern(str)
BDIGIT v
Definition: bigdecimal.c:5520
VALUE rb_eSystemExit
Definition: error.c:461
Tcl_Interp *int * st
Definition: stubs.c:508
#define TAG_RETRY
Definition: eval_intern.h:155
#define StringValue(v)
Definition: ruby.h:466