Beispiel #1
0
 internal static string r_unique(Frame caller, load_arg arg)
 {
     return Symbol.rb_id2name((uint)r_symbol(caller, arg));
 }
Beispiel #2
0
 internal static object r_entry(Frame caller, object v, load_arg arg)
 {
     Ruby.Methods.rb_hash_aset.singleton.Call2(null, arg.data, caller, null, ((Hash)(arg.data)).value.Count, v);
     if (arg.taint)
     {
         ((Basic)v).Tainted = true;
     }
     return v;
 }
Beispiel #3
0
        internal static int r_symreal(Frame caller, load_arg arg)
        {
            int id;

            id = (int)Symbol.rb_intern(((String)r_bytes(caller, arg)).value);
            arg.symbols.Add(arg.symbols.Count, id);

            return id;
        }
Beispiel #4
0
 internal static int r_symbol(Frame caller, load_arg arg)
 {
     if (r_byte(caller, arg) == TYPE_SYMLINK)
     {
         return r_symlink(caller, arg);
     }
     return r_symreal(caller, arg);
 }
Beispiel #5
0
 internal static object load_ensure(load_arg arg)
 {
     arg.symbols = null;
     return null;
 }
Beispiel #6
0
        //----------------------------------------------------------------------------------

        internal static int r_symlink(Frame caller, load_arg arg)
        {
            int id;
            int num = r_long(caller, arg);

            if (arg.symbols.ContainsKey(num))
            {
                id = arg.symbols[num];
                return id;
            }

            throw new ArgumentError("bad symbol").raise(caller);
        }
