예제 #1
0
 public ILValue(object o, GM_Type type)
 {
     if (o is short)
     {
         this.Value = (int)((short)o);
     }
     else if (type == GM_Type.String)
     {
         this.ValueText = GMCodeUtil.EscapeString(o as string);
     }
     else
     {
         this.Value = o;
     }
     Type = type;
 }
예제 #2
0
 void WriteOperand(ITextOutput output, bool escapeString = true)
 {
     if (Operand == null)
     {
         output.Write("%NULL_OPERAND%");
     }
     else if (Operand is ILLabel)
     {
         output.Write((Operand as ILLabel).Name);
     }
     else if (escapeString)
     {
         if (Operand is string)
         {
             output.Write(GMCodeUtil.EscapeString((string)Operand));
         }
         else if (Operand is ILValue)
         {
             ILValue val = Operand as ILValue;
             if (escapeString && val.Type == GM_Type.String)
             {
                 output.Write(val.ValueText);
             }
             else
             {
                 output.Write(val.ToString());
             }
         }
         else
         {
             output.Write(Operand.ToString());
         }
     }
     else
     {
         output.Write(Operand.ToString());
     }
 }
예제 #3
0
 public ILValue(string i)
 {
     this.Value = i; Type = GM_Type.String; this.ValueText = GMCodeUtil.EscapeString(i as string);
 }
예제 #4
0
        // I had multipul passes on this so trying to combine it all to do one pass
        public static SortedList <int, Instruction> Dissasemble(BinaryReader r, long length, List <string> StringList, List <string> InstanceList = null)
        {
            if (r == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (r.BaseStream.CanRead != true)
            {
                throw new IOException("Cannot read stream");
            }
            int  pc     = 0;
            long lastpc = r.BaseStream.Length / 4;
            SortedList <int, Instruction>  list                  = new SortedList <int, Instruction>();
            Dictionary <int, Label>        labels                = new Dictionary <int, Label>();
            Dictionary <int, Label>        pushEnviroment        = new Dictionary <int, Label>();
            List <Instruction>             branches              = new List <Instruction>();
            Func <Instruction, int, Label> GiveInstructionALabel = (Instruction inst, int laddress) =>
            {
                Label label;
                if (!labels.TryGetValue(laddress, out label))
                {
                    labels.Add(laddress, label = new Label(laddress));
                }
                inst.Operand = label;
                branches.Add(inst);  // add it to the branches to handle latter
                return(label);
            };

            Instruction   prev = null;
            StringBuilder sb   = new StringBuilder(50);

            while (r.BaseStream.Position < length)
            {
                Instruction i = DissasembleFromReader(pc, r);
                pc += i.Size;
                switch (i.Code)
                {
                case GMCode.Pushenv:
                {
                    Label endOfEnviroment = GiveInstructionALabel(i, i.Extra + 1);       // skip the pop
                    i.Operand = endOfEnviroment;
                    pushEnviroment.Add(i.Address, endOfEnviroment);
                    branches.Add(i);
                }
                break;

                case GMCode.Popenv:
                {
                    Label endOfEnviroment;
                    if (pushEnviroment.TryGetValue(i.Extra - 1, out endOfEnviroment))
                    {
                        i.Operand = GiveInstructionALabel(i, i.Extra - 1);          // not a break, set the label BACK to the push as we are simulating a loop
                    }
                    else
                    {
                        foreach (Instruction ii in list.Values.Reverse())
                        {
                            if (ii.Code == GMCode.Pushenv)
                            {
                                i.Operand = GiveInstructionALabel(i, ii.Address);         // we want to make these continues
                                break;
                            }
                        }
                    }
                    branches.Add(i);
                    Debug.Assert(i.Operand != null);
                }
                break;

                case GMCode.Bf:
                case GMCode.Bt:
                case GMCode.B:
                    GiveInstructionALabel(i, i.Extra);
                    break;

                case GMCode.Push:
                    if (i.Types[0] == GM_Type.Var)
                    {
                        // i.Operand = StringList[(int)i.Operand]; Don't want to touch as it might
                        sb.Clear();
                        sb.Append(GMCodeUtil.lookupInstance(i.Extra, InstanceList));
                        sb.Append('.');
                        sb.Append(StringList[(int)i.Operand & 0xFFFFF]);
                        i.OperandText = sb.ToString();
                    }
                    else if (i.Types[0] == GM_Type.String)
                    {
                        i.Operand     = StringList[(int)i.Operand];
                        i.OperandText = GMCodeUtil.EscapeString(i.Operand as string);
                    }
                    break;

                case GMCode.Pop:     // technicaly pop is always a var, but eh
                                     //i.Operand = StringList[(int)i.Operand]; Don't do it this wa as we might need to find out of its an array
                    sb.Clear();
                    sb.Append(GMCodeUtil.lookupInstance(i.Extra, InstanceList));
                    sb.Append('.');
                    sb.Append(StringList[(int)i.Operand & 0xFFFFF]);
                    i.OperandText = sb.ToString();
                    break;

                case GMCode.Call:
                    i.OperandText = StringList[(int)i.Operand];
                    i.Operand     = i.OperandText;
                    break;
                }
                i.Previous = prev;
                if (prev == null)
                {
                    prev = i;
                }
                else
                {
                    prev.Next = i;
                }
                list.Add(i.Address, i);
            }
            if (list.Count == 0)
            {
                return(list);                 // return list, its empty
            }
            Instruction last = list.Last().Value;

            if (last.Code != GMCode.Exit || last.Code != GMCode.Ret)
            {
                int address = last.Address + last.Size;
                list.Add(address, new Instruction(address, GMCode.Exit));
            } // must be done for graph and in case we have a branch that goes right outside.  Its implied in any event
            foreach (var i in branches)
            {
                Label l = i.Operand as Label;
                if (l.Origin == null) // Link the label
                {
                    l.Origin = list[l.Address];
                    list[l.Address].Label = l;
                }
            }
            return(list);
        }