~ubuntu-branches/ubuntu/trusty/ruby1.9/trusty

« back to all changes in this revision

Viewing changes to marshal.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephan Hermann
  • Date: 2008-01-24 11:42:29 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20080124114229-jw2f87rdxlq6gp11
Tags: 1.9.0.0-2ubuntu1
* Merge from debian unstable, remaining changes:
  - Robustify check for target_os, fixing build failure on lpia.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
  marshal.c -
4
4
 
5
 
  $Author: akr $
6
 
  $Date: 2007-08-30 08:12:21 +0900 (木, 30  8月 2007) $
 
5
  $Author: matz $
 
6
  $Date: 2007-11-22 10:17:52 +0900 (Thu, 22 Nov 2007) $
7
7
  created at: Thu Apr 27 16:30:01 JST 1995
8
8
 
9
9
  Copyright (C) 1993-2007 Yukihiro Matsumoto
14
14
#include "ruby/io.h"
15
15
#include "ruby/st.h"
16
16
#include "ruby/util.h"
 
17
#include "ruby/encoding.h"
17
18
 
18
19
#include <math.h>
19
20
#ifdef HAVE_FLOAT_H
82
83
static ID s_dump_data, s_load_data, s_alloc;
83
84
static ID s_getc, s_read, s_write, s_binmode;
84
85
 
 
86
ID rb_id_encoding(void);
 
87
 
 
88
typedef struct {
 
89
    VALUE newclass;
 
90
    VALUE oldclass;
 
91
    VALUE (*dumper)(VALUE);
 
92
    VALUE (*loader)(VALUE, VALUE);
 
93
} marshal_compat_t;
 
94
 
 
95
static st_table *compat_allocator_tbl;
 
96
static VALUE compat_allocator_tbl_wrapper;
 
97
 
 
98
static int
 
99
mark_marshal_compat_i(st_data_t key, st_data_t value)
 
100
{
 
101
    marshal_compat_t *p = (marshal_compat_t *)value;
 
102
    rb_gc_mark(p->newclass);
 
103
    rb_gc_mark(p->oldclass);
 
104
    return ST_CONTINUE;
 
105
}
 
106
 
 
107
static void
 
108
mark_marshal_compat_t(void *tbl)
 
109
{
 
110
    if (!tbl) return;
 
111
    st_foreach(tbl, mark_marshal_compat_i, 0);
 
112
}
 
113
 
 
114
void
 
115
rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE))
 
116
{
 
117
    marshal_compat_t *compat;
 
118
    rb_alloc_func_t allocator = rb_get_alloc_func(newclass);
 
119
 
 
120
    if (!allocator) {
 
121
        rb_raise(rb_eTypeError, "no allocator");
 
122
    }
 
123
 
 
124
    compat = ALLOC(marshal_compat_t);
 
125
    compat->newclass = Qnil;
 
126
    compat->oldclass = Qnil;
 
127
    compat->newclass = newclass;
 
128
    compat->oldclass = oldclass;
 
129
    compat->dumper = dumper;
 
130
    compat->loader = loader;
 
131
 
 
132
    st_insert(compat_allocator_tbl, (st_data_t)allocator, (st_data_t)compat);
 
133
}
 
134
 
85
135
struct dump_arg {
86
136
    VALUE obj;
87
137
    VALUE str, dest;
88
138
    st_table *symbols;
89
139
    st_table *data;
90
140
    int taint;
 
141
    st_table *compat_tbl;
 
142
    VALUE wrapper;
 
143
    st_table *encodings;
91
144
};
92
145
 
93
146
struct dump_call_arg {
96
149
    int limit;
97
150
};
98
151
 
 
152
static void
 
153
mark_dump_arg(void *ptr)
 
154
{
 
155
    struct dump_arg *p = ptr;
 
156
    if (!ptr)
 
157
        return;
 
158
    rb_mark_set(p->data);
 
159
    rb_mark_hash(p->compat_tbl);
 
160
}
 
161
 
