From: Nobuyoshi Nakada Date: 2007-09-26T04:16:16+09:00 Subject: [ruby-dev:31862] Re: huge `if' dumps core なかだです。 At Tue, 25 Sep 2007 21:12:42 +0900, Yukihiro Matsumoto wrote in [ruby-dev:31855]: > |> 以下のようにすると 1.8 、1.9 共に落ちます。 > > |> ALLOCA_N が原因のようです。 > | > |さすがに、1MBを越えるエラーメッセージが出てくれてもあまりうれし > |くないのでは。 > > でしょうね。なかださんのパッチをコミットしてくださいませんか? 1.8のほうはどうしましょうか。rb_enc_prev_char()相当がないので、 re_adjust_startpos()から流用するなら以下のような感じです。 というか、手元では[ruby-talk:247595]が当たったままだったので、そ もそも"memory exhausted"自体が発生しなかったのですが。 Index: parse.y =================================================================== --- parse.y (revision 13508) +++ parse.y (working copy) @@ -2517,5 +2517,7 @@ yyerror(msg) const char *msg; { - char *p, *pe, *buf; + const int max_line_margin = 30; + const char *p, *pe; + char *buf; int len, i; @@ -2536,15 +2538,30 @@ yyerror(msg) len = pe - p; if (len > 4) { + char *p2; + const char *pre = "", *post = ""; + + if (len > max_line_margin * 2 + 10) { + int re_mbc_startpos _((const char *, int, int, int)); + if ((len = lex_p - p) > max_line_margin) { + p = p + re_mbc_startpos(p, len, len - max_line_margin, 0); + pre = "..."; + } + if ((len = pe - lex_p) > max_line_margin) { + pe = lex_p + re_mbc_startpos(lex_p, len, max_line_margin, 1); + post = "..."; + } + len = pe - p; + } buf = ALLOCA_N(char, len+2); MEMCPY(buf, p, char, len); buf[len] = '\0'; - rb_compile_error_append("%s", buf); + rb_compile_error_append("%s%s%s", pre, buf, post); i = lex_p - p; - p = buf; pe = p + len; + p2 = buf; pe = buf + len; - while (p < pe) { - if (*p != '\t') *p = ' '; - p++; + while (p2 < pe) { + if (*p2 != '\t') *p2 = ' '; + p2++; } buf[i] = '^'; Index: regex.c =================================================================== --- regex.c (revision 13508) +++ regex.c (working copy) @@ -3110,4 +3110,26 @@ re_compile_fastmap(bufp) /* adjust startpos value to the position between characters. */ int +re_mbc_startpos(string, size, startpos, range) + const char *string; + int size, startpos, range; +{ + int i = mbc_startpos(string, startpos); + + if (i < startpos) { + if (range > 0) { + startpos = i + mbclen(string[i]); + } + else { + int len = mbclen(string[i]); + if (i + len <= startpos) + startpos = i + len; + else + startpos = i; + } + } + return startpos; +} + +int re_adjust_startpos(bufp, string, size, startpos, range) struct re_pattern_buffer *bufp; @@ -3122,18 +3144,5 @@ re_adjust_startpos(bufp, string, size, s /* Adjust startpos for mbc string */ if (current_mbctype && startpos>0 && !(bufp->options&RE_OPTIMIZE_BMATCH)) { - int i = mbc_startpos(string, startpos); - - if (i < startpos) { - if (range > 0) { - startpos = i + mbclen(string[i]); - } - else { - int len = mbclen(string[i]); - if (i + len <= startpos) - startpos = i + len; - else - startpos = i; - } - } + startpos = re_mbc_startpos(string, size, startpos, range); } return startpos; -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