From b3bf03d695ddad389bb3a569e93eca598c8c41ad Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Tue, 13 Dec 2016 08:21:24 -0800 Subject: [PATCH] Change Kernel#warn to call Warning.warn This allows Warning.warn to filter/process warning messages generated by Kernel#warn. Currently, Warning.warn can only handle messages generated by the rb_warn/rb_warning C functions. The Kernel#warn API is different than the Warning.warn API, this tries to get similar behavior, but there may be corner cases where the behavior is different. This makes str_end_with_asciichar in io.c no longer static so it can be called from error.c. --- error.c | 41 ++++++++++++++++++++++++++++++++--------- io.c | 2 +- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/error.c b/error.c index e03a4ee..772364d 100644 --- a/error.c +++ b/error.c @@ -38,13 +38,14 @@ VALUE rb_iseqw_local_variables(VALUE iseqval); VALUE rb_iseqw_new(const rb_iseq_t *); +int str_end_with_asciichar(VALUE str, int c); VALUE rb_eEAGAIN; VALUE rb_eEWOULDBLOCK; VALUE rb_eEINPROGRESS; VALUE rb_mWarning; -static ID id_warn; +static ID id_warn, id_flatten_b; extern const char ruby_description[]; @@ -276,23 +277,44 @@ rb_enc_warning(rb_encoding *enc, const char *fmt, ...) * call-seq: * warn(msg, ...) -> nil * - * Displays each of the given messages followed by a record separator on - * STDERR unless warnings have been disabled (for example with the - * -W0 flag). - * + * If warnings have been disabled (for example with the + * -W0 flag), does nothing. Otherwise, + * flattens the array of arguments and converts the + * entries to strings, makes sure all strings end with + * a newline, joins all strings into a single string, + * and calls Warning.warn with the + * resulting string. + * * warn("warning 1", "warning 2") + * warn(["warning 1\n", "warning 2"]) + * warn("warning 1", "warning 2\n") * - * produces: + * all call Warning.warn with: * - * warning 1 - * warning 2 + * "warning 1\nwarning 2\n" */ static VALUE rb_warn_m(int argc, VALUE *argv, VALUE exc) { if (!NIL_P(ruby_verbose) && argc > 0) { - rb_io_puts(argc, argv, rb_stderr); + int i; + VALUE str; + VALUE ary = rb_ary_new_from_values(argc, argv); + rb_funcall(ary, id_flatten_b, 0); + Check_Type(ary, T_ARRAY); + argc = RARRAY_LEN(ary); + argv = RARRAY_PTR(ary); + + for(i = 0; i < argc; i++) { + str = rb_obj_as_string(argv[i]); + if (RSTRING_LEN(str) == 0 || !str_end_with_asciichar(str, '\n')) { + str = rb_str_cat(rb_str_dup(str), "\n", 1); + } + rb_ary_store(ary, i, str); + } + + rb_write_warning_str(rb_ary_join(ary, rb_str_new("", 0))); } return Qnil; } @@ -2108,6 +2130,7 @@ Init_Exception(void) id_errno = rb_intern_const("errno"); id_i_path = rb_intern_const("@path"); id_warn = rb_intern_const("warn"); + id_flatten_b = rb_intern_const("flatten!"); id_iseq = rb_make_internal_id(); } diff --git a/io.c b/io.c index 1f00f6c..865b3a6 100644 --- a/io.c +++ b/io.c @@ -7123,7 +7123,7 @@ rb_f_putc(VALUE recv, VALUE ch) } -static int +int str_end_with_asciichar(VALUE str, int c) { long len = RSTRING_LEN(str); -- 2.10.1