99
162
static VALUE
100
163
class2path(VALUE klass)
101
164
{
276
339
static void
277
340
w_float(double d, struct dump_arg *arg)
278
341
{
279
 
    char buf[100];
 
342
    char buf[FLOAT_DIG + (DECIMAL_MANT + 7) / 8 + 10];
280
343
 
281
344
    if (isinf(d)) {
282
345
        if (d < 0) strcpy(buf, "-inf");
293
356
        int len;
294
357
 
295
358
        /* xxx: should not use system's sprintf(3) */
296
 
        sprintf(buf, "%.*g", FLOAT_DIG, d);
 
359
        snprintf(buf, sizeof(buf), "%.*g", FLOAT_DIG, d);
297
360
        len = strlen(buf);
298
361
        w_bytes(buf, len + save_mantissa(d, buf + len), arg);
299
362
        return;
313
376
    }
314
377
    else {
315
378
        sym = rb_id2name(id);
 
379
        if (!sym) {
 
380
            rb_raise(rb_eTypeError, "can't dump anonymous ID %ld", id);
 
381
        }
316
382
        w_byte(TYPE_SYMBOL, arg);
317
383
        w_bytes(sym, strlen(sym), arg);
318
384
        st_add_direct(arg->symbols, id, arg->symbols->num_entries);
344
410
    char *path;
345
411
 
346
412
    if (check && FL_TEST(klass, FL_SINGLETON)) {
347
 
        if (RCLASS(klass)->m_tbl->num_entries ||
348
 
            (RCLASS(klass)->iv_tbl && RCLASS(klass)->iv_tbl->num_entries > 1)) {
 
413
        if (RCLASS_M_TBL(klass)->num_entries ||
 
414
            (RCLASS_IV_TBL(klass) && RCLASS_IV_TBL(klass)->num_entries > 1)) {
349
415
            rb_raise(rb_eTypeError, "singleton can't be dumped");
350
416
        }
351
 
        klass = RCLASS(klass)->super;
 
417
        klass = RCLASS_SUPER(klass);
352
418
    }
353
419
    while (BUILTIN_TYPE(klass) == T_ICLASS) {
354
420
        path = rb_class2name(RBASIC(klass)->klass);
355
421
        w_byte(TYPE_EXTENDED, arg);
356
422
        w_unique(path, arg);
357
 
        klass = RCLASS(klass)->super;
 
423
        klass = RCLASS_SUPER(klass);
358
424
    }
359
425
}
360
426
 
363
429
{
364
430
    volatile VALUE p;
365
431
    char *path;
 
432
    st_data_t real_obj;
 
433
    VALUE klass;
366
434
 
367
 
    VALUE klass = CLASS_OF(obj);
 
435
    if (st_lookup(arg->compat_tbl, (st_data_t)obj, &real_obj)) {
 
436
        obj = (VALUE)real_obj;
 
437
    }
 
438
    klass = CLASS_OF(obj);
368
439
    w_extended(klass, arg, check);
369
440
    w_byte(type, arg);
370
441
    p = class2path(rb_class_real(klass));
373
444
}
374
445
 
375
446
static void
376
 
w_uclass(VALUE obj, VALUE base_klass, struct dump_arg *arg)
 
447
w_uclass(VALUE obj, VALUE super, struct dump_arg *arg)
377
448
{
378
449
    VALUE klass = CLASS_OF(obj);
379
450
 
380
451
    w_extended(klass, arg, Qtrue);
381
452
    klass = rb_class_real(klass);
382
 
    if (klass != base_klass) {
 
453
    if (klass != super) {
383
454
        w_byte(TYPE_UCLASS, arg);
384
455
        w_unique(RSTRING_PTR(class2path(klass)), arg);
385
456
    }
388
459
static int
389
460
w_obj_each(ID id, VALUE value, struct dump_call_arg *arg)
390
461
{
 
462
    if (id == rb_id_encoding()) return ST_CONTINUE;
391
463
    w_symbol(id, arg->arg);
392
464
    w_object(value, arg->arg, arg->limit);
393
465
    return ST_CONTINUE;
394
466
}
395
467
 
396
468
static void
397
 
w_ivar(st_table *tbl, struct dump_call_arg *arg)
398
 
{
 
469
w_encoding(VALUE obj, long num, struct dump_call_arg *arg)
 
470
{
 
471
    int encidx = rb_enc_get_index(obj);
 
472
    rb_encoding *enc = 0;
 
473
    st_data_t name;
 
474
 
 
475
    if (encidx <= 0 || !(enc = rb_enc_from_index(encidx))) {
 
476
        w_long(num, arg->arg);
 
477
        return;
 
478
    }
 
479
    w_long(num + 1, arg->arg);
 
480
    w_symbol(rb_id_encoding(), arg->arg);
 
481
    do {
 
482
        if (!arg->arg->encodings)
 
483
            arg->arg->encodings = st_init_strcasetable();
 
484
        else if (st_lookup(arg->arg->encodings, (st_data_t)rb_enc_name(enc), &name))
 
485
            break;
 
486
        name = (st_data_t)rb_str_new2(rb_enc_name(enc));
 
487
        st_insert(arg->arg->encodings, (st_data_t)rb_enc_name(enc), name);
 
488
    } while (0);
 
489
    w_object(name, arg->arg, arg->limit);
 
490
}
 
491
 
 
492
static void
 
493
w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg)
 
494
{
 
495
    long num = tbl ? tbl->num_entries : 0;
 
496
 
 
497
    w_encoding(obj, num, arg);
399
498
    if (tbl) {
400
 
        w_long(tbl->num_entries, arg->arg);
401
499
        st_foreach_safe(tbl, w_obj_each, (st_data_t)arg);
402
500
    }
403
 
    else {
404
 
        w_long(0, arg->arg);
 
501
}
 
502
 
 
503
static void
 
504
w_objivar(VALUE obj, struct dump_call_arg *arg)
 
505
{
 
506
    VALUE *ptr;
 
507
    long i, len, num;
 
508
 
 
509
    len = ROBJECT_LEN(obj);
 
510
    ptr = ROBJECT_PTR(obj);
 
511
    num = 0;
 
512
    for (i = 0; i < len; i++)
 
513
        if (ptr[i] != Qundef)
 
514
            num += 1;
 
515
 
 
516
    w_encoding(obj, num, arg);
 
517
    if (num != 0) {
 
518
        rb_ivar_foreach(obj, w_obj_each, (st_data_t)arg);
405
519
    }
406
520
}
407
521
 
411
525
    struct dump_call_arg c_arg;
412
526
    st_table *ivtbl = 0;
413
527
    st_data_t num;
 
528
    int hasiv = 0;
 
529
#define has_ivars(obj, ivtbl) ((ivtbl = rb_generic_ivar_table(obj)) != 0 || \
 
530
                               (!SPECIAL_CONST_P(obj) && ENCODING_GET(obj)))
414
531
 
415
532
    if (limit == 0) {
416
533
        rb_raise(rb_eArgError, "exceed depth limit");
426
543
        return;
427
544
    }
428
545
 
429
 
    if (ivtbl = rb_generic_ivar_table(obj)) {
 
546
    if ((hasiv = has_ivars(obj, ivtbl)) != 0) {
430
547
        w_byte(TYPE_IVAR, arg);
431
548
    }
432
549
    if (obj == Qnil) {
459
576
        if (OBJ_TAINTED(obj)) arg->taint = Qtrue;
460
577
 
461
578
        st_add_direct(arg->data, obj, arg->data->num_entries);
 
579
 
 
580
        {
 
581
            st_data_t compat_data;
 
582
            rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
 
583
            if (st_lookup(compat_allocator_tbl,
 
584
                          (st_data_t)allocator,
 
585
                          &compat_data)) {
 
586
                marshal_compat_t *compat = (marshal_compat_t*)compat_data;
 
587
                VALUE real_obj = obj;
 
588
                obj = compat->dumper(real_obj);
 
589
                st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
 
590
            }
 
591
        }
 
592
 
462
593
        if (rb_respond_to(obj, s_mdump)) {
463
594
            VALUE v;
464
595
 
465
596
            v = rb_funcall(obj, s_mdump, 0, 0);
466
597
            w_class(TYPE_USRMARSHAL, obj, arg, Qfalse);
467
598
            w_object(v, arg, limit);
468
 
            if (ivtbl) w_ivar(0, &c_arg);
 
599
            if (hasiv) w_ivar(obj, 0, &c_arg);
469
600
            return;
470
601
        }
471
602
        if (rb_respond_to(obj, s_dump)) {
472
603
            VALUE v;
 
604
            st_table *ivtbl2 = 0;
 
605
            int hasiv2;
473
606
 
474
607
            v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
475
608
            if (TYPE(v) != T_STRING) {
476
609
                rb_raise(rb_eTypeError, "_dump() must return string");
477
610
            }
478
 
            if (!ivtbl && (ivtbl = rb_generic_ivar_table(v))) {
 
611
            if ((hasiv2 = has_ivars(v, ivtbl2)) != 0 && !hasiv) {
479
612
                w_byte(TYPE_IVAR, arg);
480
613
            }
481
614
            w_class(TYPE_USERDEF, obj, arg, Qfalse);
482
615
            w_bytes(RSTRING_PTR(v), RSTRING_LEN(v), arg);
483
 
            if (ivtbl) {
484
 
                w_ivar(ivtbl, &c_arg);
 
616
            if (hasiv2) {
 
617
                w_ivar(obj, ivtbl2, &c_arg);
 
618
            }
 
619
            else if (hasiv) {
 
620
                w_ivar(obj, ivtbl, &c_arg);
485
621
            }
486
622
            return;
487
623
        }
508
644
 
509
645
          case T_FLOAT:
510
646
            w_byte(TYPE_FLOAT, arg);
511
 
            w_float(RFLOAT(obj)->value, arg);
 
647
            w_float(RFLOAT_VALUE(obj), arg);
512
648
            break;
513
649
 
514
650
          case T_BIGNUM:
515
651
            w_byte(TYPE_BIGNUM, arg);
516
652
            {
517
 
                char sign = RBIGNUM(obj)->sign ? '+' : '-';
518
 
                long len = RBIGNUM(obj)->len;
519
 
                BDIGIT *d = RBIGNUM(obj)->digits;
 
653
                char sign = RBIGNUM_SIGN(obj) ? '+' : '-';
 
654
                long len = RBIGNUM_LEN(obj);
 
655
                BDIGIT *d = RBIGNUM_DIGITS(obj);
520
656
 
521
657
                w_byte(sign, arg);
522
658
                w_long(SHORTLEN(len), arg); /* w_short? */
603
739
 
604
740
          case T_OBJECT:
605
741
            w_class(TYPE_OBJECT, obj, arg, Qtrue);
606
 
            w_ivar(ROBJECT(obj)->iv_tbl, &c_arg);
 
742
            w_objivar(obj, &c_arg);
607
743
            break;
608
744
 
609
745
          case T_DATA:
627
763
            break;
628
764
        }
629
765
    }
630
 
    if (ivtbl) {
631
 
        w_ivar(ivtbl, &c_arg);
 
766
    if (hasiv) {
 
767
        w_ivar(obj, ivtbl, &c_arg);
632
768
    }
633
769
}
634
770
 
648
784
{
649
785
    st_free_table(arg->symbols);
650
786
    st_free_table(arg->data);
 
787
    st_free_table(arg->compat_tbl);
 
788
    DATA_PTR(arg->wrapper) = 0;
 
789
    arg->wrapper = 0;
651
790
    if (arg->taint) {
652
791
        OBJ_TAINT(arg->str);
653
792
    }
720
859
    arg.symbols = st_init_numtable();
721
860
    arg.data    = st_init_numtable();
722
861
    arg.taint   = Qfalse;
 
862
    arg.compat_tbl = st_init_numtable();
 
863
    arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg);
 
864
    arg.encodings = 0;
723
865
    c_arg.obj   = obj;
724
866
    c_arg.arg   = &arg;
725
867
    c_arg.limit = limit;
739
881
    VALUE data;
740
882
    VALUE proc;
741
883
    int taint;
 
884
    st_table *compat_tbl;
 
885
    VALUE compat_tbl_wrapper;
742
886
};
743
887
 
744
888
static VALUE r_entry(VALUE v, struct load_arg *arg);
824
968
 
825
969
    if (len == 0) return rb_str_new(0, 0);
826
970
    if (TYPE(arg->src) == T_STRING) {
827
 
        if (RSTRING_LEN(arg->src) > arg->offset) {
 
971
        if (RSTRING_LEN(arg->src) - arg->offset >= len) {
828
972
            str = rb_str_new(RSTRING_PTR(arg->src)+arg->offset, len);
829
973
            arg->offset += len;
830
974
        }
899
1043
static VALUE
900
1044
r_entry(VALUE v, struct load_arg *arg)
901
1045
{
902
 
    rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v);
903
 
    if (arg->taint) OBJ_TAINT(v);
 
1046
    st_data_t real_obj = (VALUE)Qundef;
 
1047
    if (st_lookup(arg->compat_tbl, v, &real_obj)) {
 
1048
        rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), (VALUE)real_obj);
 
1049
    }
 
1050
    else {
 
1051
        rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v);
 
1052
    }
 
1053
    if (arg->taint) {
 
1054
        OBJ_TAINT(v);
 
1055
        if ((VALUE)real_obj != Qundef)
 
1056
            OBJ_TAINT((VALUE)real_obj);
 
1057
    }
 
1058
    return v;
 
1059
}
 
1060
 
 
1061
static VALUE
 
1062
r_leave(VALUE v, struct load_arg *arg)
 
1063
{
 
1064
    st_data_t data;
 
1065
    if (st_lookup(arg->compat_tbl, v, &data)) {
 
1066
        VALUE real_obj = (VALUE)data;
 
1067
        rb_alloc_func_t allocator = rb_get_alloc_func(CLASS_OF(real_obj));
 
1068
        st_data_t key = v;
 
1069
        if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
 
1070
            marshal_compat_t *compat = (marshal_compat_t*)data;
 
1071
            compat->loader(real_obj, v);
 
1072
        }
 
1073
        st_delete(arg->compat_tbl, &key, 0);
 
1074
        v = real_obj;
 
1075
    }
904
1076
    if (arg->proc) {
905
1077
        v = rb_funcall(arg->proc, rb_intern("call"), 1, v);
906
1078
    }
917
1089
        while (len--) {
918
1090
            ID id = r_symbol(arg);
919
1091
            VALUE val = r_object(arg);
920
 
            rb_ivar_set(obj, id, val);
 
1092
            if (id == rb_id_encoding()) {
 
1093
                int idx = rb_enc_find_index(StringValueCStr(val));
 
1094
                if (idx > 0) rb_enc_associate_index(obj, idx);
 
1095
            }
 
1096
            else {
 
1097
                rb_ivar_set(obj, id, val);
 
1098
            }
921
1099
        }
922
1100
    }
923
1101
}
945
1123
}
946
1124
 
947
1125
static VALUE
 
1126
obj_alloc_by_path(const char *path, struct load_arg *arg)
 
1127
{
 
1128
    VALUE klass;
 
1129
    st_data_t data;
 
1130
    rb_alloc_func_t allocator;
 
1131
 
 
1132
    klass = path2class(path);
 
1133
 
 
1134
    allocator = rb_get_alloc_func(klass);
 
1135
    if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
 
1136
        marshal_compat_t *compat = (marshal_compat_t*)data;
 
1137
        VALUE real_obj = rb_obj_alloc(klass);
 
1138
        VALUE obj = rb_obj_alloc(compat->oldclass);
 
1139
        st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
 
1140
        return obj;
 
1141
    }
 
1142
 
 
1143
    return rb_obj_alloc(klass);
 
1144
}
 
1145
 
 
1146
static VALUE
948
1147
r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
949
1148
{
950
1149
    VALUE v = Qnil;
1047
1246
                d = strtod(ptr, &e);
1048
1247
                d = load_mantissa(d, e, RSTRING_LEN(str) - (e - ptr));
1049
1248
            }
1050
 
            v = rb_float_new(d);
 
1249
            v = DOUBLE2NUM(d);
1051
1250
            v = r_entry(v, arg);
 
1251
            v = r_leave(v, arg);
1052
1252
        }
