preserve source file name encoding

* compile.c (append_compile_error), parse.y (compile_error):
  preserve encoding of source file name in exceptions.
* error.c (rb_compile_error_str, rb_compile_bug_str): add.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53278 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2015-12-24 08:25:44 +00:00
Родитель 8cda3cbb56
Коммит 26984290eb
5 изменённых файлов: 73 добавлений и 40 удалений

Просмотреть файл

@ -1,3 +1,10 @@
Thu Dec 24 17:25:42 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* compile.c (append_compile_error), parse.y (compile_error):
preserve encoding of source file name in exceptions.
* error.c (rb_compile_error_str, rb_compile_bug_str): add.
Thu Dec 24 16:17:47 2015 NARUSE, Yui <naruse@ruby-lang.org> Thu Dec 24 16:17:47 2015 NARUSE, Yui <naruse@ruby-lang.org>
* common.mk (fake.rb): $(arch)-fake.rb must depend miniruby because * common.mk (fake.rb): $(arch)-fake.rb must depend miniruby because

Просмотреть файл

@ -295,10 +295,10 @@ r_value(VALUE value)
(((INSN*)(insn))->insn_id) (((INSN*)(insn))->insn_id)
/* error */ /* error */
typedef void (*compile_error_func)(const char *, int, const char *, ...); typedef void (*compile_error_func)(VALUE, int, const char *, ...);
static void static void
append_compile_error(const char *file, int line, const char *fmt, ...) append_compile_error(VALUE file, int line, const char *fmt, ...)
{ {
VALUE err_info = rb_errinfo(); VALUE err_info = rb_errinfo();
VALUE str = rb_attr_get(err_info, idMesg); VALUE str = rb_attr_get(err_info, idMesg);
@ -306,7 +306,7 @@ append_compile_error(const char *file, int line, const char *fmt, ...)
if (RSTRING_LEN(str)) rb_str_cat2(str, "\n"); if (RSTRING_LEN(str)) rb_str_cat2(str, "\n");
if (file) { if (file) {
rb_str_cat2(str, file); rb_str_concat(str, file);
if (line) rb_str_catf(str, ":%d", line); if (line) rb_str_catf(str, ":%d", line);
rb_str_cat2(str, ": "); rb_str_cat2(str, ": ");
} }
@ -321,7 +321,7 @@ static compile_error_func
prepare_compile_error(rb_iseq_t *iseq) prepare_compile_error(rb_iseq_t *iseq)
{ {
VALUE err_info = ISEQ_COMPILE_DATA(iseq)->err_info; VALUE err_info = ISEQ_COMPILE_DATA(iseq)->err_info;
if (compile_debug) return rb_compile_bug; if (compile_debug) return rb_compile_bug_str;
if (NIL_P(err_info)) { if (NIL_P(err_info)) {
err_info = rb_exc_new_cstr(rb_eSyntaxError, ""); err_info = rb_exc_new_cstr(rb_eSyntaxError, "");
RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info); RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info);
@ -332,7 +332,7 @@ prepare_compile_error(rb_iseq_t *iseq)
#define COMPILE_ERROR prepare_compile_error(iseq) #define COMPILE_ERROR prepare_compile_error(iseq)
#define ERROR_ARGS_AT(n) ruby_sourcefile, nd_line(n), #define ERROR_ARGS_AT(n) ruby_sourcefile_string, nd_line(n),
#define ERROR_ARGS ERROR_ARGS_AT(node) #define ERROR_ARGS ERROR_ARGS_AT(node)
#define EXPECT_NODE(prefix, node, ndtype) \ #define EXPECT_NODE(prefix, node, ndtype) \
@ -340,23 +340,23 @@ do { \
NODE *error_node = (node); \ NODE *error_node = (node); \
enum node_type error_type = nd_type(error_node); \ enum node_type error_type = nd_type(error_node); \
if (error_type != (ndtype)) { \ if (error_type != (ndtype)) { \
rb_compile_bug(ERROR_ARGS_AT(error_node) \ rb_compile_bug_str(ERROR_ARGS_AT(error_node) \
prefix ": " #ndtype " is expected, but %s", \ prefix ": " #ndtype " is expected, but %s", \
ruby_node_name(error_type)); \ ruby_node_name(error_type)); \
} \ } \
} while (0) } while (0)
#define EXPECT_NODE_NONULL(prefix, parent, ndtype) \ #define EXPECT_NODE_NONULL(prefix, parent, ndtype) \
do { \ do { \
rb_compile_bug(ERROR_ARGS_AT(parent) \ rb_compile_bug_str(ERROR_ARGS_AT(parent) \
prefix ": must be " #ndtype ", but 0"); \ prefix ": must be " #ndtype ", but 0"); \
} while (0) } while (0)
#define UNKNOWN_NODE(prefix, node) \ #define UNKNOWN_NODE(prefix, node) \
do { \ do { \
NODE *error_node = (node); \ NODE *error_node = (node); \
rb_compile_bug(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \ rb_compile_bug_str(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \
ruby_node_name(nd_type(error_node))); \ ruby_node_name(nd_type(error_node))); \
} while (0) } while (0)
#define COMPILE_OK 1 #define COMPILE_OK 1
@ -494,6 +494,7 @@ iseq_add_mark_object(const rb_iseq_t *iseq, VALUE v)
return COMPILE_OK; return COMPILE_OK;
} }
#define ruby_sourcefile_string (iseq->body->location.path)
#define ruby_sourcefile RSTRING_PTR(iseq->body->location.path) #define ruby_sourcefile RSTRING_PTR(iseq->body->location.path)
static int static int
@ -512,7 +513,7 @@ validate_label(st_data_t name, st_data_t label, st_data_t arg)
LABEL *lobj = (LABEL *)label; LABEL *lobj = (LABEL *)label;
if (!lobj->link.next) { if (!lobj->link.next) {
do { do {
COMPILE_ERROR(ruby_sourcefile, lobj->position, COMPILE_ERROR(ruby_sourcefile_string, lobj->position,
"%"PRIsVALUE": undefined label", "%"PRIsVALUE": undefined label",
rb_id2str((ID)name)); rb_id2str((ID)name));
} while (0); } while (0);
@ -611,7 +612,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, NODE *node)
COMPILE(ret, "defined guard", node); COMPILE(ret, "defined guard", node);
break; break;
default: default:
rb_compile_bug(ERROR_ARGS "unknown scope"); rb_compile_bug_str(ERROR_ARGS "unknown scope");
} }
} }
@ -1559,7 +1560,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
default: default:
dump_disasm_list(FIRST_ELEMENT(anchor)); dump_disasm_list(FIRST_ELEMENT(anchor));
dump_disasm_list(list); dump_disasm_list(list);
COMPILE_ERROR(ruby_sourcefile, line, "error: set_sequence"); COMPILE_ERROR(ruby_sourcefile_string, line, "error: set_sequence");
return COMPILE_NG; return COMPILE_NG;
} }
list = list->next; list = list->next;
@ -1606,7 +1607,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
dump_disasm_list(list); dump_disasm_list(list);
xfree(generated_iseq); xfree(generated_iseq);
xfree(line_info_table); xfree(line_info_table);
COMPILE_ERROR(ruby_sourcefile, iobj->line_no, COMPILE_ERROR(ruby_sourcefile_string, iobj->line_no,
"operand size miss! (%d for %d)", "operand size miss! (%d for %d)",
iobj->operand_size, len - 1); iobj->operand_size, len - 1);
return COMPILE_NG; return COMPILE_NG;
@ -1621,7 +1622,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
/* label(destination position) */ /* label(destination position) */
LABEL *lobj = (LABEL *)operands[j]; LABEL *lobj = (LABEL *)operands[j];
if (!lobj->set) { if (!lobj->set) {
COMPILE_ERROR(ruby_sourcefile, iobj->line_no, COMPILE_ERROR(ruby_sourcefile_string, iobj->line_no,
"unknown label"); "unknown label");
return COMPILE_NG; return COMPILE_NG;
} }
@ -1716,7 +1717,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
default: default:
xfree(generated_iseq); xfree(generated_iseq);
xfree(line_info_table); xfree(line_info_table);
COMPILE_ERROR(ruby_sourcefile, iobj->line_no, COMPILE_ERROR(ruby_sourcefile_string, iobj->line_no,
"unknown operand type: %c", type); "unknown operand type: %c", type);
return COMPILE_NG; return COMPILE_NG;
} }
@ -1773,8 +1774,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
generated_iseq[code_index++] = BIN(nop); generated_iseq[code_index++] = BIN(nop);
} }
else { else {
rb_compile_bug(ruby_sourcefile, adjust->line_no, rb_compile_bug_str(ruby_sourcefile_string, adjust->line_no,
"iseq_set_sequence: adjust bug %d < %d", orig_sp, sp); "iseq_set_sequence: adjust bug %d < %d", orig_sp, sp);
} }
} }
break; break;
@ -2454,7 +2455,7 @@ insn_set_sc_state(rb_iseq_t *iseq, INSN *iobj, int state)
dump_disasm_list((LINK_ELEMENT *)iobj); dump_disasm_list((LINK_ELEMENT *)iobj);
dump_disasm_list((LINK_ELEMENT *)lobj); dump_disasm_list((LINK_ELEMENT *)lobj);
printf("\n-- %d, %d\n", lobj->sc_state, nstate); printf("\n-- %d, %d\n", lobj->sc_state, nstate);
COMPILE_ERROR(ruby_sourcefile, iobj->line_no, COMPILE_ERROR(ruby_sourcefile_string, iobj->line_no,
"insn_set_sc_state error\n"); "insn_set_sc_state error\n");
return COMPILE_NG; return COMPILE_NG;
} }
@ -2556,7 +2557,7 @@ iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
case SCS_XX: case SCS_XX:
goto normal_insn; goto normal_insn;
default: default:
COMPILE_ERROR(ruby_sourcefile, iobj->line_no, COMPILE_ERROR(ruby_sourcefile_string, iobj->line_no,
"unreachable"); "unreachable");
return COMPILE_NG; return COMPILE_NG;
} }
@ -2600,8 +2601,8 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int *cntp)
if (!NIL_P(lit)) { if (!NIL_P(lit)) {
cnt++; cnt++;
if (!RB_TYPE_P(lit, T_STRING)) { if (!RB_TYPE_P(lit, T_STRING)) {
rb_compile_bug(ERROR_ARGS "dstr: must be string: %s", rb_compile_bug_str(ERROR_ARGS "dstr: must be string: %s",
rb_builtin_type_name(TYPE(lit))); rb_builtin_type_name(TYPE(lit)));
} }
lit = node->nd_lit = rb_fstring(lit); lit = node->nd_lit = rb_fstring(lit);
ADD_INSN1(ret, nd_line(node), putobject, lit); ADD_INSN1(ret, nd_line(node), putobject, lit);
@ -2947,7 +2948,8 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int onl
} }
else { else {
if (rb_hash_lookup(literals, lit) != Qnil) { if (rb_hash_lookup(literals, lit) != Qnil) {
rb_compile_warning(ruby_sourcefile, nd_line(val), "duplicated when clause is ignored"); rb_compile_warning(ruby_sourcefile, nd_line(val),
"duplicated when clause is ignored");
} }
else { else {
rb_hash_aset(literals, lit, (VALUE)(l1) | 1); rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
@ -3823,7 +3825,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
vals = node->nd_head; vals = node->nd_head;
if (!vals) { if (!vals) {
rb_compile_bug(ERROR_ARGS "NODE_WHEN: must be NODE_ARRAY, but 0"); rb_compile_bug_str(ERROR_ARGS "NODE_WHEN: must be NODE_ARRAY, but 0");
} }
switch (nd_type(vals)) { switch (nd_type(vals)) {
case NODE_ARRAY: case NODE_ARRAY:
@ -3917,7 +3919,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
if (node->nd_state == Qundef) { if (node->nd_state == Qundef) {
/* ADD_INSN(ret, line, putundef); */ /* ADD_INSN(ret, line, putundef); */
rb_compile_bug(ERROR_ARGS "unsupported: putundef"); rb_compile_bug_str(ERROR_ARGS "unsupported: putundef");
} }
else { else {
ADD_INSN(ret, line, putnil); ADD_INSN(ret, line, putnil);
@ -4391,7 +4393,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
if (idx < 0) { if (idx < 0) {
rb_compile_bug(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%"PRIsVALUE")", rb_id2str(node->nd_vid)); rb_compile_bug_str(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%"PRIsVALUE")", rb_id2str(node->nd_vid));
} }
ADD_INSN2(ret, line, setlocal, INT2FIX(ls - idx), INT2FIX(lv)); ADD_INSN2(ret, line, setlocal, INT2FIX(ls - idx), INT2FIX(lv));
@ -5115,8 +5117,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
break; break;
default: default:
rb_compile_bug(ERROR_ARGS_AT(node->nd_head) "can't make hash with this node: %s", rb_compile_bug_str(ERROR_ARGS_AT(node->nd_head) "can't make hash with this node: %s",
ruby_node_name(type)); ruby_node_name(type));
} }
if (poped) { if (poped) {
@ -5206,7 +5208,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
if (!poped) { if (!poped) {
idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
if (idx < 0) { if (idx < 0) {
rb_compile_bug(ERROR_ARGS "unknown dvar (%"PRIsVALUE")", rb_id2str(node->nd_vid)); rb_compile_bug_str(ERROR_ARGS "unknown dvar (%"PRIsVALUE")", rb_id2str(node->nd_vid));
} }
ADD_INSN2(ret, line, getlocal, INT2FIX(ls - idx), INT2FIX(lv)); ADD_INSN2(ret, line, getlocal, INT2FIX(ls - idx), INT2FIX(lv));
} }
@ -5800,13 +5802,13 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
if (default_value == (NODE *)-1) { if (default_value == (NODE *)-1) {
/* required argument. do nothing */ /* required argument. do nothing */
rb_compile_bug(ERROR_ARGS "unreachable"); rb_compile_bug_str(ERROR_ARGS "unreachable");
} }
else if (nd_type(default_value) == NODE_LIT || else if (nd_type(default_value) == NODE_LIT ||
nd_type(default_value) == NODE_NIL || nd_type(default_value) == NODE_NIL ||
nd_type(default_value) == NODE_TRUE || nd_type(default_value) == NODE_TRUE ||
nd_type(default_value) == NODE_FALSE) { nd_type(default_value) == NODE_FALSE) {
rb_compile_bug(ERROR_ARGS "unreachable"); rb_compile_bug_str(ERROR_ARGS "unreachable");
} }
else { else {
/* if keywordcheck(_kw_bits, nth_keyword) /* if keywordcheck(_kw_bits, nth_keyword)
@ -6347,14 +6349,14 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
insn = (argc < 0) ? Qnil : RARRAY_AREF(obj, 0); insn = (argc < 0) ? Qnil : RARRAY_AREF(obj, 0);
if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) { if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) {
/* TODO: exception */ /* TODO: exception */
COMPILE_ERROR(ruby_sourcefile, line_no, COMPILE_ERROR(ruby_sourcefile_string, line_no,
"unknown instruction: %+"PRIsVALUE, insn); "unknown instruction: %+"PRIsVALUE, insn);
ret = COMPILE_NG; ret = COMPILE_NG;
break; break;
} }
if (argc != insn_len((VALUE)insn_id)-1) { if (argc != insn_len((VALUE)insn_id)-1) {
COMPILE_ERROR(ruby_sourcefile, line_no, COMPILE_ERROR(ruby_sourcefile_string, line_no,
"operand size mismatch"); "operand size mismatch");
ret = COMPILE_NG; ret = COMPILE_NG;
break; break;

22
error.c
Просмотреть файл

@ -151,6 +151,20 @@ rb_compile_error(const char *file, int line, const char *fmt, ...)
compile_err_append(str); compile_err_append(str);
} }
void
rb_compile_error_str(VALUE file, int line, void *enc, const char *fmt, ...)
{
va_list args;
VALUE str;
va_start(args, fmt);
str = compile_snprintf(enc, NULL,
NIL_P(file) ? NULL : RSTRING_PTR(file), line,
fmt, args);
va_end(args);
compile_err_append(str);
}
void void
rb_compile_error_append(const char *fmt, ...) rb_compile_error_append(const char *fmt, ...)
{ {
@ -477,6 +491,14 @@ rb_compile_bug(const char *file, int line, const char *fmt, ...)
abort(); abort();
} }
void
rb_compile_bug_str(VALUE file, int line, const char *fmt, ...)
{
report_bug(RSTRING_PTR(file), line, fmt, NULL);
abort();
}
static const char builtin_types[][10] = { static const char builtin_types[][10] = {
"", /* 0x00, */ "", /* 0x00, */
"Object", "Object",

Просмотреть файл

@ -736,6 +736,8 @@ extern VALUE rb_eEAGAIN;
extern VALUE rb_eEWOULDBLOCK; extern VALUE rb_eEWOULDBLOCK;
extern VALUE rb_eEINPROGRESS; extern VALUE rb_eEINPROGRESS;
NORETURN(PRINTF_ARGS(void rb_compile_bug(const char*, int, const char*, ...), 3, 4)); NORETURN(PRINTF_ARGS(void rb_compile_bug(const char*, int, const char*, ...), 3, 4));
NORETURN(PRINTF_ARGS(void rb_compile_bug_str(VALUE file, int line, const char *fmt, ...), 3, 4));
PRINTF_ARGS(void rb_compile_error_str(VALUE file, int line, void *enc, const char *fmt, ...), 4, 5);
VALUE rb_check_backtrace(VALUE); VALUE rb_check_backtrace(VALUE);
NORETURN(void rb_async_bug_errno(const char *,int)); NORETURN(void rb_async_bug_errno(const char *,int));
const char *rb_builtin_type_name(int t); const char *rb_builtin_type_name(int t);

10
parse.y
Просмотреть файл

@ -741,15 +741,15 @@ static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
# define WARN_S(s) s # define WARN_S(s) s
# define WARN_I(i) i # define WARN_I(i) i
# define PRIsWARN PRIsVALUE # define PRIsWARN PRIsVALUE
# define WARN_ARGS(fmt,n) ruby_sourcefile, ruby_sourceline, (fmt) # define WARN_ARGS(fmt,n) WARN_ARGS_L(ruby_sourceline,fmt,n)
# define WARN_ARGS_L(l,fmt,n) ruby_sourcefile, (l), (fmt) # define WARN_ARGS_L(l,fmt,n) ruby_sourcefile, (l), (fmt)
# define WARN_CALL rb_compile_warn # define WARN_CALL rb_compile_warn
# define WARNING_ARGS(fmt,n) WARN_ARGS(fmt,n) # define WARNING_ARGS(fmt,n) WARN_ARGS(fmt,n)
# define WARNING_ARGS_L(l,fmt,n) WARN_ARGS_L(l,fmt,n) # define WARNING_ARGS_L(l,fmt,n) WARN_ARGS_L(l,fmt,n)
# define WARNING_CALL rb_compile_warning # define WARNING_CALL rb_compile_warning
# define rb_compile_error rb_compile_error_with_enc # define rb_compile_error rb_compile_error_str
# define compile_error (parser->error_p = 1),rb_compile_error_with_enc # define compile_error (parser->error_p = 1),rb_compile_error_str
# define PARSER_ARG ruby_sourcefile, ruby_sourceline, (void *)current_enc, # define PARSER_ARG ruby_sourcefile_string, ruby_sourceline, (void *)current_enc,
#endif #endif
/* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150, /* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
@ -7020,7 +7020,7 @@ parser_set_encode(struct parser_params *parser, const char *name)
error: error:
excargs[0] = rb_eArgError; excargs[0] = rb_eArgError;
excargs[2] = rb_make_backtrace(); excargs[2] = rb_make_backtrace();
rb_ary_unshift(excargs[2], rb_sprintf("%s:%d", ruby_sourcefile, ruby_sourceline)); rb_ary_unshift(excargs[2], rb_sprintf("%"PRIsVALUE":%d", ruby_sourcefile_string, ruby_sourceline));
rb_exc_raise(rb_make_exception(3, excargs)); rb_exc_raise(rb_make_exception(3, excargs));
} }
enc = rb_enc_from_index(idx); enc = rb_enc_from_index(idx);