Beispiel #7
0
        internal static object r_object0(Frame caller, load_arg arg, object proc, ref int ivp, object extmod)
        {
            object v = null;
            int type = r_byte(caller, arg);
            int id;

            switch (type)
            {
                case TYPE_LINK: //TEST:

                    id = r_long(caller, arg);
                    v = Ruby.Methods.rb_hash_aref.singleton.Call1(null, arg.data, caller, null, id);
                    if (v == null)
                    {
                        throw new ArgumentError("dump format error (unlinked)").raise(caller);
                    }
                    return v;

                case TYPE_IVAR: //TEST:
                    {
                        int ivar = 1;
                        v = r_object0(caller, arg, null, ref ivar, extmod);
                        if (ivar > 0) r_ivar(caller, v, arg);                        
                    }
                break;

                case TYPE_EXTENDED: //TEST:
                    {
                        object m = path2module(r_unique(caller, arg), caller);
                        if (extmod == null)
                        {
                            extmod = new Array();
                            ((Array)extmod).value.Add(m);
                        }

                        int temp = 0;
                        v = r_object0(caller, arg, null, ref temp, extmod);
                        while (((Array)extmod).value.Count > 0)
                        {
                            m = ((Array)extmod).value[((Array)extmod).value.Count - 1];
                            ((Array)extmod).value.RemoveAt(((Array)extmod).value.Count - 1);
                            Class.rb_extend_object(caller, v, (Class)m);
                        }
                    }
                break;

                case TYPE_UCLASS:
                    {
                        object c = path2class(caller, r_unique(caller, arg));

                        if (((Class)c)._type == Class.Type.Singleton)
                        {
                            throw new TypeError("singleton can't be loaded").raise(caller);
                        }
                        int temp = 0;
                        v = r_object0(caller, arg, null, ref temp, extmod);
                        if (rb_special_const_p(v) || v is Object || (v is Class && ((Class)v)._type == Class.Type.Class))
                        {
                            throw new ArgumentError("dump format error (user class)").raise(caller);
                        }
                        if ((v is Class && ((Class)v)._type == Class.Type.Module) || !RTEST(Ruby.Methods.rb_class_inherited_p.singleton.Call1(null, c, caller, null, ((Basic)v).my_class)))
                        {
                            object tmp = new Object((Class)c);

                            //TODO: Write this comparison
                            //if (TYPE(v) != TYPE(tmp))
                            //{
                            //    throw new ArgumentError("dump format error (user class)").raise(caller);
                            //}
                        }
                        ((Basic)v).my_class = (Class)c;
                    }
                    break;

                case TYPE_NIL:
                    v = null;
                    break;

                case TYPE_TRUE:
                    v = true;
                    break;

                case TYPE_FALSE:
                    v = false;
                    break;

                case TYPE_FIXNUM:
                    {
                        v = r_long(caller, arg);
                    }
                    break;

                case TYPE_FLOAT:
                    {
                        double d;
                        object str = r_bytes(caller, arg);
                        string ptr = ((String)str).value;

                        if (ptr.Equals("nan"))
                        {
                            d = double.NaN;
                        }
                        else if (ptr.Equals("inf"))
                        {
                            d = double.PositiveInfinity;
                        }
                        else if (ptr.Equals("-inf"))
                        {
                            d = double.NegativeInfinity;
                        }
                        else if (ptr.Equals("-0"))
                        {
                            d = -0.0;
                        }
                        else
                        {
                            int e = 0;
                            d = String.strtod(ptr, 0, out e);
                            d = load_mantissa(d, ptr.Substring(e), ((String)str).value.Length - e);
                        }

                        v = new Float(d);
                        r_entry(caller, v, arg);
                    }
                    break;

                case TYPE_BIGNUM:
                    {
                        int len;
                        uint[] digits;
                        object data;

                        int sign = ((char)r_byte(caller, arg) == '+') ? 1 : -1;

                        len = r_long(caller, arg);
                        data = r_bytes0(caller, len * 2, arg);

                        int bigLen = (len + 1) * 2 / SIZEOF_BDIGITS;                      

                        //extract data to bytes
                        digits = new uint[bigLen];
                        byte[] digitData = new byte[bigLen * SIZEOF_BDIGITS];
                        char[] charDigitData = ((String)data).value.ToCharArray();
                        for (int i = 0; i < ((String)data).value.Length; i++)
                        {
                            digitData[i] = (byte)charDigitData[i];
                        }
                        //save data to digits
                        for (int uintCount = 0; uintCount < digits.Length; uintCount++)
                        {
                            digits[uintCount] = System.BitConverter.ToUInt32(digitData, (uintCount * 4));
                        }
                        v = new Bignum(new IronMath.integer(sign, digits));
                        r_entry(caller, v, arg);
                    }
                    break;
                case TYPE_STRING:
                    v = r_entry(caller, r_string(caller, arg), arg);
                    break;

                case TYPE_REGEXP:
                    {
                        object str = r_bytes(caller, arg);
                        int options = r_byte(caller, arg);
                        v = r_entry(caller, new Regexp(((String)str).value, options), arg);
                    }
                    break;

                case TYPE_ARRAY:
                    {
                        int len = r_long(caller, arg);

                        v = new Array();
                        r_entry(caller, v, arg);
                        while (len-- > 0)
                        {
                            ((Array)v).value.Add(r_object(caller, arg));
                        }
                    }
                    break;

                case TYPE_HASH:
                case TYPE_HASH_DEF:
                    {
                        int len = r_long(caller, arg);

                        v = new Hash();
                        r_entry(caller, v, arg);
                        while (len-- > 0)
                        {
                            object key = r_object(caller, arg);
                            object value = r_object(caller, arg);
                            ((Hash)v).Add(key, value);
                        }
                        if (type == TYPE_HASH_DEF)
                        {
                            ((Hash)v).defaultValue = r_object(caller, arg);
                        }
                    }
                    break;

                case TYPE_STRUCT:
                    {
                        Class klass;
                        object mem;
                        object[] values;
                        int len;
                        int slot;

                        string klassPath = r_unique(caller, arg);
                        klass = (Class)path2class(caller, klassPath);
                        mem = Ruby.Methods.rb_struct_s_members.singleton.Call0(klass, klass, caller, null);
                        if (mem == null)
                        {
                            throw new TypeError("uninitialized struct").raise(caller);
                        }
                        len = r_long(caller, arg);
                        values = new object[len];
                        for (int i = 0; i < len; i++)
                        {
                            slot = r_symbol(caller, arg);

                            if ((string)((Array)mem).value[i] != Symbol.rb_id2name((uint)slot))
                            {
                                string errorString = string.Format(CultureInfo.InvariantCulture, "struct {0} not compatible (:{1} for :{2})",
                                    rb_class2name(klass, caller),
                                    Symbol.rb_id2name((uint)slot),
                                    ((Array)mem).value[i]);

                                throw new TypeError(errorString).raise(caller);
                            }
                            values[i] = r_object(caller, arg);
                        }

                        v = Ruby.Methods.rb_class_new_instance.singleton.Call(klass, klass, caller, null, new Array(values));
                        r_entry(caller, v, arg);
                    }
                    break;
                case TYPE_USERDEF:
                    {
                        object klass = path2class(caller, r_unique(caller, arg));
                        object data;

                        if (!Eval.RespondTo(klass, s_load))
                        {
                            throw new TypeError(string.Format(CultureInfo.InvariantCulture, "class {0} needs to have method `_load'", rb_class2name(klass, caller))).raise(caller);
                        }

                        data = r_string(caller, arg);
                        if (ivp > 0)
                        {
                            r_ivar(caller, data, arg);
                            ivp = 0;
                        }
                        v = Eval.CallPrivate1(klass, caller, s_load, null, data);
                        r_entry(caller, v, arg);                        
                    }
                    break;
                case TYPE_USRMARSHAL: 
                    {
                        object klass = path2class(caller, r_unique(caller, arg));
                        object data;

                        v = Ruby.Methods.rb_obj_alloc.singleton.Call0(null, klass, caller, null);
                        if (extmod != null)
                        {
                            while (((Array)extmod).value.Count > 0)
                            {
                                object m = ((Array)extmod).value[((Array)extmod).value.Count - 1];
                                ((Array)extmod).value.RemoveAt(((Array)extmod).value.Count - 1);
                                Class.rb_extend_object(caller, v, (Class)m);
                            }
                        }
                        if (!Eval.RespondTo(v, s_mload))
                        {
                            throw new TypeError(string.Format(CultureInfo.InvariantCulture, "instance of {0} needs to have method `marshal_load'", rb_class2name(klass, caller))).raise(caller);
                        }
                        r_entry(caller, v, arg);
                        data = r_object(caller, arg);
                        Eval.CallPrivate1(v, caller, s_mload, null, data);
                    }
                    break;

                case TYPE_OBJECT:
                    {
                        object klass = path2class(caller, r_unique(caller, arg));
                        v = Ruby.Methods.rb_obj_alloc.singleton.Call0(null, klass, caller, null);
                        if (!(v is Object))
                        {
                            throw new ArgumentError("dump format error").raise(caller);
                        }
                        r_entry(caller, v, arg);
                        r_ivar(caller, v, arg);
                    }
                    break;

                case TYPE_DATA://TEST
                    {
                        object klass = path2class(caller, r_unique(caller, arg));
                        if (Eval.RespondTo(klass, s_alloc))
                        {
                            type_data_warn = true; //TEST: static int warn = Qtrue; - test that this is equivalent note the 'STATIC' keyword
                            if (type_data_warn)
                            {
                                Errors.rb_warn("define `allocate' instead of `_alloc'");
                                type_data_warn = false;
                            }
                            v = Eval.CallPrivate0(klass, caller, s_alloc, null);
                        }
                        else
                        {
                            v = Ruby.Methods.rb_obj_alloc.singleton.Call0(null, klass, caller, null);
                        }
                        if (!(v is Data))
                        {
                            throw new ArgumentError("dump format error").raise(caller);
                        }
                        r_entry(caller, v, arg);
                        if (!Eval.RespondTo(v, s_load_data))
                        {
                            throw new TypeError(string.Format(CultureInfo.InvariantCulture, "class {0} needs to have instance method `_load_data'", rb_class2name(klass, caller))).raise(caller);
                        }
                        int temp = 0;
                        Eval.CallPrivate1(v, caller, s_load_data, null, r_object0(caller, arg, null, ref temp, extmod));
                    }
                break;

                case TYPE_MODULE_OLD: //TEST:
                    {                     
                        object str = r_bytes(caller, arg);
                        v = rb_path2class(caller, ((String)str).value);
                        r_entry(caller, v, arg);
                    }
                break;

                case TYPE_CLASS:
                    {
                        object str = r_bytes(caller, arg);
                        v = path2class(caller, ((String)str).value);
                        r_entry(caller, v, arg);
                    }
                    break;
                case TYPE_MODULE: //TEST:
                    {                        
                        object str = r_bytes(caller, arg);

                        v = path2module(((String)str).value, caller);
                        r_entry(caller, v, arg);
                    }
                    break;

                case TYPE_SYMBOL: //TEST:
                    v = new Symbol((uint)r_symreal(caller, arg));
                    break;

                case TYPE_SYMLINK: //TEST:
                    return new Symbol((uint)r_symlink(caller, arg));

                default:
                    throw new ArgumentError(string.Format(CultureInfo.InvariantCulture, "dump format error(0x{0})", type)).raise(caller);
            }

            if (proc != null) //TEST:
            {
                Eval.CallPrivate1(proc, caller, "call", null, v);
            }
            return v;

        }
