summaryrefslogtreecommitdiff
path: root/symbol.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-10 00:41:47 (GMT)
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-10 00:41:47 (GMT)
commitf852af0e59899157ef695edccbe86d51fc04d23b (patch)
tree64f6b3a62e8525c3d44fc6b69900400fcb7c3fa2 /symbol.c
parent44c01a5d3fda7feca63e28c04baca9c9e2dd64b3 (diff)
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.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/symbol.c b/symbol.c
index 723764c..c54a743 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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) == '=') {