1053
1253
        break;
1054
1254
 
1060
1260
 
1061
1261
            NEWOBJ(big, struct RBignum);
1062
1262
            OBJSETUP(big, rb_cBignum, T_BIGNUM);
1063
 
            big->sign = (r_byte(arg) == '+');
 
1263
            RBIGNUM_SET_SIGN(big, (r_byte(arg) == '+'));
1064
1264
            len = r_long(arg);
1065
1265
            data = r_bytes0(len * 2, arg);
1066
1266
#if SIZEOF_BDIGITS == SIZEOF_SHORT
1067
 
            big->len = len;
 
1267
            rb_big_resize((VALUE)big, len);
1068
1268
#else
1069
 
            big->len = (len + 1) * 2 / sizeof(BDIGIT);
 
1269
            rb_big_resize((VALUE)big, (len + 1) * 2 / sizeof(BDIGIT));
1070
1270
#endif
1071
 
            big->digits = digits = ALLOC_N(BDIGIT, big->len);
 
1271
            digits = RBIGNUM_DIGITS(big);
1072
1272
            MEMCPY(digits, RSTRING_PTR(data), char, len * 2);
1073
1273
#if SIZEOF_BDIGITS > SIZEOF_SHORT
1074
1274
            MEMZERO((char *)digits + len * 2, char,
1075
 
                    big->len * sizeof(BDIGIT) - len * 2);
 