Beispiel #8
0
        //----------------------------------------------------------------------------------

        internal static object load(Frame caller, load_arg arg)
        {
            return r_object(caller, arg);
        }
Beispiel #9
0
 internal static object r_object( Frame caller, load_arg arg)
 {
     int temp = 0;
     return r_object0(caller, arg, arg.proc, ref temp, null);
 }
Beispiel #10
0
        internal static void r_ivar(Frame caller, object obj, load_arg arg)
        {
            int len;

            len = r_long(caller, arg);
            if (len > 0)
            {
                while (len-- > 0)
                {
                    int id = r_symbol(caller, arg);
                    object val = r_object(caller, arg);
                    rb_ivar_set(caller, obj, id, val);
                }
            }
        }
Beispiel #11
0
 internal static object r_string(Frame caller, load_arg arg)
 {
     return r_bytes(caller, arg);
 }
Beispiel #12
0
        internal static int r_long( Frame caller, load_arg arg)
        {
            int x;
            int c = ((((char)r_byte(caller, arg)) ^ 128) - 128);    

            if (c == 0) return 0;
            if (c > 0)
            {
                if (4 < c && c < 128)
                {
                    return c - 5;
                }
                if (c > SIZEOF_LONG) long_toobig(caller, c);
                x = 0;
                for (int i = 0; i < c; i++)
                {
                    x |= (int)r_byte(caller, arg) << (8 * i);
                }
            }
            else
            {
                if (-129 < c && c < -4)
                {
                    return c + 5;
                }
                c = -c;
                if (c > SIZEOF_LONG) long_toobig(caller, c);
                x = -1;
                for (int i = 0; i < c; i++)
                {
                    x &= ~((int)0xff << (8 * i));
                    x |= (int)r_byte(caller, arg) << (8 * i);
                }
            }
            return x;
        }
