Project

General

Profile

Feature #14141 ยป 2.patch

sorah (Sorah Fukumori), 11/29/2017 01:04 PM

View differences:

NEWS
31 31

  
32 32
  * Now deprecated [Feature #3072]
33 33

  
34
* Exception
35

  
36
  * Exception#display  [Feature #14141]
37

  
34 38
* Dir
35 39

  
36 40
  * Dir.glob provides new optional keyword argument, :base.
error.c
922 922

  
923 923
/*
924 924
 * call-seq:
925
 *   exception.display(port=$stderr) -> nil
926
 *
927
 * Prints formatted <i>exception</i> on the given port (default to <code>$stderr</code>).
928
 * Format includes backtrace, exception class and exception message.
929
 *
930
 * This method is useful to log caught exceptions.
931
 *
932
 *     begin
933
 *       some_work
934
 *     rescue => e
935
 *       e.display
936
 *       retry
937
 *     end
938
 */
939

  
940
static VALUE
941
exc_display(int argc, VALUE *argv, VALUE exc)
942
{
943
    VALUE out;
944

  
945
    if (argc == 0) {
946
        out = rb_stderr;
947
    }
948
    else {
949
        rb_scan_args(argc, argv, "01", &out);
950
    }
951

  
952
    rb_ec_error_write(exc, Qundef, out);
953

  
954
    return Qnil;
955
}
956

  
957
/*
958
 * call-seq:
925 959
 *   exception.message   ->  string
926 960
 *
927 961
 * Returns the result of invoking <code>exception.to_s</code>.
......
2182 2216
    rb_define_method(rb_eException, "initialize", exc_initialize, -1);
2183 2217
    rb_define_method(rb_eException, "==", exc_equal, 1);
2184 2218
    rb_define_method(rb_eException, "to_s", exc_to_s, 0);
2219
    rb_define_method(rb_eException, "display", exc_display, -1);
2220

  
2185 2221
    rb_define_method(rb_eException, "message", exc_message, 0);
2186 2222
    rb_define_method(rb_eException, "inspect", exc_inspect, 0);
2187 2223
    rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
eval_error.c
4 4
 */
5 5

  
6 6
#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P
7
#define warn_print_io(io, x) RB_GNUC_EXTENSION_BLOCK( \
8
        NIL_P(io) ? \
9
            warn_print(x) : ( \
10
            (__builtin_constant_p(x)) ? 		\
11
                rb_io_write((io), rb_str_new((x), (long)strlen(x))) : \
12
                rb_io_write((io), rb_str_new2(x)) \
13
            ) \
14
        )
7 15
#define warn_print(x) RB_GNUC_EXTENSION_BLOCK(	\
8 16
    (__builtin_constant_p(x)) ? 		\
9 17
	rb_write_error2((x), (long)strlen(x)) : \
10 18
	rb_write_error(x)			\
11 19
)
12 20
#else
21
#define warn_print_io(io, x) NIL_P(io) ? rb_write_error((x)) : rb_io_write((io), rb_str_new2(x))
13 22
#define warn_print(x) rb_write_error(x)
14 23
#endif
24

  
25
#define warn_print2_io(io,x,l) NIL_P(io) ? warn_print2(x,l) : rb_io_write((io), rb_str_new((x),(l)))
15 26
#define warn_print2(x,l) rb_write_error2((x),(l))
27

  
28
#define warn_print_str_io(io,x) NIL_P(io) ? rb_write_error_str(x) : rb_io_write((io), (x))
16 29
#define warn_print_str(x) rb_write_error_str(x)
17 30

  
18 31
static VALUE error_pos_str(void);
......
73 86
}
74 87

  
75 88
static void
76
print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, int colored)
89
print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, const VALUE io, int colored)
77 90
{
78 91
    static const char underline[] = "\033[4;1m";
79 92
    static const char bold[] = "\033[1m";
......
88 101
	    error_pos();
89 102
	}
90 103
	else {
91
	    warn_print_str(mesg);
92
	    warn_print(": ");
104
	    warn_print_str_io(io, mesg);
105
	    warn_print_io(io, ": ");
93 106
	}
94 107

  
95
        if (colored) warn_print(bold);
108
        if (colored) warn_print_io(io, bold);
96 109

  
97 110
	if (!NIL_P(emesg)) {
98 111
	    einfo = RSTRING_PTR(emesg);
......
101 114
    }
102 115

  
103 116
    if (eclass == rb_eRuntimeError && elen == 0) {
104
        if (colored) warn_print(underline);
105
	warn_print("unhandled exception\n");
117
        if (colored) warn_print_io(io, underline);
118
	warn_print_io(io, "unhandled exception\n");
106 119
    }