1275
                    RBIGNUM_LEN(big) * sizeof(BDIGIT) - len * 2);
1076
1276
#endif
1077
 
            len = big->len;
 
1277
            len = RBIGNUM_LEN(big);
1078
1278
            while (len > 0) {
1079
1279
                unsigned char *p = (unsigned char *)digits;
1080
1280
                BDIGIT num = 0;
1094
1294
            }
1095
1295
            v = rb_big_norm((VALUE)big);
1096
1296
            v = r_entry(v, arg);
 
1297
            v = r_leave(v, arg);
1097
1298
        }
1098
1299
        break;
1099
1300
 
1100
1301
      case TYPE_STRING:
1101
1302
        v = r_entry(r_string(arg), arg);
 
1303
        v = r_leave(v, arg);
1102
1304
        break;
1103
1305
 
1104
1306
      case TYPE_REGEXP:
1106
1308
            volatile VALUE str = r_bytes(arg);
1107
1309
            int options = r_byte(arg);
1108
1310
            v = r_entry(rb_reg_new(str, options), arg);
 
1311
            v = r_leave(v, arg);
1109
1312
        }
1110
1313
        break;
1111
1314
 
1118
1321
            while (len--) {
1119
1322
                rb_ary_push(v, r_object(arg));
1120
1323
            }
 