Beispiel #13
0
        internal static int r_byte(Frame caller, load_arg arg)
        {
            int c;

            if (arg.src is String)
            {
                if (((String)arg.src).value.Length > arg.offset)
                {
                    c = (byte)((String)arg.src).value[arg.offset++];
                }
                else
                {
                    throw new ArgumentError("marshal data too short").raise(caller);
                }
            }
            else
            {
                object src = arg.src;
                object v = Eval.CallPrivate(src, caller, s_getc, null);
                if (v == null)
                {
                    throw EOFError.rb_eof_error().raise(caller);
                }
                c = (byte)(int)v;
            }

            return c;
        }
Beispiel #14
0
        internal static object r_bytes0(Frame caller, int len, load_arg arg)
        {
            object str;

            if (len == 0) return new String();

            if (arg.src is String)
            {
                if (((String)arg.src).value.Length > arg.offset)
                {
                    str = new String(((String)arg.src).value.Substring(arg.offset, len));
                    arg.offset += len;
                }
                else
                {
                    goto too_short;
                }
            }
            else
            {
                object src = arg.src;
                object n = len;
                //TEST: the address of n is passed in the ruby code, these calls probably arn't equivalent 
                //        str = rb_funcall2(src, s_read, 1, &n);
                str = Eval.CallPrivate(src, caller, s_read, null, n);
                if (str == null) goto too_short;
                if (!(str is String))
                {
                    str = String.StringValue(str, caller);
                }
                if (((String)str).value.Length != len) goto too_short;
                if (((Basic)str).Tainted)
                {
                    arg.taint = true;
                }
                if(((Basic)str).Tainted)
                {
                    arg.taint = true;
                }
            }

            return str;

        too_short:
            throw new ArgumentError("marshal data too short").raise(caller);
        }
Beispiel #15
0
 internal static object r_bytes(Frame caller, load_arg arg)
 {
     return r_bytes0(caller, r_long(caller, arg), arg);
 }