variable.c


DEFINITIONS

This source file includes following functions.
  1. Init_var_tables
  2. fc_path
  3. fc_i
  4. find_class_path
  5. classname
  6. rb_mod_name
  7. rb_class_path
  8. rb_set_class_path
  9. rb_path2class
  10. rb_name_class
  11. rb_autoload_id
  12. rb_autoload
  13. rb_f_autoload
  14. rb_class2name
  15. rb_global_entry
  16. undef_getter
  17. undef_setter
  18. undef_marker
  19. val_getter
  20. val_setter
  21. val_marker
  22. var_getter
  23. var_setter
  24. var_marker
  25. readonly_setter
  26. mark_global_entry
  27. rb_gc_mark_global_tbl
  28. global_id
  29. rb_define_hooked_variable
  30. rb_define_variable
  31. rb_define_readonly_variable
  32. rb_define_virtual_variable
  33. rb_trace_eval
  34. rb_f_trace_var
  35. remove_trace
  36. rb_f_untrace_var
  37. rb_gvar_get
  38. trace_ev
  39. trace_en
  40. rb_gvar_set
  41. rb_gv_set
  42. rb_gv_get
  43. rb_gvar_defined
  44. gvar_i
  45. rb_f_global_variables
  46. rb_alias_variable
  47. rb_generic_ivar_table
  48. generic_ivar_get
  49. generic_ivar_set
  50. generic_ivar_defined
  51. generic_ivar_remove
  52. rb_mark_generic_ivar
  53. givar_mark_i
  54. givar_i
  55. rb_mark_generic_ivar_tbl
  56. rb_free_generic_ivar
  57. rb_copy_generic_ivar
  58. rb_ivar_get
  59. rb_ivar_set
  60. rb_ivar_defined
  61. ivar_i
  62. rb_obj_instance_variables
  63. rb_obj_remove_instance_variable
  64. top_const_get
  65. rb_const_get_at
  66. rb_autoload_load
  67. rb_const_get
  68. rb_mod_remove_const
  69. sv_i
  70. autoload_i
  71. rb_mod_const_at
  72. rb_mod_const_of
  73. list_i
  74. rb_const_list
  75. rb_mod_constants
  76. rb_const_defined_at
  77. rb_autoload_defined
  78. rb_const_defined
  79. mod_av_set
  80. rb_const_set
  81. rb_const_assign
  82. rb_define_const
  83. rb_define_global_const
  84. original_module
  85. cvar_override_check
  86. rb_cvar_set
  87. rb_cvar_get
  88. rb_cvar_defined
  89. rb_cv_set
  90. rb_cv_get
  91. rb_define_class_variable
  92. cv_i
  93. rb_mod_class_variables
  94. rb_mod_remove_cvar
  95. rb_iv_get
  96. rb_iv_set


   1  /**********************************************************************
   2  
   3    variable.c -
   4  
   5    $Author: matz $
   6    $Date: 2002/09/05 09:42:56 $
   7    created at: Tue Apr 19 23:55:15 JST 1994
   8  
   9    Copyright (C) 1993-2002 Yukihiro Matsumoto
  10    Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
  11    Copyright (C) 2000  Information-technology Promotion Agency, Japan
  12  
  13  **********************************************************************/
  14  
  15  #include "ruby.h"
  16  #include "env.h"
  17  #include "node.h"
  18  #include "st.h"
  19  #include "util.h"
  20  
  21  static st_table *rb_global_tbl;
  22  st_table *rb_class_tbl;
  23  
  24  void
  25  Init_var_tables()
  26  {
  27      rb_global_tbl = st_init_numtable();
  28      rb_class_tbl = st_init_numtable();
  29  }
  30  
  31  struct fc_result {
  32      ID name;
  33      VALUE klass;
  34      VALUE path;
  35      VALUE track;
  36      struct fc_result *prev;
  37  };
  38  
  39  static VALUE
  40  fc_path(fc, name)
  41      struct fc_result *fc;
  42      ID name;
  43  {
  44      VALUE path, tmp;
  45  
  46      path = rb_str_new2(rb_id2name(name));
  47      while (fc) {
  48          if (fc->track == rb_cObject) break;
  49          if (ROBJECT(fc->track)->iv_tbl &&
  50              st_lookup(ROBJECT(fc->track)->iv_tbl, rb_intern("__classpath__"), &tmp)) {
  51              tmp = rb_str_dup(tmp);
  52              rb_str_cat2(tmp, "::");
  53              rb_str_append(tmp, path);
  54  
  55              return tmp;
  56          }
  57          tmp = rb_str_new2(rb_id2name(fc->name));
  58          rb_str_cat2(tmp, "::");
  59          rb_str_append(tmp, path);
  60          path = tmp;
  61          fc = fc->prev;
  62      }
  63      return path;
  64  }
  65  
  66  static int
  67  fc_i(key, value, res)
  68      ID key;
  69      VALUE value;
  70      struct fc_result *res;
  71  {
  72      if (!rb_is_const_id(key)) return ST_CONTINUE;
  73  
  74      if (value == res->klass) {
  75          res->path = fc_path(res, key);
  76          return ST_STOP;
  77      }
  78      switch (TYPE(value)) {
  79        case T_MODULE:
  80        case T_CLASS:
  81          if (!RCLASS(value)->iv_tbl) return ST_CONTINUE;
  82          else {
  83              struct fc_result arg;
  84              struct fc_result *list;
  85  
  86              list = res;
  87              while (list) {
  88                  if (list->track == value) return ST_CONTINUE;
  89                  list = list->prev;
  90              }
  91  
  92              arg.name = key;
  93              arg.path = 0;
  94              arg.klass = res->klass;
  95              arg.track = value;
  96              arg.prev = res;
  97              st_foreach(RCLASS(value)->iv_tbl, fc_i, &arg);
  98              if (arg.path) {
  99                  res->path = arg.path;
 100                  return ST_STOP;
 101              }
 102          }
 103          break;
 104  
 105        default:
 106          break;
 107              
 108      }
 109      return ST_CONTINUE;
 110  }
 111  
 112  static VALUE
 113  find_class_path(klass)
 114      VALUE klass;
 115  {
 116      struct fc_result arg;
 117  
 118      arg.name = 0;
 119      arg.path = 0;
 120      arg.klass = klass;
 121      arg.track = rb_cObject;
 122      arg.prev = 0;
 123      if (RCLASS(rb_cObject)->iv_tbl) {
 124          st_foreach(RCLASS(rb_cObject)->iv_tbl, fc_i, &arg);
 125      }
 126      if (arg.path == 0) {
 127          st_foreach(rb_class_tbl, fc_i, &arg);
 128      }
 129      if (arg.path) {
 130          if (!ROBJECT(klass)->iv_tbl) {
 131              ROBJECT(klass)->iv_tbl = st_init_numtable();
 132          } 
 133          st_insert(ROBJECT(klass)->iv_tbl,rb_intern("__classpath__"),arg.path);
 134          return arg.path;
 135      }
 136      return Qnil;
 137  }
 138  
 139  static VALUE
 140  classname(klass)
 141      VALUE klass;
 142  {
 143      VALUE path = Qnil;
 144      ID classpath = rb_intern("__classpath__");
 145  
 146      if (TYPE(klass) == T_ICLASS) {
 147          klass = RBASIC(klass)->klass;
 148      }
 149      klass = rb_class_real(klass);
 150      if (!klass) klass = rb_cObject;
 151      if (ROBJECT(klass)->iv_tbl &&
 152          !st_lookup(ROBJECT(klass)->iv_tbl, classpath, &path)) {
 153          ID classid = rb_intern("__classid__");
 154  
 155          if (st_lookup(ROBJECT(klass)->iv_tbl, classid, &path)) {
 156              path = rb_str_new2(rb_id2name(SYM2ID(path)));
 157              st_insert(ROBJECT(klass)->iv_tbl, classpath, path);
 158              st_delete(RCLASS(klass)->iv_tbl, &classid, 0);
 159          }
 160      }
 161      if (NIL_P(path)) {
 162          path = find_class_path(klass);
 163          if (NIL_P(path)) {
 164              return 0;
 165          }
 166          return path;
 167      }
 168      if (TYPE(path) != T_STRING)
 169          rb_bug("class path is not set properly");
 170      return path;
 171  }
 172  
 173  VALUE
 174  rb_mod_name(mod)
 175      VALUE mod;
 176  {
 177      VALUE path = classname(mod);
 178  
 179      if (path) return rb_str_dup(path);
 180      return rb_str_new(0,0);
 181  }
 182  
 183  VALUE
 184  rb_class_path(klass)
 185      VALUE klass;
 186  {
 187      VALUE path = classname(klass);
 188  
 189      if (path) return path;
 190      else {
 191          VALUE str;
 192          char *s = "Class";
 193  
 194          if (TYPE(klass) == T_MODULE) {
 195              if (rb_obj_class(klass) == rb_cModule) {
 196                  s = "Module";
 197              }
 198              else {
 199                  s = rb_class2name(RBASIC(klass)->klass);
 200              }
 201          }
 202          str = rb_str_new(0, 2 + strlen(s) + 3 + 2 * SIZEOF_LONG + 1);
 203          sprintf(RSTRING(str)->ptr, "#<%s:0x%lx>", s, klass);
 204          RSTRING(str)->len = strlen(RSTRING(str)->ptr);
 205  
 206          return str;
 207      }
 208  }
 209  
 210  void
 211  rb_set_class_path(klass, under, name)
 212      VALUE klass, under;
 213      const char *name;
 214  {
 215      VALUE str;
 216  
 217      if (under == rb_cObject) {
 218          str = rb_str_new2(name);
 219      }
 220      else {
 221          str = rb_str_dup(rb_class_path(under));
 222          rb_str_cat2(str, "::");
 223          rb_str_cat2(str, name);
 224      }
 225      rb_iv_set(klass, "__classpath__", str);
 226  }
 227  
 228  VALUE
 229  rb_path2class(path)
 230      const char *path;
 231  {
 232      const char *pbeg, *p;
 233      ID id;
 234      VALUE c = rb_cObject;
 235  
 236      if (path[0] == '#') {
 237          rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
 238      }
 239      pbeg = p = path;
 240      while (*p) {
 241          VALUE str;
 242  
 243          while (*p && *p != ':') p++;
 244          str = rb_str_new(pbeg, p-pbeg);
 245          id = rb_intern(RSTRING(str)->ptr);
 246          if (p[0] == ':') {
 247              if (p[1] != ':') goto undefined_class;
 248              p += 2;
 249              pbeg = p;
 250          }
 251          if (!rb_const_defined(c, id)) {
 252            undefined_class:
 253              rb_raise(rb_eArgError, "undefined class/module %s", rb_id2name(id));
 254              rb_raise(rb_eArgError, "undefined class/module %s", path);
 255          }
 256          c = rb_const_get_at(c, id);
 257          switch (TYPE(c)) {
 258            case T_MODULE:
 259            case T_CLASS:
 260              break;
 261            default:
 262              rb_raise(rb_eTypeError, "%s does not refer class/module %d", path, TYPE(c));
 263          }
 264      }
 265  
 266      return c;
 267  }
 268  
 269  void
 270  rb_name_class(klass, id)
 271      VALUE klass;
 272      ID id;
 273  {
 274      rb_iv_set(klass, "__classid__", ID2SYM(id));
 275  }
 276  
 277  static st_table *autoload_tbl = 0;
 278  
 279  static void
 280  rb_autoload_id(id, filename)
 281      ID id;
 282      const char *filename;
 283  {
 284      rb_secure(4);
 285      if (!rb_is_const_id(id)) {
 286          rb_name_error(id, "autoload must be constant name");
 287      }
 288  
 289      if (!autoload_tbl) {
 290          autoload_tbl = st_init_numtable();
 291      }
 292      st_insert(autoload_tbl, id, strdup(filename));
 293  }
 294  
 295  void
 296  rb_autoload(klass, filename)
 297      const char *klass, *filename;
 298  {
 299      rb_autoload_id(rb_intern(klass), filename);
 300  }
 301  
 302  VALUE
 303  rb_f_autoload(obj, klass, file)
 304      VALUE obj, klass, file;
 305  {
 306      rb_autoload_id(rb_to_id(klass), StringValuePtr(file));
 307      return Qnil;
 308  }
 309  
 310  char *
 311  rb_class2name(klass)
 312      VALUE klass;
 313  {
 314      return RSTRING(rb_class_path(klass))->ptr;
 315  }
 316  
 317  struct trace_var {
 318      int removed;
 319      void (*func)();
 320      VALUE data;
 321      struct trace_var *next;
 322  };
 323  
 324  struct global_variable {
 325      int   counter;
 326      void *data;
 327      VALUE (*getter)();
 328      void  (*setter)();
 329      void  (*marker)();
 330      int block_trace;
 331      struct trace_var *trace;
 332  };
 333  
 334  struct global_entry {
 335      struct global_variable *var;
 336      ID id;
 337  };
 338  
 339  static VALUE undef_getter();
 340  static void  undef_setter();
 341  static void  undef_marker();
 342  
 343  static VALUE val_getter();
 344  static void  val_setter();
 345  static void  val_marker();
 346  
 347  static VALUE var_getter();
 348  static void  var_setter();
 349  static void  var_marker();
 350  
 351  struct global_entry*
 352  rb_global_entry(id)
 353      ID id;
 354  {
 355      struct global_entry *entry;
 356  
 357      if (!st_lookup(rb_global_tbl, id, &entry)) {
 358          struct global_variable *var;
 359          entry = ALLOC(struct global_entry);
 360          st_add_direct(rb_global_tbl, id, entry);
 361          var = ALLOC(struct global_variable);
 362          entry->id = id;
 363          entry->var = var;
 364          var->counter = 1;
 365          var->data = 0;
 366          var->getter = undef_getter;
 367          var->setter = undef_setter;
 368          var->marker = undef_marker;
 369  
 370          var->block_trace = 0;
 371          var->trace = 0;
 372      }
 373      return entry;
 374  }
 375  
 376  static VALUE
 377  undef_getter(id)
 378      ID id;
 379  {
 380      rb_warning("global variable `%s' not initialized", rb_id2name(id));
 381  
 382      return Qnil;
 383  }
 384  
 385  static void
 386  undef_setter(val, id, data, var)
 387      VALUE val;
 388      ID id;
 389      void *data;
 390      struct global_variable *var;
 391  {
 392      var->getter = val_getter;
 393      var->setter = val_setter;
 394      var->marker = val_marker;
 395  
 396      var->data = (void*)val;
 397  }
 398  
 399  static void
 400  undef_marker()
 401  {
 402  }
 403  
 404  static VALUE
 405  val_getter(id, val)
 406      ID id;
 407      VALUE val;
 408  {
 409      return val;
 410  }
 411  
 412  static void
 413  val_setter(val, id, data, var)
 414      VALUE val;
 415      ID id;
 416      void *data;
 417      struct global_variable *var;
 418  {
 419      var->data = (void*)val;
 420  }
 421  
 422  static void
 423  val_marker(data)
 424      VALUE data;
 425  {
 426      if (data) rb_gc_mark_maybe(data);
 427  }
 428  
 429  static VALUE
 430  var_getter(id, var)
 431      ID id;
 432      VALUE *var;
 433  {
 434      if (!var) return Qnil;
 435      return *var;
 436  }
 437  
 438  static void
 439  var_setter(val, id, var)
 440      VALUE val;
 441      ID id;
 442      VALUE *var;
 443  {
 444      *var = val;
 445  }
 446  
 447  static void
 448  var_marker(var)
 449      VALUE *var;
 450  {
 451      if (var) rb_gc_mark_maybe(*var);
 452  }
 453  
 454  static void
 455  readonly_setter(val, id, var)
 456      VALUE val;
 457      ID id;
 458      void *var;
 459  {
 460      rb_name_error(id, "can't set variable %s", rb_id2name(id));
 461  }
 462  
 463  static int
 464  mark_global_entry(key, entry)
 465      ID key;
 466      struct global_entry *entry;
 467  {
 468      struct trace_var *trace;
 469      struct global_variable *var = entry->var;
 470  
 471      (*var->marker)(var->data);
 472      trace = var->trace;
 473      while (trace) {
 474          if (trace->data) rb_gc_mark_maybe(trace->data);
 475          trace = trace->next;
 476      }
 477      return ST_CONTINUE;
 478  }
 479  
 480  void
 481  rb_gc_mark_global_tbl()
 482  {
 483      st_foreach(rb_global_tbl, mark_global_entry, 0);
 484  }
 485  
 486  static ID
 487  global_id(name)
 488      const char *name;
 489  {
 490      ID id;
 491  
 492      if (name[0] == '$') id = rb_intern(name);
 493      else {
 494          char *buf = ALLOCA_N(char, strlen(name)+2);
 495          buf[0] = '$';
 496          strcpy(buf+1, name);
 497          id = rb_intern(buf);
 498      }
 499      return id;
 500  }
 501  
 502  void
 503  rb_define_hooked_variable(name, var, getter, setter)
 504      const char  *name;
 505      VALUE *var;
 506      VALUE (*getter)();
 507      void  (*setter)();
 508  {
 509      struct global_variable *gvar;
 510      ID id = global_id(name);
 511  
 512      gvar = rb_global_entry(id)->var;
 513      gvar->data = (void*)var;
 514      gvar->getter = getter?getter:var_getter;
 515      gvar->setter = setter?setter:var_setter;
 516      gvar->marker = var_marker;
 517  }
 518  
 519  void
 520  rb_define_variable(name, var)
 521      const char  *name;
 522      VALUE *var;
 523  {
 524      rb_define_hooked_variable(name, var, 0, 0);
 525  }
 526  
 527  void
 528  rb_define_readonly_variable(name, var)
 529      const char  *name;
 530      VALUE *var;
 531  {
 532      rb_define_hooked_variable(name, var, 0, readonly_setter);
 533  }
 534  
 535  void
 536  rb_define_virtual_variable(name, getter, setter)
 537      const char  *name;
 538      VALUE (*getter)();
 539      void  (*setter)();
 540  {
 541      if (!getter) getter = val_getter;
 542      if (!setter) setter = readonly_setter;
 543      rb_define_hooked_variable(name, 0, getter, setter);
 544  }
 545  
 546  static void
 547  rb_trace_eval(cmd, val)
 548      VALUE cmd, val;
 549  {
 550      rb_eval_cmd(cmd, rb_ary_new3(1, val), 0);
 551  }
 552  
 553  VALUE
 554  rb_f_trace_var(argc, argv)
 555      int argc;
 556      VALUE *argv;
 557  {
 558      VALUE var, cmd;
 559      struct global_entry *entry;
 560      struct trace_var *trace;
 561  
 562      rb_secure(4);
 563      if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
 564          cmd = rb_f_lambda();
 565      }
 566      if (NIL_P(cmd)) {
 567          return rb_f_untrace_var(argc, argv);
 568      }
 569      entry = rb_global_entry(rb_to_id(var));
 570      if (OBJ_TAINTED(cmd)) {
 571          rb_raise(rb_eSecurityError, "Insecure: tainted variable trace");
 572      }
 573      trace = ALLOC(struct trace_var);
 574      trace->next = entry->var->trace;
 575      trace->func = rb_trace_eval;
 576      trace->data = cmd;
 577      trace->removed = 0;
 578      entry->var->trace = trace;
 579  
 580      return Qnil;
 581  }
 582  
 583  static void
 584  remove_trace(var)
 585      struct global_variable *var;
 586  {
 587      struct trace_var *trace = var->trace;
 588      struct trace_var t;
 589      struct trace_var *next;
 590  
 591      t.next = trace;
 592      trace = &t;
 593      while (trace->next) {
 594          next = trace->next;
 595          if (next->removed) {
 596              trace->next = next->next;
 597              free(next);
 598          }
 599          else {
 600              trace = next;
 601          }
 602      }
 603      var->trace = t.next;
 604  }
 605  
 606  VALUE
 607  rb_f_untrace_var(argc, argv)
 608      int argc;
 609      VALUE *argv;
 610  {
 611      VALUE var, cmd;
 612      ID id;
 613      struct global_entry *entry;
 614      struct trace_var *trace;
 615  
 616      rb_scan_args(argc, argv, "11", &var, &cmd);
 617      id = rb_to_id(var);
 618      if (!st_lookup(rb_global_tbl, id, &entry)) {
 619          rb_name_error(id, "undefined global variable %s", rb_id2name(id));
 620      }
 621  
 622      trace = entry->var->trace;
 623      if (NIL_P(cmd)) {
 624          VALUE ary = rb_ary_new();
 625  
 626          while (trace) {
 627              struct trace_var *next = trace->next;
 628              rb_ary_push(ary, (VALUE)trace->data);
 629              trace->removed = 1;
 630              trace = next;
 631          }
 632  
 633          if (!entry->var->block_trace) remove_trace(entry->var);
 634          return ary;
 635      }
 636      else {
 637          while (trace) {
 638              if (trace->data == cmd) {
 639                  trace->removed = 1;
 640                  if (!entry->var->block_trace) remove_trace(entry->var);
 641                  return rb_ary_new3(1, cmd);
 642              }
 643              trace = trace->next;
 644          }
 645      }
 646      return Qnil;
 647  }
 648  
 649  VALUE
 650  rb_gvar_get(entry)
 651      struct global_entry *entry;
 652  {
 653      struct global_variable *var = entry->var;
 654      return (*var->getter)(entry->id, var->data, var);
 655  }
 656  
 657  struct trace_data {
 658      struct trace_var *trace;
 659      VALUE val;
 660  };
 661      
 662  static VALUE
 663  trace_ev(data)
 664      struct trace_data *data;
 665  {
 666      struct trace_var *trace = data->trace;
 667  
 668      while (trace) {
 669          (*trace->func)(trace->data, data->val);
 670          trace = trace->next;
 671      }
 672      return Qnil;                /* not reached */
 673  }
 674  
 675  static VALUE
 676  trace_en(var)
 677      struct global_variable *var;
 678  {
 679      var->block_trace = 0;
 680      remove_trace(var);
 681      return Qnil;                /* not reached */
 682  }
 683  
 684  VALUE
 685  rb_gvar_set(entry, val)
 686      struct global_entry *entry;
 687      VALUE val;
 688  {
 689      struct trace_data trace;
 690      struct global_variable *var = entry->var;
 691  
 692      if (rb_safe_level() >= 4)
 693          rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
 694      (*var->setter)(val, entry->id, var->data, var);
 695  
 696      if (var->trace && !var->block_trace) {
 697          var->block_trace = 1;
 698          trace.trace = var->trace;
 699          trace.val = val;
 700          rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
 701      }
 702      return val;
 703  }
 704  
 705  VALUE
 706  rb_gv_set(name, val)
 707      const char *name;
 708      VALUE val;
 709  {
 710      struct global_entry *entry;
 711  
 712      entry = rb_global_entry(global_id(name));
 713      return rb_gvar_set(entry, val);
 714  }
 715  
 716  VALUE
 717  rb_gv_get(name)
 718      const char *name;
 719  {
 720      struct global_entry *entry;
 721  
 722      entry = rb_global_entry(global_id(name));
 723      return rb_gvar_get(entry);
 724  }
 725  
 726  VALUE
 727  rb_gvar_defined(entry)
 728      struct global_entry *entry;
 729  {
 730      if (entry->var->getter == undef_getter) return Qfalse;
 731      return Qtrue;
 732  }
 733  
 734  static int
 735  gvar_i(key, entry, ary)
 736      ID key;
 737      struct global_entry *entry;
 738      VALUE ary;
 739  {
 740      rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
 741      return ST_CONTINUE;
 742  }
 743  
 744  VALUE
 745  rb_f_global_variables()
 746  {
 747      VALUE ary = rb_ary_new();
 748      char buf[4];
 749      char *s = "&`'+123456789";
 750  
 751      st_foreach(rb_global_tbl, gvar_i, ary);
 752      if (!NIL_P(rb_backref_get())) {
 753          while (*s) {
 754              sprintf(buf, "$%c", *s++);
 755              rb_ary_push(ary, rb_str_new2(buf));
 756          }
 757      }
 758      return ary;
 759  }
 760  
 761  void
 762  rb_alias_variable(name1, name2)
 763      ID name1;
 764      ID name2;
 765  {
 766      struct global_entry *entry1, *entry2;
 767  
 768      if (rb_safe_level() >= 4)
 769          rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
 770  
 771      entry2 = rb_global_entry(name2);
 772      if (!st_lookup(rb_global_tbl, name1, &entry1)) {
 773          entry1 = ALLOC(struct global_entry);
 774          st_add_direct(rb_global_tbl, name1, entry1);
 775          entry1->id = name1;
 776      }
 777      else if (entry1->var != entry2->var) {
 778          struct global_variable *var = entry1->var;
 779          if (var->block_trace) {
 780              rb_raise(rb_eRuntimeError, "can't alias in tracer");
 781          }
 782          var->counter--;
 783          if (var->counter == 0) {
 784              struct trace_var *trace = var->trace;
 785              while (trace) {
 786                  struct trace_var *next = trace->next;
 787                  free(trace);
 788                  trace = next;
 789              }
 790              free(var);
 791          }
 792      }
 793      else {
 794          return;
 795      }
 796      entry2->var->counter++;
 797      entry1->var = entry2->var;
 798  }
 799  
 800  static int special_generic_ivar = 0;
 801  static st_table *generic_iv_tbl;
 802  
 803  st_table*
 804  rb_generic_ivar_table(obj)
 805      VALUE obj;
 806  {
 807      st_table *tbl;
 808  
 809      if (!generic_iv_tbl) return 0;
 810      if (!st_lookup(generic_iv_tbl, obj, &tbl)) return 0;
 811      return tbl;
 812  }
 813  
 814  static VALUE
 815  generic_ivar_get(obj, id)
 816      VALUE obj;
 817      ID id;
 818  {
 819      st_table *tbl;
 820      VALUE val;
 821  
 822      if (!generic_iv_tbl) return Qnil;
 823      if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qnil;
 824      if (st_lookup(tbl, id, &val)) {
 825          return val;
 826      }
 827      return Qnil;
 828  }
 829  
 830  static void
 831  generic_ivar_set(obj, id, val)
 832      VALUE obj;
 833      ID id;
 834      VALUE val;
 835  {
 836      st_table *tbl;
 837  
 838      if (rb_special_const_p(obj)) {
 839          special_generic_ivar = 1;
 840      }
 841      if (!generic_iv_tbl) {
 842          generic_iv_tbl = st_init_numtable();
 843      }
 844  
 845      if (!st_lookup(generic_iv_tbl, obj, &tbl)) {
 846          FL_SET(obj, FL_EXIVAR);
 847          tbl = st_init_numtable();
 848          st_add_direct(generic_iv_tbl, obj, tbl);
 849          st_add_direct(tbl, id, val);
 850          return;
 851      }
 852      st_insert(tbl, id, val);
 853  }
 854  
 855  static VALUE
 856  generic_ivar_defined(obj, id)
 857      VALUE obj;
 858      ID id;
 859  {
 860      st_table *tbl;
 861      VALUE val;
 862  
 863      if (!generic_iv_tbl) return Qfalse;
 864      if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qfalse;
 865      if (st_lookup(tbl, id, &val)) {
 866          return Qtrue;
 867      }
 868      return Qfalse;
 869  }
 870  
 871  static int
 872  generic_ivar_remove(obj, id, valp)
 873      VALUE obj;
 874      ID id;
 875      VALUE *valp;
 876  {
 877      st_table *tbl;
 878      int status;
 879  
 880      if (!generic_iv_tbl) return 0;
 881      if (!st_lookup(generic_iv_tbl, obj, &tbl)) return 0;
 882      status = st_delete(tbl, &id, valp);
 883      if (tbl->num_entries == 0) {
 884          st_delete(generic_iv_tbl, &obj, &tbl);
 885          st_free_table(tbl);
 886      }
 887      return status;
 888  }
 889  
 890  void
 891  rb_mark_generic_ivar(obj)
 892      VALUE obj;
 893  {
 894      st_table *tbl;
 895  
 896      if (!generic_iv_tbl) return;
 897      if (st_lookup(generic_iv_tbl, obj, &tbl)) {
 898          rb_mark_tbl(tbl);
 899      }
 900  }
 901  
 902  static int
 903  givar_mark_i(key, value)
 904      ID key;
 905      VALUE value;
 906  {
 907      rb_gc_mark(value);
 908      return ST_CONTINUE;
 909  }
 910  
 911  static int
 912  givar_i(obj, tbl)
 913      VALUE obj;
 914      st_table *tbl;
 915  {
 916      if (rb_special_const_p(obj)) {
 917          st_foreach(tbl, givar_mark_i, 0);
 918      }
 919      return ST_CONTINUE;
 920  }
 921  
 922  void
 923  rb_mark_generic_ivar_tbl()
 924  {
 925      if (!generic_iv_tbl) return;
 926      if (special_generic_ivar == 0) return;
 927      st_foreach(generic_iv_tbl, givar_i, 0);
 928  }
 929  
 930  void
 931  rb_free_generic_ivar(obj)
 932      VALUE obj;
 933  {
 934      st_table *tbl;
 935  
 936      if (st_delete(generic_iv_tbl, &obj, &tbl))
 937          st_free_table(tbl);
 938  }
 939  
 940  void
 941  rb_copy_generic_ivar(clone, obj)
 942      VALUE clone, obj;
 943  {
 944      st_table *tbl;
 945  
 946      if (!generic_iv_tbl) return;
 947      if (st_lookup(generic_iv_tbl, obj, &tbl)) {
 948          st_table *old;
 949  
 950          if (st_lookup(generic_iv_tbl, clone, &old)) {
 951              st_free_table(old);
 952              st_insert(generic_iv_tbl, clone, st_copy(tbl));
 953          }
 954          else {
 955              st_add_direct(generic_iv_tbl, clone, st_copy(tbl));
 956          }
 957      }
 958  }
 959  
 960  VALUE
 961  rb_ivar_get(obj, id)
 962      VALUE obj;
 963      ID id;
 964  {
 965      VALUE val;
 966  
 967      switch (TYPE(obj)) {
 968        case T_OBJECT:
 969        case T_CLASS:
 970        case T_MODULE:
 971          if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val))
 972              return val;
 973          break;
 974        default:
 975          if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
 976              return generic_ivar_get(obj, id);
 977          break;
 978      }
 979      rb_warning("instance variable %s not initialized", rb_id2name(id));
 980  
 981      return Qnil;
 982  }
 983  
 984  VALUE
 985  rb_ivar_set(obj, id, val)
 986      VALUE obj;
 987      ID id;
 988      VALUE val;
 989  {
 990      if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
 991          rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
 992      if (OBJ_FROZEN(obj)) rb_error_frozen("object");
 993      switch (TYPE(obj)) {
 994        case T_OBJECT:
 995        case T_CLASS:
 996        case T_MODULE:
 997          if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable();
 998          st_insert(ROBJECT(obj)->iv_tbl, id, val);
 999          break;
1000        default:
1001          generic_ivar_set(obj, id, val);
1002          break;
1003      }
1004      return val;
1005  }
1006  
1007  VALUE
1008  rb_ivar_defined(obj, id)
1009      VALUE obj;
1010      ID id;
1011  {
1012      switch (TYPE(obj)) {
1013        case T_OBJECT:
1014        case T_CLASS:
1015        case T_MODULE:
1016          if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0))
1017              return Qtrue;
1018          break;
1019        default:
1020          if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
1021              return generic_ivar_defined(obj, id);
1022          break;
1023      }
1024      return Qfalse;
1025  }
1026  
1027  static int
1028  ivar_i(key, entry, ary)
1029      ID key;
1030      struct global_entry *entry;
1031      VALUE ary;
1032  {
1033      if (rb_is_instance_id(key)) {
1034          rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
1035      }
1036      return ST_CONTINUE;
1037  }
1038  
1039  VALUE
1040  rb_obj_instance_variables(obj)
1041      VALUE obj;
1042  {
1043      VALUE ary;
1044  
1045      ary = rb_ary_new();
1046      switch (TYPE(obj)) {
1047        case T_OBJECT:
1048        case T_CLASS:
1049        case T_MODULE:
1050          if (ROBJECT(obj)->iv_tbl) {
1051              st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, ary);
1052          }
1053          break;
1054        default:
1055          if (!generic_iv_tbl) break;
1056          if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
1057              st_table *tbl;
1058  
1059              if (st_lookup(generic_iv_tbl, obj, &tbl)) {
1060                  st_foreach(tbl, ivar_i, ary);
1061              }
1062          }
1063          break;
1064      }
1065      return ary;
1066  }
1067  
1068  VALUE
1069  rb_obj_remove_instance_variable(obj, name)
1070      VALUE obj, name;
1071  {
1072      VALUE val = Qnil;
1073      ID id = rb_to_id(name);
1074  
1075      if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
1076          rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
1077      if (OBJ_FROZEN(obj)) rb_error_frozen("object");
1078      if (!rb_is_instance_id(id)) {
1079          rb_name_error(id, "`%s' is not an instance variable", rb_id2name(id));
1080      }
1081  
1082      switch (TYPE(obj)) {
1083        case T_OBJECT:
1084        case T_CLASS:
1085        case T_MODULE:
1086          if (ROBJECT(obj)->iv_tbl && st_delete(ROBJECT(obj)->iv_tbl, &id, &val)) {
1087              return val;
1088          }
1089          break;
1090        default:
1091          if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
1092              if (generic_ivar_remove(obj, id, &val)) {
1093                  return val;
1094              }
1095          }
1096          break;
1097      }
1098      rb_name_error(id, "instance variable %s not defined", rb_id2name(id));
1099      return Qnil;                /* not reached */
1100  }
1101  
1102  static int
1103  top_const_get(id, klassp)
1104      ID id;
1105      VALUE *klassp;
1106  {
1107      /* pre-defined class */
1108      if (st_lookup(rb_class_tbl, id, klassp)) return Qtrue;
1109  
1110      /* autoload */
1111      if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
1112          rb_autoload_load(id);
1113          *klassp = rb_const_get(rb_cObject, id);
1114          return Qtrue;
1115      }
1116      return Qfalse;
1117  }
1118  
1119  VALUE
1120  rb_const_get_at(klass, id)
1121      VALUE klass;
1122      ID id;
1123  {
1124      VALUE value;
1125  
1126      if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) {
1127          return value;
1128      }
1129      if (klass == rb_cObject && top_const_get(id, &value)) {
1130          return value;
1131      }
1132      rb_name_error(id, "uninitialized constant %s::%s",
1133                    RSTRING(rb_class_path(klass))->ptr,
1134                    rb_id2name(id));
1135      return Qnil;                /* not reached */
1136  }
1137  
1138  void
1139  rb_autoload_load(id)
1140      ID id;
1141  {
1142      char *modname;
1143      VALUE module;
1144  
1145      st_delete(autoload_tbl, &id, &modname);
1146      if (rb_provided(modname)) {
1147          free(modname);
1148          return;
1149      }
1150      module = rb_str_new2(modname);
1151      free(modname);
1152      FL_UNSET(module, FL_TAINT);
1153      rb_f_require(Qnil, module);
1154  }
1155  
1156  VALUE
1157  rb_const_get(klass, id)
1158      VALUE klass;
1159      ID id;
1160  {
1161      VALUE value, tmp;
1162      int mod_retry = 0;
1163  
1164      tmp = klass;
1165    retry:
1166      while (tmp) {
1167          if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
1168              return value;
1169          }
1170          if (tmp == rb_cObject && top_const_get(id, &value)) return value;
1171          tmp = RCLASS(tmp)->super;
1172      }
1173      if (!mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
1174          mod_retry = 1;
1175          tmp = rb_cObject;
1176          goto retry;
1177      }
1178  
1179      /* Uninitialized constant */
1180      if (klass && klass != rb_cObject) {
1181          rb_name_error(id, "uninitialized constant %s at %s",
1182                        rb_id2name(id),
1183                        RSTRING(rb_class_path(klass))->ptr);
1184      }
1185      else { /* global_uninitialized */
1186          rb_name_error(id, "uninitialized constant %s",rb_id2name(id));
1187      }
1188      return Qnil;                /* not reached */
1189  }
1190  
1191  VALUE
1192  rb_mod_remove_const(mod, name)
1193      VALUE mod, name;
1194  {
1195      ID id = rb_to_id(name);
1196      VALUE val;
1197  
1198      if (!rb_is_const_id(id)) {
1199          rb_name_error(id, "`%s' is not constant", rb_id2name(id));
1200      }
1201      if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
1202          rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
1203      if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
1204  
1205      if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) {
1206          return val;
1207      }
1208      if (rb_const_defined_at(mod, id)) {
1209          rb_name_error(id, "cannot remove %s::%s", 
1210                   rb_class2name(mod), rb_id2name(id));
1211      }
1212      rb_name_error(id, "constant %s::%s not defined", 
1213                    rb_class2name(mod), rb_id2name(id));
1214      return Qnil;                /* not reached */
1215  }
1216  
1217  static int
1218  sv_i(key, value, tbl)
1219      ID key;
1220      VALUE value;
1221      st_table *tbl;
1222  {
1223      if (rb_is_const_id(key)) {
1224          if (!st_lookup(tbl, key, 0)) {
1225              st_insert(tbl, key, key);
1226          }
1227      }
1228      return ST_CONTINUE;
1229  }
1230  
1231  static int
1232  autoload_i(key, name, tbl)
1233      ID key;
1234      const char *name;
1235      st_table *tbl;
1236  {
1237      if (!st_lookup(tbl, key, 0)) {
1238          st_insert(tbl, key, key);
1239      }
1240      return ST_CONTINUE;
1241  }
1242  
1243  void*
1244  rb_mod_const_at(mod, data)
1245      VALUE mod;
1246      void *data;
1247  {
1248      st_table *tbl = data;
1249      if (!tbl) {
1250          tbl = st_init_numtable();
1251      }
1252      if (RCLASS(mod)->iv_tbl) {
1253          st_foreach(RCLASS(mod)->iv_tbl, sv_i, tbl);
1254      }
1255      if ((VALUE)mod == rb_cObject) {
1256          st_foreach(rb_class_tbl, sv_i, tbl);
1257          if (autoload_tbl) {
1258              st_foreach(autoload_tbl, autoload_i, tbl);
1259          }
1260      }
1261      return tbl;
1262  }
1263  
1264  void*
1265  rb_mod_const_of(mod, data)
1266      VALUE mod;
1267      void *data;
1268  {
1269      for (;;) {
1270          data = rb_mod_const_at(mod, data);
1271          mod = RCLASS(mod)->super;
1272          if (!mod) break;
1273      }
1274      return data;
1275  }
1276  
1277  static int
1278  list_i(key, value, ary)
1279      ID key, value;
1280      VALUE ary;
1281  {
1282      rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
1283      return ST_CONTINUE;
1284  }
1285  
1286  VALUE
1287  rb_const_list(data)
1288      void *data;
1289  {
1290      st_table *tbl = data;
1291      VALUE ary;
1292  
1293      if (!tbl) return rb_ary_new2(0);
1294      ary = rb_ary_new2(tbl->num_entries);
1295      st_foreach(tbl, list_i, ary);
1296      st_free_table(tbl);
1297  
1298      return ary;
1299  }
1300  
1301  VALUE
1302  rb_mod_constants(mod)
1303      VALUE mod;
1304  {
1305      return rb_const_list(rb_mod_const_of(mod, 0));
1306  }
1307  
1308  int
1309  rb_const_defined_at(klass, id)
1310      VALUE klass;
1311      ID id;
1312  {
1313      if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
1314          return Qtrue;
1315      }
1316      if (klass == rb_cObject) {
1317          return rb_const_defined(klass, id);
1318      }
1319      return Qfalse;
1320  }
1321  
1322  int
1323  rb_autoload_defined(id)
1324      ID id;
1325  {
1326      if (autoload_tbl && st_lookup(autoload_tbl, id, 0))
1327          return Qtrue;
1328      return Qfalse;
1329  }
1330  
1331  int
1332  rb_const_defined(klass, id)
1333      VALUE klass;
1334      ID id;
1335  {
1336      VALUE tmp = klass;
1337  
1338      while (tmp) {
1339          if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
1340              return Qtrue;
1341          }
1342          tmp = RCLASS(tmp)->super;
1343      }
1344      if (BUILTIN_TYPE(klass) == T_MODULE) {
1345          return rb_const_defined(rb_cObject, id);
1346      }
1347      if (st_lookup(rb_class_tbl, id, 0))
1348          return Qtrue;
1349      return rb_autoload_defined(id);
1350  }
1351  
1352  static void
1353  mod_av_set(klass, id, val, isconst)
1354      VALUE klass;
1355      ID id;
1356      VALUE val;
1357      int isconst;
1358  {
1359      char *dest = isconst ? "constant" : "class variable";
1360  
1361      if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4)
1362          rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
1363      if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
1364      if (!RCLASS(klass)->iv_tbl) {
1365          RCLASS(klass)->iv_tbl = st_init_numtable();
1366      }
1367      else if (isconst) {
1368          if (st_lookup(RCLASS(klass)->iv_tbl, id, 0) ||
1369              (klass == rb_cObject && st_lookup(rb_class_tbl, id, 0))) {
1370              rb_warn("already initialized %s %s", dest, rb_id2name(id));
1371          }
1372      }
1373  
1374      st_insert(RCLASS(klass)->iv_tbl, id, val);
1375  }
1376  
1377  void
1378  rb_const_set(klass, id, val)
1379      VALUE klass;
1380      ID id;
1381      VALUE val;
1382  {
1383      mod_av_set(klass, id, val, Qtrue);
1384  }
1385  
1386  void
1387  rb_const_assign(klass, id, val)
1388      VALUE klass;
1389      ID id;
1390      VALUE val;
1391  {
1392      VALUE tmp = klass;
1393      
1394      while (tmp) {
1395          if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
1396              st_insert(RCLASS(tmp)->iv_tbl, id, val);
1397              return;
1398          }
1399          tmp = RCLASS(tmp)->super;
1400      }
1401      /* pre-defined class */
1402      if (st_lookup(rb_class_tbl, id, 0)) {
1403          st_delete(rb_class_tbl, &id, 0);
1404          st_insert(RCLASS(rb_cObject)->iv_tbl, id, val);
1405          return;
1406      }
1407  
1408      /* autoload */
1409      if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
1410          char *modname;
1411  
1412          st_delete(autoload_tbl, &id, &modname);
1413          free(modname);
1414          st_insert(RCLASS(rb_cObject)->iv_tbl, id, val);
1415          return;
1416      }
1417  
1418      /* Uninitialized constant */
1419      if (klass && klass != rb_cObject)
1420          rb_name_error(id, "uninitialized constant %s::%s",
1421                        RSTRING(rb_class_path(klass))->ptr,
1422                        rb_id2name(id));
1423      else {
1424          rb_name_error(id, "uninitialized constant %s",rb_id2name(id));
1425      }
1426  }
1427  
1428  void
1429  rb_define_const(klass, name, val)
1430      VALUE klass;
1431      const char *name;
1432      VALUE val;
1433  {
1434      ID id = rb_intern(name);
1435  
1436      if (klass == rb_cObject) {
1437          rb_secure(4);
1438      }
1439      rb_const_set(klass, id, val);
1440  }
1441  
1442  void
1443  rb_define_global_const(name, val)
1444      const char *name;
1445      VALUE val;
1446  {
1447      rb_define_const(rb_cObject, name, val);
1448  }
1449  
1450  static VALUE
1451  original_module(c)
1452      VALUE c;
1453  {
1454      if (TYPE(c) == T_ICLASS)
1455          return RBASIC(c)->klass;
1456      return c;
1457  }
1458  
1459  static void
1460  cvar_override_check(id, a)
1461      VALUE a;
1462  {
1463      VALUE base = original_module(a);
1464  
1465      a = RCLASS(a)->super;
1466      while (a) {
1467          if (RCLASS(a)->iv_tbl) {
1468              if (st_lookup(RCLASS(a)->iv_tbl,id,0)) {
1469                  rb_warning("class variable %s of %s is overridden by %s",
1470                             rb_id2name(id), rb_class2name(original_module(a)),
1471                             rb_class2name(base));
1472              }
1473          }
1474          a = RCLASS(a)->super;
1475      }
1476  }
1477  
1478  void
1479  rb_cvar_set(klass, id, val, warn)
1480      VALUE klass;
1481      ID id;
1482      VALUE val;
1483      int warn;
1484  {
1485      VALUE tmp;
1486  
1487      tmp = klass;
1488      while (tmp) {
1489          if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
1490              if (OBJ_FROZEN(tmp)) rb_error_frozen("class/module");
1491              if (!OBJ_TAINTED(tmp) && rb_safe_level() >= 4)
1492                  rb_raise(rb_eSecurityError, "Insecure: can't modify class variable");
1493              if (warn && RTEST(ruby_verbose) && klass != tmp) {
1494                  rb_warning("already initialized class variable %s", rb_id2name(id));
1495              }
1496              st_insert(RCLASS(tmp)->iv_tbl,id,val);
1497              if (RTEST(ruby_verbose)) {
1498                  cvar_override_check(id, tmp);
1499              }
1500              return;
1501          }
1502          tmp = RCLASS(tmp)->super;
1503      }
1504  
1505      mod_av_set(klass, id, val, Qfalse);
1506  }
1507  
1508  VALUE
1509  rb_cvar_get(klass, id)
1510      VALUE klass;
1511      ID id;
1512  {
1513      VALUE value;
1514      VALUE tmp;
1515  
1516      tmp = klass;
1517      while (tmp) {
1518          if (RCLASS(tmp)->iv_tbl) {
1519              if (st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
1520                  if (RTEST(ruby_verbose)) {
1521                      cvar_override_check(id, tmp);
1522                  }
1523                  return value;
1524              }
1525          }
1526          tmp = RCLASS(tmp)->super;
1527      }
1528  
1529      rb_name_error(id,"uninitialized class variable %s in %s",
1530                    rb_id2name(id), rb_class2name(klass));
1531      return Qnil;                /* not reached */
1532  }
1533  
1534  VALUE
1535  rb_cvar_defined(klass, id)
1536      VALUE klass;
1537      ID id;
1538  {
1539      VALUE tmp;
1540  
1541      tmp = klass;
1542      while (tmp) {
1543          if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
1544              return Qtrue;
1545          }
1546          tmp = RCLASS(tmp)->super;
1547      }
1548  
1549      return Qfalse;
1550  }
1551  
1552  void
1553  rb_cv_set(klass, name, val)
1554      VALUE klass;
1555      const char *name;
1556      VALUE val;
1557  {
1558      ID id = rb_intern(name);
1559      if (!rb_is_class_id(id)) {
1560          rb_name_error(id, "wrong class variable name %s", name);
1561      }
1562      rb_cvar_set(klass, id, val, Qfalse);
1563  }
1564  
1565  VALUE
1566  rb_cv_get(klass, name)
1567      VALUE klass;
1568      const char *name;
1569  {
1570      ID id = rb_intern(name);
1571      if (!rb_is_class_id(id)) {
1572          rb_name_error(id, "wrong class variable name %s", name);
1573      }
1574      return rb_cvar_get(klass, id);
1575  }
1576  
1577  void
1578  rb_define_class_variable(klass, name, val)
1579      VALUE klass;
1580      const char *name;
1581      VALUE val;
1582  {
1583      ID id = rb_intern(name);
1584  
1585      if (!rb_is_class_id(id)) {
1586          rb_name_error(id, "wrong class variable name %s", name);
1587      }
1588      rb_cvar_set(klass, id, val, Qtrue);
1589  }
1590  
1591  static int
1592  cv_i(key, value, ary)
1593      ID key;
1594      VALUE value;
1595      VALUE ary;
1596  {
1597      if (rb_is_class_id(key)) {
1598          VALUE kval = rb_str_new2(rb_id2name(key));
1599          if (!rb_ary_includes(ary, kval)) {
1600              rb_ary_push(ary, kval);
1601          }
1602      }
1603      return ST_CONTINUE;
1604  }
1605  
1606  VALUE
1607  rb_mod_class_variables(obj)
1608      VALUE obj;
1609  {
1610      VALUE ary = rb_ary_new();
1611  
1612      for (;;) {
1613          if (RCLASS(obj)->iv_tbl) {
1614              st_foreach(RCLASS(obj)->iv_tbl, cv_i, ary);
1615          }
1616          obj = RCLASS(obj)->super;
1617          if (!obj) break;
1618      }
1619      return ary;
1620  }
1621  
1622  VALUE
1623  rb_mod_remove_cvar(mod, name)
1624      VALUE mod, name;
1625  {
1626      ID id = rb_to_id(name);
1627      VALUE val;
1628  
1629      if (!rb_is_class_id(id)) {
1630          rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
1631      }
1632      if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
1633          rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
1634      if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
1635  
1636      if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) {
1637          return val;
1638      }
1639      if (rb_cvar_defined(mod, id)) {
1640          rb_name_error(id, "cannot remove %s for %s", 
1641                   rb_id2name(id), rb_class2name(mod));
1642      }
1643      rb_name_error(id, "class variable %s not defined for %s",
1644                    rb_id2name(id), rb_class2name(mod));
1645      return Qnil;                /* not reached */
1646  }
1647  
1648  VALUE
1649  rb_iv_get(obj, name)
1650      VALUE obj;
1651      const char *name;
1652  {
1653      ID id = rb_intern(name);
1654  
1655      return rb_ivar_get(obj, id);
1656  }
1657  
1658  VALUE
1659  rb_iv_set(obj, name, val)
1660      VALUE obj;
1661      const char *name;
1662      VALUE val;
1663  {
1664      ID id = rb_intern(name);
1665  
1666      return rb_ivar_set(obj, id, val);
1667  }