evilr 1.0.0-x86-mswin32-60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +19 -0
- data/README.rdoc +148 -0
- data/Rakefile +41 -0
- data/ext/evilr/evilr.c +993 -0
- data/ext/evilr/extconf.rb +7 -0
- data/lib/1.8/evilr.so +0 -0
- data/lib/1.9/evilr.so +0 -0
- data/lib/evilr.rb +1 -0
- data/spec/evilr_spec.rb +1157 -0
- metadata +88 -0
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
|
+
}
|