1324
            v = r_leave(v, arg);
1121
1325
        }
1122
1326
        break;
1123
1327
 
1136
1340
            if (type == TYPE_HASH_DEF) {
1137
1341
                RHASH(v)->ifnone = r_object(arg);
1138
1342
            }
 
1343
            v = r_leave(v, arg);
1139
1344
        }
1140
1345
        break;
1141
1346
 
1142
1347
      case TYPE_STRUCT:
1143
1348
        {
1144
 
            VALUE klass, mem, values;
 
1349
            VALUE klass, mem;
 
1350
            VALUE values;
1145
1351
            volatile long i;    /* gcc 2.7.2.3 -O2 bug?? */
1146
1352
            long len;
1147
1353
            ID slot;
1148
1354
 
1149
1355
            klass = path2class(r_unique(arg));
 
1356
            len = r_long(arg);
 
1357
 
 
1358
            v = rb_obj_alloc(klass);
 
1359
            if (TYPE(v) != T_STRUCT) {
 
1360
                rb_raise(rb_eTypeError, "class %s not a struct", rb_class2name(klass));
 
1361
            }
1150
1362
            mem = rb_struct_s_members(klass);
1151
 
            if (mem == Qnil) {
1152
 
                rb_raise(rb_eTypeError, "uninitialized struct");
1153
 
            }
1154
 
            len = r_long(arg);
 
1363
            if (RARRAY_LEN(mem) != len) {
 
1364
                rb_raise(rb_eTypeError, "struct %s not compatible (struct size differs)",
 
1365
                         rb_class2name(klass));
 
1366
            }
1155
1367
 
 
1368
            v = r_entry(v, arg);
1156
1369
            values = rb_ary_new2(len);
1157
1370
            for (i=0; i<len; i++) {
1158
 
                rb_ary_push(values, Qnil);
1159
 
            }
1160
 
            v = rb_struct_alloc(klass, values);
1161
 
            v = r_entry(v, arg);
1162
 
            for (i=0; i<len; i++) {
1163
1371
                slot = r_symbol(arg);
1164
1372
 
1165
1373
                if (RARRAY_PTR(mem)[i] != ID2SYM(slot)) {
1168
1376
                             rb_id2name(slot),
1169
1377
                             rb_id2name(SYM2ID(RARRAY_PTR(mem)[i])));
1170
1378
                }
1171
 
                rb_struct_aset(v, LONG2FIX(i), r_object(arg));
 
1379
                rb_ary_push(values, r_object(arg));
1172
1380
            }
 
