evilr 1.0.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
data/ext/evilr/evilr.c ADDED
@@ -0,0 +1,993 @@
1
+ #include <signal.h>
2
+ #include <string.h>
3
+ #include <stdio.h>
4
+ #include <sys/types.h>
5
+ #include <unistd.h>
6
+
7
+ #include <ruby.h>
8
+ #ifdef RUBY19
9
+ #include <ruby/st.h>
10
+ #else
11
+ #include <st.h>
12
+ #endif
13
+
14
+ /* ruby uses a magic number for this, arguably the only time
15
+ * it is more evil that evilr. */
16
+ #ifndef SAFE_LEVEL_MAX
17
+ #define SAFE_LEVEL_MAX 4
18
+ #endif
19
+
20
+ /* Partial struct definition == evil */
21
+ struct METHOD {
22
+ VALUE recv;
23
+ VALUE rclass;
24
+ ID id;
25
+ };
26
+
27
+ #ifdef RUBY19
28
+ struct BLOCK {
29
+ VALUE self;
30
+ VALUE *lfp;
31
+ VALUE *dfp;
32
+ void *block_iseq;
33
+ VALUE proc;
34
+ };
35
+ #else
36
+ /* More partial definition evil */
37
+ struct BLOCK {
38
+ void *var;
39
+ void *body;
40
+ VALUE self;
41
+ };
42
+ #endif
43
+
44
+ /* Ruby 1.8.6 support */
45
+ #ifndef RCLASS_SUPER
46
+ #define RCLASS_SUPER(c) RCLASS(c)->super
47
+ #endif
48
+ #ifndef RCLASS_IV_TBL
49
+ #define RCLASS_IV_TBL(c) RCLASS(c)->iv_tbl
50
+ #endif
51
+ #ifndef RCLASS_M_TBL
52
+ #define RCLASS_M_TBL(c) RCLASS(c)->m_tbl
53
+ #endif
54
+
55
+ #define OBJECT_SIZE sizeof(struct RClass)
56
+ #define RBASIC_SET_KLASS(o, c) (RBASIC(o)->klass = c)
57
+ #define RBASIC_KLASS(o) (RBASIC(o)->klass)
58
+ #define RBASIC_FLAGS(o) (RBASIC(o)->flags)
59
+ #define IS_SINGLETON_CLASS(o) (FL_TEST(o, FL_SINGLETON))
60
+ #define HAS_SINGLETON_CLASS(o) (FL_TEST(RBASIC_KLASS(o), FL_SINGLETON))
61
+
62
+ #ifdef RUBY19
63
+ #define RCLASS_SET_SUPER(o, c) (RCLASS(o)->ptr->super = c)
64
+ #else
65
+ #define RCLASS_SET_SUPER(o, c) (RCLASS(o)->super = c)
66
+ #define ROBJECT_IVPTR(o) (ROBJECT(o)->iv_tbl)
67
+ extern int ruby_safe_level;
68
+ #endif
69
+
70
+ VALUE empty;
71
+ ID evilr__attached;
72
+ ID evilr__bind;
73
+ ID evilr__clone;
74
+
75
+ /* Helper functions */
76
+
77
+ /* Raise TypeError if an immediate value is given. */
78
+ static void evilr__check_immediate(VALUE self) {
79
+ if (SPECIAL_CONST_P(self)) {
80
+ rb_raise(rb_eTypeError, "can't use immediate value");
81
+ }
82
+ }
83
+
84
+ /* Raise TypeError if either self or other is an immediate value. */
85
+ static void evilr__check_immediates(VALUE self, VALUE other) {
86
+ evilr__check_immediate(self);
87
+ evilr__check_immediate(other);
88
+ }
89
+
90
+ /* Raise TypeError if self doesn't have the given ruby internal type
91
+ * number (e.g. T_OBJECT). */
92
+ static void evilr__check_type(unsigned int type, VALUE self) {
93
+ if (BUILTIN_TYPE(self) != type) {
94
+ rb_raise(rb_eTypeError, "incompatible type used");
95
+ }
96
+ }
97
+
98
+ /* Return the ruby internal type number that instances of the
99
+ * given class use. */
100
+ static unsigned int evilr__class_type(VALUE klass) {
101
+ evilr__check_type(T_CLASS, klass);
102
+ return BUILTIN_TYPE(rb_obj_alloc(klass));
103
+ }
104
+
105
+ /* Raise TypeError if instances of the given class don't have the
106
+ * given ruby internal type number. */
107
+ static void evilr__check_class_type(unsigned int type, VALUE self) {
108
+ if (evilr__class_type(self) != type) {
109
+ rb_raise(rb_eTypeError, "incompatible type used");
110
+ }
111
+ }
112
+
113
+ /* Raise TypeError if the given value has the ruby internal type number T_DATA. */
114
+ static void evilr__check_data_type(VALUE self) {
115
+ if (BUILTIN_TYPE(self) == T_DATA) {
116
+ rb_raise(rb_eTypeError, "incompatible type used");
117
+ }
118
+ }
119
+
120
+ /* Return the next class in the super chain, skipping any iclasses (included modules).
121
+ * Returns NULL if this is the last class in the super chain. */
122
+ static VALUE evilr__next_class(VALUE klass) {
123
+ VALUE c;
124
+ for (c = RCLASS_SUPER(klass); c && BUILTIN_TYPE(c) != T_CLASS; c = RCLASS_SUPER(c)); /* empty */
125
+ return c;
126
+ }
127
+
128
+ /* If the given class includes no modules, return it. Otherwise, return the last iclass
129
+ * before the next class in the super chain. */
130
+ static VALUE evilr__iclass_before_next_class(VALUE klass) {
131
+ VALUE c, i = NULL;
132
+ for (c = RCLASS_SUPER(klass); c && BUILTIN_TYPE(c) != T_CLASS; i = c, c = RCLASS_SUPER(c)); /* empty */
133
+ return i == NULL ? klass : i;
134
+ }
135
+
136
+ /* Walk the super chain from klass until either before or an iclass for mod is encountered. If
137
+ * before is encountered first, return NULL. If an iclass for mod is encountered first, return
138
+ * the iclass. */
139
+ static VALUE evilr__iclass_matching_before(VALUE klass, VALUE mod, VALUE before) {
140
+ VALUE c;
141
+ for (c = RCLASS_SUPER(klass); c && c != before; c = RCLASS_SUPER(c)) {
142
+ if (BUILTIN_TYPE(c) == T_ICLASS && RBASIC_KLASS(c) == mod) {
143
+ return c;
144
+ }
145
+ }
146
+ return NULL;
147
+ }
148
+
149
+ /* If there is an iclass for mod anywhere in the super chain of klass, return the iclass.
150
+ * Otherwise, return NULL. */
151
+ static VALUE evilr__iclass_matching(VALUE klass, VALUE mod) {
152
+ return evilr__iclass_matching_before(klass, mod, NULL);
153
+ }
154
+
155
+ /* If self has a singleton class, set the superclass of the
156
+ * singleton class to the given klass, keeping all modules
157
+ * that are included in the singleton class. Otherwise, set the
158
+ * object's klass to the given klass. */
159
+ void evilr__reparent_singleton_class(VALUE self, VALUE klass) {
160
+ VALUE self_klass = RBASIC_KLASS(self);
161
+
162
+ if (IS_SINGLETON_CLASS(self_klass)) {
163
+ RCLASS_SET_SUPER(evilr__iclass_before_next_class(self_klass), klass);
164
+ rb_clear_cache_by_class(self_klass);
165
+ } else {
166
+ RBASIC_SET_KLASS(self, klass);
167
+ }
168
+ }
169
+
170
+ /* Set the superclass of self to the given klass, keeping all
171
+ * modules that are included in the class. */
172
+ void evilr__reparent_class(VALUE self, VALUE klass) {
173
+ RCLASS_SET_SUPER(evilr__iclass_before_next_class(self), klass);
174
+ rb_clear_cache_by_class(self);
175
+ }
176
+
177
+ /* Raise TypeError if self is an immediate value or if klass is
178
+ * not a Class. */
179
+ void evilr__check_obj_and_class(VALUE self, VALUE klass) {
180
+ evilr__check_immediates(self, klass);
181
+ evilr__check_type(T_CLASS, klass);
182
+ }
183
+
184
+ /* If no arguments are given, return Object. If an argument is
185
+ * given and it is a class object whose instances use the ruby
186
+ * internal class number T_OBJECT, return that class. If an argument
187
+ * is given and it isn't a class or it's instances don't use T_OBJECT,
188
+ * return a TypeError. Otherwise, return an ArgumentError. */
189
+ static VALUE evilr__optional_class(int argc, VALUE *argv) {
190
+ VALUE klass;
191
+
192
+ switch(argc) {
193
+ case 0:
194
+ klass = rb_cObject;
195
+ break;
196
+ case 1:
197
+ klass = argv[0];
198
+ evilr__check_class_type(T_OBJECT, klass);
199
+ break;
200
+ default:
201
+ rb_raise(rb_eArgError, "wrong number of arguments: %i for 1", argc);
202
+ break;
203
+ }
204
+ return klass;
205
+ }
206
+
207
+ /* Make the given klass the singleton class of self. */
208
+ void evilr__make_singleton(VALUE self, VALUE klass) {
209
+ FL_SET(klass, FL_SINGLETON);
210
+ RBASIC_SET_KLASS(self, klass);
211
+ rb_singleton_class_attached(klass, self);
212
+ }
213
+
214
+ /* Check that super is a Class object whose instances use the same internal
215
+ * type number as instances of klass, and that the instances don't use
216
+ * type number T_DATA. */
217
+ void evilr__check_compatible_classes(VALUE klass, VALUE super) {
218
+ evilr__check_immediate(super);
219
+ evilr__check_type(T_CLASS, super);
220
+ evilr__check_class_type(evilr__class_type(klass), super);
221
+ evilr__check_data_type(rb_obj_alloc(klass));
222
+ }
223
+
224
+ /* Walk the super chain starting with the given iclass and include
225
+ * the modules related to each iclass into the mod such that the
226
+ * order of the initial iclass super chain and mod's super chain are
227
+ * the same. */
228
+ void evilr__include_iclasses(VALUE mod, VALUE iclass) {
229
+ if (iclass && BUILTIN_TYPE(iclass) == T_ICLASS) {
230
+ evilr__include_iclasses(mod, RCLASS_SUPER(iclass));
231
+ rb_include_module(mod, RBASIC_KLASS(iclass));
232
+ }
233
+ rb_clear_cache_by_class(mod);
234
+ }
235
+
236
+ /* Ruby methods */
237
+
238
+ /* call-seq:
239
+ * class=(klass) -> Object
240
+ *
241
+ * Modifies the receiver's class to be +klass+. The receiver's current class
242
+ * and any singleton class (and any modules that extend the object) are
243
+ * ignored. If the receiver is an immediate or instances of +klass+ don't use the
244
+ * same internal type as the receiver, a +TypeError+ is raised.
245
+ */
246
+ static VALUE evilr_class_e(VALUE self, VALUE klass) {
247
+ evilr__check_immediate(self);
248
+ evilr__check_type(evilr__class_type(klass), self);
249
+ evilr__check_data_type(self);
250
+
251
+ RBASIC_SET_KLASS(self, klass);
252
+ return self;
253
+ }
254
+
255
+ /* call-seq:
256
+ * evilr_debug_print -> nil
257
+ *
258
+ * Prints to stdout the receiver and all entries in the receiver's klass's super chain,
259
+ * using the pointers of the current entry, it's klass, iv_tbl, m_tbl, and super entry,
260
+ * as well as the entry's flags. If Class or Module is given, uses their
261
+ * super chain, not the super chain of their klass. If the receiver is an immediate value,
262
+ * a +TypeError+ is raised. */
263
+ static VALUE evilr_debug_print(VALUE self) {
264
+ if (self == NULL) {
265
+ return Qnil;
266
+ }
267
+ evilr__check_immediate(self);
268
+ switch(BUILTIN_TYPE(self)) {
269
+ case T_CLASS:
270
+ case T_ICLASS:
271
+ case T_MODULE:
272
+ printf("self %p klass %p flags 0x%lx iv_tbl %p m_tbl %p super %p\n", (void *)self, (void *)RBASIC_KLASS(self), RBASIC_FLAGS(self), (void *)RCLASS_IV_TBL(self), (void *)RCLASS_M_TBL(self), (void *)RCLASS_SUPER(self));
273
+ self = RCLASS_SUPER(self);
274
+ break;
275
+ default:
276
+ printf("self %p klass %p flags 0x%lx iv_tbl/ptr %p\n", (void *)self, (void *)RBASIC_KLASS(self), RBASIC_FLAGS(self), (void *)ROBJECT_IVPTR(self));
277
+ self = RBASIC_KLASS(self);
278
+ break;
279
+ }
280
+ return evilr_debug_print(self);
281
+ }
282
+
283
+
284
+ /* call-seq:
285
+ * swap(other) -> self
286
+ *
287
+ * Swap the contents of the receiver with +other+:
288
+ *
289
+ * a = []
290
+ * b = {}
291
+ * a.swap(b) # => {}
292
+ * a # => {}
293
+ * b # => []
294
+ *
295
+ * You cannot swap a Class or Module except with another
296
+ * Class or Module, and you can only swap a Class with a Class and
297
+ * a Module with a Module (no swapping a Class with Module), and you
298
+ * cannot swap immediate values. If an invalid swap attempt is
299
+ * detected, a +TypeError+ is raised.*/
300
+ static VALUE evilr_swap(VALUE self, VALUE other) {
301
+ char tmp[OBJECT_SIZE];
302
+ evilr__check_immediates(self, other);
303
+ if ((BUILTIN_TYPE(self) == T_MODULE || BUILTIN_TYPE(self) == T_CLASS ||
304
+ BUILTIN_TYPE(other) == T_MODULE || BUILTIN_TYPE(other) == T_CLASS) &&
305
+ BUILTIN_TYPE(self) != BUILTIN_TYPE(other)) {
306
+ rb_raise(rb_eTypeError, "incompatible types used");
307
+ }
308
+ memcpy(tmp, ROBJECT(self), OBJECT_SIZE);
309
+ memcpy(ROBJECT(self), ROBJECT(other), OBJECT_SIZE);
310
+ memcpy(ROBJECT(other), tmp, OBJECT_SIZE);
311
+ return self;
312
+ }
313
+
314
+ /* call-seq:
315
+ * swap_instance_variables(other) -> self
316
+ *
317
+ * Swaps only the instance variables of the receiver and +other+.
318
+ * You can only swap the instance variables between two objects that
319
+ * use the internal type number T_OBJECT, or between Classes and Modules.
320
+ * You cannot swap instance variables of immediate values, since they
321
+ * do not have instance variables. Invalid swap attempts will raise
322
+ * +TypeError+. */
323
+ static VALUE evilr_swap_instance_variables(VALUE self, VALUE other) {
324
+ #ifndef RUBY19
325
+ struct st_table *tmp;
326
+ #endif
327
+ evilr__check_immediates(self, other);
328
+
329
+ switch(BUILTIN_TYPE(self)) {
330
+ case T_OBJECT:
331
+ if (BUILTIN_TYPE(other) != T_OBJECT) {
332
+ goto bad_types;
333
+ }
334
+ break;
335
+ case T_MODULE:
336
+ case T_CLASS:
337
+ if (BUILTIN_TYPE(other) != T_MODULE && BUILTIN_TYPE(other) != T_CLASS) {
338
+ goto bad_types;
339
+ }
340
+ break;
341
+ default:
342
+ bad_types:
343
+ rb_raise(rb_eTypeError, "incompatible types used");
344
+ }
345
+
346
+ #ifdef RUBY19
347
+ if (BUILTIN_TYPE(self) == T_MODULE || BUILTIN_TYPE(self) == T_CLASS) {
348
+ struct st_table *tmp;
349
+ tmp = RCLASS_IV_TBL(self);
350
+ RCLASS(self)->ptr->iv_tbl = RCLASS_IV_TBL(other);
351
+ RCLASS(other)->ptr->iv_tbl = tmp;
352
+ } else {
353
+ char tmp[OBJECT_SIZE];
354
+ memcpy(tmp, &(ROBJECT(self)->as), sizeof(ROBJECT(tmp)->as));
355
+ memcpy(&(ROBJECT(self)->as), &(ROBJECT(other)->as), sizeof(ROBJECT(self)->as));
356
+ memcpy(&(ROBJECT(other)->as), tmp, sizeof(ROBJECT(other)->as));
357
+ }
358
+ #else
359
+ /* RClass and RObject have iv_tbl at same position in the structure
360
+ * so no funny business is needed */
361
+ tmp = ROBJECT_IVPTR(self);
362
+ ROBJECT(self)->iv_tbl = ROBJECT_IVPTR(other);
363
+ ROBJECT(other)->iv_tbl = tmp;
364
+ #endif
365
+ return self;
366
+ }
367
+
368
+ /* call-seq:
369
+ * swap_method_tables(other) -> self
370
+ *
371
+ * Swap the method table of the receiver with the method table of the given
372
+ * class or module. If +other+ is not a class or module, raise a +TypeError+. */
373
+ static VALUE evilr_swap_method_tables(VALUE self, VALUE other) {
374
+ struct st_table *tmp;
375
+
376
+ evilr__check_immediate(other);
377
+ if(BUILTIN_TYPE(other) != T_MODULE && BUILTIN_TYPE(other) != T_CLASS) {
378
+ rb_raise(rb_eTypeError, "non-class or module used");
379
+ }
380
+
381
+ tmp = RCLASS_M_TBL(self);
382
+ RCLASS(self)->m_tbl = RCLASS_M_TBL(other);
383
+ RCLASS(other)->m_tbl = tmp;
384
+ rb_clear_cache_by_class(self);
385
+ rb_clear_cache_by_class(other);
386
+ return self;
387
+ }
388
+
389
+ /* call-seq:
390
+ * swap_singleton_class(other) -> self
391
+ *
392
+ * Swap the singleton classes of the receiver and +other+. If either
393
+ * the receiver or +other+ is an immediate, a +TypeError+ is raised.
394
+ * If either object does not have a singleton class, an empty singleton
395
+ * class is created for it before swapping. Any modules that extend
396
+ * either object are swapped as well.
397
+ * */
398
+ static VALUE evilr_swap_singleton_class(VALUE self, VALUE other) {
399
+ VALUE tmp;
400
+
401
+ evilr__check_immediates(self, other);
402
+
403
+ /* Create singleton classes to be swapped if they doesn't exist */
404
+ (void)rb_singleton_class(other);
405
+ (void)rb_singleton_class(self);
406
+
407
+ tmp = rb_obj_class(other);
408
+ evilr__reparent_singleton_class(other, rb_obj_class(self));
409
+ evilr__reparent_singleton_class(self, tmp);
410
+
411
+ tmp = RBASIC_KLASS(self);
412
+ RBASIC_SET_KLASS(self, RBASIC_KLASS(other));
413
+ RBASIC_SET_KLASS(other, tmp);
414
+
415
+ /* Attach each singleton class to its object */
416
+ rb_singleton_class_attached(RBASIC_KLASS(self), self);
417
+ rb_singleton_class_attached(RBASIC_KLASS(other), other);
418
+
419
+ return self;
420
+ }
421
+
422
+ /* call-seq:
423
+ * unfreeze -> self
424
+ *
425
+ * Unfreezes the given object. Will raise a +SecurityError+ if
426
+ * <tt>$SAFE</tt> > 0. Has no effect if the object is not yet frozen. */
427
+ static VALUE evilr_unfreeze(VALUE self) {
428
+ if (rb_safe_level() > 0) {
429
+ rb_raise(rb_eSecurityError, "can't unfreeze objects when $SAFE > 0");
430
+ }
431
+ FL_UNSET(self, FL_FREEZE);
432
+ return self;
433
+ }
434
+
435
+ /* call-seq:
436
+ * set_safe_level=(int) -> int
437
+ *
438
+ * Sets the <tt>$SAFE</tt> level to the given integer. If the number is
439
+ * greater than 4, sets it to 4. Allows lowering the <tt>$SAFE</tt> level
440
+ * by passing an integer lower than the current level. Returns the value
441
+ * passed in. */
442
+ static VALUE evilr_set_safe_level(VALUE self, VALUE safe) {
443
+ int s = NUM2INT(safe);
444
+ if (s > SAFE_LEVEL_MAX) {
445
+ s = SAFE_LEVEL_MAX;
446
+ }
447
+ #ifdef RUBY19
448
+ rb_set_safe_level_force(s);
449
+ #else
450
+ ruby_safe_level = s;
451
+ #endif
452
+ return safe;
453
+ }
454
+
455
+ /* call-seq:
456
+ * uninclude(mod) -> mod || nil
457
+ *
458
+ * Unincludes the given module +mod+ from the receiver or any of the receiver's
459
+ * ancestors. Walks the super chain of the receiver, and if an iclass for +mod+ is
460
+ * encountered, the super chain is modified to skip that iclass. Returns +mod+ if
461
+ * an iclass for mod was present in the super chain, and +nil+ otherwise. If +mod+ is
462
+ * not a Module, a +TypeError+ is raised. */
463
+ static VALUE evilr_uninclude(VALUE klass, VALUE mod) {
464
+ VALUE cur, prev;
465
+
466
+ evilr__check_immediate(mod);
467
+ evilr__check_type(T_MODULE, mod);
468
+
469
+ for (prev = klass, cur = RCLASS_SUPER(klass); cur ; prev = cur, cur = RCLASS_SUPER(cur)) {
470
+ if (BUILTIN_TYPE(prev) == T_CLASS) {
471
+ rb_clear_cache_by_class(prev);
472
+ }
473
+ if (BUILTIN_TYPE(cur) == T_ICLASS && RBASIC_KLASS(cur) == mod) {
474
+ RCLASS_SET_SUPER(prev, RCLASS_SUPER(cur));
475
+ return mod;
476
+ }
477
+ }
478
+
479
+ return Qnil;
480
+ }
481
+
482
+ /* call-seq:
483
+ * unextend(mod) -> mod || nil
484
+ *
485
+ * Unextends the given module +mod+ from the receiver. If the receiver's class includes the
486
+ * module, does not uninclude it, so this should not affect any other objects besides the
487
+ * receiver. If +mod+ already extended the object, returns +mod+, otherwise returns +nil+.
488
+ * Raises +TypeError+ if +mod+ is not a Module or if the receiver is an immediate. */
489
+ static VALUE evilr_unextend(VALUE self, VALUE mod) {
490
+ VALUE prev, cur;
491
+
492
+ evilr__check_immediates(self, mod);
493
+ evilr__check_type(T_MODULE, mod);
494
+
495
+ self = rb_singleton_class(self);
496
+ rb_clear_cache_by_class(self);
497
+ for (prev = self, cur = RCLASS_SUPER(self); cur && BUILTIN_TYPE(cur) != T_CLASS; prev = cur, cur = RCLASS_SUPER(cur)) {
498
+ if (BUILTIN_TYPE(cur) == T_ICLASS && RBASIC_KLASS(cur) == mod) {
499
+ RCLASS_SET_SUPER(prev, RCLASS_SUPER(cur));
500
+ return mod;
501
+ }
502
+ }
503
+
504
+ return Qnil;
505
+ }
506
+
507
+ #define INCLUDE_BETWEEN_VAL(x) (x) ? (BUILTIN_TYPE(x) == T_ICLASS ? RBASIC_KLASS(x) : (x)) : Qnil
508
+ /* call-seq:
509
+ * include_between(mod){|p, c| } -> mod || nil
510
+ *
511
+ * Walks the receiver's super chain, yielding the previous and current entries in
512
+ * the super chain at every step. The first time the block returns +true+, +mod+ is
513
+ * inserted into the super chain between the two values, and the method returns
514
+ * immediately. Raises +TypeError+ if +mod+ is not a Module.
515
+ * If the block ever returns +true+, the return value is +mod+. If
516
+ * the block never returns +true+, the return value is +nil+. On the first block call,
517
+ * the first block argument is the receiver, and on the last block call, the last block
518
+ * argument is +nil+. */
519
+ static VALUE evilr_include_between(VALUE klass, VALUE mod) {
520
+ VALUE iclass, prev, cur;
521
+
522
+ evilr__check_immediate(mod);
523
+ evilr__check_type(T_MODULE, mod);
524
+
525
+ /* Create ICLASS for module by inserting it and removing it.
526
+ * If module already in super chain, will change it's position. */
527
+ rb_include_module(klass, mod);
528
+ iclass = evilr__iclass_matching(klass, mod);
529
+ evilr_uninclude(klass, mod);
530
+
531
+ for (prev = klass, cur = RCLASS_SUPER(klass); prev ; prev = cur, cur = cur ? RCLASS_SUPER(cur) : cur) {
532
+ if (BUILTIN_TYPE(prev) == T_CLASS) {
533
+ rb_clear_cache_by_class(prev);
534
+ }
535
+ if (rb_yield_values(2, INCLUDE_BETWEEN_VAL(prev), INCLUDE_BETWEEN_VAL(cur)) == Qtrue) {
536
+ RCLASS_SET_SUPER(prev, iclass);
537
+ RCLASS_SET_SUPER(iclass, cur);
538
+ return mod;
539
+ }
540
+ }
541
+ return Qnil;
542
+ }
543
+
544
+ /* call-seq:
545
+ * extend_between(mod){|p, c| } -> mod || nil
546
+ *
547
+ * Walks the receiver's singleton class's super chain until it reaches the receiver's
548
+ * class, yielding the previous and current entries in the super chain at every step.
549
+ * The first time the block returns +true+, +mod+ is inserted into the super chain
550
+ * between the two values and the method returns immediately. Raises +TypeError+ if
551
+ * +mod+ is not a Module or if the receiver is an immediate.
552
+ * If the block ever returns +true+, the return value is
553
+ * +mod+. If the block never returns +true+, the return value is +nil+. On the first block call,
554
+ * the first block argument is the receiver's singleton class, and on the last block call,
555
+ * the last block argument is the receiver's class. */
556
+ static VALUE evilr_extend_between(VALUE self, VALUE mod) {
557
+ VALUE sc, iclass, klass, prev, cur;
558
+
559
+ evilr__check_immediates(self, mod);
560
+ evilr__check_type(T_MODULE, mod);
561
+
562
+ sc = rb_singleton_class(self);
563
+ klass = rb_obj_class(self);
564
+ rb_extend_object(self, mod);
565
+ iclass = evilr__iclass_matching_before(sc, mod, klass);
566
+ if (iclass == NULL) {
567
+ rb_raise(rb_eArgError, "module already included in object's class");
568
+ }
569
+ evilr_unextend(self, mod);
570
+
571
+ for (prev = sc, cur = RCLASS_SUPER(sc); prev && prev != klass; prev = cur, cur = cur ? RCLASS_SUPER(cur) : cur) {
572
+ if (rb_yield_values(2, INCLUDE_BETWEEN_VAL(prev), INCLUDE_BETWEEN_VAL(cur)) == Qtrue) {
573
+ RCLASS_SET_SUPER(prev, iclass);
574
+ RCLASS_SET_SUPER(iclass, cur);
575
+ return mod;
576
+ }
577
+ }
578
+ return Qnil;
579
+ }
580
+
581
+ /* call-seq:
582
+ * detach_singleton -> self
583
+ *
584
+ * If the receiver is a singleton class, it is transformed into a
585
+ * regular class and it is detached from the instance. Note that
586
+ * this means it becomes the class of the object to which it was previous
587
+ * attached. If the receiver is not a singleton class, has no effect.
588
+ * Returns the receiver. */
589
+ static VALUE evilr_detach_singleton(VALUE klass) {
590
+ if (IS_SINGLETON_CLASS(klass)) {
591
+ FL_UNSET(klass, FL_SINGLETON);
592
+ if (RCLASS_IV_TBL(klass)) {
593
+ st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&evilr__attached, 0);
594
+ }
595
+ }
596
+ return klass;
597
+ }
598
+
599
+ /* call-seq:
600
+ * detach_singleton_class -> Class
601
+ *
602
+ * If the receiver has a singleton class, it is detached from the
603
+ * receiver and becomes the receiver's class. If the receiver is
604
+ * an immediate, a +TypeError+ is raised. Returns the (possibly new) class
605
+ * of the receiver. */
606
+ static VALUE evilr_detach_singleton_class(VALUE self) {
607
+ evilr__check_immediate(self);
608
+ return evilr_detach_singleton(RBASIC_KLASS(self));
609
+ }
610
+
611
+ /* call-seq:
612
+ * dup_singleton_class(klass=Object) -> Class || nil
613
+ *
614
+ * If the receiver has a singleton class, a copy of the class is returned,
615
+ * and the superclass of that class is set to the given +klass+. Any
616
+ * modules that extend the object become modules included in the returned class.
617
+ * If the receiver does not have a singleton class, +nil+ is returned and no
618
+ * changes are made. If the receiver is an immediate, a +TypeError+ is raised. */
619
+ static VALUE evilr_dup_singleton_class(int argc, VALUE *argv, VALUE self) {
620
+ VALUE klass;
621
+ evilr__check_immediate(self);
622
+
623
+ if (!HAS_SINGLETON_CLASS(self)) {
624
+ return Qnil;
625
+ }
626
+ klass = evilr__optional_class(argc, argv);
627
+ self = rb_singleton_class_clone(self);
628
+ evilr__reparent_class(self, klass);
629
+ FL_UNSET(self, FL_SINGLETON);
630
+ return self;
631
+ }
632
+
633
+ /* call-seq:
634
+ * push_singleton_class(klass) -> klass
635
+ *
636
+ * Makes the given class the closest singleton class of the receiver, without changing any
637
+ * existing singleton class relationships. Designed to be used with +pop_singleton_class+
638
+ * to implement a method table stack on an object. If the receiver is an immediate or
639
+ * +klass+ is not a class, raises +TypeError+. */
640
+ static VALUE evilr_push_singleton_class(VALUE self, VALUE klass) {
641
+ evilr__check_obj_and_class(self, klass);
642
+ evilr__reparent_class(evilr__iclass_before_next_class(klass), RBASIC_KLASS(self));
643
+ evilr__make_singleton(self, klass);
644
+ return klass;
645
+ }
646
+
647
+ /* call-seq:
648
+ * pop_singleton_class -> Class || nil
649
+ *
650
+ * Removes the closest singleton class from the receiver and returns it.
651
+ * If the receiver does not have a singleton class, does nothing and returns +nil+.
652
+ * Designed to be used with +push_singleton_class+
653
+ * to implement a method table stack on an object. If the receiver is an immediate,
654
+ * raises +TypeError+. */
655
+ static VALUE evilr_pop_singleton_class(VALUE self) {
656
+ VALUE klass;
657
+
658
+ evilr__check_immediate(self);
659
+ klass = RBASIC_KLASS(self);
660
+
661
+ if (IS_SINGLETON_CLASS(klass)) {
662
+ RBASIC_SET_KLASS(self, evilr__next_class(klass));
663
+ } else {
664
+ klass = Qnil;
665
+ }
666
+ return klass;
667
+ }
668
+
669
+ /* call-seq:
670
+ * remove_singleton_classes -> nil
671
+ *
672
+ * Removes all singleton classes from the receiver. Designed to be used with
673
+ * +push_singleton_class+ and +pop_singleton_class+ to implement a method table
674
+ * stack on an object, this clears the stack. If the receiver is an immediate,
675
+ * raises +TypeError+. */
676
+ static VALUE evilr_remove_singleton_classes(VALUE self) {
677
+ evilr__check_immediate(self);
678
+ RBASIC_SET_KLASS(self, rb_obj_class(self));
679
+ return Qnil;
680
+ }
681
+
682
+ /* call-seq:
683
+ * set_singleton_class(klass) -> klass
684
+ *
685
+ * Makes the given +klass+ the singleton class of the receiver,
686
+ * ignoring any existing singleton class and modules extending the receiver.
687
+ * Modules already included in +klass+ become modules that extend the receiver.
688
+ * If the receiver is an immediate or +klass+ is not a Class,
689
+ * raises +TypeError+. */
690
+ static VALUE evilr_set_singleton_class(VALUE self, VALUE klass) {
691
+ evilr__check_obj_and_class(self, klass);
692
+ RCLASS_SET_SUPER(evilr__iclass_before_next_class(klass), rb_obj_class(self));
693
+ rb_clear_cache_by_class(klass);
694
+ evilr__make_singleton(self, klass);
695
+ return klass;
696
+ }
697
+
698
+ /* call-seq:
699
+ * remove_singleton_class -> klass || nil
700
+ *
701
+ * Removes the singleton class of the receiver, detaching it from the
702
+ * receiver and making it a regular class. If the receiver does not
703
+ * currently have a singleton class, returns +nil+. If the receiver is an
704
+ * immediate, raises +TypeError+. */
705
+ static VALUE evilr_remove_singleton_class(VALUE self) {
706
+ VALUE klass;
707
+ evilr__check_immediate(self);
708
+
709
+ if (HAS_SINGLETON_CLASS(self)) {
710
+ klass = evilr_detach_singleton_class(self);
711
+ RBASIC_SET_KLASS(self, evilr__next_class(klass));
712
+ } else {
713
+ klass = Qnil;
714
+ }
715
+ return klass;
716
+ }
717
+
718
+ /* call-seq:
719
+ * singleton_class_instance -> Object || nil
720
+ *
721
+ * Returns the object attached to the singleton class.
722
+ * If the class does not have an object attached to it (possibly because
723
+ * it isn't a singleton class), returns +nil+. */
724
+ static VALUE evilr_singleton_class_instance(VALUE klass) {
725
+ VALUE obj;
726
+ if(RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), evilr__attached, &obj)) {
727
+ return obj;
728
+ }
729
+ return Qnil;
730
+ }
731
+
732
+ /* call-seq:
733
+ * to_module -> Module
734
+ *
735
+ * Makes a copy of the class, converts the copy to a module, and returns it. The
736
+ * returned module can be included in other classes. */
737
+ static VALUE evilr_to_module(VALUE klass) {
738
+ VALUE mod, iclass;
739
+
740
+ if (IS_SINGLETON_CLASS(klass)) {
741
+ if((mod = evilr_singleton_class_instance(klass))) {
742
+ mod = rb_singleton_class_clone(mod);
743
+ (void)evilr_detach_singleton(mod);
744
+ } else {
745
+ rb_raise(rb_eTypeError, "singleton class without attached instance");
746
+ }
747
+ } else {
748
+ mod = rb_obj_clone(klass);
749
+ }
750
+
751
+ RBASIC_SET_KLASS(mod, rb_cModule);
752
+ iclass = RCLASS_SUPER(mod);
753
+ RCLASS_SET_SUPER(mod, NULL);
754
+ FL_UNSET(mod, T_MASK);
755
+ FL_SET(mod, T_MODULE);
756
+ evilr__include_iclasses(mod, iclass);
757
+
758
+ return mod;
759
+ }
760
+
761
+ /* call-seq:
762
+ * to_class(klass=Object) -> Class
763
+ *
764
+ * Makes a copy of the module, converts the copy to a class, and returns it. The
765
+ * returned class can then have instances created from it. The +klass+ argument
766
+ * sets the superclass of the returned class. If +klass+ is not a Class,
767
+ * raises +TypeError+. */
768
+ static VALUE evilr_to_class(int argc, VALUE *argv, VALUE self) {
769
+ VALUE klass = evilr__optional_class(argc, argv);
770
+
771
+ self = rb_obj_clone(self);
772
+ RBASIC_SET_KLASS(self, rb_singleton_class(klass));
773
+ RCLASS_SET_SUPER(self, klass);
774
+ FL_UNSET(self, T_MASK);
775
+ FL_SET(self, T_CLASS);
776
+ return self;
777
+ }
778
+
779
+ /* call-seq:
780
+ * flags -> Integer
781
+ *
782
+ * Returns the internal flags value of the receiver as an +Integer+. Raises +TypeError+
783
+ * if the receiver is an immediate. */
784
+ static VALUE evilr_flags(VALUE self) {
785
+ evilr__check_immediate(self);
786
+ return UINT2NUM(RBASIC_FLAGS(self));
787
+ }
788
+
789
+ /* call-seq:
790
+ * superclass=(klass) -> klass
791
+ *
792
+ * Modifies the superclass of the current class to be the given
793
+ * class. Any modules included in the receiver remain included.
794
+ * Raises +TypeError+ if klass is not a Class or if the receiver
795
+ * and class are not compatible (where their instances use
796
+ * different internal types). */
797
+ static VALUE evilr_superclass_e(VALUE klass, VALUE super) {
798
+ VALUE iclass;
799
+ evilr__check_compatible_classes(klass, super);
800
+ iclass = evilr__iclass_before_next_class(klass);
801
+ RCLASS_SET_SUPER(iclass, super);
802
+ rb_clear_cache_by_class(klass);
803
+ return super;
804
+ }
805
+
806
+ /* call-seq:
807
+ * inherit(*classes) -> self
808
+ *
809
+ * Make copies of all given +classes+ as modules, and includes
810
+ * those modules in the receiver. Raises +TypeError+ if any of the
811
+ * +classes+ is not a Class or is not compatible with the receiver. */
812
+ static VALUE evilr_inherit(int argc, VALUE* argv, VALUE klass) {
813
+ int i;
814
+
815
+ for(i = 0; i < argc; i++) {
816
+ evilr__check_compatible_classes(klass, argv[i]);
817
+ rb_include_module(klass, evilr_to_module(argv[i]));
818
+ }
819
+
820
+ return klass;
821
+ }
822
+
823
+ /* call-seq:
824
+ * force_bind(object) -> Method
825
+ *
826
+ * Returns a +Method+ object bound to the given object. Doesn't
827
+ * check that the method is compatible with the object, unlike +bind+. */
828
+ static VALUE evilr_force_bind(VALUE self, VALUE obj) {
829
+ struct METHOD *data;
830
+
831
+ evilr__check_immediate(obj);
832
+ self = rb_funcall(self, evilr__clone, 0);
833
+ /* Data_Get_Struct seems to complain about types on 1.9,
834
+ * so skip the type check. */
835
+ data = (struct METHOD*)DATA_PTR(self);
836
+ data->rclass = CLASS_OF(obj);
837
+ return rb_funcall(self, evilr__bind, 1, obj);
838
+ }
839
+
840
+ /* call-seq:
841
+ * self -> Object
842
+ *
843
+ * Returns the self of the receiver, which is the default context
844
+ * used in evaluating the receiver. */
845
+ static VALUE evilr_self(VALUE self) {
846
+ struct BLOCK *data;
847
+ data = (struct BLOCK*)DATA_PTR(self);
848
+ return data->self;
849
+ }
850
+
851
+ /* call-seq:
852
+ * self=(object) -> object
853
+ *
854
+ * Sets the self of the receiver to the given object, modifying the
855
+ * used in evaluating the receiver. Example:
856
+ *
857
+ * p = Proc.new{self[:a]}
858
+ * h1 = {:a=>1}
859
+ * h2 = {:a=>2}
860
+ * p.self = h1
861
+ * p.call # => 1
862
+ * p.self = h2
863
+ * p.call # => 2
864
+ * */
865
+ static VALUE evilr_self_e(VALUE self, VALUE obj) {
866
+ struct BLOCK *data;
867
+ data = (struct BLOCK*)DATA_PTR(self);
868
+ data->self = obj;
869
+ return data->self;
870
+ }
871
+
872
+ /* call-seq:
873
+ * segfault
874
+ *
875
+ * Dereferences the NULL pointer, which should cause SIGSEGV
876
+ * (a segmentation fault), and the death of the process, though
877
+ * it could possibly be rescued. */
878
+ static VALUE evilr_segfault(VALUE self) {
879
+ self = *(char *)NULL;
880
+ return self;
881
+ }
882
+
883
+ /* call-seq:
884
+ * seppuku
885
+ *
886
+ * Kills the current process with SIGKILL, which should
887
+ * terminate the process immediately without any recovery possible. */
888
+ static VALUE evilr_seppuku(VALUE self) {
889
+ kill(getpid(), SIGKILL);
890
+ return self;
891
+ }
892
+
893
+ /* call-seq:
894
+ * allocate -> object
895
+ *
896
+ * Allocate memory for the new instance. Basically a copy of
897
+ * +rb_class_allocate_instance+. */
898
+ static VALUE evilr_empty_alloc(VALUE klass) {
899
+ NEWOBJ(obj, struct RObject);
900
+ OBJSETUP(obj, klass, T_OBJECT);
901
+ return (VALUE)obj;
902
+ }
903
+
904
+ /* call-seq:
905
+ * new(*args)-> object
906
+ *
907
+ * Allocates memory for the instance and then calls initialize
908
+ * on the object. */
909
+ static VALUE evilr_empty_new(int argc, VALUE* argv, VALUE klass) {
910
+ VALUE obj;
911
+ obj = evilr_empty_alloc(klass);
912
+ rb_obj_call_init(obj, argc, argv);
913
+ return obj;
914
+ }
915
+
916
+ /* call-seq:
917
+ * superclass -> Class || nil
918
+ *
919
+ * Returns the superclass of the class, or nil if current class is
920
+ * +Empty+. Basically a copy of the standard superclass method,
921
+ * without some checking. */
922
+ static VALUE evilr_empty_superclass(VALUE klass) {
923
+ return klass == empty ? Qnil : evilr__next_class(klass);
924
+ }
925
+
926
+ /* call-seq:
927
+ * initialize -> self
928
+ *
929
+ * Returns the receiver. */
930
+ static VALUE evilr_empty_initialize(VALUE self) {
931
+ return self;
932
+ }
933
+
934
+ /* Empty is an almost completely empty class, even more basic than
935
+ * BasicObject. It has no parent class, and only implements
936
+ * +allocate+, +new+, +initialize+, and +superclass+. All other
937
+ * behavior must be added by the user. Note that if you want to
938
+ * call a method defined in Object, Kernel, or BasicObject that
939
+ * isn't defined in Empty, you can use <tt>UndefinedMethod#force_bind</tt>,
940
+ * to do so:
941
+ *
942
+ * Object.instance_method(:puts).force_bind(Empty.new).call()
943
+ */
944
+ void Init_evilr(void) {
945
+ empty = rb_define_class("Empty", rb_cObject);
946
+ rb_define_alloc_func(empty, evilr_empty_alloc);
947
+ rb_define_singleton_method(empty, "new", evilr_empty_new, -1);
948
+ rb_define_singleton_method(empty, "superclass", evilr_empty_superclass, 0);
949
+ rb_define_method(empty, "initialize", evilr_empty_initialize, 0);
950
+ RCLASS_SET_SUPER(empty, NULL);
951
+ rb_global_variable(&empty);
952
+
953
+ evilr__attached = rb_intern("__attached__");
954
+ evilr__bind = rb_intern("bind");
955
+ evilr__clone = rb_intern("clone");
956
+
957
+ rb_define_method(rb_cObject, "class=", evilr_class_e, 1);
958
+ rb_define_method(rb_cObject, "evilr_debug_print", evilr_debug_print, 0);
959
+ rb_define_method(rb_cObject, "extend_between", evilr_extend_between, 1);
960
+ rb_define_method(rb_cObject, "flags", evilr_flags, 0);
961
+ rb_define_method(rb_cObject, "detach_singleton_class", evilr_detach_singleton_class, 0);
962
+ rb_define_method(rb_cObject, "dup_singleton_class", evilr_dup_singleton_class, -1);
963
+ rb_define_method(rb_cObject, "pop_singleton_class", evilr_pop_singleton_class, 0);
964
+ rb_define_method(rb_cObject, "push_singleton_class", evilr_push_singleton_class, 1);
965
+ rb_define_method(rb_cObject, "remove_singleton_class", evilr_remove_singleton_class, 0);
966
+ rb_define_method(rb_cObject, "remove_singleton_classes", evilr_remove_singleton_classes, 0);
967
+ rb_define_method(rb_cObject, "set_singleton_class", evilr_set_singleton_class, 1);
968
+ rb_define_method(rb_cObject, "swap", evilr_swap, 1);
969
+ rb_define_method(rb_cObject, "swap_instance_variables", evilr_swap_instance_variables, 1);
970
+ rb_define_method(rb_cObject, "swap_singleton_class", evilr_swap_singleton_class, 1);
971
+ rb_define_method(rb_cObject, "unextend", evilr_unextend, 1);
972
+ rb_define_method(rb_cObject, "unfreeze", evilr_unfreeze, 0);
973
+
974
+ rb_define_method(rb_mKernel, "segfault", evilr_segfault, 0);
975
+ rb_define_method(rb_mKernel, "seppuku", evilr_seppuku, 0);
976
+ rb_define_method(rb_mKernel, "set_safe_level", evilr_set_safe_level, 1);
977
+
978
+ rb_define_method(rb_cModule, "include_between", evilr_include_between, 1);
979
+ rb_define_method(rb_cModule, "swap_method_tables", evilr_swap_method_tables, 1);
980
+ rb_define_method(rb_cModule, "to_class", evilr_to_class, -1);
981
+ rb_define_method(rb_cModule, "uninclude", evilr_uninclude, 1);
982
+
983
+ rb_define_method(rb_cClass, "detach_singleton", evilr_detach_singleton, 0);
984
+ rb_define_method(rb_cClass, "inherit", evilr_inherit, -1);
985
+ rb_define_method(rb_cClass, "singleton_class_instance", evilr_singleton_class_instance, 0);
986
+ rb_define_method(rb_cClass, "superclass=", evilr_superclass_e, 1);
987
+ rb_define_method(rb_cClass, "to_module", evilr_to_module, 0);
988
+
989
+ rb_define_method(rb_cUnboundMethod, "force_bind", evilr_force_bind, 1);
990
+
991
+ rb_define_method(rb_cProc, "self", evilr_self, 0);
992
+ rb_define_method(rb_cProc, "self=", evilr_self_e, 1);
993
+ }