Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
symbol.c
Go to the documentation of this file.
1/**********************************************************************
2
3 symbol.h -
4
5 $Author$
6 created at: Tue Jul 8 15:49:54 JST 2014
7
8 Copyright (C) 2014 Yukihiro Matsumoto
9
10**********************************************************************/
11
12#include "ruby/encoding.h"
13#include "ruby/st.h"
14#include "internal.h"
15#include "symbol.h"
16#include "gc.h"
17#include "probes.h"
18
19#ifndef SYMBOL_DEBUG
20# define SYMBOL_DEBUG 0
21#endif
22#ifndef CHECK_ID_SERIAL
23# define CHECK_ID_SERIAL SYMBOL_DEBUG
24#endif
25
26#define SYMBOL_PINNED_P(sym) (RSYMBOL(sym)->id&~ID_SCOPE_MASK)
27
28#define STATIC_SYM2ID(sym) RSHIFT((unsigned long)(sym), RUBY_SPECIAL_SHIFT)
29
30static ID register_static_symid(ID, const char *, long, rb_encoding *);
31static ID register_static_symid_str(ID, VALUE);
32#define REGISTER_SYMID(id, name) register_static_symid((id), (name), strlen(name), enc)
33#include "id.c"
34
35#define is_identchar(p,e,enc) (ISALNUM((unsigned char)*(p)) || (*(p)) == '_' || !ISASCII(*(p)))
36
37#define op_tbl_count numberof(op_tbl)
38STATIC_ASSERT(op_tbl_name_size, sizeof(op_tbl[0].name) == 3);
39#define op_tbl_len(i) (!op_tbl[i].name[1] ? 1 : !op_tbl[i].name[2] ? 2 : 3)
40
41static void
42Init_op_tbl(void)
43{
44 int i;
45 rb_encoding *const enc = rb_usascii_encoding();
46
47 for (i = '!'; i <= '~'; ++i) {
48 if (!ISALNUM(i) && i != '_') {
49 char c = (char)i;
50 register_static_symid(i, &c, 1, enc);
51 }
52 }
53 for (i = 0; i < op_tbl_count; ++i) {
54 register_static_symid(op_tbl[i].token, op_tbl[i].name, op_tbl_len(i), enc);
55 }
56}
57
58static const int ID_ENTRY_UNIT = 512;
59
64};
65
67#define global_symbols ruby_global_symbols
68
69static const struct st_hash_type symhash = {
72};
73
74void
76{
77 VALUE dsym_fstrs = rb_ident_hash_new();
78 global_symbols.dsymbol_fstr_hash = dsym_fstrs;
80 rb_obj_hide(dsym_fstrs);
81
82 global_symbols.str_sym = st_init_table_with_size(&symhash, 1000);
85
86 Init_op_tbl();
87 Init_id();
88}
89
90WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type));
91WARN_UNUSED_RESULT(static VALUE dsymbol_check(const VALUE sym));
92WARN_UNUSED_RESULT(static ID lookup_str_id(VALUE str));
93WARN_UNUSED_RESULT(static VALUE lookup_str_sym(const VALUE str));
94WARN_UNUSED_RESULT(static VALUE lookup_id_str(ID id));
95WARN_UNUSED_RESULT(static ID intern_str(VALUE str, int mutable));
96
97ID
99{
100 VALUE str, sym;
101 int scope;
102
103 if (!is_notop_id(id)) {
104 switch (id) {
105 case tAREF: case tASET:
106 return tASET; /* only exception */
107 }
108 rb_name_error(id, "cannot make operator ID :%"PRIsVALUE" attrset",
109 rb_id2str(id));
110 }
111 else {
112 scope = id_type(id);
113 switch (scope) {
114 case ID_LOCAL: case ID_INSTANCE: case ID_GLOBAL:
115 case ID_CONST: case ID_CLASS: case ID_JUNK:
116 break;
117 case ID_ATTRSET:
118 return id;
119 default:
120 {
121 if ((str = lookup_id_str(id)) != 0) {
122 rb_name_error(id, "cannot make unknown type ID %d:%"PRIsVALUE" attrset",
123 scope, str);
124 }
125 else {
126 rb_name_error_str(Qnil, "cannot make unknown type anonymous ID %d:%"PRIxVALUE" attrset",
127 scope, (VALUE)id);
128 }
129 }
130 }
131 }
132
133 /* make new symbol and ID */
134 if (!(str = lookup_id_str(id))) {
135 static const char id_types[][8] = {
136 "local",
137 "instance",
138 "invalid",
139 "global",
140 "attrset",
141 "const",
142 "class",
143 "junk",
144 };
145 rb_name_error(id, "cannot make anonymous %.*s ID %"PRIxVALUE" attrset",
146 (int)sizeof(id_types[0]), id_types[scope], (VALUE)id);
147 }
148 str = rb_str_dup(str);
149 rb_str_cat(str, "=", 1);
150 sym = lookup_str_sym(str);
151 id = sym ? rb_sym2id(sym) : intern_str(str, 1);
152 return id;
153}
154
155static int
156is_special_global_name(const char *m, const char *e, rb_encoding *enc)
157{
158 int mb = 0;
159
160 if (m >= e) return 0;
161 if (is_global_name_punct(*m)) {
162 ++m;
163 }
164 else if (*m == '-') {
165 if (++m >= e) return 0;
166 if (is_identchar(m, e, enc)) {
167 if (!ISASCII(*m)) mb = 1;
168 m += rb_enc_mbclen(m, e, enc);
169 }
170 }
171 else {
172 if (!ISDIGIT(*m)) return 0;
173 do {
174 if (!ISASCII(*m)) mb = 1;
175 ++m;
176 } while (m < e && ISDIGIT(*m));
177 }
178 return m == e ? mb + 1 : 0;
179}
180
181int
182rb_symname_p(const char *name)
183{
185}
186
187int
189{
190 return rb_enc_symname2_p(name, strlen(name), enc);
191}
192
193static int
194rb_sym_constant_char_p(const char *name, long nlen, rb_encoding *enc)
195{
196 int c, len;
197 const char *end = name + nlen;
198
199 if (nlen < 1) return FALSE;
200 if (ISASCII(*name)) return ISUPPER(*name);
201 c = rb_enc_precise_mbclen(name, end, enc);
202 if (!MBCLEN_CHARFOUND_P(c)) return FALSE;
204 c = rb_enc_mbc_to_codepoint(name, end, enc);
205 if (ONIGENC_IS_UNICODE(enc)) {
206 static int ctype_titlecase = 0;
207 if (rb_enc_isupper(c, enc)) return TRUE;
208 if (rb_enc_islower(c, enc)) return FALSE;
209 if (!ctype_titlecase) {
210 static const UChar cname[] = "titlecaseletter";
211 static const UChar *const end = cname + sizeof(cname) - 1;
212 ctype_titlecase = ONIGENC_PROPERTY_NAME_TO_CTYPE(enc, cname, end);
213 }
214 if (rb_enc_isctype(c, ctype_titlecase, enc)) return TRUE;
215 }
216 else {
217 /* fallback to case-folding */
219 const OnigUChar *beg = (const OnigUChar *)name;
220 int r = enc->mbc_case_fold(ONIGENC_CASE_FOLD,
221 &beg, (const OnigUChar *)end,
222 fold, enc);
223 if (r > 0 && (r != len || memcmp(fold, name, r)))
224 return TRUE;
225 }
226 return FALSE;
227}
228
229#define IDSET_ATTRSET_FOR_SYNTAX ((1U<<ID_LOCAL)|(1U<<ID_CONST))
230#define IDSET_ATTRSET_FOR_INTERN (~(~0U<<(1<<ID_SCOPE_SHIFT)) & ~(1U<<ID_ATTRSET))
231
232int
233rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset)
234{
235 const char *m = name;
236 const char *e = m + len;
237 int type = ID_JUNK;
238
239 if (!rb_enc_asciicompat(enc)) return -1;
240 if (!m || len <= 0) return -1;
241 switch (*m) {
242 case '\0':
243 return -1;
244
245 case '$':
246 type = ID_GLOBAL;
247 if (is_special_global_name(++m, e, enc)) return type;
248 goto id;
249
250 case '@':
252 if (*++m == '@') {
253 ++m;
254 type = ID_CLASS;
255 }
256 goto id;
257
258 case '<':
259 switch (*++m) {
260 case '<': ++m; break;
261 case '=': if (*++m == '>') ++m; break;
262 default: break;
263 }
264 break;
265
266 case '>':
267 switch (*++m) {
268 case '>': case '=': ++m; break;
269 }
270 break;
271
272 case '=':
273 switch (*++m) {
274 case '~': ++m; break;
275 case '=': if (*++m == '=') ++m; break;
276 default: return -1;
277 }
278 break;
279
280 case '*':
281 if (*++m == '*') ++m;
282 break;
283
284 case '+': case '-':
285 if (*++m == '@') ++m;
286 break;
287
288 case '|': case '^': case '&': case '/': case '%': case '~': case '`':
289 ++m;
290 break;
291
292 case '[':
293 if (m[1] != ']') goto id;
294 ++m;
295 if (*++m == '=') ++m;
296 break;
297
298 case '!':
299 if (len == 1) return ID_JUNK;
300 switch (*++m) {
301 case '=': case '~': ++m; break;
302 default:
303 if (allowed_attrset & (1U << ID_JUNK)) goto id;
304 return -1;
305 }
306 break;
307
308 default:
309 type = rb_sym_constant_char_p(m, e-m, enc) ? ID_CONST : ID_LOCAL;
310 id:
311 if (m >= e || (*m != '_' && !ISALPHA(*m) && ISASCII(*m))) {
312 if (len > 1 && *(e-1) == '=') {
313 type = rb_enc_symname_type(name, len-1, enc, allowed_attrset);
314 if (type != ID_ATTRSET) return ID_ATTRSET;
315 }
316 return -1;
317 }
318 while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
319 if (m >= e) break;
320 switch (*m) {
321 case '!': case '?':
322 if (type == ID_GLOBAL || type == ID_CLASS || type == ID_INSTANCE) return -1;
323 type = ID_JUNK;
324 ++m;
325 if (m + 1 < e || *m != '=') break;
326 /* fall through */
327 case '=':
328 if (!(allowed_attrset & (1U << type))) return -1;
330 ++m;
331 break;
332 }
333 break;
334 }
335 return m == e ? type : -1;
336}
337
338int
339rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
340{
342}
343
344static int
345rb_str_symname_type(VALUE name, unsigned int allowed_attrset)
346{
347 const char *ptr = StringValuePtr(name);
348 long len = RSTRING_LEN(name);
349 int type = rb_enc_symname_type(ptr, len, rb_enc_get(name), allowed_attrset);
351 return type;
352}
353
354static void
355set_id_entry(rb_id_serial_t num, VALUE str, VALUE sym)
356{
357 size_t idx = num / ID_ENTRY_UNIT;
358 VALUE ary, ids = global_symbols.ids;
359 if (idx >= (size_t)RARRAY_LEN(ids) || NIL_P(ary = rb_ary_entry(ids, (long)idx))) {
360 ary = rb_ary_tmp_new(ID_ENTRY_UNIT * ID_ENTRY_SIZE);
361 rb_ary_store(ids, (long)idx, ary);
362 }
363 idx = (num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE;
364 rb_ary_store(ary, (long)idx + ID_ENTRY_STR, str);
365 rb_ary_store(ary, (long)idx + ID_ENTRY_SYM, sym);
366}
367
368static VALUE
369get_id_serial_entry(rb_id_serial_t num, ID id, const enum id_entry_type t)
370{
371 if (num && num <= global_symbols.last_id) {
372 size_t idx = num / ID_ENTRY_UNIT;
373 VALUE ids = global_symbols.ids;
374 VALUE ary;
375 if (idx < (size_t)RARRAY_LEN(ids) && !NIL_P(ary = rb_ary_entry(ids, (long)idx))) {
376 long pos = (long)(num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE;
377 VALUE result = rb_ary_entry(ary, pos + t);
378 if (NIL_P(result)) return 0;
379#if CHECK_ID_SERIAL
380 if (id) {
381 VALUE sym = result;
382 if (t != ID_ENTRY_SYM)
383 sym = rb_ary_entry(ary, pos + ID_ENTRY_SYM);
384 if (STATIC_SYM_P(sym)) {
385 if (STATIC_SYM2ID(sym) != id) return 0;
386 }
387 else {
388 if (RSYMBOL(sym)->id != id) return 0;
389 }
390 }
391#endif
392 return result;
393 }
394 }
395 return 0;
396}
397
398static VALUE
399get_id_entry(ID id, const enum id_entry_type t)
400{
401 return get_id_serial_entry(rb_id_to_serial(id), id, t);
402}
403
404static inline ID
405#ifdef __GNUC__
406__attribute__((unused))
407#endif
408rb_id_serial_to_id(rb_id_serial_t num)
409{
410 if (is_notop_id((ID)num)) {
411 VALUE sym = get_id_serial_entry(num, 0, ID_ENTRY_SYM);
412 return SYM2ID(sym);
413 }
414 else {
415 return (ID)num;
416 }
417}
418
419#if SYMBOL_DEBUG
420static int
421register_sym_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
422{
423 if (existing) {
424 rb_fatal("symbol :% "PRIsVALUE" is already registered with %"PRIxVALUE,
425 (VALUE)*key, (VALUE)*value);
426 }
427 *value = arg;
428 return ST_CONTINUE;
429}
430#endif
431
432static void
433register_sym(VALUE str, VALUE sym)
434{
435#if SYMBOL_DEBUG
437 register_sym_update_callback, (st_data_t)sym);
438#else
440#endif
441}
442
443static void
444unregister_sym(VALUE str, VALUE sym)
445{
446 st_data_t str_data = (st_data_t)str;
447 if (!st_delete(global_symbols.str_sym, &str_data, NULL)) {
448 rb_bug("%p can't remove str from str_id (%s)", (void *)sym, RSTRING_PTR(str));
449 }
450}
451
452static ID
453register_static_symid(ID id, const char *name, long len, rb_encoding *enc)
454{
456 return register_static_symid_str(id, str);
457}
458
459static ID
460register_static_symid_str(ID id, VALUE str)
461{
462 rb_id_serial_t num = rb_id_to_serial(id);
463 VALUE sym = STATIC_ID2SYM(id);
464
466 str = rb_fstring(str);
467
469
470 register_sym(str, sym);
471 set_id_entry(num, str, sym);
472
473 return id;
474}
475
476static int
477sym_check_asciionly(VALUE str)
478{
479 if (!rb_enc_asciicompat(rb_enc_get(str))) return FALSE;
480 switch (rb_enc_str_coderange(str)) {
482 rb_raise(rb_eEncodingError, "invalid symbol in encoding %s :%+"PRIsVALUE,
485 return TRUE;
486 }
487 return FALSE;
488}
489
490#if 0
491/*
492 * _str_ itself will be registered at the global symbol table. _str_
493 * can be modified before the registration, since the encoding will be
494 * set to ASCII-8BIT if it is a special global name.
495 */
496
497static inline void
498must_be_dynamic_symbol(VALUE x)
499{
500 if (UNLIKELY(!DYNAMIC_SYM_P(x))) {
501 if (STATIC_SYM_P(x)) {
502 VALUE str = lookup_id_str(RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT));
503
504 if (str) {
505 rb_bug("wrong argument: %s (inappropriate Symbol)", RSTRING_PTR(str));
506 }
507 else {
508 rb_bug("wrong argument: inappropriate Symbol (%p)", (void *)x);
509 }
510 }
511 else {
512 rb_bug("wrong argument type %s (expected Symbol)", rb_builtin_class_name(x));
513 }
514 }
515}
516#endif
517
518static VALUE
519dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc, const ID type)
520{
522 long hashval;
523
525 OBJ_FREEZE(dsym);
526 RB_OBJ_WRITE(dsym, &RSYMBOL(dsym)->fstr, str);
527 RSYMBOL(dsym)->id = type;
528
529 /* we want hashval to be in Fixnum range [ruby-core:15713] r15672 */
530 hashval = (long)rb_str_hash(str);
531 RSYMBOL(dsym)->hashval = RSHIFT((long)hashval, 1);
532
533 register_sym(str, dsym);
534 rb_hash_aset(global_symbols.dsymbol_fstr_hash, str, Qtrue);
535
536 RUBY_DTRACE_CREATE_HOOK(SYMBOL, RSTRING_PTR(RSYMBOL(dsym)->fstr));
537
538 return dsym;
539}
540
541static inline VALUE
542dsymbol_check(const VALUE sym)
543{
545 const VALUE fstr = RSYMBOL(sym)->fstr;
546 const ID type = RSYMBOL(sym)->id & ID_SCOPE_MASK;
547 RSYMBOL(sym)->fstr = 0;
548
549 unregister_sym(fstr, sym);
550 return dsymbol_alloc(rb_cSymbol, fstr, rb_enc_get(fstr), type);
551 }
552 else {
553 return sym;
554 }
555}
556
557static ID
558lookup_str_id(VALUE str)
559{
560 st_data_t sym_data;
561 if (st_lookup(global_symbols.str_sym, (st_data_t)str, &sym_data)) {
562 const VALUE sym = (VALUE)sym_data;
563
564 if (STATIC_SYM_P(sym)) {
565 return STATIC_SYM2ID(sym);
566 }
567 else if (DYNAMIC_SYM_P(sym)) {
568 ID id = RSYMBOL(sym)->id;
569 if (id & ~ID_SCOPE_MASK) return id;
570 }
571 else {
572 rb_bug("non-symbol object %s:%"PRIxVALUE" for %"PRIsVALUE" in symbol table",
574 }
575 }
576 return (ID)0;
577}
578
579static VALUE
580lookup_str_sym(const VALUE str)
581{
582 st_data_t sym_data;
583 if (st_lookup(global_symbols.str_sym, (st_data_t)str, &sym_data)) {
584 VALUE sym = (VALUE)sym_data;
585
586 if (DYNAMIC_SYM_P(sym)) {
587 sym = dsymbol_check(sym);
588 }
589 return sym;
590 }
591 else {
592 return (VALUE)0;
593 }
594}
595
596static VALUE
597lookup_id_str(ID id)
598{
599 return get_id_entry(id, ID_ENTRY_STR);
600}
601
602ID
603rb_intern3(const char *name, long len, rb_encoding *enc)
604{
605 VALUE sym;
606 struct RString fake_str;
607 VALUE str = rb_setup_fake_str(&fake_str, name, len, enc);
609
610 sym = lookup_str_sym(str);
611 if (sym) return rb_sym2id(sym);
612 str = rb_enc_str_new(name, len, enc); /* make true string */
613 return intern_str(str, 1);
614}
615
616static ID
617next_id_base(void)
618{
619 rb_id_serial_t next_serial = global_symbols.last_id + 1;
620
621 if (next_serial == 0) {
622 return (ID)-1;
623 }
624 else {
625 const size_t num = ++global_symbols.last_id;
626 return num << ID_SCOPE_SHIFT;
627 }
628}
629
630static ID
631intern_str(VALUE str, int mutable)
632{
633 ID id;
634 ID nid;
635
636 id = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
637 if (id == (ID)-1) id = ID_JUNK;
638 if (sym_check_asciionly(str)) {
639 if (!mutable) str = rb_str_dup(str);
641 }
642 if ((nid = next_id_base()) == (ID)-1) {
643 str = rb_str_ellipsize(str, 20);
644 rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %"PRIsVALUE")",
645 str);
646 }
647 id |= nid;
648 id |= ID_STATIC_SYM;
649 return register_static_symid_str(id, str);
650}
651
652ID
653rb_intern2(const char *name, long len)
654{
656}
657
658#undef rb_intern
659ID
660rb_intern(const char *name)
661{
662 return rb_intern2(name, strlen(name));
663}
664
665ID
667{
668 VALUE sym = lookup_str_sym(str);
669
670 if (sym) {
671 return SYM2ID(sym);
672 }
673
674 return intern_str(str, 0);
675}
676
677void
679{
680 VALUE str = RSYMBOL(sym)->fstr;
681
682 if (str) {
683 RSYMBOL(sym)->fstr = 0;
684 unregister_sym(str, sym);
685 rb_hash_delete_entry(global_symbols.dsymbol_fstr_hash, str);
686 }
687}
688
689/*
690 * call-seq:
691 * str.intern -> symbol
692 * str.to_sym -> symbol
693 *
694 * Returns the Symbol corresponding to <i>str</i>, creating the
695 * symbol if it did not previously exist. See Symbol#id2name.
696 *
697 * "Koala".intern #=> :Koala
698 * s = 'cat'.to_sym #=> :cat
699 * s == :cat #=> true
700 * s = '@cat'.to_sym #=> :@cat
701 * s == :@cat #=> true
702 *
703 * This can also be used to create symbols that cannot be represented using the
704 * <code>:xxx</code> notation.
705 *
706 * 'cat and dog'.to_sym #=> :"cat and dog"
707 */
708
709VALUE
711{
712#if USE_SYMBOL_GC
713 rb_encoding *enc, *ascii;
714 int type;
715#else
716 ID id;
717#endif
718 VALUE sym = lookup_str_sym(str);
719
720 if (sym) {
721 return sym;
722 }
723
724#if USE_SYMBOL_GC
725 enc = rb_enc_get(str);
726 ascii = rb_usascii_encoding();
727 if (enc != ascii && sym_check_asciionly(str)) {
728 str = rb_str_dup(str);
729 rb_enc_associate(str, ascii);
731 enc = ascii;
732 }
733 else {
734 str = rb_str_dup(str);
736 }
737 str = rb_fstring(str);
738 type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
739 if (type < 0) type = ID_JUNK;
740 return dsymbol_alloc(rb_cSymbol, str, enc, type);
741#else
742 id = intern_str(str, 0);
743 return ID2SYM(id);
744#endif
745}
746
747ID
749{
750 ID id;
751 if (STATIC_SYM_P(sym)) {
752 id = STATIC_SYM2ID(sym);
753 }
754 else if (DYNAMIC_SYM_P(sym)) {
755 sym = dsymbol_check(sym);
756 id = RSYMBOL(sym)->id;
757 if (UNLIKELY(!(id & ~ID_SCOPE_MASK))) {
758 VALUE fstr = RSYMBOL(sym)->fstr;
759 ID num = next_id_base();
760
761 RSYMBOL(sym)->id = id |= num;
762 /* make it permanent object */
763 set_id_entry(rb_id_to_serial(num), fstr, sym);
764 rb_hash_delete_entry(global_symbols.dsymbol_fstr_hash, fstr);
765 }
766 }
767 else {
768 rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol)",
770 }
771 return id;
772}
773
774#undef rb_id2sym
775VALUE
777{
778 if (!DYNAMIC_ID_P(x)) return STATIC_ID2SYM(x);
779 return get_id_entry(x, ID_ENTRY_SYM);
780}
781
782
783VALUE
785{
786 if (DYNAMIC_SYM_P(sym)) {
787 return RSYMBOL(sym)->fstr;
788 }
789 else {
790 return rb_id2str(STATIC_SYM2ID(sym));
791 }
792}
793
794VALUE
796{
797 return lookup_id_str(id);
798}
799
800const char *
802{
803 VALUE str = rb_id2str(id);
804
805 if (!str) return 0;
806 return RSTRING_PTR(str);
807}
808
809ID
811{
812 return next_id_base() | ID_INTERNAL | ID_STATIC_SYM;
813}
814
815static int
816symbols_i(st_data_t key, st_data_t value, st_data_t arg)
817{
818 VALUE ary = (VALUE)arg;
819 VALUE sym = (VALUE)value;
820
821 if (STATIC_SYM_P(sym)) {
823 return ST_CONTINUE;
824 }
825 else if (!DYNAMIC_SYM_P(sym)) {
826 rb_bug("invalid symbol: %s", RSTRING_PTR((VALUE)key));
827 }
829 RSYMBOL(sym)->fstr = 0;
830 return ST_DELETE;
831 }
832 else {
834 return ST_CONTINUE;
835 }
836
837}
838
839VALUE
841{
842 VALUE ary = rb_ary_new2(global_symbols.str_sym->num_entries);
843 st_foreach(global_symbols.str_sym, symbols_i, ary);
844 return ary;
845}
846
847size_t
849{
850 return (size_t)global_symbols.last_id;
851}
852
853int
855{
856 return is_const_id(id);
857}
858
859int
861{
862 return is_class_id(id);
863}
864
865int
867{
868 return is_global_id(id);
869}
870
871int
873{
874 return is_instance_id(id);
875}
876
877int
879{
880 return is_attrset_id(id);
881}
882
883int
885{
886 return is_local_id(id);
887}
888
889int
891{
892 return is_junk_id(id);
893}
894
895int
897{
898 return is_const_sym(sym);
899}
900
901int
903{
904 return is_attrset_sym(sym);
905}
906
918ID
919rb_check_id(volatile VALUE *namep)
920{
921 VALUE tmp;
922 VALUE name = *namep;
923
924 if (STATIC_SYM_P(name)) {
925 return STATIC_SYM2ID(name);
926 }
927 else if (DYNAMIC_SYM_P(name)) {
928 if (SYMBOL_PINNED_P(name)) {
929 return RSYMBOL(name)->id;
930 }
931 else {
932 *namep = RSYMBOL(name)->fstr;
933 return 0;
934 }
935 }
936 else if (!RB_TYPE_P(name, T_STRING)) {
938 if (NIL_P(tmp)) {
939 rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
940 name);
941 }
942 name = tmp;
943 *namep = name;
944 }
945
946 sym_check_asciionly(name);
947
948 return lookup_str_id(name);
949}
950
951VALUE
952rb_check_symbol(volatile VALUE *namep)
953{
954 VALUE sym;
955 VALUE tmp;
956 VALUE name = *namep;
957
958 if (STATIC_SYM_P(name)) {
959 return name;
960 }
961 else if (DYNAMIC_SYM_P(name)) {
962 if (!SYMBOL_PINNED_P(name)) {
963 name = dsymbol_check(name);
964 *namep = name;
965 }
966 return name;
967 }
968 else if (!RB_TYPE_P(name, T_STRING)) {
970 if (NIL_P(tmp)) {
971 rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
972 name);
973 }
974 name = tmp;
975 *namep = name;
976 }
977
978 sym_check_asciionly(name);
979
980 if ((sym = lookup_str_sym(name)) != 0) {
981 return sym;
982 }
983
984 return Qnil;
985}
986
987ID
988rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
989{
990 struct RString fake_str;
991 const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
992
993 sym_check_asciionly(name);
994
995 return lookup_str_id(name);
996}
997
998VALUE
999rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
1000{
1001 VALUE sym;
1002 struct RString fake_str;
1003 const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
1004
1005 sym_check_asciionly(name);
1006
1007 if ((sym = lookup_str_sym(name)) != 0) {
1008 return sym;
1009 }
1010
1011 return Qnil;
1012}
1013
1014#undef rb_sym_intern_ascii_cstr
1015#ifdef __clang__
1016NOINLINE(VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc));
1017#else
1021#endif
1022
1023VALUE
1024rb_sym_intern(const char *ptr, long len, rb_encoding *enc)
1025{
1026 struct RString fake_str;
1027 const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
1028 return rb_str_intern(name);
1029}
1030
1031VALUE
1032rb_sym_intern_ascii(const char *ptr, long len)
1033{
1035}
1036
1037VALUE
1039{
1041}
1042
1043VALUE
1045{
1046 return rb_convert_type_with_id(obj, T_SYMBOL, "Symbol", idTo_sym);
1047}
1048
1049int
1051{
1052 return rb_str_symname_type(name, 0) == ID_CONST;
1053}
1054
1055int
1057{
1058 return rb_str_symname_type(name, 0) == ID_CLASS;
1059}
1060
1061int
1063{
1064 return rb_str_symname_type(name, 0) == ID_INSTANCE;
1065}
1066
1067int
1069{
1070 return rb_str_symname_type(name, 0) == ID_LOCAL;
1071}
1072
1073#include "id_table.c"
#define sym(x)
Definition: date_core.c:3717
enum ruby_id_types id_types
Definition: debug.c:29
struct RIMemo * ptr
Definition: debug.c:65
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1032
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:866
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1316
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
int rb_enc_to_index(rb_encoding *enc)
Definition: encoding.c:125
void rb_enc_set_index(VALUE obj, int idx)
Definition: encoding.c:830
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1020
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1340
#define rb_enc_isupper(c, enc)
Definition: encoding.h:233
#define ENC_CODERANGE_7BIT
Definition: encoding.h:104
#define rb_enc_isctype(c, t, enc)
Definition: encoding.h:229
int rb_enc_str_coderange(VALUE)
Definition: string.c:657
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:796
#define rb_enc_name(enc)
Definition: encoding.h:177
#define rb_enc_mbc_to_codepoint(p, e, enc)
Definition: encoding.h:208
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:192
#define rb_enc_asciicompat(enc)
Definition: encoding.h:245
#define rb_enc_islower(c, enc)
Definition: encoding.h:232
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:106
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:191
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
VALUE rb_newobj_of(VALUE klass, VALUE flags)
Definition: gc.c:2309
VALUE rb_id2str(ID id)
Definition: symbol.c:795
VALUE rb_check_symbol(volatile VALUE *namep)
Definition: symbol.c:952
const char * rb_id2name(ID id)
Definition: symbol.c:801
VALUE rb_sym2str(VALUE sym)
Definition: symbol.c:784
char ary[RSTRING_EMBED_LEN_MAX+1]
Definition: ruby.h:999
ID rb_intern2(const char *name, long len)
Definition: symbol.c:653
VALUE rb_cSymbol
Definition: ruby.h:2048
ID rb_intern(const char *name)
Definition: symbol.c:660
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:919
ID rb_intern_str(VALUE str)
Definition: symbol.c:666
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
void rb_bug(const char *fmt,...)
Definition: error.c:636
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:1515
VALUE rb_eTypeError
Definition: error.c:924
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:1530
void rb_fatal(const char *fmt,...)
Definition: error.c:2722
const char * rb_builtin_class_name(VALUE x)
Definition: error.c:799
VALUE rb_eRuntimeError
Definition: error.c:922
VALUE rb_eEncodingError
Definition: error.c:930
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:78
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2914
unsigned short token
Definition: id.c:36
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
const char * name
Definition: nkf.c:208
unsigned char OnigUChar
Definition: onigmo.h:79
#define ONIGENC_IS_UNICODE(enc)
Definition: onigmo.h:327
#define UChar
Definition: onigmo.h:76
#define ONIGENC_PROPERTY_NAME_TO_CTYPE(enc, p, end)
Definition: onigmo.h:369
#define ONIGENC_CASE_FOLD
Definition: onigmo.h:120
#define ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM
Definition: onigmo.h:135
int nid
@ tASET
Definition: parse.h:141
@ tAREF
Definition: parse.h:140
#define RARRAY_LEN(a)
#define NULL
int memcmp(const void *, const void *, size_t)
Definition: memcmp.c:7
#define RSTRING_LEN(str)
unsigned long st_data_t
#define ID_GLOBAL
int rb_objspace_garbage_object_p(VALUE obj)
Definition: gc.c:3620
size_t strlen(const char *)
#define T_STRING
#define StringValuePtr(v)
#define ID_CLASS
#define ISUPPER(c)
const VALUE VALUE obj
#define RSTRING_PTR(str)
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:7079
#define NOINLINE(x)
VALUE rb_ident_hash_new(void)
Definition: hash.c:4278
#define NIL_P(v)
#define ID_CONST
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
#define ID2SYM(x)
#define SYM2ID(x)
const char const char *typedef unsigned long VALUE
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
#define STATIC_SYM_P(x)
uint32_t i
#define char
VALUE rb_fstring(VALUE)
Definition: string.c:312
__inline__ const void *__restrict__ size_t len
#define OBJ_FREEZE(x)
#define ID_ATTRSET
#define RB_OBJ_WRITE(a, slot, b)
#define long
#define RB_GC_GUARD(v)
#define DYNAMIC_SYM_P(x)
#define ISALNUM(c)
#define RUBY_DTRACE_CREATE_HOOK(name, arg)
#define PRIsVALUE
VALUE rb_ary_tmp_new(long)
Definition: array.c:768
#define ID_SCOPE_SHIFT
#define PRIxVALUE
#define TRUE
#define FALSE
VALUE rb_str_ellipsize(VALUE, long)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
Definition: string.c:10185
#define Qtrue
#define ID_JUNK
#define UNLIKELY(x)
#define ISDIGIT(c)
VALUE rb_hash_delete_entry(VALUE hash, VALUE key)
Definition: hash.c:2326
#define Qnil
#define ID_INSTANCE
int rb_str_hash_cmp(VALUE, VALUE)
Definition: string.c:3173
#define RB_TYPE_P(obj, type)
#define FL_WB_PROTECTED
#define T_SYMBOL
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
Definition: hash.c:2852
#define ID_LOCAL
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
st_index_t rb_str_hash(VALUE)
Definition: string.c:3163
unsigned long ID
rb_control_frame_t * __attribute__((__fastcall__)) *rb_insn_func_t)(rb_execution_context_t *
VALUE ID id
#define ID_SCOPE_MASK
#define rb_ary_new2
void rb_ary_store(VALUE, long, VALUE)
Definition: array.c:1079
#define ID_INTERNAL
#define ID_STATIC_SYM
#define ISASCII(c)
#define RSHIFT(x, y)
VALUE rb_ary_entry(VALUE, long)
Definition: array.c:1512
#define ISALPHA(c)
unsigned long VALUE
Definition: ruby.h:102
int st_delete(st_table *tab, st_data_t *key, st_data_t *value)
Definition: st.c:1418
void st_add_direct(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1251
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
Definition: st.c:1101
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
Definition: st.c:1717
int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:1509
st_table * st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
Definition: st.c:577
VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc)
Definition: string.c:385
int(* mbc_case_fold)(OnigCaseFoldType flag, const OnigUChar **pp, const OnigUChar *end, OnigUChar *to, const struct OnigEncodingTypeST *enc)
Definition: onigmo.h:169
Definition: ruby.h:988
#define op_tbl_len(i)
Definition: symbol.c:39
void Init_sym(void)
Definition: symbol.c:75
VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:1024
#define is_identchar(p, e, enc)
Definition: symbol.c:35
#define SYMBOL_PINNED_P(sym)
Definition: symbol.c:26
int rb_enc_symname_p(const char *name, rb_encoding *enc)
Definition: symbol.c:188
ID rb_sym2id(VALUE sym)
Definition: symbol.c:748
rb_symbols_t ruby_global_symbols
Definition: symbol.c:66
int rb_is_instance_name(VALUE name)
Definition: symbol.c:1062
int rb_symname_p(const char *name)
Definition: symbol.c:182
WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type))
VALUE rb_sym_all_symbols(void)
Definition: symbol.c:840
#define global_symbols
Definition: symbol.c:67
void rb_gc_free_dsymbol(VALUE sym)
Definition: symbol.c:678
int rb_is_global_id(ID id)
Definition: symbol.c:866
#define op_tbl_count
Definition: symbol.c:37
ID rb_intern3(const char *name, long len, rb_encoding *enc)
Definition: symbol.c:603
size_t rb_sym_immortal_count(void)
Definition: symbol.c:848
#define STATIC_SYM2ID(sym)
Definition: symbol.c:28
VALUE rb_to_symbol_type(VALUE obj)
Definition: symbol.c:1044
int rb_is_instance_id(ID id)
Definition: symbol.c:872
STATIC_ASSERT(op_tbl_name_size, sizeof(op_tbl[0].name)==3)
int rb_is_class_name(VALUE name)
Definition: symbol.c:1056
int rb_is_junk_id(ID id)
Definition: symbol.c:890
int rb_is_const_id(ID id)
Definition: symbol.c:854
#define IDSET_ATTRSET_FOR_SYNTAX
Definition: symbol.c:229
ID rb_make_internal_id(void)
Definition: symbol.c:810
int rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset)
Definition: symbol.c:233
VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:999
ID rb_id_attrset(ID id)
Definition: symbol.c:98
VALUE rb_id2sym(ID x)
Definition: symbol.c:776
int rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
Definition: symbol.c:339
FUNC_MINIMIZED(VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc))
int rb_is_attrset_sym(VALUE sym)
Definition: symbol.c:902
int rb_is_const_name(VALUE name)
Definition: symbol.c:1050
VALUE rb_sym_intern_ascii_cstr(const char *ptr)
Definition: symbol.c:1038
#define IDSET_ATTRSET_FOR_INTERN
Definition: symbol.c:230
int rb_is_class_id(ID id)
Definition: symbol.c:860
int rb_is_attrset_id(ID id)
Definition: symbol.c:878
int rb_is_local_id(ID id)
Definition: symbol.c:884
int rb_is_const_sym(VALUE sym)
Definition: symbol.c:896
ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:988
id_entry_type
Definition: symbol.c:60
@ ID_ENTRY_STR
Definition: symbol.c:61
@ ID_ENTRY_SIZE
Definition: symbol.c:63
@ ID_ENTRY_SYM
Definition: symbol.c:62
VALUE rb_sym_intern_ascii(const char *ptr, long len)
Definition: symbol.c:1032
int rb_is_local_name(VALUE name)
Definition: symbol.c:1068
VALUE rb_str_intern(VALUE str)
Definition: symbol.c:710
#define STATIC_ID2SYM(id)
Definition: symbol.h:18
#define is_attrset_id(id)
Definition: symbol.h:39
#define is_class_id(id)
Definition: symbol.h:41
#define is_const_id(id)
Definition: symbol.h:40
#define is_const_sym(sym)
Definition: symbol.h:99
#define is_notop_id(id)
Definition: symbol.h:35
#define is_junk_id(id)
Definition: symbol.h:42
#define is_global_id(id)
Definition: symbol.h:37
#define is_local_id(id)
Definition: symbol.h:36
#define DYNAMIC_ID_P(id)
Definition: symbol.h:17
#define is_instance_id(id)
Definition: symbol.h:38
uint32_t rb_id_serial_t
Definition: symbol.h:55
#define RSYMBOL(obj)
Definition: symbol.h:33
#define is_attrset_sym(sym)
Definition: symbol.h:98