1381
            rb_struct_initialize(v, values);
 
1382
            v = r_leave(v, arg);
1173
1383
        }
1174
1384
        break;
1175
1385
 
1189
1399
            }
1190
1400
            v = rb_funcall(klass, s_load, 1, data);
1191
1401
            v = r_entry(v, arg);
 
1402
            v = r_leave(v, arg);
1192
1403
        }
1193
1404
        break;
1194
1405
 
1211
1422
            v = r_entry(v, arg);
1212
1423
            data = r_object(arg);
1213
1424
            rb_funcall(v, s_mload, 1, data);
 
1425
            v = r_leave(v, arg);
1214
1426
        }
1215
1427
        break;
1216
1428
 
1217
1429
      case TYPE_OBJECT:
1218
1430
        {
1219
 
            VALUE klass = path2class(r_unique(arg));
1220
 
 
1221
 
            v = rb_obj_alloc(klass);
 
1431
            v = obj_alloc_by_path(r_unique(arg), arg);
1222
1432
            if (TYPE(v) != T_OBJECT) {
1223
1433
                rb_raise(rb_eArgError, "dump format error");
1224
1434
            }
1225
1435
            v = r_entry(v, arg);
1226
1436
            r_ivar(v, arg);
 
1437
            v = r_leave(v, arg);
1227
1438
        }
