hash.c
DEFINITIONS
This source file includes following functions.
- rb_hash_modify
- rb_hash_freeze
- rb_hash
- eql
- rb_any_cmp
- rb_any_hash
- rb_hash_foreach_iter
- rb_hash_foreach_call
- rb_hash_foreach_ensure
- rb_hash_foreach
- rb_hash_s_alloc
- rb_hash_new
- rb_hash_initialize
- rb_hash_s_create
- to_hash
- rb_hash_rehash_i
- rb_hash_rehash
- rb_hash_aref
- rb_hash_fetch
- rb_hash_default
- rb_hash_set_default
- rb_hash_default_proc
- index_i
- rb_hash_index
- rb_hash_indexes
- rb_hash_delete
- shift_i
- rb_hash_shift
- delete_if_i
- rb_hash_delete_if
- rb_hash_reject_bang
- rb_hash_reject
- select_i
- rb_hash_select
- clear_i
- rb_hash_clear
- rb_hash_aset
- replace_i
- rb_hash_become
- rb_hash_size
- rb_hash_empty_p
- each_value_i
- rb_hash_each_value
- each_key_i
- rb_hash_each_key
- each_pair_i
- rb_hash_each_pair
- to_a_i
- rb_hash_to_a
- rb_hash_sort
- inspect_i
- inspect_hash
- rb_hash_inspect
- to_s_hash
- rb_hash_to_s
- rb_hash_to_hash
- keys_i
- rb_hash_keys
- values_i
- rb_hash_values
- rb_hash_has_key
- rb_hash_search_value
- rb_hash_has_value
- equal_i
- rb_hash_equal
- rb_hash_invert_i
- rb_hash_invert
- rb_hash_update_i
- rb_hash_update_block_i
- rb_hash_update
- env_delete
- env_delete_m
- rb_f_getenv
- env_fetch
- path_tainted_p
- rb_env_path_tainted
- envix
- ruby_setenv
- ruby_unsetenv
- env_aset
- env_keys
- env_each_key
- env_values
- env_each_value
- env_each
- env_reject_bang
- env_delete_if
- env_select
- env_to_s
- env_inspect
- env_to_a
- env_none
- env_size
- env_empty_p
- env_has_key
- env_has_value
- env_index
- env_indexes
- env_to_hash
- env_reject
- Init_Hash
1
2
3
4
5
6
7
8
9
10
11
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;
1083 }
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
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
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
1120
1121 int i=envix(name);
1122
1123 if (environ == origenviron) {
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++)
1131 tmpenv[j] = strdup(environ[j]);
1132 tmpenv[max] = 0;
1133 environ = tmpenv;
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]) {
1149 REALLOC_N(environ, char*, i+2);
1150 environ[i+1] = 0;
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);
1159 #else
1160
1161
1162
1163
1164
1165 strcpy(environ[i],name); strupr(environ[i]);
1166 sprintf(environ[i] + strlen(name),"=%s", value);
1167 #endif
1168
1169 #endif
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
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__
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
1682 envtbl = rb_hash_s_new(0, NULL, rb_cHash);
1683 rb_define_global_const("ENV", envtbl);
1684 #endif
1685 }