107 120
    else {
108 121
	VALUE epath;
109 122

  
110 123
	epath = rb_class_name(eclass);
111 124
	if (elen == 0) {
112
            if (colored) warn_print(underline);
113
	    warn_print_str(epath);
114
	    warn_print("\n");
125
            if (colored) warn_print_io(io, underline);
126
	    warn_print_str_io(io, epath);
127
	    warn_print_io(io, "\n");
115 128
	}
116 129
	else {
117 130
	    const char *tail = 0;
......
123 136
		len = tail - einfo;
124 137
		tail++;		/* skip newline */
125 138
	    }
126
	    warn_print_str(tail ? rb_str_subseq(emesg, 0, len) : emesg);
139
	    warn_print_str_io(io, tail ? rb_str_subseq(emesg, 0, len) : emesg);
127 140
	    if (epath) {
128
		warn_print(" (");
129
                if (colored) warn_print(underline);
130
                warn_print_str(epath);
131
                if (colored) warn_print(reset);
132
                if (colored) warn_print(bold);
133
		warn_print(")\n");
141
		warn_print_io(io, " (");
142
                if (colored) warn_print_io(io, underline);
143
                warn_print_str_io(io, epath);
144
                if (colored) warn_print_io(io, reset);
145
                if (colored) warn_print_io(io, bold);
146
		warn_print_io(io, ")\n");
134 147
	    }
135 148
	    if (tail) {
136
		warn_print_str(rb_str_subseq(emesg, tail - einfo, elen - len - 1));
149
		warn_print_str_io(io, rb_str_subseq(emesg, tail - einfo, elen - len - 1));
137 150
	    }
138
	    if (tail ? einfo[elen-1] != '\n' : !epath) warn_print2("\n", 1);
151
	    if (tail ? einfo[elen-1] != '\n' : !epath) warn_print2_io(io, "\n", 1);
139 152
	}
140 153
    }
141
    if (colored) warn_print(reset);
154
    if (colored) warn_print_io(io, reset);
142 155
}
143 156

  
144 157
static void
145
print_backtrace(const VALUE eclass, const VALUE errat, int reverse)
158
print_backtrace(const VALUE eclass, const VALUE errat, const VALUE io, int reverse)
146 159
{
147 160
    if (!NIL_P(errat)) {
148 161
	long i;
......
163 176
	    if (RB_TYPE_P(line, T_STRING)) {
164 177
		VALUE str = rb_str_new_cstr("\t");
165 178
		if (reverse) rb_str_catf(str, "%*ld: ", width, len - i);
166
		warn_print_str(rb_str_catf(str, "from %"PRIsVALUE"\n", line));
179
		warn_print_str_io(io, rb_str_catf(str, "from %"PRIsVALUE"\n", line));
167 180
	    }
168 181
	    if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
169
		warn_print_str(rb_sprintf("\t ... %ld levels...\n",
182
		warn_print_str_io(io, rb_sprintf("\t ... %ld levels...\n",
170 183
					  len - TRACE_HEAD - TRACE_TAIL));
171 184
		i = len - TRACE_TAIL;
172 185
	    }
......
175 188
}
176 189

  
177 190
void
178
rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo)
191
rb_ec_error_write(volatile VALUE errinfo, volatile VALUE errat, volatile VALUE io)
179 192
{
180
    volatile VALUE errat = Qundef;
181
    volatile int raised_flag = ec->raised_flag;
182 193
    volatile VALUE eclass = Qundef, emesg = Qundef;
183 194

  
184 195
    if (NIL_P(errinfo))
185 196
	return;
186
    rb_ec_raised_clear(ec);
187 197

  
188
    EC_PUSH_TAG(ec);
189
    if (EC_EXEC_TAG() == TAG_NONE) {
190
	errat = rb_get_backtrace(errinfo);
191
    }
192
    else if (errat == Qundef) {
198
    if (errat == Qundef) {
193 199
	errat = Qnil;
194 200
    }
195
    else if (eclass == Qundef || emesg != Qundef) {
196
	goto error;
197
    }
198 201
    if ((eclass = CLASS_OF(errinfo)) != Qundef) {
199 202
	VALUE e = rb_check_funcall(errinfo, rb_intern("message"), 0, 0);
200 203
	if (e != Qundef) {
......
203 206
	}
204 207
    }
205 208
    if (rb_stderr_tty_p()) {
206
	warn_print("\033[1mTraceback \033[m(most recent call last):\n");
207
	print_backtrace(eclass, errat, TRUE);
208
	print_errinfo(eclass, errat, emesg, TRUE);
209
	warn_print_io(io, "\033[1mTraceback \033[m(most recent call last):\n");
210
	print_backtrace(eclass, errat, io, TRUE);
211
	print_errinfo(eclass, errat, emesg, io, TRUE);
209 212
    }
210 213
    else {
211
	print_errinfo(eclass, errat, emesg, FALSE);
212
	print_backtrace(eclass, errat, FALSE);
214
	print_errinfo(eclass, errat, emesg, io, FALSE);
215
	print_backtrace(eclass, errat, io, FALSE);
213 216
    }
214
  error:
217
}
218

  
219
void
220
rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo)
221
{
222
    volatile int raised_flag = ec->raised_flag;
223
    volatile VALUE errat;
224

  
225
    if (NIL_P(errinfo))
226
	return;
227
    rb_ec_raised_clear(ec);
228

  
229
    EC_PUSH_TAG(ec);
230
    if (EC_EXEC_TAG() == TAG_NONE) {
231
	errat = rb_get_backtrace(errinfo);
232
    }
233

  
234
    rb_ec_error_write(errinfo, errat, Qnil);
235

  
236
error:
215 237
    EC_POP_TAG();
216 238
    ec->errinfo = errinfo;
217 239
    rb_ec_raised_set(ec, raised_flag);
218
-