1228
1439
        break;
1229
1440
 
1251
1462
                        rb_class2name(klass));
1252
1463
           }
1253
1464
           rb_funcall(v, s_load_data, 1, r_object0(arg, 0, extmod));
 
1465
           v = r_leave(v, arg);
1254
1466
       }
1255
1467
       break;
1256
1468
 
1260
1472
 
1261
1473
            v = rb_path2class(RSTRING_PTR(str));
1262
1474
            v = r_entry(v, arg);
 
1475
            v = r_leave(v, arg);
1263
1476
        }
1264
1477
        break;
1265
1478
 
1269
1482
 
1270
1483
            v = path2class(RSTRING_PTR(str));
1271
1484
            v = r_entry(v, arg);
 
1485
            v = r_leave(v, arg);
1272
1486
        }
1273
1487
        break;
1274
1488
 
1278
1492
 
1279
1493
            v = path2module(RSTRING_PTR(str));
1280
1494
            v = r_entry(v, arg);
 
1495
            v = r_leave(v, arg);
1281
1496
        }
1282
1497
        break;
1283
1498
 
1312
1527
load_ensure(struct load_arg *arg)
1313
1528
{
1314
1529
    st_free_table(arg->symbols);
 
1530
    st_free_table(arg->compat_tbl);
 
1531
    DATA_PTR(arg->compat_tbl_wrapper) = 0;
 
1532
    arg->compat_tbl_wrapper = 0;
1315
1533
    return 0;
1316
1534
}
1317
1535
 
1350
1568
    }
1351
1569
    arg.src = port;
1352
1570
    arg.offset = 0;
 
1571
    arg.compat_tbl = st_init_numtable();
 
1572
    arg.compat_tbl_wrapper = Data_Wrap_Struct(rb_cData, rb_mark_tbl, 0, arg.compat_tbl);
1353
1573
 
1354
1574
    major = r_byte(&arg);
1355
1575
    minor = r_byte(&arg);
1429
1649
 
1430
1650
    rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR));
1431
1651
    rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR));
 
1652
 
 
1653
    compat_allocator_tbl = st_init_numtable();
 
1654
    rb_gc_register_address(&compat_allocator_tbl_wrapper);
 
1655
    compat_allocator_tbl_wrapper =
 
1656
        Data_Wrap_Struct(rb_cData, mark_marshal_compat_t, 0, compat_allocator_tbl);
1432
1657
}
1433
1658
 
1434
1659
VALUE