diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-10-22 04:09:24 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-10-22 04:09:24 +0000 |
commit | 1cc1c2f77e9bcb66afc403e805c2be0088e3095a (patch) | |
tree | 91d0af7f1c0a88817d1d088b1010c891f8149301 | |
parent | 0e851c5288a26efe252792f77a931e0787c87cca (diff) |
* object.c (sym_inspect), parse.y (parser_yylex, rb_symname_p): check
if valid as a symbol name more strictly. [ruby-dev:27478]
* test/ruby/test_symbol.rb: tests for [ruby-core:03573].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@9439 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | intern.h | 1 | ||||
-rw-r--r-- | object.c | 2 | ||||
-rw-r--r-- | parse.y | 123 |
4 files changed, 125 insertions, 8 deletions
@@ -1,3 +1,10 @@ +Sat Oct 22 13:08:21 2005 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * object.c (sym_inspect), parse.y (parser_yylex, rb_symname_p): check + if valid as a symbol name more strictly. [ruby-dev:27478] + + * test/ruby/test_symbol.rb: tests for [ruby-core:03573]. + Fri Oct 21 19:21:56 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp> * rubysig.h (CHECK_INTS): fixed typo. (I believe bit-or is improper) @@ -335,6 +335,7 @@ int rb_is_instance_id _((ID)); int rb_is_class_id _((ID)); int rb_is_local_id _((ID)); int rb_is_junk_id _((ID)); +int rb_symname_p _((const char*)); VALUE rb_backref_get _((void)); void rb_backref_set _((VALUE)); VALUE rb_lastline_get _((void)); @@ -1174,7 +1174,7 @@ sym_inspect(sym) str = rb_str_new(0, strlen(name)+1); RSTRING(str)->ptr[0] = ':'; strcpy(RSTRING(str)->ptr+1, name); - if (rb_is_junk_id(id)) { + if (!rb_symname_p(name)) { str = rb_str_dump(str); strncpy(RSTRING(str)->ptr, ":\"", 2); } @@ -3344,6 +3344,7 @@ yylex() register int c; int space_seen = 0; int cmd_state; + enum lex_state last_state; if (lex_strterm) { int token; @@ -4231,6 +4232,7 @@ yylex() return '%'; case '$': + last_state = lex_state; lex_state = EXPR_END; newtok(); c = nextc(); @@ -4273,7 +4275,13 @@ yylex() tokadd('$'); tokadd(c); c = nextc(); - tokadd(c); + if (is_identchar(c)) { + tokadd(c); + } + else { + pushback(c); + } + gvar: tokfix(); yylval.id = rb_intern(tok()); /* xxx shouldn't check if valid option variable */ @@ -4283,6 +4291,11 @@ yylex() case '`': /* $`: string before last match */ case '\'': /* $': string after last match */ case '+': /* $+: string matches last paren. */ + if (last_state == EXPR_FNAME) { + tokadd('$'); + tokadd(c); + goto gvar; + } yylval.node = NEW_BACK_REF(c); return tBACK_REF; @@ -4295,6 +4308,7 @@ yylex() c = nextc(); } while (ISDIGIT(c)); pushback(c); + if (last_state == EXPR_FNAME) goto gvar; tokfix(); yylval.node = NEW_NTH_REF(atoi(tok()+1)); return tNTH_REF; @@ -4372,8 +4386,8 @@ yylex() { int result = 0; - enum lex_state last_state = lex_state; + last_state = lex_state; switch (tok()[0]) { case '$': lex_state = EXPR_END; @@ -5867,6 +5881,99 @@ internal_id() return ID_INTERNAL | (++last_id << ID_SCOPE_SHIFT); } +static int +is_special_global_name(m) + const char *m; +{ + switch (*m) { + case '~': case '*': case '$': case '?': case '!': case '@': + case '/': case '\\': case ';': case ',': case '.': case '=': + case ':': case '<': case '>': case '\"': + case '&': case '`': case '\'': case '+': + case '0': + ++m; + break; + case '-': + ++m; + if (is_identchar(*m)) m += mbclen(*m); + break; + default: + if (!ISDIGIT(*m)) return 0; + do ++m; while (ISDIGIT(*m)); + } + return !*m; +} + +int +rb_symname_p(name) + const char *name; +{ + const char *m = name; + int localid = Qfalse; + + if (!m) return Qfalse; + switch (*m) { + case '\0': + return Qfalse; + + case '$': + if (is_special_global_name(++m)) return Qtrue; + goto id; + + case '@': + if (*++m == '@') ++m; + goto id; + + case '<': + switch (*++m) { + case '<': ++m; break; + case '=': if (*++m == '>') ++m; break; + default: break; + } + break; + + case '>': + if (*++m == '>') ++m; + break; + + case '=': + switch (*++m) { + case '~': ++m; break; + case '=': if (*++m == '=') ++m; break; + default: return Qfalse; + } + break; + + case '*': + if (*++m == '*') ++m; + break; + + case '+': case '-': + if (*++m == '@') ++m; + break; + + case '|': case '^': case '&': case '/': case '%': case '~': case '`': + break; + + case '[': + if (*++m == ']' && *++m == '=') ++m; + break; + + default: + localid = !ISUPPER(*m); + id: + if (*m != '_' && !ISALPHA(*m) && !ismbchar(*m)) return Qfalse; + while (is_identchar(*m)) m += mbclen(*m); + if (localid) { + switch (*m) { + case '!': case '?': case '=': ++m; + } + } + break; + } + return *m ? Qfalse : Qtrue; +} + ID rb_intern(name) const char *name; @@ -5883,8 +5990,7 @@ rb_intern(name) switch (*name) { case '$': id |= ID_GLOBAL; - m++; - if (!is_identchar(*m)) m++; + if (is_special_global_name(++m)) goto new_id; break; case '@': if (name[1] == '@') { @@ -5897,7 +6003,7 @@ rb_intern(name) m++; break; default: - if (name[0] != '_' && !ISALPHA(name[0]) && !ismbchar(name[0])) { + if (name[0] != '_' && ISASCII(name[0]) && !ISALNUM(name[0])) { /* operators */ int i; @@ -5931,10 +6037,13 @@ rb_intern(name) } break; } - while (m <= name + last && is_identchar(*m)) { - m += mbclen(*m); + if (!ISDIGIT(*m)) { + while (m <= name + last && is_identchar(*m)) { + m += mbclen(*m); + } } if (*m) id = ID_JUNK; + new_id: id |= ++last_id << ID_SCOPE_SHIFT; id_regist: name = strdup(name); |