ruby-changes:55881
From: Nobuyoshi <ko1@a...>
Date: Wed, 29 May 2019 00:07:06 +0900 (JST)
Subject: [ruby-changes:55881] Nobuyoshi Nakada: c730c25354 (trunk): parse.y: warn escaped whitespace
https://git.ruby-lang.org/ruby.git/commit/?id=c730c25354 From c730c25354a18e99b9147c30ecc8f986d6a172f1 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Tue, 28 May 2019 21:39:13 +0900 Subject: parse.y: warn escaped whitespace * parse.y (warn_space_char_code): warn whitespace characters escaped with meta/control prefix. diff --git a/parse.y b/parse.y index a218819..091efa9 100644 --- a/parse.y +++ b/parse.y @@ -6139,6 +6139,36 @@ tok_hex(struct parser_params *p, size_t *numlen) https://github.com/ruby/ruby/blob/trunk/parse.y#L6139 #define tokcopy(p, n) memcpy(tokspace(p, n), (p)->lex.pcur - (n), (n)) static int +escaped_control_code(int c) +{ + int c2 = 0; + switch (c) { + case ' ': + c2 = 's'; + break; + case '\n': + c2 = 'n'; + break; + case '\t': + c2 = 't'; + break; + case '\v': + c2 = 'v'; + break; + case '\r': + c2 = 'r'; + break; + case '\f': + c2 = 'f'; + break; + } + return c2; +} + +#define WARN_SPACE_CHAR(c, prefix) \ + rb_warn1("invalid character syntax; use "prefix"\\%c", WARN_I(c2)) + +static int tokadd_codepoint(struct parser_params *p, rb_encoding **encp, int regexp_literal, int wide) { @@ -6290,6 +6320,16 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp) https://github.com/ruby/ruby/blob/trunk/parse.y#L6320 } else if (c == -1 || !ISASCII(c)) goto eof; else { + int c2 = escaped_control_code(c); + if (c2) { + if (ISCNTRL(c) || !(flags & ESCAPE_CONTROL)) { + WARN_SPACE_CHAR(c2, "\\M-"); + } + else { + WARN_SPACE_CHAR(c2, "\\C-\\M-"); + } + } + else if (ISCNTRL(c)) goto eof; return ((c & 0xff) | 0x80); } @@ -6306,6 +6346,28 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp) https://github.com/ruby/ruby/blob/trunk/parse.y#L6346 else if (c == '?') return 0177; else if (c == -1 || !ISASCII(c)) goto eof; + else { + int c2 = escaped_control_code(c); + if (c2) { + if (ISCNTRL(c)) { + if (flags & ESCAPE_META) { + WARN_SPACE_CHAR(c2, "\\M-"); + } + else { + WARN_SPACE_CHAR(c2, ""); + } + } + else { + if (flags & ESCAPE_META) { + WARN_SPACE_CHAR(c2, "\\M-\\C-"); + } + else { + WARN_SPACE_CHAR(c2, "\\C-"); + } + } + } + else if (ISCNTRL(c)) goto eof; + } return c & 0x9f; eof: @@ -8009,29 +8071,9 @@ parse_qmark(struct parser_params *p, int space_seen) https://github.com/ruby/ruby/blob/trunk/parse.y#L8071 } if (rb_enc_isspace(c, p->enc)) { if (!IS_ARG()) { - int c2 = 0; - switch (c) { - case ' ': - c2 = 's'; - break; - case '\n': - c2 = 'n'; - break; - case '\t': - c2 = 't'; - break; - case '\v': - c2 = 'v'; - break; - case '\r': - c2 = 'r'; - break; - case '\f': - c2 = 'f'; - break; - } + int c2 = escaped_control_code(c); if (c2) { - rb_warn1("invalid character syntax; use ?\\%c", WARN_I(c2)); + WARN_SPACE_CHAR(c2, "?"); } } ternary: diff --git a/test/ruby/test_literal.rb b/test/ruby/test_literal.rb index ff40474..3f5acde 100644 --- a/test/ruby/test_literal.rb +++ b/test/ruby/test_literal.rb @@ -45,6 +45,7 @@ class TestRubyLiteral < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_literal.rb#L45 assert_equal "A", ?A assert_instance_of String, ?\n assert_equal "\n", ?\n + assert_equal " ", ?\s assert_equal " ", ?\ # space assert_equal '', '' assert_equal 'string', 'string' diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 11a77ba..fca8d74 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -548,6 +548,19 @@ class TestParse < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_parse.rb#L548 assert_equal("\x81", eval('"\C-\M-a"')) assert_equal("\177", eval('"\c?"')) + + assert_warning(/use \\C-\\s/) {assert_equal("\x00", eval('"\C- "'))} + assert_warning(/use \\M-\\s/) {assert_equal("\xa0", eval('"\M- "'))} + assert_warning(/use \\M-\\C-\\s/) {assert_equal("\x80", eval('"\M-\C- "'))} + assert_warning(/use \\C-\\M-\\s/) {assert_equal("\x80", eval('"\C-\M- "'))} + assert_warning(/use \\t/) {assert_equal("\x09", eval("\"\\C-\t\""))} + assert_warning(/use \\M-\\t/) {assert_equal("\x89", eval("\"\\M-\t\""))} + assert_warning(/use \\M-\\t/) {assert_equal("\x89", eval("\"\\M-\\C-\t\""))} + assert_warning(/use \\M-\\t/) {assert_equal("\x89", eval("\"\\C-\\M-\t\""))} + assert_syntax_error("\"\\C-\x01\"", 'Invalid escape character syntax') + assert_syntax_error("\"\\M-\x01\"", 'Invalid escape character syntax') + assert_syntax_error("\"\\M-\\C-\x01\"", 'Invalid escape character syntax') + assert_syntax_error("\"\\C-\\M-\x01\"", 'Invalid escape character syntax') end def test_question @@ -565,6 +578,19 @@ class TestParse < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_parse.rb#L578 assert_equal("\u{1234}", eval('?\u1234')) e = assert_syntax_error('"#{?\u123}"', 'invalid Unicode escape') assert_not_match(/end-of-input/, e.message) + + assert_warning(/use ?\\C-\\s/) {assert_equal("\x00", eval('?\C- '))} + assert_warning(/use ?\\M-\\s/) {assert_equal("\xa0", eval('?\M- '))} + assert_warning(/use ?\\M-\\C-\\s/) {assert_equal("\x80", eval('?\M-\C- '))} + assert_warning(/use ?\\C-\\M-\\s/) {assert_equal("\x80", eval('?\C-\M- '))} + assert_warning(/use ?\\t/) {assert_equal("\x09", eval("?\\C-\t"))} + assert_warning(/use ?\\M-\\t/) {assert_equal("\x89", eval("?\\M-\t"))} + assert_warning(/use ?\\M-\\t/) {assert_equal("\x89", eval("?\\M-\\C-\t"))} + assert_warning(/use ?\\M-\\t/) {assert_equal("\x89", eval("?\\C-\\M-\t"))} + assert_syntax_error("?\\C-\x01", 'Invalid escape character syntax') + assert_syntax_error("?\\M-\x01", 'Invalid escape character syntax') + assert_syntax_error("?\\M-\\C-\x01", 'Invalid escape character syntax') + assert_syntax_error("?\\C-\\M-\x01", 'Invalid escape character syntax') end def test_percent -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/