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