hash.c


DEFINITIONS

This source file includes following functions.
  1. rb_hash_modify
  2. rb_hash_freeze
  3. rb_hash
  4. eql
  5. rb_any_cmp
  6. rb_any_hash
  7. rb_hash_foreach_iter
  8. rb_hash_foreach_call
  9. rb_hash_foreach_ensure
  10. rb_hash_foreach
  11. rb_hash_s_alloc
  12. rb_hash_new
  13. rb_hash_initialize
  14. rb_hash_s_create
  15. to_hash
  16. rb_hash_rehash_i
  17. rb_hash_rehash
  18. rb_hash_aref
  19. rb_hash_fetch
  20. rb_hash_default
  21. rb_hash_set_default
  22. rb_hash_default_proc
  23. index_i
  24. rb_hash_index
  25. rb_hash_indexes
  26. rb_hash_delete
  27. shift_i
  28. rb_hash_shift
  29. delete_if_i
  30. rb_hash_delete_if
  31. rb_hash_reject_bang
  32. rb_hash_reject
  33. select_i
  34. rb_hash_select
  35. clear_i
  36. rb_hash_clear
  37. rb_hash_aset
  38. replace_i
  39. rb_hash_become
  40. rb_hash_size
  41. rb_hash_empty_p
  42. each_value_i
  43. rb_hash_each_value
  44. each_key_i
  45. rb_hash_each_key
  46. each_pair_i
  47. rb_hash_each_pair
  48. to_a_i
  49. rb_hash_to_a
  50. rb_hash_sort
  51. inspect_i
  52. inspect_hash
  53. rb_hash_inspect
  54. to_s_hash
  55. rb_hash_to_s
  56. rb_hash_to_hash
  57. keys_i
  58. rb_hash_keys
  59. values_i
  60. rb_hash_values
  61. rb_hash_has_key
  62. rb_hash_search_value
  63. rb_hash_has_value
  64. equal_i
  65. rb_hash_equal
  66. rb_hash_invert_i
  67. rb_hash_invert
  68. rb_hash_update_i
  69. rb_hash_update_block_i
  70. rb_hash_update
  71. env_delete
  72. env_delete_m
  73. rb_f_getenv
  74. env_fetch
  75. path_tainted_p
  76. rb_env_path_tainted
  77. envix
  78. ruby_setenv
  79. ruby_unsetenv
  80. env_aset
  81. env_keys
  82. env_each_key
  83. env_values
  84. env_each_value
  85. env_each
  86. env_reject_bang
  87. env_delete_if
  88. env_select
  89. env_to_s
  90. env_inspect
  91. env_to_a
  92. env_none
  93. env_size
  94. env_empty_p
  95. env_has_key
  96. env_has_value
  97. env_index
  98. env_indexes
  99. env_to_hash
  100. env_reject
  101. Init_Hash


   1  /**********************************************************************
   2  
   3    hash.c -
   4  
   5    $Author: matz $
   6    $Date: 2002/09/03 05:20:06 $
   7    created at: Mon Nov 22 18:51:18 JST 1993
   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 "st.h"
  17  #include "util.h"
  18  #include "rubysig.h"
  19  
  20  #define HASH_DELETED  FL_USER1
  21  #define HASH_PROC_DEFAULT FL_USER2
  22  
  23  static void
  24  rb_hash_modify(hash)
  25      VALUE hash;
  26  {
  27      if (!RHASH(hash)->tbl) rb_raise(rb_eTypeError, "uninitialized Hash");
  28      if (OBJ_FROZEN(hash)) rb_error_frozen("hash");
  29      if (!OBJ_TAINTED(hash) && rb_safe_level() >= 4)
  30          rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
  31  }
  32  
  33  VALUE
  34  rb_hash_freeze(hash)
  35      VALUE hash;
  36  {
  37      return rb_obj_freeze(hash);
  38  }
  39  
  40  VALUE rb_cHash;
  41  
  42  static VALUE envtbl;
  43  static ID id_hash, id_yield, id_default;
  44  
  45  VALUE
  46  rb_hash(obj)
  47      VALUE obj;
  48  {
  49      return rb_funcall(obj, id_hash, 0);
  50  }
  51  
  52  static VALUE
  53  eql(args)
  54      VALUE *args;
  55  {
  56      return (VALUE)rb_eql(args[0], args[1]);
  57  }
  58  
  59  static int
  60  rb_any_cmp(a, b)
  61      VALUE a, b;
  62  {
  63      VALUE args[2];
  64      if (FIXNUM_P(a) && FIXNUM_P(b)) {
  65          return a != b;
  66      }
  67      if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString &&
  68          TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
  69          return rb_str_cmp(a, b);
  70      }
  71      if (SYMBOL_P(a) && SYMBOL_P(b)) {
  72          return a != b;
  73      }
  74      if (a == Qundef || b == Qundef) return -1;
  75  
  76      args[0] = a;
  77      args[1] = b;
  78      return !rb_with_disable_interrupt(eql, (VALUE)args);
  79  }
  80  
  81  static int
  82  rb_any_hash(a)
  83      VALUE a;
  84  {
  85      VALUE hval;
  86  
  87      switch (TYPE(a)) {
  88        case T_FIXNUM:
  89        case T_SYMBOL:
  90          return (int)a;
  91          break;
  92  
  93        case T_STRING:
  94          return rb_str_hash(a);
  95          break;
  96  
  97        default:
  98          DEFER_INTS;
  99          hval = rb_funcall(a, id_hash, 0);
 100          if (FIXNUM_P(hval)) {
 101              hval %= 536870923;
 102          }
 103          else {
 104              hval = rb_funcall(hval, '%', 1, INT2FIX(536870923));
 105          }
 106          ENABLE_INTS;
 107          return (int)FIX2LONG(hval);
 108      }
 109  }
 110  
 111  static struct st_hash_type objhash = {
 112      rb_any_cmp,
 113      rb_any_hash,
 114  };
 115  
 116  struct rb_hash_foreach_arg {
 117      VALUE hash;
 118      enum st_retval (*func)();
 119      char *arg;
 120  };
 121  
 122  static int
 123  rb_hash_foreach_iter(key, value, arg)
 124      VALUE key, value;
 125      struct rb_hash_foreach_arg *arg;
 126  {
 127      int status;
 128      st_table *tbl = RHASH(arg->hash)->tbl;
 129      struct st_table_entry **bins = tbl->bins;
 130  
 131      if (key == Qundef) return ST_CONTINUE;
 132      status = (*arg->func)(key, value, arg->arg);
 133      if (RHASH(arg->hash)->tbl != tbl || RHASH(arg->hash)->tbl->bins != bins){
 134          rb_raise(rb_eIndexError, "rehash occurred during iteration");
 135      }
 136      return status;
 137  }
 138  
 139  static VALUE
 140  rb_hash_foreach_call(arg)
 141      struct rb_hash_foreach_arg *arg;
 142  {
 143      st_foreach(RHASH(arg->hash)->tbl, rb_hash_foreach_iter, arg);
 144      return Qnil;
 145  }
 146  
 147  static VALUE
 148  rb_hash_foreach_ensure(hash)
 149      VALUE hash;
 150  {
 151      RHASH(hash)->iter_lev--;
 152  
 153      if (RHASH(hash)->iter_lev == 0) {
 154          if (FL_TEST(hash, HASH_DELETED)) {
 155              st_cleanup_safe(RHASH(hash)->tbl, Qundef);
 156              FL_UNSET(hash, HASH_DELETED);
 157          }
 158      }
 159      return 0;
 160  }
 161  
 162  static int
 163  rb_hash_foreach(hash, func, farg)
 164      VALUE hash;
 165      enum st_retval (*func)();
 166      char *farg;
 167  {
 168      struct rb_hash_foreach_arg arg;
 169  
 170      RHASH(hash)->iter_lev++;
 171      arg.hash = hash;
 172      arg.func = func;
 173      arg.arg  = farg;
 174      return rb_ensure(rb_hash_foreach_call, (VALUE)&arg, rb_hash_foreach_ensure, hash);
 175  }
 176  
 177  static VALUE
 178  rb_hash_s_alloc(klass)
 179      VALUE klass;
 180  {
 181      NEWOBJ(hash, struct RHash);
 182      OBJSETUP(hash, klass, T_HASH);
 183  
 184      hash->ifnone = Qnil;
 185      hash->tbl = st_init_table(&objhash);
 186  
 187      return (VALUE)hash;
 188  }
 189  
 190  VALUE
 191  rb_hash_new()
 192  {
 193      return rb_hash_s_alloc(rb_cHash);
 194  }
 195  
 196  static VALUE
 197  rb_hash_initialize(argc, argv, hash)
 198      int argc;
 199      VALUE *argv;
 200      VALUE hash;
 201  {
 202      VALUE ifnone;
 203  
 204      rb_hash_modify(hash);
 205      if (rb_block_given_p()) {
 206          if (argc > 0) {
 207              rb_raise(rb_eArgError, "wrong number of arguments");
 208          }
 209          RHASH(hash)->ifnone = rb_f_lambda();
 210          FL_SET(hash, HASH_PROC_DEFAULT);
 211      }
 212      else {
 213          rb_scan_args(argc, argv, "01", &ifnone);
 214          RHASH(hash)->ifnone = ifnone;
 215      }
 216  
 217      return hash;
 218  }
 219  
 220  static VALUE
 221  rb_hash_s_create(argc, argv, klass)
 222      int argc;
 223      VALUE *argv;
 224      VALUE klass;
 225  {
 226      VALUE hash;
 227      int i;
 228  
 229      if (argc == 1 && TYPE(argv[0]) == T_HASH) {
 230          hash = rb_obj_alloc(klass);
 231              
 232          RHASH(hash)->ifnone = Qnil;
 233          RHASH(hash)->tbl = st_copy(RHASH(argv[0])->tbl);
 234  
 235          return hash;
 236      }
 237  
 238      if (argc % 2 != 0) {
 239          rb_raise(rb_eArgError, "odd number args for Hash");
 240      }
 241  
 242      hash = rb_obj_alloc(klass);
 243      for (i=0; i<argc; i+=2) {
 244          rb_hash_aset(hash, argv[i], argv[i + 1]);
 245      }
 246  
 247      return hash;
 248  }
 249  
 250  static VALUE
 251  to_hash(hash)
 252      VALUE hash;
 253  {
 254      return rb_convert_type(hash, T_HASH, "Hash", "to_hash");
 255  }
 256  
 257  static int
 258  rb_hash_rehash_i(key, value, tbl)
 259      VALUE key, value;
 260      st_table *tbl;
 261  {
 262      if (key != Qundef) st_insert(tbl, key, value);
 263      return ST_CONTINUE;
 264  }
 265  
 266  static VALUE
 267  rb_hash_rehash(hash)
 268      VALUE hash;
 269  {
 270      st_table *tbl;
 271  
 272      rb_hash_modify(hash);
 273      tbl = st_init_table_with_size(&objhash, RHASH(hash)->tbl->num_entries);
 274      st_foreach(RHASH(hash)->tbl, rb_hash_rehash_i, tbl);
 275      st_free_table(RHASH(hash)->tbl);
 276      RHASH(hash)->tbl = tbl;
 277  
 278      return hash;
 279  }
 280  
 281  VALUE
 282  rb_hash_aref(hash, key)
 283      VALUE hash, key;
 284  {
 285      VALUE val;
 286  
 287      if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
 288          return rb_funcall(hash, id_default, 1, key);
 289      }
 290      return val;
 291  }
 292  
 293  static VALUE
 294  rb_hash_fetch(argc, argv, hash)
 295      int argc;
 296      VALUE *argv;
 297      VALUE hash;
 298  {
 299      VALUE key, if_none;
 300      VALUE val;
 301  
 302      rb_scan_args(argc, argv, "11", &key, &if_none);
 303  
 304      if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
 305          if (rb_block_given_p()) {
 306              if (argc > 1) {
 307                 rb_raise(rb_eArgError, "wrong number of arguments");
 308              }
 309              return rb_yield(key);
 310          }
 311          if (argc == 1) {
 312              rb_raise(rb_eIndexError, "key not found");
 313          }
 314          return if_none;
 315      }
 316      return val;
 317  }
 318  
 319  static VALUE
 320  rb_hash_default(argc, argv, hash)
 321      int argc;
 322      VALUE *argv;
 323      VALUE hash;
 324  {
 325      VALUE key;
 326  
 327      rb_scan_args(argc, argv, "01", &key);
 328      if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
 329          return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, key);
 330      }
 331      return RHASH(hash)->ifnone;
 332  }
 333  
 334  static VALUE
 335  rb_hash_set_default(hash, ifnone)
 336      VALUE hash, ifnone;
 337  {
 338      rb_hash_modify(hash);
 339      RHASH(hash)->ifnone = ifnone;
 340      FL_UNSET(hash, HASH_PROC_DEFAULT);
 341      return ifnone;
 342  }
 343  
 344  static VALUE
 345  rb_hash_default_proc(hash)
 346      VALUE hash;
 347  {
 348      if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
 349          return RHASH(hash)->ifnone;
 350      }
 351      return Qnil;
 352  }
 353  
 354  static int
 355  index_i(key, value, args)
 356      VALUE key, value;
 357      VALUE *args;
 358  {
 359      if (rb_equal(value, args[0])) {
 360          args[1] = key;
 361          return ST_STOP;
 362      }
 363      return ST_CONTINUE;
 364  }
 365  
 366  static VALUE
 367  rb_hash_index(hash, value)
 368      VALUE hash, value;
 369  {
 370      VALUE args[2];
 371  
 372      args[0] = value;
 373      args[1] = Qnil;
 374  
 375      st_foreach(RHASH(hash)->tbl, index_i, args);
 376  
 377      return args[1];
 378  }
 379  
 380  static VALUE
 381  rb_hash_indexes(argc, argv, hash)
 382      int argc;
 383      VALUE *argv;
 384      VALUE hash;
 385  {
 386      VALUE indexes;
 387      int i;
 388  
 389      rb_warn("Hash#%s is deprecated; use Hash#select",
 390              rb_id2name(rb_frame_last_func()));
 391      indexes = rb_ary_new2(argc);
 392      for (i=0; i<argc; i++) {
 393          RARRAY(indexes)->ptr[i] = rb_hash_aref(hash, argv[i]);
 394          RARRAY(indexes)->len++;
 395      }
 396      return indexes;
 397  }
 398  
 399  VALUE
 400  rb_hash_delete(hash, key)
 401      VALUE hash, key;
 402  {
 403      VALUE val;
 404  
 405      rb_hash_modify(hash);
 406      if (RHASH(hash)->iter_lev > 0) {
 407          if (st_delete_safe(RHASH(hash)->tbl, &key, &val, Qundef)) {
 408              FL_SET(hash, HASH_DELETED);
 409              return val;
 410          }
 411      }
 412      else if (st_delete(RHASH(hash)->tbl, &key, &val))
 413          return val;
 414      if (rb_block_given_p()) {
 415          return rb_yield(key);
 416      }
 417      return Qnil;
 418  }
 419  
 420  struct shift_var {
 421      int stop;
 422      VALUE key;
 423      VALUE val;
 424  };
 425  
 426  static int
 427  shift_i(key, value, var)
 428      VALUE key, value;
 429      struct shift_var *var;
 430  {
 431      if (key == Qundef) return ST_CONTINUE;
 432      if (var->stop) return ST_STOP;
 433      var->stop = 1;
 434      var->key = key;
 435      var->val = value;
 436      return ST_DELETE;
 437  }
 438  
 439  static VALUE
 440  rb_hash_shift(hash)
 441      VALUE hash;
 442  {
 443      struct shift_var var;
 444  
 445      rb_hash_modify(hash);
 446      var.stop = 0;
 447      st_foreach(RHASH(hash)->tbl, shift_i, &var);
 448  
 449      if (var.stop) {
 450          return rb_assoc_new(var.key, var.val);
 451      }
 452      else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
 453          return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, Qnil);
 454      }
 455      else {
 456          return RHASH(hash)->ifnone;
 457      }
 458  }
 459  
 460  static int
 461  delete_if_i(key, value)
 462      VALUE key, value;
 463  {
 464      if (key == Qundef) return ST_CONTINUE;
 465      if (RTEST(rb_yield(rb_assoc_new(key, value))))
 466          return ST_DELETE;
 467      return ST_CONTINUE;
 468  }
 469  
 470  VALUE
 471  rb_hash_delete_if(hash)
 472      VALUE hash;
 473  {
 474      rb_hash_modify(hash);
 475      rb_hash_foreach(hash, delete_if_i, 0);
 476      return hash;
 477  }
 478  
 479  VALUE
 480  rb_hash_reject_bang(hash)
 481      VALUE hash;
 482  {
 483      int n = RHASH(hash)->tbl->num_entries;
 484      rb_hash_delete_if(hash);
 485      if (n == RHASH(hash)->tbl->num_entries) return Qnil;
 486      return hash;
 487  }
 488  
 489  static VALUE
 490  rb_hash_reject(hash)
 491      VALUE hash;
 492  {
 493      return rb_hash_delete_if(rb_obj_dup(hash));
 494  }
 495  
 496  static int
 497  select_i(key, value, result)
 498      VALUE key, value;
 499  {
 500      VALUE assoc;
 501  
 502      if (key == Qundef) return ST_CONTINUE;
 503      assoc = rb_assoc_new(key, value);
 504      if (RTEST(rb_yield(assoc)))
 505          rb_ary_push(result, assoc);
 506      return ST_CONTINUE;
 507  }
 508  
 509  VALUE
 510  rb_hash_select(argc, argv, hash)
 511      int argc;
 512      VALUE *argv;
 513      VALUE hash;
 514  {
 515      VALUE result = rb_ary_new();
 516      long i;
 517  
 518      if (rb_block_given_p()) {
 519          if (argc > 0) {
 520              rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
 521          }
 522          rb_hash_foreach(hash, select_i, result);
 523      }
 524      else {
 525          for (i=0; i<argc; i++) {
 526              rb_ary_push(result, rb_hash_aref(hash, argv[i]));
 527          }
 528      }
 529      return result;
 530  }
 531  
 532  static int
 533  clear_i(key, value, dummy)
 534      VALUE key, value, dummy;
 535  {
 536      return ST_DELETE;
 537  }
 538  
 539  static VALUE
 540  rb_hash_clear(hash)
 541      VALUE hash;
 542  {
 543      rb_hash_modify(hash);
 544      st_foreach(RHASH(hash)->tbl, clear_i, 0);
 545  
 546      return hash;
 547  }
 548  
 549  VALUE
 550  rb_hash_aset(hash, key, val)
 551      VALUE hash, key, val;
 552  {
 553      rb_hash_modify(hash);
 554      if (TYPE(key) != T_STRING || st_lookup(RHASH(hash)->tbl, key, 0)) {
 555          st_insert(RHASH(hash)->tbl, key, val);
 556      }
 557      else {
 558          st_add_direct(RHASH(hash)->tbl, rb_str_new4(key), val);
 559      }
 560      return val;
 561  }
 562  
 563  static int
 564  replace_i(key, val, hash)
 565      VALUE key, val, hash;
 566  {
 567      if (key != Qundef) {
 568          rb_hash_aset(hash, key, val);
 569      }
 570  
 571      return ST_CONTINUE;
 572  }
 573  
 574  static VALUE
 575  rb_hash_become(hash, hash2)
 576      VALUE hash, hash2;
 577  {
 578      hash2 = to_hash(hash2);
 579      rb_hash_clear(hash);
 580      st_foreach(RHASH(hash2)->tbl, replace_i, hash);
 581      RHASH(hash)->ifnone = RHASH(hash2)->ifnone;
 582      if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
 583          FL_SET(hash, HASH_PROC_DEFAULT);
 584      }
 585      else {
 586          FL_UNSET(hash, HASH_PROC_DEFAULT);
 587      }
 588  
 589      return hash;
 590  }
 591  
 592  static VALUE
 593  rb_hash_size(hash)
 594      VALUE hash;
 595  {
 596      return INT2FIX(RHASH(hash)->tbl->num_entries);
 597  }
 598  
 599  static VALUE
 600  rb_hash_empty_p(hash)
 601      VALUE hash;
 602  {
 603      if (RHASH(hash)->tbl->num_entries == 0)
 604          return Qtrue;
 605      return Qfalse;
 606  }
 607  
 608  static int
 609  each_value_i(key, value)
 610      VALUE key, value;
 611  {
 612      if (key == Qundef) return ST_CONTINUE;
 613      rb_yield(value);
 614      return ST_CONTINUE;
 615  }
 616  
 617  static VALUE
 618  rb_hash_each_value(hash)
 619      VALUE hash;
 620  {
 621      rb_hash_foreach(hash, each_value_i, 0);
 622      return hash;
 623  }
 624  
 625  static int
 626  each_key_i(key, value)
 627      VALUE key, value;
 628  {
 629      if (key == Qundef) return ST_CONTINUE;
 630      rb_yield(key);
 631      return ST_CONTINUE;
 632  }
 633  
 634  static VALUE
 635  rb_hash_each_key(hash)
 636      VALUE hash;
 637  {
 638      rb_hash_foreach(hash, each_key_i, 0);
 639      return hash;
 640  }
 641  
 642  static int
 643  each_pair_i(key, value)
 644      VALUE key, value;
 645  {
 646      if (key == Qundef) return ST_CONTINUE;
 647      rb_yield(rb_assoc_new(key, value));
 648      return ST_CONTINUE;
 649  }
 650  
 651  static VALUE
 652  rb_hash_each_pair(hash)
 653      VALUE hash;
 654  {
 655      rb_hash_foreach(hash, each_pair_i, 0);
 656      return hash;
 657  }
 658  
 659  static int
 660  to_a_i(key, value, ary)
 661      VALUE key, value, ary;
 662  {
 663      if (key == Qundef) return ST_CONTINUE;
 664      rb_ary_push(ary, rb_assoc_new(key, value));
 665      return ST_CONTINUE;
 666  }
 667  
 668  static VALUE
 669  rb_hash_to_a(hash)
 670      VALUE hash;
 671  {
 672      VALUE ary;
 673  
 674      ary = rb_ary_new();
 675      st_foreach(RHASH(hash)->tbl, to_a_i, ary);
 676      if (OBJ_TAINTED(hash)) OBJ_TAINT(ary);
 677  
 678      return ary;
 679  }
 680  
 681  static VALUE
 682  rb_hash_sort(hash)
 683      VALUE hash;
 684  {
 685      VALUE entries = rb_hash_to_a(hash);
 686      rb_ary_sort_bang(entries);
 687      return entries;
 688  }
 689  
 690  static int
 691  inspect_i(key, value, str)
 692      VALUE key, value, str;
 693  {
 694      VALUE str2;
 695  
 696      if (key == Qundef) return ST_CONTINUE;
 697      if (RSTRING(str)->len > 1) {
 698          rb_str_cat2(str, ", ");
 699      }
 700      str2 = rb_inspect(key);
 701      rb_str_buf_append(str, str2);
 702      OBJ_INFECT(str, str2);
 703      rb_str_buf_cat2(str, "=>");
 704      str2 = rb_inspect(value);
 705      rb_str_buf_append(str, str2);
 706      OBJ_INFECT(str, str2);
 707  
 708      return ST_CONTINUE;
 709  }
 710  
 711  static VALUE
 712  inspect_hash(hash)
 713      VALUE hash;
 714  {
 715      VALUE str;
 716  
 717      str = rb_str_buf_new2("{");
 718      st_foreach(RHASH(hash)->tbl, inspect_i, str);
 719      rb_str_buf_cat2(str, "}");
 720      OBJ_INFECT(str, hash);
 721  
 722      return str;
 723  }
 724  
 725  static VALUE
 726  rb_hash_inspect(hash)
 727      VALUE hash;
 728  {
 729      if (RHASH(hash)->tbl == 0 || RHASH(hash)->tbl->num_entries == 0)
 730          return rb_str_new2("{}");
 731      if (rb_inspecting_p(hash)) return rb_str_new2("{...}");
 732      return rb_protect_inspect(inspect_hash, hash, 0);
 733  }
 734  
 735  static VALUE
 736  to_s_hash(hash)
 737      VALUE hash;
 738  {
 739      return rb_ary_to_s(rb_hash_to_a(hash));
 740  }
 741  
 742  static VALUE
 743  rb_hash_to_s(hash)
 744      VALUE hash;
 745  {
 746      if (rb_inspecting_p(hash)) return rb_str_new2("{...}");
 747      return rb_protect_inspect(to_s_hash, hash, 0);
 748  }
 749  
 750  static VALUE
 751  rb_hash_to_hash(hash)
 752      VALUE hash;
 753  {
 754      return hash;
 755  }
 756  
 757  static int
 758  keys_i(key, value, ary)
 759      VALUE key, value, ary;
 760  {
 761      if (key == Qundef) return ST_CONTINUE;
 762      rb_ary_push(ary, key);
 763      return ST_CONTINUE;
 764  }
 765  
 766  static VALUE
 767  rb_hash_keys(hash)
 768      VALUE hash;
 769  {
 770      VALUE ary;
 771  
 772      ary = rb_ary_new();
 773      st_foreach(RHASH(hash)->tbl, keys_i, ary);
 774  
 775      return ary;
 776  }
 777  
 778  static int
 779  values_i(key, value, ary)
 780      VALUE key, value, ary;
 781  {
 782      if (key == Qundef) return ST_CONTINUE;
 783      rb_ary_push(ary, value);
 784      return ST_CONTINUE;
 785  }
 786  
 787  static VALUE
 788  rb_hash_values(hash)
 789      VALUE hash;
 790  {
 791      VALUE ary;
 792  
 793      ary = rb_ary_new();
 794      st_foreach(RHASH(hash)->tbl, values_i, ary);
 795  
 796      return ary;
 797  }
 798  
 799  static VALUE
 800  rb_hash_has_key(hash, key)
 801      VALUE hash;
 802      VALUE key;
 803  {
 804      if (st_lookup(RHASH(hash)->tbl, key, 0)) {
 805          return Qtrue;
 806      }
 807      return Qfalse;
 808  }
 809  
 810  static int
 811  rb_hash_search_value(key, value, data)
 812      VALUE key, value, *data;
 813  {
 814      if (key == Qundef) return ST_CONTINUE;
 815      if (rb_equal(value, data[1])) {
 816          data[0] = Qtrue;
 817          return ST_STOP;
 818      }
 819      return ST_CONTINUE;
 820  }
 821  
 822  static VALUE
 823  rb_hash_has_value(hash, val)
 824      VALUE hash;
 825      VALUE val;
 826  {
 827      VALUE data[2];
 828  
 829      data[0] = Qfalse;
 830      data[1] = val;
 831      st_foreach(RHASH(hash)->tbl, rb_hash_search_value, data);
 832      return data[0];
 833  }
 834  
 835  struct equal_data {
 836      int result;
 837      st_table *tbl;
 838  };
 839  
 840  static int
 841  equal_i(key, val1, data)
 842      VALUE key, val1;
 843      struct equal_data *data;
 844  {
 845      VALUE val2;
 846  
 847      if (key == Qundef) return ST_CONTINUE;
 848      if (!st_lookup(data->tbl, key, &val2)) {
 849          data->result = Qfalse;
 850          return ST_STOP;
 851      }
 852      if (!rb_equal(val1, val2)) {
 853          data->result = Qfalse;
 854          return ST_STOP;
 855      }
 856      return ST_CONTINUE;
 857  }
 858  
 859  static VALUE
 860  rb_hash_equal(hash1, hash2)
 861      VALUE hash1, hash2;
 862  {
 863      struct equal_data data;
 864  
 865      if (hash1 == hash2) return Qtrue;
 866      if (TYPE(hash2) != T_HASH) return Qfalse;
 867      if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries)
 868          return Qfalse;
 869      if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) &&
 870            FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
 871          return Qfalse;
 872  
 873      data.tbl = RHASH(hash2)->tbl;
 874      data.result = Qtrue;
 875      st_foreach(RHASH(hash1)->tbl, equal_i, &data);
 876  
 877      return data.result;
 878  }
 879  
 880  static int
 881  rb_hash_invert_i(key, value, hash)
 882      VALUE key, value;
 883      VALUE hash;
 884  {
 885      if (key == Qundef) return ST_CONTINUE;
 886      rb_hash_aset(hash, value, key);
 887      return ST_CONTINUE;
 888  }
 889  
 890  static VALUE
 891  rb_hash_invert(hash)
 892      VALUE hash;
 893  {
 894      VALUE h = rb_hash_new();
 895  
 896      st_foreach(RHASH(hash)->tbl, rb_hash_invert_i, h);
 897      return h;
 898  }
 899  
 900  static int
 901  rb_hash_update_i(key, value, hash)
 902      VALUE key, value;
 903      VALUE hash;
 904  {
 905      if (key == Qundef) return ST_CONTINUE;
 906      rb_hash_aset(hash, key, value);
 907      return ST_CONTINUE;
 908  }
 909  
 910  static int
 911  rb_hash_update_block_i(key, value, hash)
 912      VALUE key, value;
 913      VALUE hash;
 914  {
 915      if (key == Qundef) return ST_CONTINUE;
 916      if (rb_hash_has_key(hash, key)) {
 917          value = rb_yield(rb_ary_new3(3, key, rb_hash_aref(hash, key), value));
 918      }
 919      rb_hash_aset(hash, key, value);
 920      return ST_CONTINUE;
 921  }
 922  
 923  static VALUE
 924  rb_hash_update(hash1, hash2)
 925      VALUE hash1, hash2;
 926  {
 927      hash2 = to_hash(hash2);
 928      if (rb_block_given_p()) {
 929          st_foreach(RHASH(hash2)->tbl, rb_hash_update_block_i, hash1);
 930      }
 931      else {
 932          st_foreach(RHASH(hash2)->tbl, rb_hash_update_i, hash1);
 933      }
 934      return hash1;
 935  }
 936  
 937  static int path_tainted = -1;
 938  
 939  static char **origenviron;
 940  #ifdef NT
 941  #define GET_ENVIRON(e) (e = rb_w32_get_environ())
 942  #define FREE_ENVIRON(e) rb_w32_free_environ(e)
 943  static char **my_environ;
 944  #undef environ
 945  #define environ my_environ
 946  #else
 947  extern char **environ;
 948  #define GET_ENVIRON(e) (e)
 949  #define FREE_ENVIRON(e)
 950  #endif
 951  
 952  static VALUE
 953  env_delete(obj, name)
 954      VALUE obj, name;
 955  {
 956      char *nam, *val;
 957  
 958      rb_secure(4);
 959      SafeStringValue(name);
 960      nam = RSTRING(name)->ptr;
 961      if (strlen(nam) != RSTRING(name)->len) {
 962          rb_raise(rb_eArgError, "bad environment variable name");
 963      }
 964      val = getenv(nam);
 965      if (val) {
 966          VALUE value = rb_tainted_str_new2(val);
 967  
 968          ruby_setenv(nam, 0);
 969  #ifdef __BORLANDC__
 970          if (strcmpi(nam, "PATH") == 0) {
 971  #else
 972          if (strcmp(nam, "PATH") == 0) {
 973  #endif
 974              path_tainted = 0;
 975          }
 976          return value;
 977      }
 978      return Qnil;
 979  }
 980  
 981  static VALUE
 982  env_delete_m(obj, name)
 983      VALUE obj, name;
 984  {
 985      VALUE val = env_delete(obj, name);
 986      if (rb_block_given_p()) rb_yield(name);
 987      return val;
 988  }
 989  
 990  static VALUE
 991  rb_f_getenv(obj, name)
 992      VALUE obj, name;
 993  {
 994      char *nam, *env;
 995  
 996      StringValue(name);
 997      nam = RSTRING(name)->ptr;
 998      if (strlen(nam) != RSTRING(name)->len) {
 999          rb_raise(rb_eArgError, "bad environment variable name");
1000      }
1001      env = getenv(nam);
1002      if (env) {
1003  #ifdef __BORLANDC__
1004          if (strcmpi(nam, "PATH") == 0 && !rb_env_path_tainted())
1005  #else
1006          if (strcmp(nam, "PATH") == 0 && !rb_env_path_tainted())
1007  #endif
1008              return rb_str_new2(env);
1009          return rb_tainted_str_new2(env);
1010      }
1011      return Qnil;
1012  }
1013  
1014  static VALUE
1015  env_fetch(argc, argv)
1016      int argc;
1017      VALUE *argv;
1018  {
1019      VALUE key, if_none;
1020      char *nam, *env;
1021  
1022      rb_scan_args(argc, argv, "11", &key, &if_none);
1023      StringValue(key);
1024      nam = RSTRING(key)->ptr;
1025      if (strlen(nam) != RSTRING(key)->len) {
1026          rb_raise(rb_eArgError, "bad environment variable name");
1027      }
1028      env = getenv(nam);
1029      if (!env) {
1030          if (rb_block_given_p()) {
1031              if (argc > 1) {
1032                  rb_raise(rb_eArgError, "wrong number of arguments");
1033              }
1034              return rb_yield(key);
1035          }
1036          if (argc == 1) {
1037              rb_raise(rb_eIndexError, "key not found");
1038          }
1039          return if_none;
1040      }
1041  #ifdef __BORLANDC__
1042      if (strcmpi(nam, "PATH") == 0 && !rb_env_path_tainted())
1043  #else
1044      if (strcmp(nam, "PATH") == 0 && !rb_env_path_tainted())
1045  #endif
1046          return rb_str_new2(env);
1047      return rb_tainted_str_new2(env);
1048  }
1049  
1050  static void
1051  path_tainted_p(path)
1052      char *path;
1053  {
1054      path_tainted = rb_path_check(path)?0:1;
1055  }
1056  
1057  int
1058  rb_env_path_tainted()
1059  {
1060      if (path_tainted < 0) {
1061          path_tainted_p(getenv("PATH"));
1062      }
1063      return path_tainted;
1064  }
1065  
1066  static int
1067  envix(nam)
1068  char *nam;
1069  {
1070      register int i, len = strlen(nam);
1071      char **env;
1072  
1073      env = GET_ENVIRON(environ);
1074      for (i = 0; env[i]; i++) {
1075          if (
1076  #ifdef WIN32
1077              strnicmp(env[i],nam,len) == 0
1078  #else
1079              memcmp(env[i],nam,len) == 0
1080  #endif
1081              && env[i][len] == '=')
1082              break;                      /* memcmp must come first to avoid */
1083      }                                   /* potential SEGV's */
1084      FREE_ENVIRON(environ);
1085      return i;
1086  }
1087  
1088  void
1089  ruby_setenv(name, value)
1090      const char *name;
1091      const char *value;
1092  {
1093  #if defined(WIN32) && !defined(__CYGWIN32__)
1094      /* The sane way to deal with the environment.
1095       * Has these advantages over putenv() & co.:
1096       *  * enables us to store a truly empty value in the
1097       *    environment (like in UNIX).
1098       *  * we don't have to deal with RTL globals, bugs and leaks.
1099       *  * Much faster.
1100       * Why you may want to enable USE_WIN32_RTL_ENV:
1101       *  * environ[] and RTL functions will not reflect changes,
1102       *    which might be an issue if extensions want to access
1103       *    the env. via RTL.  This cuts both ways, since RTL will
1104       *    not see changes made by extensions that call the Win32
1105       *    functions directly, either.
1106       * GSAR 97-06-07
1107       *
1108       * REMARK: USE_WIN32_RTL_ENV is already obsoleted since we don't use
1109       *         RTL's environ global variable directly yet.
1110       */
1111      SetEnvironmentVariable(name,value);
1112  #elif defined __CYGWIN__
1113  #undef setenv
1114  #undef unsetenv
1115      if (value)
1116          setenv(name,value,1);
1117      else
1118          unsetenv(name);
1119  #else  /* WIN32 */
1120  
1121      int i=envix(name);                  /* where does it go? */
1122  
1123      if (environ == origenviron) {       /* need we copy environment? */
1124          int j;
1125          int max;
1126          char **tmpenv;
1127  
1128          for (max = i; environ[max]; max++) ;
1129          tmpenv = ALLOC_N(char*, max+2);
1130          for (j=0; j<max; j++)           /* copy environment */
1131              tmpenv[j] = strdup(environ[j]);
1132          tmpenv[max] = 0;
1133          environ = tmpenv;               /* tell exec where it is now */
1134      }
1135      if (!value) {
1136          if (environ != origenviron) {
1137              char **envp = origenviron;
1138              while (*envp && *envp != environ[i]) envp++;
1139              if (!*envp)
1140                  free(environ[i]);
1141          }
1142          while (environ[i]) {
1143              environ[i] = environ[i+1];
1144              i++;
1145          }
1146          return;
1147      }
1148      if (!environ[i]) {                  /* does not exist yet */
1149          REALLOC_N(environ, char*, i+2); /* just expand it a bit */
1150          environ[i+1] = 0;       /* make sure it's null terminated */
1151      }
1152      else {
1153          if (environ[i] != origenviron[i])
1154              free(environ[i]);
1155      }
1156      environ[i] = ALLOC_N(char, strlen(name) + strlen(value) + 2);
1157  #ifndef MSDOS
1158      sprintf(environ[i],"%s=%s",name,value); /* all that work just for this */
1159  #else
1160      /* MS-DOS requires environment variable names to be in uppercase */
1161      /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
1162       * some utilities and applications may break because they only look
1163       * for upper case strings. (Fixed strupr() bug here.)]
1164       */
1165      strcpy(environ[i],name); strupr(environ[i]);
1166      sprintf(environ[i] + strlen(name),"=%s", value);
1167  #endif /* MSDOS */
1168  
1169  #endif /* WIN32 */
1170  }
1171  
1172  void
1173  ruby_unsetenv(name)
1174      const char *name;
1175  {
1176      ruby_setenv(name, 0);
1177  }
1178  
1179  static VALUE
1180  env_aset(obj, nm, val)
1181      VALUE obj, nm, val;
1182  {
1183      char *name, *value;
1184  
1185      if (rb_safe_level() >= 4) {
1186          rb_raise(rb_eSecurityError, "cannot change environment variable");
1187      }
1188  
1189      if (NIL_P(val)) {
1190          env_delete(obj, nm);
1191          return Qnil;
1192      }
1193  
1194      StringValue(nm);
1195      StringValue(val);
1196      name = RSTRING(nm)->ptr;
1197      value = RSTRING(val)->ptr;
1198      if (strlen(name) != RSTRING(nm)->len)
1199          rb_raise(rb_eArgError, "bad environment variable name");
1200      if (strlen(value) != RSTRING(val)->len)
1201          rb_raise(rb_eArgError, "bad environment variable value");
1202  
1203      ruby_setenv(name, value);
1204      if (strcmp(name, "PATH") == 0) {
1205          if (OBJ_TAINTED(val)) {
1206              /* already tainted, no check */
1207              path_tainted = 1;
1208              return val;
1209          }
1210          else {
1211              path_tainted_p(value);
1212          }
1213      }
1214      return val;
1215  }
1216  
1217  static VALUE
1218  env_keys()
1219  {
1220      char **env;
1221      VALUE ary = rb_ary_new();
1222  
1223      env = GET_ENVIRON(environ);
1224      while (*env) {
1225          char *s = strchr(*env, '=');
1226          if (s) {
1227              rb_ary_push(ary, rb_tainted_str_new(*env, s-*env));
1228          }
1229          env++;
1230      }
1231      FREE_ENVIRON(environ);
1232      return ary;
1233  }
1234  
1235  static VALUE
1236  env_each_key(hash)
1237      VALUE hash;
1238  {
1239      char **env;
1240  
1241      env = GET_ENVIRON(environ);
1242      while (*env) {
1243          char *s = strchr(*env, '=');
1244          if (s) {
1245              rb_yield(rb_tainted_str_new(*env, s-*env));
1246          }
1247          env++;
1248      }
1249      FREE_ENVIRON(environ);
1250      return Qnil;
1251  }
1252  
1253  static VALUE
1254  env_values()
1255  {
1256      char **env;
1257      VALUE ary = rb_ary_new();
1258  
1259      env = GET_ENVIRON(environ);
1260      while (*env) {
1261          char *s = strchr(*env, '=');
1262          if (s) {
1263              rb_ary_push(ary, rb_tainted_str_new2(s+1));
1264          }
1265          env++;
1266      }
1267      FREE_ENVIRON(environ);
1268      return ary;
1269  }
1270  
1271  static VALUE
1272  env_each_value(hash)
1273      VALUE hash;
1274  {
1275      char **env;
1276  
1277      env = GET_ENVIRON(environ);
1278      while (*env) {
1279          char *s = strchr(*env, '=');
1280          if (s) {
1281              rb_yield(rb_tainted_str_new2(s+1));
1282          }
1283          env++;
1284      }
1285      FREE_ENVIRON(environ);
1286      return Qnil;
1287  }
1288  
1289  static VALUE
1290  env_each(hash)
1291      VALUE hash;
1292  {
1293      char **env;
1294  
1295      env = GET_ENVIRON(environ);
1296      while (*env) {
1297          char *s = strchr(*env, '=');
1298          if (s) {
1299              rb_yield(rb_assoc_new(rb_tainted_str_new(*env, s-*env),
1300                                    rb_tainted_str_new2(s+1)));
1301          }
1302          env++;
1303      }
1304      FREE_ENVIRON(environ);
1305      return Qnil;
1306  }
1307  
1308  static VALUE
1309  env_reject_bang()
1310  {
1311      volatile VALUE keys;
1312      VALUE *ptr;
1313      long len;
1314      int del = 0;
1315  
1316      rb_secure(4);
1317      keys = env_keys();
1318      ptr = RARRAY(keys)->ptr;
1319      len = RARRAY(keys)->len; 
1320  
1321      while (len--) {
1322          VALUE val = rb_f_getenv(Qnil, *ptr);
1323          if (!NIL_P(val)) {
1324              if (RTEST(rb_yield(rb_assoc_new(*ptr, val)))) {
1325                  env_delete(Qnil, *ptr);
1326                  del++;
1327              }
1328          }
1329          ptr++;
1330      }
1331      if (del == 0) return Qnil;
1332      return envtbl;
1333  }
1334  
1335  static VALUE
1336  env_delete_if()
1337  {
1338      env_reject_bang();
1339      return envtbl;
1340  }
1341  
1342  static VALUE
1343  env_select(argc, argv)
1344      int argc;
1345      VALUE *argv;
1346  {
1347      VALUE result = rb_ary_new();
1348      long i;
1349  
1350      if (rb_block_given_p()) {
1351          char **env;
1352  
1353          if (argc > 0) {
1354              rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
1355          }
1356          env = GET_ENVIRON(environ);
1357          while (*env) {
1358              char *s = strchr(*env, '=');
1359              if (s) {
1360                  VALUE assoc = rb_assoc_new(rb_tainted_str_new(*env, s-*env),
1361                                             rb_tainted_str_new2(s+1));
1362                  if (RTEST(rb_yield(assoc))) {
1363                      rb_ary_push(result, assoc);
1364                  }
1365              }
1366              env++;
1367          }
1368          FREE_ENVIRON(environ);
1369      }
1370      else {
1371          for (i=0; i<argc; i++) {
1372              rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
1373          }
1374      }
1375      return result;
1376  }
1377  
1378  static VALUE
1379  env_to_s()
1380  {
1381      return rb_str_new2("ENV");
1382  }
1383  
1384  static VALUE
1385  env_inspect()
1386  {
1387      char **env;
1388      VALUE str = rb_str_buf_new2("{");
1389      VALUE i;
1390  
1391      env = GET_ENVIRON(environ);
1392      while (*env) {
1393          char *s = strchr(*env, '=');
1394  
1395          if (env != environ) {
1396              rb_str_buf_cat2(str, ", ");
1397          }
1398          if (s) {
1399              rb_str_buf_cat2(str, "\"");
1400              rb_str_buf_cat(str, *env, s-*env);
1401              rb_str_buf_cat2(str, "\"=>");
1402              i = rb_inspect(rb_str_new2(s+1));
1403              rb_str_buf_append(str, i);
1404          }
1405          env++;
1406      }
1407      FREE_ENVIRON(environ);
1408      rb_str_buf_cat2(str, "}");
1409      OBJ_TAINT(str);
1410  
1411      return str;
1412  }
1413  
1414  static VALUE
1415  env_to_a()
1416  {
1417      char **env;
1418      VALUE ary = rb_ary_new();
1419  
1420      env = GET_ENVIRON(environ);
1421      while (*env) {
1422          char *s = strchr(*env, '=');
1423          if (s) {
1424              rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(*env, s-*env),
1425                                            rb_tainted_str_new2(s+1)));
1426          }
1427          env++;
1428      }
1429      FREE_ENVIRON(environ);
1430      return ary;
1431  }
1432  
1433  static VALUE
1434  env_none()
1435  {
1436      return Qnil;
1437  }
1438  
1439  static VALUE
1440  env_size()
1441  {
1442      int i;
1443      char **env;
1444  
1445      env = GET_ENVIRON(environ);
1446      for(i=0; env[i]; i++)
1447          ;
1448      FREE_ENVIRON(environ);
1449      return INT2FIX(i);
1450  }
1451  
1452  static VALUE
1453  env_empty_p()
1454  {
1455      char **env;
1456  
1457      env = GET_ENVIRON(environ);
1458      if (env[0] == 0) {
1459          FREE_ENVIRON(environ);
1460          return Qtrue;
1461      }
1462      FREE_ENVIRON(environ);
1463      return Qfalse;
1464  }
1465  
1466  static VALUE
1467  env_has_key(env, key)
1468      VALUE env, key;
1469  {
1470      char *s;
1471  
1472      s = StringValuePtr(key);
1473      if (strlen(s) != RSTRING(key)->len)
1474          rb_raise(rb_eArgError, "bad environment variable name");
1475      if (getenv(s)) return Qtrue;
1476      return Qfalse;
1477  }
1478  
1479  static VALUE
1480  env_has_value(dmy, value)
1481      VALUE dmy, value;
1482  {
1483      char **env;
1484  
1485      if (TYPE(value) != T_STRING) return Qfalse;
1486      env = GET_ENVIRON(environ);
1487      while (*env) {
1488          char *s = strchr(*env, '=')+1;
1489          if (s) {
1490              if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0) {
1491                  FREE_ENVIRON(environ);
1492                  return Qtrue;
1493              }
1494          }
1495          env++;
1496      }
1497      FREE_ENVIRON(environ);
1498      return Qfalse;
1499  }
1500  
1501  static VALUE
1502  env_index(dmy, value)
1503      VALUE dmy, value;
1504  {
1505      char **env;
1506      VALUE str;
1507  
1508      if (TYPE(value) != T_STRING) return Qnil;
1509      env = GET_ENVIRON(environ);
1510      while (*env) {
1511          char *s = strchr(*env, '=')+1;
1512          if (s) {
1513              if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0) {
1514                  str = rb_tainted_str_new(*env, s-*env-1);
1515                  FREE_ENVIRON(environ);
1516                  return str;
1517              }
1518          }
1519          env++;
1520      }
1521      FREE_ENVIRON(environ);
1522      return Qnil;
1523  }
1524  
1525  static VALUE
1526  env_indexes(argc, argv)
1527      int argc;
1528      VALUE *argv;
1529  {
1530      int i;
1531      VALUE indexes = rb_ary_new2(argc);
1532  
1533      rb_warn("ENV.%s is deprecated; use ENV.select",
1534              rb_id2name(rb_frame_last_func()));
1535      for (i=0;i<argc;i++) {
1536          char *v = 0;
1537          if (TYPE(argv[i]) == T_STRING) {
1538              v = getenv(RSTRING(argv[i])->ptr);
1539          }
1540          if (v) {
1541              RARRAY(indexes)->ptr[i] = rb_tainted_str_new2(v);
1542          }
1543          else {
1544              RARRAY(indexes)->ptr[i] = Qnil;
1545          }
1546          RARRAY(indexes)->len = i+1;
1547      }
1548  
1549      return indexes;
1550  }
1551  
1552  static VALUE
1553  env_to_hash()
1554  {
1555      char **env;
1556      VALUE hash = rb_hash_new();
1557  
1558      env = GET_ENVIRON(environ);
1559      while (*env) {
1560          char *s = strchr(*env, '=');
1561          if (s) {
1562              rb_hash_aset(hash, rb_tainted_str_new(*env, s-*env),
1563                                 rb_tainted_str_new2(s+1));
1564          }
1565          env++;
1566      }
1567      FREE_ENVIRON(environ);
1568      return hash;
1569  }
1570  
1571  static VALUE
1572  env_reject()
1573  {
1574      return rb_hash_delete_if(env_to_hash());
1575  }
1576  
1577  void
1578  Init_Hash()
1579  {
1580      id_hash = rb_intern("hash");
1581      id_yield = rb_intern("yield");
1582      id_default = rb_intern("default");
1583  
1584      rb_cHash = rb_define_class("Hash", rb_cObject);
1585  
1586      rb_include_module(rb_cHash, rb_mEnumerable);
1587  
1588      rb_define_singleton_method(rb_cHash, "allocate", rb_hash_s_alloc, 0);
1589      rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
1590      rb_define_method(rb_cHash,"initialize", rb_hash_initialize, -1);
1591  
1592      rb_define_method(rb_cHash,"become", rb_hash_become, 1);
1593      rb_define_method(rb_cHash,"rehash", rb_hash_rehash, 0);
1594  
1595      rb_define_method(rb_cHash,"to_hash", rb_hash_to_hash, 0);
1596      rb_define_method(rb_cHash,"to_a", rb_hash_to_a, 0);
1597      rb_define_method(rb_cHash,"to_s", rb_hash_to_s, 0);
1598      rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0);
1599  
1600      rb_define_method(rb_cHash,"==", rb_hash_equal, 1);
1601      rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
1602      rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1);
1603      rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
1604      rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
1605      rb_define_method(rb_cHash,"default", rb_hash_default, -1);
1606      rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
1607      rb_define_method(rb_cHash,"default_proc", rb_hash_default_proc, 0);
1608      rb_define_method(rb_cHash,"index", rb_hash_index, 1);
1609      rb_define_method(rb_cHash,"indexes", rb_hash_indexes, -1);
1610      rb_define_method(rb_cHash,"indices", rb_hash_indexes, -1);
1611      rb_define_method(rb_cHash,"size", rb_hash_size, 0);
1612      rb_define_method(rb_cHash,"length", rb_hash_size, 0);
1613      rb_define_method(rb_cHash,"empty?", rb_hash_empty_p, 0);
1614  
1615      rb_define_method(rb_cHash,"each", rb_hash_each_pair, 0);
1616      rb_define_method(rb_cHash,"each_value", rb_hash_each_value, 0);
1617      rb_define_method(rb_cHash,"each_key", rb_hash_each_key, 0);
1618      rb_define_method(rb_cHash,"each_pair", rb_hash_each_pair, 0);
1619      rb_define_method(rb_cHash,"sort", rb_hash_sort, 0);
1620  
1621      rb_define_method(rb_cHash,"keys", rb_hash_keys, 0);
1622      rb_define_method(rb_cHash,"values", rb_hash_values, 0);
1623  
1624      rb_define_method(rb_cHash,"shift", rb_hash_shift, 0);
1625      rb_define_method(rb_cHash,"delete", rb_hash_delete, 1);
1626      rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0);
1627      rb_define_method(rb_cHash,"select", rb_hash_select, -1);
1628      rb_define_method(rb_cHash,"reject", rb_hash_reject, 0);
1629      rb_define_method(rb_cHash,"reject!", rb_hash_reject_bang, 0);
1630      rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
1631      rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
1632      rb_define_method(rb_cHash,"update", rb_hash_update, 1);
1633      rb_define_method(rb_cHash,"replace", rb_hash_become, 1);
1634  
1635      rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1);
1636      rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1);
1637      rb_define_method(rb_cHash,"has_key?", rb_hash_has_key, 1);
1638      rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1);
1639      rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1);
1640      rb_define_method(rb_cHash,"value?", rb_hash_has_value, 1);
1641  
1642  #ifndef __MACOS__ /* environment variables nothing on MacOS. */
1643      origenviron = environ;
1644      envtbl = rb_obj_alloc(rb_cObject);
1645      rb_extend_object(envtbl, rb_mEnumerable);
1646  
1647      rb_define_singleton_method(envtbl,"[]", rb_f_getenv, 1);
1648      rb_define_singleton_method(envtbl,"fetch", env_fetch, -1);
1649      rb_define_singleton_method(envtbl,"[]=", env_aset, 2);
1650      rb_define_singleton_method(envtbl,"store", env_aset, 2);
1651      rb_define_singleton_method(envtbl,"each", env_each, 0);
1652      rb_define_singleton_method(envtbl,"each_pair", env_each, 0);
1653      rb_define_singleton_method(envtbl,"each_key", env_each_key, 0);
1654      rb_define_singleton_method(envtbl,"each_value", env_each_value, 0);
1655      rb_define_singleton_method(envtbl,"delete", env_delete_m, 1);
1656      rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0);
1657      rb_define_singleton_method(envtbl,"reject", env_reject, 0);
1658      rb_define_singleton_method(envtbl,"reject!", env_reject_bang, 0);
1659      rb_define_singleton_method(envtbl,"select", env_select, -1);
1660      rb_define_singleton_method(envtbl,"to_s", env_to_s, 0);
1661      rb_define_singleton_method(envtbl,"inspect", env_inspect, 0);
1662      rb_define_singleton_method(envtbl,"rehash", env_none, 0);
1663      rb_define_singleton_method(envtbl,"to_a", env_to_a, 0);
1664      rb_define_singleton_method(envtbl,"index", env_index, 1);
1665      rb_define_singleton_method(envtbl,"indexes", env_indexes, -1);
1666      rb_define_singleton_method(envtbl,"indices", env_indexes, -1);
1667      rb_define_singleton_method(envtbl,"size", env_size, 0);
1668      rb_define_singleton_method(envtbl,"length", env_size, 0);
1669      rb_define_singleton_method(envtbl,"empty?", env_empty_p, 0);
1670      rb_define_singleton_method(envtbl,"keys", env_keys, 0);
1671      rb_define_singleton_method(envtbl,"values", env_values, 0);
1672      rb_define_singleton_method(envtbl,"include?", env_has_key, 1);
1673      rb_define_singleton_method(envtbl,"member?", env_has_key, 1);
1674      rb_define_singleton_method(envtbl,"has_key?", env_has_key, 1);
1675      rb_define_singleton_method(envtbl,"has_value?", env_has_value, 1);
1676      rb_define_singleton_method(envtbl,"key?", env_has_key, 1);
1677      rb_define_singleton_method(envtbl,"value?", env_has_value, 1);
1678      rb_define_singleton_method(envtbl,"to_hash", env_to_hash, 0);
1679  
1680      rb_define_global_const("ENV", envtbl);
1681  #else /* __MACOS__ */
1682          envtbl = rb_hash_s_new(0, NULL, rb_cHash);
1683      rb_define_global_const("ENV", envtbl);
1684  #endif  /* ifndef __MACOS__  environment variables nothing on MacOS. */
1685  }