Ruby  2.4.2p198(2017-09-14revision59899)
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 *);
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
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) {
51  }
52 }
53 
54 enum {ID_ENTRY_UNIT = 512};
55 
60 };
61 
62 static struct symbols {
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 
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));
93 WARN_UNUSED_RESULT(static VALUE lookup_str_sym(const VALUE str));
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
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))) {
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
342 {
343  if (num && num <= global_symbols.last_id) {
344  size_t idx = num / ID_ENTRY_UNIT;
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
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
385 {
386 #if SYMBOL_DEBUG
388  register_sym_update_callback, (st_data_t)sym);
389 #else
391 #endif
392 }
393 
394 static void
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
412 {
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
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);
486 
487  RUBY_DTRACE_CREATE_HOOK(SYMBOL, RSTRING_PTR(RSYMBOL(dsym)->fstr));
488 
489  return dsym;
490 }
491 
492 static inline VALUE
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
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
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
549 {
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
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 
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);
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);
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);
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);
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  VALUE str;
748 
749  if ((str = lookup_id_str(id)) != 0) {
750  if (RBASIC(str)->klass == 0)
752  return str;
753  }
754 
755  return 0;
756 }
757 
758 const char *
760 {
761  VALUE str = rb_id2str(id);
762 
763  if (!str) return 0;
764  return RSTRING_PTR(str);
765 }
766 
767 ID
769 {
771 }
772 
773 static int
775 {
776  VALUE ary = (VALUE)arg;
777  VALUE sym = (VALUE)value;
778 
779  if (STATIC_SYM_P(sym)) {
780  rb_ary_push(ary, sym);
781  return ST_CONTINUE;
782  }
783  else if (!DYNAMIC_SYM_P(sym)) {
784  rb_bug("invalid symbol: %s", RSTRING_PTR((VALUE)key));
785  }
786  else if (!SYMBOL_PINNED_P(sym) && rb_objspace_garbage_object_p(sym)) {
787  RSYMBOL(sym)->fstr = 0;
788  return ST_DELETE;
789  }
790  else {
791  rb_ary_push(ary, sym);
792  return ST_CONTINUE;
793  }
794 
795 }
796 
797 /*
798  * call-seq:
799  * Symbol.all_symbols => array
800  *
801  * Returns an array of all the symbols currently in Ruby's symbol
802  * table.
803  *
804  * Symbol.all_symbols.size #=> 903
805  * Symbol.all_symbols[1,20] #=> [:floor, :ARGV, :Binding, :symlink,
806  * :chown, :EOFError, :$;, :String,
807  * :LOCK_SH, :"setuid?", :$<,
808  * :default_proc, :compact, :extend,
809  * :Tms, :getwd, :$=, :ThreadGroup,
810  * :wait2, :$>]
811  */
812 
813 VALUE
815 {
818  return ary;
819 }
820 
821 size_t
823 {
824  return (size_t)global_symbols.last_id;
825 }
826 
827 int
829 {
830  return is_const_id(id);
831 }
832 
833 int
835 {
836  return is_class_id(id);
837 }
838 
839 int
841 {
842  return is_global_id(id);
843 }
844 
845 int
847 {
848  return is_instance_id(id);
849 }
850 
851 int
853 {
854  return is_attrset_id(id);
855 }
856 
857 int
859 {
860  return is_local_id(id);
861 }
862 
863 int
865 {
866  return is_junk_id(id);
867 }
868 
869 int
871 {
872  return is_const_sym(sym);
873 }
874 
875 int
877 {
878  return is_class_sym(sym);
879 }
880 
881 int
883 {
884  return is_global_sym(sym);
885 }
886 
887 int
889 {
890  return is_instance_sym(sym);
891 }
892 
893 int
895 {
896  return is_attrset_sym(sym);
897 }
898 
899 int
901 {
902  return is_local_sym(sym);
903 }
904 
905 int
907 {
908  return is_junk_sym(sym);
909 }
910 
922 ID
923 rb_check_id(volatile VALUE *namep)
924 {
925  VALUE tmp;
926  VALUE name = *namep;
927 
928  if (STATIC_SYM_P(name)) {
929  return STATIC_SYM2ID(name);
930  }
931  else if (DYNAMIC_SYM_P(name)) {
932  if (SYMBOL_PINNED_P(name)) {
933  return RSYMBOL(name)->id;
934  }
935  else {
936  *namep = RSYMBOL(name)->fstr;
937  return 0;
938  }
939  }
940  else if (!RB_TYPE_P(name, T_STRING)) {
941  tmp = rb_check_string_type(name);
942  if (NIL_P(tmp)) {
943  rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
944  name);
945  }
946  name = tmp;
947  *namep = name;
948  }
949 
950  sym_check_asciionly(name);
951 
952  return lookup_str_id(name);
953 }
954 
955 VALUE
956 rb_check_symbol(volatile VALUE *namep)
957 {
958  VALUE sym;
959  VALUE tmp;
960  VALUE name = *namep;
961 
962  if (STATIC_SYM_P(name)) {
963  return name;
964  }
965  else if (DYNAMIC_SYM_P(name)) {
966  if (!SYMBOL_PINNED_P(name)) {
967  name = dsymbol_check(name);
968  *namep = name;
969  }
970  return name;
971  }
972  else if (!RB_TYPE_P(name, T_STRING)) {
973  tmp = rb_check_string_type(name);
974  if (NIL_P(tmp)) {
975  rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
976  name);
977  }
978  name = tmp;
979  *namep = name;
980  }
981 
982  sym_check_asciionly(name);
983 
984  if ((sym = lookup_str_sym(name)) != 0) {
985  return sym;
986  }
987 
988  return Qnil;
989 }
990 
991 ID
992 rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
993 {
994  struct RString fake_str;
995  const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
996 
997  sym_check_asciionly(name);
998 
999  return lookup_str_id(name);
1000 }
1001 
1002 VALUE
1003 rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
1004 {
1005  VALUE sym;
1006  struct RString fake_str;
1007  const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
1008 
1009  sym_check_asciionly(name);
1010 
1011  if ((sym = lookup_str_sym(name)) != 0) {
1012  return sym;
1013  }
1014 
1015  return Qnil;
1016 }
1017 
1018 #undef rb_sym_intern_cstr
1019 #undef rb_sym_intern_ascii_cstr
1020 #ifdef __clang__
1021 NOINLINE(VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc));
1022 #else
1023 FUNC_MINIMIZED(VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc));
1024 FUNC_MINIMIZED(VALUE rb_sym_intern_cstr(const char *ptr, rb_encoding *enc));
1025 FUNC_MINIMIZED(VALUE rb_sym_intern_ascii(const char *ptr, long len));
1027 #endif
1028 
1029 VALUE
1030 rb_sym_intern(const char *ptr, long len, rb_encoding *enc)
1031 {
1032  struct RString fake_str;
1033  const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
1034  return rb_str_intern(name);
1035 }
1036 
1037 VALUE
1038 rb_sym_intern_cstr(const char *ptr, rb_encoding *enc)
1039 {
1040  return rb_sym_intern(ptr, strlen(ptr), enc);
1041 }
1042 
1043 VALUE
1044 rb_sym_intern_ascii(const char *ptr, long len)
1045 {
1046  return rb_sym_intern(ptr, len, rb_usascii_encoding());
1047 }
1048 
1049 VALUE
1051 {
1052  return rb_sym_intern_ascii(ptr, strlen(ptr));
1053 }
1054 
1055 static ID
1057 {
1058  ID id;
1059  struct RString fake_str;
1060  /* make local name by chopping '=' */
1061  const VALUE localname = rb_setup_fake_str(&fake_str,
1062  RSTRING_PTR(name), RSTRING_LEN(name) - 1,
1063  rb_enc_get(name));
1064  OBJ_FREEZE(localname);
1065 
1066  if ((id = lookup_str_id(localname)) != 0) {
1067  return id;
1068  }
1069  RB_GC_GUARD(name);
1070  return (ID)0;
1071 }
1072 
1073 static ID
1075 {
1076  if (rb_is_attrset_name(name)) {
1077  return attrsetname_to_attr_id(name);
1078  }
1079 
1080  return (ID)0;
1081 }
1082 
1083 int
1085 {
1086  return rb_str_symname_type(name, 0) == ID_CONST;
1087 }
1088 
1089 int
1091 {
1092  return rb_str_symname_type(name, 0) == ID_CLASS;
1093 }
1094 
1095 int
1097 {
1098  return rb_str_symname_type(name, 0) == ID_GLOBAL;
1099 }
1100 
1101 int
1103 {
1104  return rb_str_symname_type(name, 0) == ID_INSTANCE;
1105 }
1106 
1107 int
1109 {
1111 }
1112 
1113 int
1115 {
1116  return rb_str_symname_type(name, 0) == ID_LOCAL;
1117 }
1118 
1119 int
1121 {
1122  switch (rb_str_symname_type(name, 0)) {
1123  case ID_LOCAL: case ID_ATTRSET: case ID_JUNK:
1124  return TRUE;
1125  }
1126  return FALSE;
1127 }
1128 
1129 int
1131 {
1132  return rb_str_symname_type(name, IDSET_ATTRSET_FOR_SYNTAX) == -1;
1133 }
1134 
1135 #include "id_table.c"
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:1906
VALUE dsymbol_fstr_hash
Definition: symbol.c:66
const char * rb_builtin_class_name(VALUE x)
Definition: error.c:645
#define T_SYMBOL
Definition: ruby.h:508
#define ISDIGIT(c)
Definition: ruby.h:2129
Definition: st.h:99
int rb_is_instance_id(ID id)
Definition: symbol.c:846
ID rb_intern2(const char *name, long len)
Definition: symbol.c:604
static int rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset)
Definition: symbol.c:205
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:923
ID rb_make_internal_id(void)
Definition: symbol.c:768
static ID register_static_symid_str(ID, VALUE)
Definition: symbol.c:411
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1196
static void register_sym(VALUE str, VALUE sym)
Definition: symbol.c:384
static void Init_id(void)
Definition: id.c:63
#define RARRAY_LEN(a)
Definition: ruby.h:1026
static rb_id_serial_t rb_id_to_serial(ID id)
Definition: symbol.h:58
void rb_bug(const char *fmt,...)
Definition: error.c:482
#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:1030
Definition: st.h:79
static VALUE lookup_str_sym(const VALUE str)
Definition: symbol.c:531
#define IDSET_ATTRSET_FOR_SYNTAX
Definition: symbol.c:201
unsigned int UINT8 __attribute__((__mode__(__QI__)))
Definition: ffi_common.h:110
static void Init_op_tbl(void)
Definition: symbol.c:38
#define is_const_sym(sym)
Definition: symbol.h:88
int rb_is_class_name(VALUE name)
Definition: symbol.c:1090
VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc)
Definition: string.c:367
VALUE ids
Definition: symbol.c:65
int rb_is_attrset_sym(VALUE sym)
Definition: symbol.c:894
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2664
VALUE rb_sym_intern_ascii(const char *ptr, long len)
Definition: symbol.c:1044
#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
const int id
Definition: nkf.c:209
static void set_id_entry(rb_id_serial_t num, VALUE str, VALUE sym)
Definition: symbol.c:327
int rb_is_const_id(ID id)
Definition: symbol.c:828
#define ID_CONST
Definition: id.h:37
static const struct @116 op_tbl[]
VALUE rb_eTypeError
Definition: error.c:762
#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:905
VALUE rb_eEncodingError
Definition: error.c:768
#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:1114
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:532
int rb_enc_str_coderange(VALUE)
Definition: string.c:620
#define PRIxVALUE
Definition: ruby.h:133
int rb_is_global_sym(VALUE sym)
Definition: symbol.c:882
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2207
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:3014
#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:2985
unsigned short token
Definition: id.c:36
static ID attrsetname_to_attr_id(VALUE name)
Definition: symbol.c:1056
#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:1371
static ID rb_id_serial_to_id(rb_id_serial_t num)
Definition: symbol.c:359
int rb_enc_symname_p(const char *name, rb_encoding *enc)
Definition: symbol.c:196
VALUE rb_id2sym(ID x)
Definition: symbol.c:726
#define tASET
Definition: id.c:29
enum ruby_id_types id_types
Definition: debug.c:27
int rb_is_method_name(VALUE name)
Definition: symbol.c:1120
VALUE rb_check_symbol(volatile VALUE *namep)
Definition: symbol.c:956
#define ENC_CODERANGE_7BIT
Definition: encoding.h:100
#define rb_ary_new2
Definition: intern.h:90
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:1219
#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
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:1204
static VALUE dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type)
Definition: symbol.c:470
#define is_attrset_sym(sym)
Definition: symbol.h:87
#define ISALPHA(c)
Definition: ruby.h:2128
int rb_is_junk_sym(VALUE sym)
Definition: symbol.c:906
#define ID_STATIC_SYM
Definition: id.h:30
#define RBASIC_SET_CLASS_RAW(obj, cls)
Definition: internal.h:1313
#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:814
int rb_is_junk_name(VALUE name)
Definition: symbol.c:1130
Definition: ruby.h:961
#define ID_SCOPE_MASK
Definition: id.h:32
#define is_global_sym(sym)
Definition: symbol.h:85
static void unregister_sym(VALUE str, VALUE sym)
Definition: symbol.c:395
int rb_is_const_name(VALUE name)
Definition: symbol.c:1084
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1576
#define is_class_id(id)
Definition: symbol.h:41
static ID lookup_str_id(VALUE str)
Definition: symbol.c:509
static int is_special_global_name(const char *m, const char *e, rb_encoding *enc)
Definition: symbol.c:164
VALUE rb_eRuntimeError
Definition: error.c:761
#define ID_INSTANCE
Definition: id.h:34
int rb_is_class_id(ID id)
Definition: symbol.c:834
int rb_is_global_name(VALUE name)
Definition: symbol.c:1096
#define st_init_table_with_size
Definition: regint.h:177
VALUE rb_hash_delete_entry(VALUE hash, VALUE key)
Definition: hash.c:1112
static VALUE dsymbol_check(const VALUE sym)
Definition: symbol.c:493
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:2121
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:799
#define ID_SCOPE_SHIFT
Definition: id.h:31
#define ISALNUM(c)
Definition: ruby.h:2127
#define is_instance_sym(sym)
Definition: symbol.h:86
char ary[RSTRING_EMBED_LEN_MAX+1]
Definition: ruby.h:972
int rb_is_class_sym(VALUE sym)
Definition: symbol.c:876
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:6154
#define ISUPPER(c)
Definition: ruby.h:2125
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:102
#define OBJ_FREEZE(x)
Definition: ruby.h:1308
#define NOINLINE(x)
Definition: defines.h:46
#define DYNAMIC_ID_P(id)
Definition: symbol.h:17
Definition: util.c:833
#define is_attrset_id(id)
Definition: symbol.h:39
rb_id_serial_t last_id
Definition: symbol.c:63
#define RUBY_DTRACE_CREATE_HOOK(name, arg)
Definition: internal.h:1753
int rb_is_local_sym(VALUE sym)
Definition: symbol.c:900
int rb_str_hash_cmp(VALUE, VALUE)
Definition: string.c:2995
static const struct st_hash_type symhash
Definition: symbol.c:69
#define RSTRING_LEN(str)
Definition: ruby.h:978
const char * rb_id2name(ID id)
Definition: symbol.c:759
int rb_is_instance_name(VALUE name)
Definition: symbol.c:1102
VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:1003
#define TRUE
Definition: nkf.h:175
static ID intern_str(VALUE str, int mutable)
Definition: symbol.c:582
#define STATIC_SYM2ID(sym)
Definition: symbol.c:24
static int sym_check_asciionly(VALUE str)
Definition: symbol.c:428
void rb_fatal(const char *fmt,...)
Definition: error.c:2261
#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
#define tAREF
Definition: id.c:28
unsigned long VALUE
Definition: ruby.h:85
static VALUE result
Definition: nkf.c:40
#define RBASIC(obj)
Definition: ruby.h:1204
VALUE rb_obj_hide(VALUE obj)
Definition: object.c:51
#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:992
VALUE rb_sym_intern_ascii_cstr(const char *ptr)
Definition: symbol.c:1050
#define STATIC_SYM_P(x)
Definition: ruby.h:380
static ID next_id_base(void)
Definition: symbol.c:568
#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:9169
#define op_tbl_len(i)
Definition: symbol.c:35
void rb_gc_free_dsymbol(VALUE sym)
Definition: symbol.c:629
FUNC_MINIMIZED(VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc))
int rb_is_global_id(ID id)
Definition: symbol.c:840
VALUE rb_fstring(VALUE)
Definition: string.c:305
static struct symbols global_symbols
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:870
static VALUE get_id_entry(rb_id_serial_t num, const enum id_entry_type t)
Definition: symbol.c:341
VALUE rb_str_dup(VALUE)
Definition: string.c:1436
int rb_is_junk_id(ID id)
Definition: symbol.c:864
register unsigned int len
Definition: zonetab.h:51
#define RSTRING_PTR(str)
Definition: ruby.h:982
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:1038
VALUE rb_ident_hash_new(void)
Definition: hash.c:2808
#define is_local_id(id)
Definition: symbol.h:36
Definition: symbol.c:62
int rb_is_instance_sym(VALUE sym)
Definition: symbol.c:888
static int symbols_i(st_data_t key, st_data_t value, st_data_t arg)
Definition: symbol.c:774
static int rb_str_symname_type(VALUE name, unsigned int allowed_attrset)
Definition: symbol.c:317
#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:1955
#define is_junk_id(id)
Definition: symbol.h:42
#define FL_WB_PROTECTED
Definition: ruby.h:1216
VALUE rb_check_string_type(VALUE)
Definition: string.c:2164
int rb_is_attrset_name(VALUE name)
Definition: symbol.c:1108
#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:822
static int is_global_name_punct(const int c)
Definition: symbol.h:95
static int id_type(ID id)
Definition: symbol.h:45
#define UNLIKELY(x)
Definition: ffi_common.h:126
int rb_is_local_id(ID id)
Definition: symbol.c:858
#define is_class_sym(sym)
Definition: symbol.h:89
#define op_tbl_count
Definition: symbol.c:33
static VALUE lookup_id_str(ID id)
Definition: symbol.c:548
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:758
st_table * str_sym
Definition: symbol.c:64
const char * name
Definition: nkf.c:208
#define ID2SYM(x)
Definition: ruby.h:383
int rb_is_attrset_id(ID id)
Definition: symbol.c:852
#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:1123
static ID attrsetname_to_attr(VALUE name)
Definition: symbol.c:1074
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1305
static ID register_static_symid(ID, const char *, long, rb_encoding *)
Definition: symbol.c:404
#define is_notop_id(id)
Definition: symbol.h:35
RUBY_EXTERN VALUE rb_cSymbol
Definition: ruby.h:1908
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
st_index_t num_entries
Definition: st.h:86
Definition: id.h:167
WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type))
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1437
char * ptr
Definition: ruby.h:966
id_entry_type
Definition: symbol.c:56
#define ID_CLASS
Definition: id.h:38