Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)
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 "gc.h"
13#include "internal.h"
14#include "internal/error.h"
15#include "internal/gc.h"
16#include "internal/hash.h"
17#include "internal/object.h"
18#include "internal/symbol.h"
19#include "internal/vm.h"
20#include "probes.h"
21#include "ruby/encoding.h"
22#include "ruby/st.h"
23#include "symbol.h"
24#include "vm_sync.h"
25
26#ifndef USE_SYMBOL_GC
27# define USE_SYMBOL_GC 1
28#endif
29#ifndef SYMBOL_DEBUG
30# define SYMBOL_DEBUG 0
31#endif
32#ifndef CHECK_ID_SERIAL
33# define CHECK_ID_SERIAL SYMBOL_DEBUG
34#endif
35
36#define SYMBOL_PINNED_P(sym) (RSYMBOL(sym)->id&~ID_SCOPE_MASK)
37
38#define STATIC_SYM2ID(sym) RSHIFT((unsigned long)(sym), RUBY_SPECIAL_SHIFT)
39
40static ID register_static_symid(ID, const char *, long, rb_encoding *);
41static ID register_static_symid_str(ID, VALUE);
42#define REGISTER_SYMID(id, name) register_static_symid((id), (name), strlen(name), enc)
43#include "id.c"
44
45#define is_identchar(p,e,enc) (ISALNUM((unsigned char)*(p)) || (*(p)) == '_' || !ISASCII(*(p)))
46
47#define op_tbl_count numberof(op_tbl)
48STATIC_ASSERT(op_tbl_name_size, sizeof(op_tbl[0].name) == 3);
49#define op_tbl_len(i) (!op_tbl[i].name[1] ? 1 : !op_tbl[i].name[2] ? 2 : 3)
50
51static void
52Init_op_tbl(void)
53{
54 int i;
55 rb_encoding *const enc = rb_usascii_encoding();
56
57 for (i = '!'; i <= '~'; ++i) {
58 if (!ISALNUM(i) && i != '_') {
59 char c = (char)i;
60 register_static_symid(i, &c, 1, enc);
61 }
62 }
63 for (i = 0; i < op_tbl_count; ++i) {
64 register_static_symid(op_tbl[i].token, op_tbl[i].name, op_tbl_len(i), enc);
65 }
66}
67
68static const int ID_ENTRY_UNIT = 512;
69
74};
75
77
78static const struct st_hash_type symhash = {
81};
82
83void
85{
87
88 VALUE dsym_fstrs = rb_ident_hash_new();
89 symbols->dsymbol_fstr_hash = dsym_fstrs;
91 rb_obj_hide(dsym_fstrs);
92
93 symbols->str_sym = st_init_table_with_size(&symhash, 1000);
94 symbols->ids = rb_ary_tmp_new(0);
96
97 Init_op_tbl();
98 Init_id();
99}
100
101WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(rb_symbols_t *symbols, const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type));
102WARN_UNUSED_RESULT(static VALUE dsymbol_check(rb_symbols_t *symbols, const VALUE sym));
103WARN_UNUSED_RESULT(static ID lookup_str_id(VALUE str));
104WARN_UNUSED_RESULT(static VALUE lookup_str_sym_with_lock(rb_symbols_t *symbols, const VALUE str));
105WARN_UNUSED_RESULT(static VALUE lookup_str_sym(const VALUE str));
106WARN_UNUSED_RESULT(static VALUE lookup_id_str(ID id));
107WARN_UNUSED_RESULT(static ID intern_str(VALUE str, int mutable));
108
109#define GLOBAL_SYMBOLS_ENTER(symbols) rb_symbols_t *symbols = &ruby_global_symbols; RB_VM_LOCK_ENTER()
110#define GLOBAL_SYMBOLS_LEAVE() RB_VM_LOCK_LEAVE()
111
112ID
114{
115 VALUE str, sym;
116 int scope;
117
118 if (!is_notop_id(id)) {
119 switch (id) {
120 case tAREF: case tASET:
121 return tASET; /* only exception */
122 }
123 rb_name_error(id, "cannot make operator ID :%"PRIsVALUE" attrset",
124 rb_id2str(id));
125 }
126 else {
127 scope = id_type(id);
128 switch (scope) {
129 case ID_LOCAL: case ID_INSTANCE: case ID_GLOBAL:
130 case ID_CONST: case ID_CLASS: case ID_JUNK:
131 break;
132 case ID_ATTRSET:
133 return id;
134 default:
135 {
136 if ((str = lookup_id_str(id)) != 0) {
137 rb_name_error(id, "cannot make unknown type ID %d:%"PRIsVALUE" attrset",
138 scope, str);
139 }
140 else {
141 rb_name_error_str(Qnil, "cannot make unknown type anonymous ID %d:%"PRIxVALUE" attrset",
142 scope, (VALUE)id);
143 }
144 }
145 }
146 }
147
148 /* make new symbol and ID */
149 if (!(str = lookup_id_str(id))) {
150 static const char id_types[][8] = {
151 "local",
152 "instance",
153 "invalid",
154 "global",
155 "attrset",
156 "const",
157 "class",
158 "junk",
159 };
160 rb_name_error(id, "cannot make anonymous %.*s ID %"PRIxVALUE" attrset",
161 (int)sizeof(id_types[0]), id_types[scope], (VALUE)id);
162 }
163 str = rb_str_dup(str);
164 rb_str_cat(str, "=", 1);
165 sym = lookup_str_sym(str);
166 id = sym ? rb_sym2id(sym) : intern_str(str, 1);
167 return id;
168}
169
170static int
171is_special_global_name(const char *m, const char *e, rb_encoding *enc)
172{
173 int mb = 0;
174
175 if (m >= e) return 0;
176 if (is_global_name_punct(*m)) {
177 ++m;
178 }
179 else if (*m == '-') {
180 if (++m >= e) return 0;
181 if (is_identchar(m, e, enc)) {
182 if (!ISASCII(*m)) mb = 1;
183 m += rb_enc_mbclen(m, e, enc);
184 }
185 }
186 else {
187 if (!ISDIGIT(*m)) return 0;
188 do {
189 if (!ISASCII(*m)) mb = 1;
190 ++m;
191 } while (m < e && ISDIGIT(*m));
192 }
193 return m == e ? mb + 1 : 0;
194}
195
196int
197rb_symname_p(const char *name)
198{
200}
201
202int
204{
205 return rb_enc_symname2_p(name, strlen(name), enc);
206}
207
208static int
209rb_sym_constant_char_p(const char *name, long nlen, rb_encoding *enc)
210{
211 int c, len;
212 const char *end = name + nlen;
213
214 if (nlen < 1) return FALSE;
215 if (ISASCII(*name)) return ISUPPER(*name);
216 c = rb_enc_precise_mbclen(name, end, enc);
217 if (!MBCLEN_CHARFOUND_P(c)) return FALSE;
219 c = rb_enc_mbc_to_codepoint(name, end, enc);
220 if (ONIGENC_IS_UNICODE(enc)) {
221 static int ctype_titlecase = 0;
222 if (rb_enc_isupper(c, enc)) return TRUE;
223 if (rb_enc_islower(c, enc)) return FALSE;
224 if (!ctype_titlecase) {
225 static const UChar cname[] = "titlecaseletter";
226 static const UChar *const end = cname + sizeof(cname) - 1;
227 ctype_titlecase = ONIGENC_PROPERTY_NAME_TO_CTYPE(enc, cname, end);
228 }
229 if (rb_enc_isctype(c, ctype_titlecase, enc)) return TRUE;
230 }
231 else {
232 /* fallback to case-folding */
234 const OnigUChar *beg = (const OnigUChar *)name;
235 int r = enc->mbc_case_fold(ONIGENC_CASE_FOLD,
236 &beg, (const OnigUChar *)end,
237 fold, enc);
238 if (r > 0 && (r != len || memcmp(fold, name, r)))
239 return TRUE;
240 }
241 return FALSE;
242}
243
244#define IDSET_ATTRSET_FOR_SYNTAX ((1U<<ID_LOCAL)|(1U<<ID_CONST))
245#define IDSET_ATTRSET_FOR_INTERN (~(~0U<<(1<<ID_SCOPE_SHIFT)) & ~(1U<<ID_ATTRSET))
246
248 const enum { invalid, stophere, needmore, } kind;
249 const enum ruby_id_types type;
250 const long nread;
251};
252
253#define t struct enc_synmane_type_leading_chars_tag
254
256enc_synmane_type_leading_chars(const char *name, long len, rb_encoding *enc, int allowed_attrset)
257{
258 const char *m = name;
259 const char *e = m + len;
260
261 if (! rb_enc_asciicompat(enc)) {
262 return (t) { invalid, 0, 0, };
263 }
264 else if (! m) {
265 return (t) { invalid, 0, 0, };
266 }
267 else if ( len <= 0 ) {
268 return (t) { invalid, 0, 0, };
269 }
270 switch (*m) {
271 case '\0':
272 return (t) { invalid, 0, 0, };
273
274 case '$':
275 if (is_special_global_name(++m, e, enc)) {
276 return (t) { stophere, ID_GLOBAL, len, };
277 }
278 else {
279 return (t) { needmore, ID_GLOBAL, 1, };
280 }
281
282 case '@':
283 switch (*++m) {
284 default: return (t) { needmore, ID_INSTANCE, 1, };
285 case '@': return (t) { needmore, ID_CLASS, 2, };
286 }
287
288 case '<':
289 switch (*++m) {
290 default: return (t) { stophere, ID_JUNK, 1, };
291 case '<': return (t) { stophere, ID_JUNK, 2, };
292 case '=':
293 switch (*++m) {
294 default: return (t) { stophere, ID_JUNK, 2, };
295 case '>': return (t) { stophere, ID_JUNK, 3, };
296 }
297 }
298
299 case '>':
300 switch (*++m) {
301 default: return (t) { stophere, ID_JUNK, 1, };
302 case '>': case '=': return (t) { stophere, ID_JUNK, 2, };
303 }
304
305 case '=':
306 switch (*++m) {
307 default: return (t) { invalid, 0, 1, };
308 case '~': return (t) { stophere, ID_JUNK, 2, };
309 case '=':
310 switch (*++m) {
311 default: return (t) { stophere, ID_JUNK, 2, };
312 case '=': return (t) { stophere, ID_JUNK, 3, };
313 }
314 }
315
316 case '*':
317 switch (*++m) {
318 default: return (t) { stophere, ID_JUNK, 1, };
319 case '*': return (t) { stophere, ID_JUNK, 2, };
320 }
321
322 case '+': case '-':
323 switch (*++m) {
324 default: return (t) { stophere, ID_JUNK, 1, };
325 case '@': return (t) { stophere, ID_JUNK, 2, };
326 }
327
328 case '|': case '^': case '&': case '/': case '%': case '~': case '`':
329 return (t) { stophere, ID_JUNK, 1, };
330
331 case '[':
332 switch (*++m) {
333 default: return (t) { needmore, ID_JUNK, 0, };
334 case ']':
335 switch (*++m) {
336 default: return (t) { stophere, ID_JUNK, 2, };
337 case '=': return (t) { stophere, ID_JUNK, 3, };
338 }
339 }
340
341 case '!':
342 switch (*++m) {
343 case '=': case '~': return (t) { stophere, ID_JUNK, 2, };
344 default:
345 if (allowed_attrset & (1U << ID_JUNK)) {
346 return (t) { needmore, ID_JUNK, 1, };
347 }
348 else {
349 return (t) { stophere, ID_JUNK, 1, };
350 }
351 }
352
353 default:
354 if (rb_sym_constant_char_p(name, len, enc)) {
355 return (t) { needmore, ID_CONST, 0, };
356 }
357 else {
358 return (t) { needmore, ID_LOCAL, 0, };
359 }
360 }
361}
362#undef t
363
364int
365rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset)
366{
368 enc_synmane_type_leading_chars(name, len, enc, allowed_attrset);
369 const char *m = name + f.nread;
370 const char *e = name + len;
371 int type = (int)f.type;
372
373 switch (f.kind) {
374 case invalid: return -1;
375 case stophere: goto stophere;
376 case needmore: break;
377 }
378
379 if (m >= e || (*m != '_' && !ISALPHA(*m) && ISASCII(*m))) {
380 if (len > 1 && *(e-1) == '=') {
381 type = rb_enc_symname_type(name, len-1, enc, allowed_attrset);
382 if (type != ID_ATTRSET) return ID_ATTRSET;
383 }
384 return -1;
385 }
386 while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
387 if (m >= e) goto stophere;
388 switch (*m) {
389 case '!': case '?':
390 if (type == ID_GLOBAL || type == ID_CLASS || type == ID_INSTANCE) return -1;
391 type = ID_JUNK;
392 ++m;
393 if (m + 1 < e || *m != '=') break;
394 /* fall through */
395 case '=':
396 if (!(allowed_attrset & (1U << type))) return -1;
398 ++m;
399 break;
400 }
401
402 stophere:
403 return m == e ? type : -1;
404}
405
406int
407rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
408{
410}
411
412static int
413rb_str_symname_type(VALUE name, unsigned int allowed_attrset)
414{
415 const char *ptr = StringValuePtr(name);
416 long len = RSTRING_LEN(name);
417 int type = rb_enc_symname_type(ptr, len, rb_enc_get(name), allowed_attrset);
419 return type;
420}
421
422static void
423set_id_entry(rb_symbols_t *symbols, rb_id_serial_t num, VALUE str, VALUE sym)
424{
426 size_t idx = num / ID_ENTRY_UNIT;
427
428 VALUE ary, ids = symbols->ids;
429 if (idx >= (size_t)RARRAY_LEN(ids) || NIL_P(ary = rb_ary_entry(ids, (long)idx))) {
430 ary = rb_ary_tmp_new(ID_ENTRY_UNIT * ID_ENTRY_SIZE);
431 rb_ary_store(ids, (long)idx, ary);
432 }
433 idx = (num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE;
434 rb_ary_store(ary, (long)idx + ID_ENTRY_STR, str);
435 rb_ary_store(ary, (long)idx + ID_ENTRY_SYM, sym);
436}
437
438static VALUE
439get_id_serial_entry(rb_id_serial_t num, ID id, const enum id_entry_type t)
440{
441 VALUE result = 0;
442
443 GLOBAL_SYMBOLS_ENTER(symbols);
444 {
445 if (num && num <= symbols->last_id) {
446 size_t idx = num / ID_ENTRY_UNIT;
447 VALUE ids = symbols->ids;
448 VALUE ary;
449 if (idx < (size_t)RARRAY_LEN(ids) && !NIL_P(ary = rb_ary_entry(ids, (long)idx))) {
450 long pos = (long)(num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE;
451 result = rb_ary_entry(ary, pos + t);
452
453 if (NIL_P(result)) {
454 result = 0;
455 }
456 else {
457#if CHECK_ID_SERIAL
458 if (id) {
459 VALUE sym = result;
460 if (t != ID_ENTRY_SYM)
461 sym = rb_ary_entry(ary, pos + ID_ENTRY_SYM);
462 if (STATIC_SYM_P(sym)) {
463 if (STATIC_SYM2ID(sym) != id) result = 0;
464 }
465 else {
466 if (RSYMBOL(sym)->id != id) result = 0;
467 }
468 }
469#endif
470 }
471 }
472 }
473 }
475
476 return result;
477}
478
479static VALUE
480get_id_entry(ID id, const enum id_entry_type t)
481{
482 return get_id_serial_entry(rb_id_to_serial(id), id, t);
483}
484
485static inline ID
486#ifdef __GNUC__
487__attribute__((unused))
488#endif
489rb_id_serial_to_id(rb_id_serial_t num)
490{
491 if (is_notop_id((ID)num)) {
492 VALUE sym = get_id_serial_entry(num, 0, ID_ENTRY_SYM);
493 return SYM2ID(sym);
494 }
495 else {
496 return (ID)num;
497 }
498}
499
500#if SYMBOL_DEBUG
501static int
502register_sym_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
503{
504 if (existing) {
505 rb_fatal("symbol :% "PRIsVALUE" is already registered with %"PRIxVALUE,
506 (VALUE)*key, (VALUE)*value);
507 }
508 *value = arg;
509 return ST_CONTINUE;
510}
511#endif
512
513static void
514register_sym(rb_symbols_t *symbols, VALUE str, VALUE sym)
515{
517
518#if SYMBOL_DEBUG
519 st_update(symbols->str_sym, (st_data_t)str,
520 register_sym_update_callback, (st_data_t)sym);
521#else
523#endif
524}
525
526static void
527unregister_sym(rb_symbols_t *symbols, VALUE str, VALUE sym)
528{
530
531 st_data_t str_data = (st_data_t)str;
532 if (!st_delete(symbols->str_sym, &str_data, NULL)) {
533 rb_bug("%p can't remove str from str_id (%s)", (void *)sym, RSTRING_PTR(str));
534 }
535}
536
537static ID
538register_static_symid(ID id, const char *name, long len, rb_encoding *enc)
539{
541 return register_static_symid_str(id, str);
542}
543
544static ID
545register_static_symid_str(ID id, VALUE str)
546{
547 rb_id_serial_t num = rb_id_to_serial(id);
548 VALUE sym = STATIC_ID2SYM(id);
549
551 str = rb_fstring(str);
552
554
555 GLOBAL_SYMBOLS_ENTER(symbols)
556 {
557 register_sym(symbols, str, sym);
558 set_id_entry(symbols, num, str, sym);
559 }
561
562 return id;
563}
564
565static int
566sym_check_asciionly(VALUE str)
567{
568 if (!rb_enc_asciicompat(rb_enc_get(str))) return FALSE;
569 switch (rb_enc_str_coderange(str)) {
571 rb_raise(rb_eEncodingError, "invalid symbol in encoding %s :%+"PRIsVALUE,
574 return TRUE;
575 }
576 return FALSE;
577}
578
579#if 0
580/*
581 * _str_ itself will be registered at the global symbol table. _str_
582 * can be modified before the registration, since the encoding will be
583 * set to ASCII-8BIT if it is a special global name.
584 */
585
586static inline void
587must_be_dynamic_symbol(VALUE x)
588{
589 if (UNLIKELY(!DYNAMIC_SYM_P(x))) {
590 if (STATIC_SYM_P(x)) {
591 VALUE str = lookup_id_str(RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT));
592
593 if (str) {
594 rb_bug("wrong argument: %s (inappropriate Symbol)", RSTRING_PTR(str));
595 }
596 else {
597 rb_bug("wrong argument: inappropriate Symbol (%p)", (void *)x);
598 }
599 }
600 else {
601 rb_bug("wrong argument type %s (expected Symbol)", rb_builtin_class_name(x));
602 }
603 }
604}
605#endif
606
607static VALUE
608dsymbol_alloc(rb_symbols_t *symbols, const VALUE klass, const VALUE str, rb_encoding * const enc, const ID type)
609{
611
612 const VALUE dsym = rb_newobj_of(klass, T_SYMBOL | FL_WB_PROTECTED);
613 long hashval;
614
616 OBJ_FREEZE(dsym);
617 RB_OBJ_WRITE(dsym, &RSYMBOL(dsym)->fstr, str);
618 RSYMBOL(dsym)->id = type;
619
620 /* we want hashval to be in Fixnum range [ruby-core:15713] r15672 */
621 hashval = (long)rb_str_hash(str);
622 RSYMBOL(dsym)->hashval = RSHIFT((long)hashval, 1);
623 register_sym(symbols, str, dsym);
625 RUBY_DTRACE_CREATE_HOOK(SYMBOL, RSTRING_PTR(RSYMBOL(dsym)->fstr));
626
627 return dsym;
628}
629
630static inline VALUE
631dsymbol_check(rb_symbols_t *symbols, const VALUE sym)
632{
634
636 const VALUE fstr = RSYMBOL(sym)->fstr;
637 const ID type = RSYMBOL(sym)->id & ID_SCOPE_MASK;
638 RSYMBOL(sym)->fstr = 0;
639 unregister_sym(symbols, fstr, sym);
640 return dsymbol_alloc(symbols, rb_cSymbol, fstr, rb_enc_get(fstr), type);
641 }
642 else {
643 return sym;
644 }
645}
646
647static ID
648lookup_str_id(VALUE str)
649{
650 st_data_t sym_data;
651 int found;
652
653 GLOBAL_SYMBOLS_ENTER(symbols);
654 {
655 found = st_lookup(symbols->str_sym, (st_data_t)str, &sym_data);
656 }
658
659 if (found) {
660 const VALUE sym = (VALUE)sym_data;
661
662 if (STATIC_SYM_P(sym)) {
663 return STATIC_SYM2ID(sym);
664 }
665 else if (DYNAMIC_SYM_P(sym)) {
666 ID id = RSYMBOL(sym)->id;
667 if (id & ~ID_SCOPE_MASK) return id;
668 }
669 else {
670 rb_bug("non-symbol object %s:%"PRIxVALUE" for %"PRIsVALUE" in symbol table",
672 }
673 }
674 return (ID)0;
675}
676
677static VALUE
678lookup_str_sym_with_lock(rb_symbols_t *symbols, const VALUE str)
679{
680 st_data_t sym_data;
681 if (st_lookup(symbols->str_sym, (st_data_t)str, &sym_data)) {
682 VALUE sym = (VALUE)sym_data;
683 if (DYNAMIC_SYM_P(sym)) {
684 sym = dsymbol_check(symbols, sym);
685 }
686 return sym;
687 }
688 else {
689 return Qfalse;
690 }
691}
692
693static VALUE
694lookup_str_sym(const VALUE str)
695{
696 VALUE sym;
697
698 GLOBAL_SYMBOLS_ENTER(symbols);
699 {
700 sym = lookup_str_sym_with_lock(symbols, str);
701 }
703
704 return sym;
705}
706
707static VALUE
708lookup_id_str(ID id)
709{
710 return get_id_entry(id, ID_ENTRY_STR);
711}
712
713ID
714rb_intern3(const char *name, long len, rb_encoding *enc)
715{
716 VALUE sym;
717 struct RString fake_str;
718 VALUE str = rb_setup_fake_str(&fake_str, name, len, enc);
720 sym = lookup_str_sym(str);
721 if (sym) return rb_sym2id(sym);
722 str = rb_enc_str_new(name, len, enc); /* make true string */
723 return intern_str(str, 1);
724}
725
726static ID
727next_id_base_with_lock(rb_symbols_t *symbols)
728{
729 ID id;
730 rb_id_serial_t next_serial = symbols->last_id + 1;
731
732 if (next_serial == 0) {
733 id = (ID)-1;
734 }
735 else {
736 const size_t num = ++symbols->last_id;
737 id = num << ID_SCOPE_SHIFT;
738 }
739
740 return id;
741}
742
743static ID
744next_id_base(void)
745{
746 ID id;
747 GLOBAL_SYMBOLS_ENTER(symbols);
748 {
749 id = next_id_base_with_lock(symbols);
750 }
752 return id;
753}
754
755static ID
756intern_str(VALUE str, int mutable)
757{
758 ID id;
759 ID nid;
760
761 id = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
762 if (id == (ID)-1) id = ID_JUNK;
763 if (sym_check_asciionly(str)) {
764 if (!mutable) str = rb_str_dup(str);
766 }
767 if ((nid = next_id_base()) == (ID)-1) {
768 str = rb_str_ellipsize(str, 20);
769 rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %"PRIsVALUE")",
770 str);
771 }
772 id |= nid;
773 id |= ID_STATIC_SYM;
774 return register_static_symid_str(id, str);
775}
776
777ID
778rb_intern2(const char *name, long len)
779{
781}
782
783#undef rb_intern
784ID
785rb_intern(const char *name)
786{
787 return rb_intern2(name, strlen(name));
788}
789
790ID
792{
793 VALUE sym = lookup_str_sym(str);
794
795 if (sym) {
796 return SYM2ID(sym);
797 }
798
799 return intern_str(str, 0);
800}
801
802void
804{
805 VALUE str = RSYMBOL(sym)->fstr;
806
807 if (str) {
808 RSYMBOL(sym)->fstr = 0;
809
810 GLOBAL_SYMBOLS_ENTER(symbols);
811 {
812 unregister_sym(symbols, str, sym);
814 }
816 }
817}
818
819/*
820 * call-seq:
821 * str.intern -> symbol
822 * str.to_sym -> symbol
823 *
824 * Returns the Symbol corresponding to <i>str</i>, creating the
825 * symbol if it did not previously exist. See Symbol#id2name.
826 *
827 * "Koala".intern #=> :Koala
828 * s = 'cat'.to_sym #=> :cat
829 * s == :cat #=> true
830 * s = '@cat'.to_sym #=> :@cat
831 * s == :@cat #=> true
832 *
833 * This can also be used to create symbols that cannot be represented using the
834 * <code>:xxx</code> notation.
835 *
836 * 'cat and dog'.to_sym #=> :"cat and dog"
837 */
838
839VALUE
841{
842 VALUE sym;
843#if USE_SYMBOL_GC
844 rb_encoding *enc, *ascii;
845 int type;
846#else
847 ID id;
848#endif
849 GLOBAL_SYMBOLS_ENTER(symbols);
850 {
851 sym = lookup_str_sym_with_lock(symbols, str);
852
853 if (sym) {
854 // ok
855 }
856 else {
857#if USE_SYMBOL_GC
858 enc = rb_enc_get(str);
859 ascii = rb_usascii_encoding();
860 if (enc != ascii && sym_check_asciionly(str)) {
861 str = rb_str_dup(str);
862 rb_enc_associate(str, ascii);
864 enc = ascii;
865 }
866 else {
867 str = rb_str_dup(str);
869 }
870 str = rb_fstring(str);
871 type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
872 if (type < 0) type = ID_JUNK;
873 sym = dsymbol_alloc(symbols, rb_cSymbol, str, enc, type);
874#else
875 id = intern_str(str, 0);
876 sym = ID2SYM(id);
877#endif
878 }
879 }
881 return sym;
882}
883
884ID
886{
887 ID id;
888 if (STATIC_SYM_P(sym)) {
889 id = STATIC_SYM2ID(sym);
890 }
891 else if (DYNAMIC_SYM_P(sym)) {
892 GLOBAL_SYMBOLS_ENTER(symbols);
893 {
894 sym = dsymbol_check(symbols, sym);
895 id = RSYMBOL(sym)->id;
896
897 if (UNLIKELY(!(id & ~ID_SCOPE_MASK))) {
898 VALUE fstr = RSYMBOL(sym)->fstr;
899 ID num = next_id_base_with_lock(symbols);
900
901 RSYMBOL(sym)->id = id |= num;
902 /* make it permanent object */
903
904 set_id_entry(symbols, rb_id_to_serial(num), fstr, sym);
906 }
907 }
909 }
910 else {
911 rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol)",
913 }
914 return id;
915}
916
917#undef rb_id2sym
918VALUE
920{
921 if (!DYNAMIC_ID_P(x)) return STATIC_ID2SYM(x);
922 return get_id_entry(x, ID_ENTRY_SYM);
923}
924
925
926VALUE
928{
929 if (DYNAMIC_SYM_P(sym)) {
930 return RSYMBOL(sym)->fstr;
931 }
932 else {
933 return rb_id2str(STATIC_SYM2ID(sym));
934 }
935}
936
937VALUE
939{
940 return lookup_id_str(id);
941}
942
943const char *
945{
946 VALUE str = rb_id2str(id);
947
948 if (!str) return 0;
949 return RSTRING_PTR(str);
950}
951
952ID
954{
955 return next_id_base() | ID_INTERNAL | ID_STATIC_SYM;
956}
957
958static int
959symbols_i(st_data_t key, st_data_t value, st_data_t arg)
960{
961 VALUE ary = (VALUE)arg;
962 VALUE sym = (VALUE)value;
963
964 if (STATIC_SYM_P(sym)) {
966 return ST_CONTINUE;
967 }
968 else if (!DYNAMIC_SYM_P(sym)) {
969 rb_bug("invalid symbol: %s", RSTRING_PTR((VALUE)key));
970 }
972 RSYMBOL(sym)->fstr = 0;
973 return ST_DELETE;
974 }
975 else {
977 return ST_CONTINUE;
978 }
979
980}
981
982VALUE
984{
985 VALUE ary;
986
987 GLOBAL_SYMBOLS_ENTER(symbols);
988 {
989 ary = rb_ary_new2(symbols->str_sym->num_entries);
990 st_foreach(symbols->str_sym, symbols_i, ary);
991 }
993
994 return ary;
995}
996
997size_t
999{
1000 return (size_t)ruby_global_symbols.last_id;
1001}
1002
1003int
1005{
1006 return is_const_id(id);
1007}
1008
1009int
1011{
1012 return is_class_id(id);
1013}
1014
1015int
1017{
1018 return is_global_id(id);
1019}
1020
1021int
1023{
1024 return is_instance_id(id);
1025}
1026
1027int
1029{
1030 return is_attrset_id(id);
1031}
1032
1033int
1035{
1036 return is_local_id(id);
1037}
1038
1039int
1041{
1042 return is_junk_id(id);
1043}
1044
1045int
1047{
1048 return is_const_sym(sym);
1049}
1050
1051int
1053{
1054 return is_attrset_sym(sym);
1055}
1056
1068ID
1069rb_check_id(volatile VALUE *namep)
1070{
1071 VALUE tmp;
1072 VALUE name = *namep;
1073
1074 if (STATIC_SYM_P(name)) {
1075 return STATIC_SYM2ID(name);
1076 }
1077 else if (DYNAMIC_SYM_P(name)) {
1078 if (SYMBOL_PINNED_P(name)) {
1079 return RSYMBOL(name)->id;
1080 }
1081 else {
1082 *namep = RSYMBOL(name)->fstr;
1083 return 0;
1084 }
1085 }
1086 else if (!RB_TYPE_P(name, T_STRING)) {
1088 if (NIL_P(tmp)) {
1089 rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
1090 name);
1091 }
1092 name = tmp;
1093 *namep = name;
1094 }
1095
1096 sym_check_asciionly(name);
1097
1098 return lookup_str_id(name);
1099}
1100
1113VALUE
1114rb_check_symbol(volatile VALUE *namep)
1115{
1116 VALUE sym;
1117 VALUE tmp;
1118 VALUE name = *namep;
1119
1120 if (STATIC_SYM_P(name)) {
1121 return name;
1122 }
1123 else if (DYNAMIC_SYM_P(name)) {
1124 if (!SYMBOL_PINNED_P(name)) {
1125 GLOBAL_SYMBOLS_ENTER(symbols);
1126 {
1127 name = dsymbol_check(symbols, name);
1128 }
1130
1131 *namep = name;
1132 }
1133 return name;
1134 }
1135 else if (!RB_TYPE_P(name, T_STRING)) {
1137 if (NIL_P(tmp)) {
1138 rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
1139 name);
1140 }
1141 name = tmp;
1142 *namep = name;
1143 }
1144
1145 sym_check_asciionly(name);
1146
1147 if ((sym = lookup_str_sym(name)) != 0) {
1148 return sym;
1149 }
1150
1151 return Qnil;
1152}
1153
1154ID
1155rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
1156{
1157 struct RString fake_str;
1158 const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
1159
1160 sym_check_asciionly(name);
1161
1162 return lookup_str_id(name);
1163}
1164
1165VALUE
1166rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
1167{
1168 VALUE sym;
1169 struct RString fake_str;
1170 const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
1171
1172 sym_check_asciionly(name);
1173
1174 if ((sym = lookup_str_sym(name)) != 0) {
1175 return sym;
1176 }
1177
1178 return Qnil;
1179}
1180
1181#undef rb_sym_intern_ascii_cstr
1182#ifdef __clang__
1183NOINLINE(VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc));
1184#else
1185FUNC_MINIMIZED(VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc));
1186FUNC_MINIMIZED(VALUE rb_sym_intern_ascii(const char *ptr, long len));
1188#endif
1189
1190VALUE
1191rb_sym_intern(const char *ptr, long len, rb_encoding *enc)
1192{
1193 struct RString fake_str;
1194 const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
1195 return rb_str_intern(name);
1196}
1197
1198VALUE
1199rb_sym_intern_ascii(const char *ptr, long len)
1200{
1202}
1203
1204VALUE
1206{
1208}
1209
1210VALUE
1212{
1213 return rb_convert_type_with_id(obj, T_SYMBOL, "Symbol", idTo_sym);
1214}
1215
1216int
1218{
1219 return rb_str_symname_type(name, 0) == ID_CONST;
1220}
1221
1222int
1224{
1225 return rb_str_symname_type(name, 0) == ID_CLASS;
1226}
1227
1228int
1230{
1231 return rb_str_symname_type(name, 0) == ID_INSTANCE;
1232}
1233
1234int
1236{
1237 return rb_str_symname_type(name, 0) == ID_LOCAL;
1238}
1239
1240#include "id_table.c"
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1141
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:846
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1672
#define NOINLINE(x)
Definition: attributes.h:82
#define FUNC_MINIMIZED(x)
Definition: attributes.h:126
#define WARN_UNUSED_RESULT(x)
Definition: compilers.h:64
#define ISUPPER
Definition: ctype.h:39
#define ISDIGIT
Definition: ctype.h:43
#define ISALPHA
Definition: ctype.h:42
#define ISASCII
Definition: ctype.h:35
#define ISALNUM
Definition: ctype.h:41
enum ruby_id_types id_types
Definition: debug.c:47
struct RIMemo * ptr
Definition: debug.c:88
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1230
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:1064
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1525
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:1070
int rb_enc_to_index(rb_encoding *enc)
Definition: encoding.c:197
void rb_enc_set_index(VALUE obj, int idx)
Definition: encoding.c:1028
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1218
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1549
big_t * num
Definition: enough.c:232
#define sym(name)
Definition: enumerator.c:4007
uint8_t len
Definition: escape.c:17
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
#define RSTRING_LEN(string)
Definition: fbuffer.h:22
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
#define UNLIKELY(x)
Definition: ffi_common.h:126
#define FL_WB_PROTECTED
Definition: fl_type.h:50
#define PRIsVALUE
Definition: function.c:10
int rb_objspace_garbage_object_p(VALUE obj)
Definition: gc.c:3933
VALUE rb_newobj_of(VALUE klass, VALUE flags)
Definition: gc.c:2371
void rb_gc_register_mark_object(VALUE obj)
Inform the garbage collector that object is a live Ruby object that should not be moved.
Definition: gc.c:8022
#define rb_intern_str(string)
Definition: generator.h:16
VALUE rb_cSymbol
Definition: string.c:81
#define OBJ_FREEZE
Definition: fl_type.h:134
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
void rb_bug(const char *fmt,...)
Definition: error.c:768
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:1649
VALUE rb_ident_hash_new(void)
Definition: hash.c:4443
VALUE rb_eTypeError
Definition: error.c:1057
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:1664
void rb_fatal(const char *fmt,...)
Definition: error.c:2968
const char * rb_builtin_class_name(VALUE x)
Definition: error.c:937
VALUE rb_eRuntimeError
Definition: error.c:1055
VALUE rb_eEncodingError
Definition: error.c:1063
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:92
VALUE rb_convert_type_with_id(VALUE v, int t, const char *nam, ID mid)
Definition: object.c:2944
VALUE rb_hash_delete_entry(VALUE hash, VALUE key)
Definition: hash.c:2309
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2901
void *PTR64 __attribute__((mode(DI)))
Definition: ffi.c:41
#define tAREF
Definition: id.c:28
#define tASET
Definition: id.c:29
unsigned short token
Definition: id.c:36
@ tNEXT_ID
Definition: id.h:211
#define ID_GLOBAL
Definition: id.h:35
#define ID_CLASS
Definition: id.h:38
#define ID_CONST
Definition: id.h:37
#define ID_ATTRSET
Definition: id.h:36
#define ID_SCOPE_SHIFT
Definition: id.h:31
#define ID_JUNK
Definition: id.h:39
#define ID_INSTANCE
Definition: id.h:34
#define ID_LOCAL
Definition: id.h:33
ruby_id_types
Definition: id.h:16
#define ID_SCOPE_MASK
Definition: id.h:32
#define ID_INTERNAL
Definition: id.h:40
#define ID_STATIC_SYM
Definition: id.h:30
#define rb_enc_isupper(c, enc)
Definition: encoding.h:224
#define ENC_CODERANGE_7BIT
Definition: encoding.h:93
#define rb_enc_isctype(c, t, enc)
Definition: encoding.h:220
int rb_enc_str_coderange(VALUE)
Definition: string.c:725
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:857
#define rb_enc_name(enc)
Definition: encoding.h:168
#define rb_enc_mbc_to_codepoint(p, e, enc)
Definition: encoding.h:199
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:183
#define rb_enc_asciicompat(enc)
Definition: encoding.h:236
#define rb_enc_islower(c, enc)
Definition: encoding.h:223
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:95
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:182
#define rb_ary_new2
Definition: array.h:72
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2962
VALUE rb_check_string_type(VALUE)
Definition: string.c:2462
VALUE rb_str_ellipsize(VALUE, long)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
Definition: string.c:10517
int rb_str_hash_cmp(VALUE, VALUE)
Definition: string.c:3324
VALUE rb_str_dup(VALUE)
Definition: string.c:1631
st_index_t rb_str_hash(VALUE)
Definition: string.c:3314
#define ID2SYM
Definition: symbol.h:44
#define SYM2ID
Definition: symbol.h:45
Internal header for GC.
Internal header for Hash.
Internal header for Object.
#define STATIC_ASSERT
Definition: static_assert.h:14
VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc)
Definition: string.c:435
VALUE rb_fstring(VALUE)
Definition: string.c:353
Internal header for RubyVM.
#define RUBY_DTRACE_CREATE_HOOK(name, arg)
Definition: vm.h:120
#define rb_sym_intern_ascii_cstr(...)
Definition: internal.h:74
#define PRIxVALUE
Definition: inttypes.h:75
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
#define RB_GC_GUARD(v)
Definition: memory.h:91
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
const int id
Definition: nkf.c:209
const char * name
Definition: nkf.c:208
#define TRUE
Definition: nkf.h:175
#define FALSE
Definition: nkf.h:174
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
#define RARRAY_LEN
Definition: rarray.h:52
#define NULL
Definition: regenc.h:69
#define RB_OBJ_WRITE(a, slot, b)
WB for new reference from ‘a’ to ‘b’.
Definition: rgengc.h:107
#define StringValuePtr(v)
Definition: rstring.h:51
@ RUBY_SPECIAL_SHIFT
#define STATIC_SYM_P
#define Qtrue
#define Qnil
#define Qfalse
#define NIL_P
#define f
@ ST_DELETE
Definition: st.h:99
@ ST_CONTINUE
Definition: st.h:99
unsigned long st_data_t
Definition: st.h:22
#define st_foreach
Definition: st.h:142
#define st_lookup
Definition: st.h:128
#define st_init_table_with_size
Definition: st.h:104
#define st_add_direct
Definition: st.h:154
#define st_delete
Definition: st.h:118
#define st_update
Definition: st.h:136
size_t strlen(const char *)
#define const
Definition: strftime.c:108
int(* mbc_case_fold)(OnigCaseFoldType flag, const OnigUChar **pp, const OnigUChar *end, OnigUChar *to, const struct OnigEncodingTypeST *enc)
Definition: onigmo.h:169
char ary[RSTRING_EMBED_LEN_MAX+1]
Definition: rstring.h:84
enum ruby_id_types type
Definition: symbol.c:249
enum enc_synmane_type_leading_chars_tag::@168 kind
rb_id_serial_t last_id
Definition: symbol.h:62
VALUE ids
Definition: symbol.h:64
st_table * str_sym
Definition: symbol.h:63
VALUE dsymbol_fstr_hash
Definition: symbol.h:65
st_index_t num_entries
Definition: st.h:86
#define op_tbl_len(i)
Definition: symbol.c:49
ID rb_intern2(const char *name, long len)
Definition: symbol.c:778
#define t
Definition: symbol.c:253
void Init_sym(void)
Definition: symbol.c:84
VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:1191
#define is_identchar(p, e, enc)
Definition: symbol.c:45
#define SYMBOL_PINNED_P(sym)
Definition: symbol.c:36
int rb_enc_symname_p(const char *name, rb_encoding *enc)
Definition: symbol.c:203
ID rb_sym2id(VALUE sym)
Definition: symbol.c:885
rb_symbols_t ruby_global_symbols
Definition: symbol.c:76
int rb_is_instance_name(VALUE name)
Definition: symbol.c:1229
int rb_symname_p(const char *name)
Definition: symbol.c:197
VALUE rb_check_symbol(volatile VALUE *namep)
Returns Symbol for the given name if it is interned already, or nil.
Definition: symbol.c:1114
VALUE rb_sym_all_symbols(void)
Definition: symbol.c:983
void rb_gc_free_dsymbol(VALUE sym)
Definition: symbol.c:803
int rb_is_global_id(ID id)
Definition: symbol.c:1016
#define GLOBAL_SYMBOLS_LEAVE()
Definition: symbol.c:110
#define op_tbl_count
Definition: symbol.c:47
ID rb_intern3(const char *name, long len, rb_encoding *enc)
Definition: symbol.c:714
size_t rb_sym_immortal_count(void)
Definition: symbol.c:998
#define STATIC_SYM2ID(sym)
Definition: symbol.c:38
VALUE rb_sym2str(VALUE sym)
Definition: symbol.c:927
VALUE rb_to_symbol_type(VALUE obj)
Definition: symbol.c:1211
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:1069
int rb_is_instance_id(ID id)
Definition: symbol.c:1022
int rb_is_class_name(VALUE name)
Definition: symbol.c:1223
int rb_is_junk_id(ID id)
Definition: symbol.c:1040
int rb_is_const_id(ID id)
Definition: symbol.c:1004
#define IDSET_ATTRSET_FOR_SYNTAX
Definition: symbol.c:244
ID rb_make_internal_id(void)
Definition: symbol.c:953
ID rb_intern(const char *name)
Definition: symbol.c:785
int rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset)
Definition: symbol.c:365
VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:1166
#define GLOBAL_SYMBOLS_ENTER(symbols)
Definition: symbol.c:109
ID rb_id_attrset(ID id)
Definition: symbol.c:113
VALUE rb_id2sym(ID x)
Definition: symbol.c:919
int rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
Definition: symbol.c:407
int rb_is_attrset_sym(VALUE sym)
Definition: symbol.c:1052
int rb_is_const_name(VALUE name)
Definition: symbol.c:1217
#define IDSET_ATTRSET_FOR_INTERN
Definition: symbol.c:245
int rb_is_class_id(ID id)
Definition: symbol.c:1010
const char * rb_id2name(ID id)
Definition: symbol.c:944
int rb_is_attrset_id(ID id)
Definition: symbol.c:1028
int rb_is_local_id(ID id)
Definition: symbol.c:1034
int rb_is_const_sym(VALUE sym)
Definition: symbol.c:1046
ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:1155
id_entry_type
Definition: symbol.c:70
@ ID_ENTRY_STR
Definition: symbol.c:71
@ ID_ENTRY_SIZE
Definition: symbol.c:73
@ ID_ENTRY_SYM
Definition: symbol.c:72
VALUE rb_sym_intern_ascii(const char *ptr, long len)
Definition: symbol.c:1199
int rb_is_local_name(VALUE name)
Definition: symbol.c:1235
VALUE rb_str_intern(VALUE str)
Definition: symbol.c:840
#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
unsigned long VALUE
Definition: value.h:38
unsigned long ID
Definition: value.h:39
#define T_STRING
Definition: value_type.h:77
#define DYNAMIC_SYM_P
Definition: value_type.h:85
#define T_SYMBOL
Definition: value_type.h:79
#define rb_id2str(id)
Definition: vm_backtrace.c:30
#define ASSERT_vm_locking()
Definition: vm_sync.h:134