diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-04-10 00:41:47 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-04-10 00:41:47 +0000 |
commit | f852af0e59899157ef695edccbe86d51fc04d23b (patch) | |
tree | 64f6b3a62e8525c3d44fc6b69900400fcb7c3fa2 /symbol.c | |
parent | 44c01a5d3fda7feca63e28c04baca9c9e2dd64b3 (diff) | |
download | ruby-f852af0e59899157ef695edccbe86d51fc04d23b.tar.gz |
symbol.c: non-ASCII constant names
* symbol.c (rb_sym_constant_char_p): support for non-ASCII
constant names. [Feature #13770]
* object.c (rb_mod_const_get, rb_mod_const_defined): support for
non-ASCII constant names.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63130 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'symbol.c')
-rw-r--r-- | symbol.c | 38 |
1 files changed, 37 insertions, 1 deletions
@@ -199,6 +199,42 @@ rb_enc_symname_p(const char *name, rb_encoding *enc) return rb_enc_symname2_p(name, strlen(name), enc); } +static int +rb_sym_constant_char_p(const char *name, long nlen, rb_encoding *enc) +{ + int c, len; + const char *end = name + nlen; + + if (nlen < 1) return FALSE; + if (ISASCII(*name)) return ISUPPER(*name); + c = rb_enc_precise_mbclen(name, end, enc); + if (!MBCLEN_CHARFOUND_P(c)) return FALSE; + len = MBCLEN_CHARFOUND_LEN(c); + c = rb_enc_mbc_to_codepoint(name, end, enc); + if (ONIGENC_IS_UNICODE(enc)) { + static int ctype_titlecase = 0; + if (rb_enc_isupper(c, enc)) return TRUE; + if (rb_enc_islower(c, enc)) return FALSE; + if (!ctype_titlecase) { + static const UChar cname[] = "titlecaseletter"; + static const UChar *const end = cname + sizeof(cname) - 1; + ctype_titlecase = ONIGENC_PROPERTY_NAME_TO_CTYPE(enc, cname, end); + } + if (rb_enc_isctype(c, ctype_titlecase, enc)) return TRUE; + } + else { + /* fallback to case-folding */ + OnigUChar fold[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM]; + const OnigUChar *beg = (const OnigUChar *)name; + int r = enc->mbc_case_fold(ONIGENC_CASE_FOLD, + &beg, (const OnigUChar *)end, + fold, enc); + if (r > 0 && (r != len || memcmp(fold, name, r))) + return TRUE; + } + return FALSE; +} + #define IDSET_ATTRSET_FOR_SYNTAX ((1U<<ID_LOCAL)|(1U<<ID_CONST)) #define IDSET_ATTRSET_FOR_INTERN (~(~0U<<(1<<ID_SCOPE_SHIFT)) & ~(1U<<ID_ATTRSET)) @@ -279,7 +315,7 @@ rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int a break; default: - type = ISUPPER(*m) ? ID_CONST : ID_LOCAL; + type = rb_sym_constant_char_p(m, e-m, enc) ? ID_CONST : ID_LOCAL; id: if (m >= e || (*m != '_' && !ISALPHA(*m) && ISASCII(*m))) { if (len > 1 && *(e-1) == '=') { |