aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs
diff options
context:
space:
mode:
authorUbitUmarov2018-02-23 14:52:34 +0000
committerUbitUmarov2018-02-23 14:52:34 +0000
commit2129d941acbc5f83aca4dc4c30a62d3226888136 (patch)
treee12f2391978c923ef780f558ee5a32d857ee9124 /OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs
parentMerge branch 'master' into httptests (diff)
downloadopensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.zip
opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.tar.gz
opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.tar.bz2
opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.tar.xz
rename XMREngine as Yengine (still not all done), big mess source formating changes, move state files to proper folder, fix a source file locking on errors, more changes for cross platform including from Mike,... yes yes i know a messy commit
Diffstat (limited to 'OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs2348
1 files changed, 2348 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs
new file mode 100644
index 0000000..a0bb3e0
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs
@@ -0,0 +1,2348 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
29using System;
30using System.Collections.Generic;
31using System.Globalization;
32using System.IO;
33using System.Reflection.Emit;
34using System.Runtime.Serialization;
35using System.Text;
36using System.Threading;
37
38using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
39using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
40using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
41using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
42using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
43using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
44using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
45
46namespace OpenSim.Region.ScriptEngine.Yengine
47{
48 public class XMRInstArrays
49 {
50 public XMR_Array[] iarArrays;
51 public char[] iarChars;
52 public double[] iarFloats;
53 public int[] iarIntegers;
54 public LSL_List[] iarLists;
55 public object[] iarObjects;
56 public LSL_Rotation[] iarRotations;
57 public string[] iarStrings;
58 public LSL_Vector[] iarVectors;
59 public XMRSDTypeClObj[] iarSDTClObjs;
60 public Delegate[][] iarSDTIntfObjs;
61
62 private XMRInstAbstract instance;
63 private int heapUse;
64
65 private static readonly XMR_Array[] noArrays = new XMR_Array[0];
66 private static readonly char[] noChars = new char[0];
67 private static readonly double[] noFloats = new double[0];
68 private static readonly int[] noIntegers = new int[0];
69 private static readonly LSL_List[] noLists = new LSL_List[0];
70 private static readonly object[] noObjects = new object[0];
71 private static readonly LSL_Rotation[] noRotations = new LSL_Rotation[0];
72 private static readonly string[] noStrings = new string[0];
73 private static readonly LSL_Vector[] noVectors = new LSL_Vector[0];
74 private static readonly XMRSDTypeClObj[] noSDTClObjs = new XMRSDTypeClObj[0];
75 private static readonly Delegate[][] noSDTIntfObjs = new Delegate[0][];
76
77 public XMRInstArrays(XMRInstAbstract inst)
78 {
79 instance = inst;
80 }
81
82 ~XMRInstArrays()
83 {
84 heapUse = instance.UpdateHeapUse(heapUse, 0);
85 }
86
87 public void AllocVarArrays(XMRInstArSizes ars)
88 {
89 ClearOldArrays();
90
91 heapUse = instance.UpdateHeapUse(heapUse,
92 ars.iasChars * HeapTrackerObject.HT_CHAR +
93 ars.iasFloats * HeapTrackerObject.HT_SFLT +
94 ars.iasIntegers * HeapTrackerObject.HT_INT +
95 ars.iasRotations * HeapTrackerObject.HT_ROT +
96 ars.iasVectors * HeapTrackerObject.HT_VEC +
97 ars.iasSDTIntfObjs * HeapTrackerObject.HT_DELE);
98
99 iarArrays = (ars.iasArrays > 0) ? new XMR_Array[ars.iasArrays] : noArrays;
100 iarChars = (ars.iasChars > 0) ? new char[ars.iasChars] : noChars;
101 iarFloats = (ars.iasFloats > 0) ? new double[ars.iasFloats] : noFloats;
102 iarIntegers = (ars.iasIntegers > 0) ? new int[ars.iasIntegers] : noIntegers;
103 iarLists = (ars.iasLists > 0) ? new LSL_List[ars.iasLists] : noLists;
104 iarObjects = (ars.iasObjects > 0) ? new object[ars.iasObjects] : noObjects;
105 iarRotations = (ars.iasRotations > 0) ? new LSL_Rotation[ars.iasRotations] : noRotations;
106 iarStrings = (ars.iasStrings > 0) ? new string[ars.iasStrings] : noStrings;
107 iarVectors = (ars.iasVectors > 0) ? new LSL_Vector[ars.iasVectors] : noVectors;
108 iarSDTClObjs = (ars.iasSDTClObjs > 0) ? new XMRSDTypeClObj[ars.iasSDTClObjs] : noSDTClObjs;
109 iarSDTIntfObjs = (ars.iasSDTIntfObjs > 0) ? new Delegate[ars.iasSDTIntfObjs][] : noSDTIntfObjs;
110 }
111
112 /**
113 * @brief Do not write directly to iarLists[index], rather use this method.
114 */
115 public void PopList(int index, LSL_List lis)
116 {
117 LSL_List old = iarLists[index];
118 int newheapuse = heapUse + HeapTrackerList.Size(lis) - HeapTrackerList.Size(old);
119 heapUse = instance.UpdateHeapUse(heapUse, newheapuse);
120 iarLists[index] = lis;
121 }
122
123 /**
124 * @brief Do not write directly to iarObjects[index], rather use this method.
125 */
126 public void PopObject(int index, object obj)
127 {
128 object old = iarObjects[index];
129 int newheapuse = heapUse + HeapTrackerObject.Size(obj) - HeapTrackerObject.Size(old);
130 heapUse = instance.UpdateHeapUse(heapUse, newheapuse);
131 iarObjects[index] = obj;
132 }
133
134 /**
135 * @brief Do not write directly to iarStrings[index], rather use this method.
136 */
137 public void PopString(int index, string str)
138 {
139 string old = iarStrings[index];
140 int newheapuse = heapUse + HeapTrackerString.Size(str) - HeapTrackerString.Size(old);
141 heapUse = instance.UpdateHeapUse(heapUse, newheapuse);
142 iarStrings[index] = str;
143 }
144
145 /**
146 * @brief Write all arrays out to a file.
147 */
148 public delegate void Sender(object value);
149 public void SendArrays(Sender sender)
150 {
151 sender(iarArrays);
152 sender(iarChars);
153 sender(iarFloats);
154 sender(iarIntegers);
155 sender(iarLists);
156 sender(iarObjects);
157 sender(iarRotations);
158 sender(iarStrings);
159 sender(iarVectors);
160 sender(iarSDTClObjs);
161 sender(iarSDTIntfObjs);
162 }
163
164 /**
165 * @brief Read all arrays in from a file.
166 */
167 public delegate object Recver();
168 public void RecvArrays(Recver recver)
169 {
170 ClearOldArrays();
171
172 iarArrays = (XMR_Array[])recver();
173 char[] chrs = (char[])recver();
174 double[] flts = (double[])recver();
175 int[] ints = (int[])recver();
176 LSL_List[] liss = (LSL_List[])recver();
177 object[] objs = (object[])recver();
178 LSL_Rotation[] rots = (LSL_Rotation[])recver();
179 string[] strs = (string[])recver();
180 LSL_Vector[] vecs = (LSL_Vector[])recver();
181 iarSDTClObjs = (XMRSDTypeClObj[])recver();
182 Delegate[][] dels = (Delegate[][])recver();
183
184 int newheapuse = heapUse;
185
186 // value types simply are the size of the value * number of values
187 newheapuse += chrs.Length * HeapTrackerObject.HT_CHAR;
188 newheapuse += flts.Length * HeapTrackerObject.HT_SFLT;
189 newheapuse += ints.Length * HeapTrackerObject.HT_INT;
190 newheapuse += rots.Length * HeapTrackerObject.HT_ROT;
191 newheapuse += vecs.Length * HeapTrackerObject.HT_VEC;
192 newheapuse += dels.Length * HeapTrackerObject.HT_DELE;
193
194 // lists, objects, strings are the sum of the size of each element
195 foreach(LSL_List lis in liss)
196 newheapuse += HeapTrackerList.Size(lis);
197
198 foreach(object obj in objs)
199 newheapuse += HeapTrackerObject.Size(obj);
200
201 foreach(string str in strs)
202 newheapuse += HeapTrackerString.Size(str);
203
204 // others (XMR_Array, XMRSDTypeClObj) keep track of their own heap usage
205
206 // update script heap usage, throwing an exception before finalizing changes
207 heapUse = instance.UpdateHeapUse(heapUse, newheapuse);
208
209 iarChars = chrs;
210 iarFloats = flts;
211 iarIntegers = ints;
212 iarLists = liss;
213 iarObjects = objs;
214 iarRotations = rots;
215 iarStrings = strs;
216 iarVectors = vecs;
217 iarSDTIntfObjs = dels;
218 }
219
220 private void ClearOldArrays()
221 {
222 int newheapuse = heapUse;
223
224 iarArrays = null;
225 if(iarChars != null)
226 {
227 newheapuse -= iarChars.Length * HeapTrackerObject.HT_CHAR;
228 iarChars = null;
229 }
230 if(iarFloats != null)
231 {
232 newheapuse -= iarFloats.Length * HeapTrackerObject.HT_SFLT;
233 iarFloats = null;
234 }
235 if(iarIntegers != null)
236 {
237 newheapuse -= iarIntegers.Length * HeapTrackerObject.HT_INT;
238 iarIntegers = null;
239 }
240 if(iarLists != null)
241 {
242 foreach(LSL_List lis in iarLists)
243 newheapuse -= HeapTrackerList.Size(lis);
244 iarLists = null;
245 }
246 if(iarObjects != null)
247 {
248 foreach(object obj in iarObjects)
249 newheapuse -= HeapTrackerObject.Size(obj);
250 iarObjects = null;
251 }
252 if(iarRotations != null)
253 {
254 newheapuse -= iarRotations.Length * HeapTrackerObject.HT_ROT;
255 iarRotations = null;
256 }
257 if(iarStrings != null)
258 {
259 foreach(string str in iarStrings)
260 newheapuse -= HeapTrackerString.Size(str);
261 iarStrings = null;
262 }
263 if(iarVectors != null)
264 {
265 newheapuse -= iarVectors.Length * HeapTrackerObject.HT_VEC;
266 iarVectors = null;
267 }
268 iarSDTClObjs = null;
269 if(iarSDTIntfObjs != null)
270 {
271 newheapuse -= iarSDTIntfObjs.Length * HeapTrackerObject.HT_DELE;
272 iarSDTIntfObjs = null;
273 }
274
275 heapUse = instance.UpdateHeapUse(heapUse, newheapuse);
276 }
277 }
278
279 public class XMRInstArSizes
280 {
281 public int iasArrays;
282 public int iasChars;
283 public int iasFloats;
284 public int iasIntegers;
285 public int iasLists;
286 public int iasObjects;
287 public int iasRotations;
288 public int iasStrings;
289 public int iasVectors;
290 public int iasSDTClObjs;
291 public int iasSDTIntfObjs;
292
293 public void WriteAsmFile(TextWriter asmFileWriter, string label)
294 {
295 asmFileWriter.WriteLine(" {0}Arrays {1}", label, iasArrays);
296 asmFileWriter.WriteLine(" {0}Chars {1}", label, iasChars);
297 asmFileWriter.WriteLine(" {0}Floats {1}", label, iasFloats);
298 asmFileWriter.WriteLine(" {0}Integers {1}", label, iasIntegers);
299 asmFileWriter.WriteLine(" {0}Lists {1}", label, iasLists);
300 asmFileWriter.WriteLine(" {0}Objects {1}", label, iasObjects);
301 asmFileWriter.WriteLine(" {0}Rotations {1}", label, iasRotations);
302 asmFileWriter.WriteLine(" {0}Strings {1}", label, iasStrings);
303 asmFileWriter.WriteLine(" {0}Vectors {1}", label, iasVectors);
304 asmFileWriter.WriteLine(" {0}SDTClObjs {1}", label, iasSDTClObjs);
305 asmFileWriter.WriteLine(" {0}SDTIntfObjs {1}", label, iasSDTIntfObjs);
306 }
307
308 public void WriteToFile(BinaryWriter objFileWriter)
309 {
310 objFileWriter.Write(iasArrays);
311 objFileWriter.Write(iasChars);
312 objFileWriter.Write(iasFloats);
313 objFileWriter.Write(iasIntegers);
314 objFileWriter.Write(iasLists);
315 objFileWriter.Write(iasObjects);
316 objFileWriter.Write(iasRotations);
317 objFileWriter.Write(iasStrings);
318 objFileWriter.Write(iasVectors);
319 objFileWriter.Write(iasSDTClObjs);
320 objFileWriter.Write(iasSDTIntfObjs);
321 }
322
323 public void ReadFromFile(BinaryReader objFileReader)
324 {
325 iasArrays = objFileReader.ReadInt32();
326 iasChars = objFileReader.ReadInt32();
327 iasFloats = objFileReader.ReadInt32();
328 iasIntegers = objFileReader.ReadInt32();
329 iasLists = objFileReader.ReadInt32();
330 iasObjects = objFileReader.ReadInt32();
331 iasRotations = objFileReader.ReadInt32();
332 iasStrings = objFileReader.ReadInt32();
333 iasVectors = objFileReader.ReadInt32();
334 iasSDTClObjs = objFileReader.ReadInt32();
335 iasSDTIntfObjs = objFileReader.ReadInt32();
336 }
337 }
338
339 public class XMRStackFrame
340 {
341 public XMRStackFrame nextSF;
342 public string funcName;
343 public int callNo;
344 public object[] objArray;
345 }
346
347 /*
348 * Contains only items required by the stand-alone compiler
349 * so the compiler doesn't need to pull in all of OpenSim.
350 *
351 * Inherit from ScriptBaseClass so we can be used as 'this'
352 * parameter for backend-API calls, eg llSay().
353 */
354 public abstract class XMRInstAbstract: ScriptBaseClass
355 {
356 public const int CallMode_NORMAL = 0; // when function is called, it proceeds normally
357 public const int CallMode_SAVE = 1; // StackSaveException() was thrown, push args/locals to stackFrames
358 public const int CallMode_RESTORE = 2; // when function is called, it pops state from stackFrames
359
360 public bool suspendOnCheckRunHold; // suspend script execution until explicitly set false
361 public bool suspendOnCheckRunTemp; // suspend script execution for single step only
362 public int stackLimit; // stack must have at least this many bytes free on entry to functions
363 public int m_StackLeft; // total number of stack bytes yet to be used (init to stacksize)
364
365 public ScriptObjCode m_ObjCode; // script object code this instance was created from
366
367 public object[] ehArgs; // event handler argument array
368 public bool doGblInit = true; // default state_entry() needs to initialize global variables
369 public int stateCode = 0; // state the script is in (0 = 'default')
370 public int newStateCode = -1; // if >= 0, in the middle of exiting 'stateCode' and entering 'newStateCode'
371 public ScriptEventCode eventCode = ScriptEventCode.None;
372 // what event handler is executing (or None if not)
373
374 public int callMode = CallMode_NORMAL;
375 // to capture stack frames on stackFrames:
376 // set to CallMode_SAVE just before throwing StackSaveException()
377 // from within CheckRun() and cleared to CallMode_NORMAL when
378 // the exception is caught
379 // to restore stack frames from stackFrames:
380 // set to CallMode_RESTORE just before calling CallSEH() and
381 // cleared to CallMode_NORMAL by CheckRun()
382 public XMRStackFrame stackFrames; // stack frames being saved/restored
383
384 private static readonly char[] justacomma = { ',' };
385
386 /*
387 * These arrays hold the global variable values for the script instance.
388 * The array lengths are determined by the script compilation,
389 * and are found in ScriptObjCode.glblSizes.
390 */
391 public XMRInstArrays glblVars;
392
393 public XMRInstAbstract()
394 {
395 glblVars = new XMRInstArrays(this);
396 }
397
398 /****************************************************************\
399 * Abstract function prototypes. *
400 * These functions require access to the OpenSim environment. *
401 \****************************************************************/
402
403 public abstract void CheckRunWork();
404 public abstract void StateChange();
405
406 [xmrMethodCallsCheckRunAttribute] // calls CheckRun()
407 [xmrMethodIsNoisyAttribute] // calls Stub<somethingorother>()
408 public abstract LSL_List xmrEventDequeue(double timeout, int returnMask1, int returnMask2,
409 int backgroundMask1, int backgroundMask2);
410
411 [xmrMethodIsNoisyAttribute] // calls Stub<somethingorother>()
412 public abstract void xmrEventEnqueue(LSL_List ev);
413
414 [xmrMethodIsNoisyAttribute] // calls Stub<somethingorother>()
415 public abstract LSL_List xmrEventSaveDets();
416
417 [xmrMethodIsNoisyAttribute] // calls Stub<somethingorother>()
418 public abstract void xmrEventLoadDets(LSL_List dpList);
419
420
421 /**************************************************\
422 * Functions what don't require runtime support *
423 * beyond what the compiler provides. *
424 \**************************************************/
425
426 protected int heapLimit;
427 private int heapUsed;
428
429 public virtual int UpdateHeapUse(int olduse, int newuse)
430 {
431 if(newuse <= olduse)
432 Interlocked.Add(ref heapUsed, newuse - olduse);
433 else
434 {
435 int newtotal, oldtotal;
436 do
437 {
438 oldtotal = Interlocked.Add(ref heapUsed, 0);
439 newtotal = oldtotal + newuse - olduse;
440 if(newtotal > heapLimit)
441 {
442 // System.GC.Collect ();
443 // System.GC.WaitForPendingFinalizers ();
444 oldtotal = Interlocked.Add(ref heapUsed, 0);
445 newtotal = oldtotal + newuse - olduse;
446 if(newtotal > heapLimit)
447 throw new OutOfHeapException(oldtotal, newtotal, heapLimit);
448 }
449 } while(Interlocked.CompareExchange(ref heapUsed, newtotal, oldtotal) != oldtotal);
450 }
451
452 return newuse;
453 }
454
455 public int xmrHeapLeft()
456 {
457 return heapLimit - heapUsed;
458 }
459
460 public int xmrHeapUsed()
461 {
462 return heapUsed;
463 }
464
465 /**
466 * @brief Call script's event handler function from the very beginning.
467 * @param instance.stateCode = which state the event is happening in
468 * @param instance.eventCode = which event is happening in that state
469 * @returns when event handler has completed or throws an exception
470 * with instance.eventCode = ScriptEventCode.None
471 */
472 public void CallSEH()
473 {
474 ScriptEventHandler seh;
475
476 /*
477 * CallMode_NORMAL: run event handler from the beginning normally
478 * CallMode_RESTORE: restore event handler stack from stackFrames
479 */
480 callMode = (stackFrames == null) ? XMRInstAbstract.CallMode_NORMAL :
481 XMRInstAbstract.CallMode_RESTORE;
482
483 while(true)
484 {
485 if(this.newStateCode < 0)
486 {
487 // Process event given by 'stateCode' and 'eventCode'.
488 // The event handler should call CheckRun() as often as convenient.
489 int newState = this.stateCode;
490 seh = this.m_ObjCode.scriptEventHandlerTable[newState, (int)this.eventCode];
491 if(seh != null)
492 {
493 try
494 {
495 seh(this);
496 }
497 catch(ScriptChangeStateException scse)
498 {
499 newState = scse.newState;
500 }
501 }
502 this.ehArgs = null; // we are done with them and no args for
503 // exit_state()/enter_state() anyway
504
505 // The usual case is no state change.
506 // Even a 'state <samestate>;' statement has no effect except to exit out.
507 // It does not execute the state_exit() or state_entry() handlers.
508 // See http://wiki.secondlife.com/wiki/State
509 if(newState == this.stateCode)
510 break;
511
512 // Save new state in a more permanent location in case we
513 // get serialized out while in the state_exit() handler.
514 this.newStateCode = newState;
515 }
516
517 // Call old state's state_exit() handler.
518 this.eventCode = ScriptEventCode.state_exit;
519 seh = this.m_ObjCode.scriptEventHandlerTable[this.stateCode, (int)ScriptEventCode.state_exit];
520 if(seh != null)
521 {
522 try
523 {
524 seh(this);
525 }
526 catch(ScriptChangeStateException scse)
527 {
528 this.newStateCode = scse.newState;
529 }
530 }
531
532 // Switch over to the new state's state_entry() handler.
533 this.stateCode = this.newStateCode;
534 this.eventCode = ScriptEventCode.state_entry;
535 this.newStateCode = -1;
536
537 // Now that the old state can't possibly start any more activity,
538 // cancel any listening handlers, etc, of the old state.
539 this.StateChange();
540
541 // Loop back to execute new state's state_entry() handler.
542 }
543
544 // Event no longer being processed.
545 this.eventCode = ScriptEventCode.None;
546 }
547
548 /**
549 * @brief For compatibility with old code.
550 */
551 public void CheckRun(int line)
552 {
553 CheckRunStack();
554 }
555
556 /**
557 * @brief Called at beginning of complex functions to see if they
558 * are nested too deep possibly in a recursive loop.
559 */
560 public void CheckRunStack()
561 {
562 if(m_StackLeft < stackLimit)
563 throw new OutOfStackException();
564
565 CheckRunQuick();
566 }
567
568 /**
569 * @brief Called in each iteration of a loop to see if running too long.
570 */
571 public void CheckRunQuick()
572 {
573 // if (suspendOnCheckRunHold || suspendOnCheckRunTemp)
574 CheckRunWork();
575 }
576
577 /**
578 * @brief Called during CallMode_SAVE to create a stackframe save object that saves
579 * local variables and calling point within the function.
580 * @param funcName = name of function whose frame is being saved
581 * @param callNo = call number (ie, return address) within function to restart at
582 * @param nSaves = number of variables the function will save
583 * @returns an object[nSaves] where function can save variables
584 */
585 public object[] CaptureStackFrame(string funcName, int callNo, int nSaves)
586 {
587 XMRStackFrame sf = new XMRStackFrame();
588 sf.nextSF = stackFrames;
589 sf.funcName = funcName;
590 sf.callNo = callNo;
591 sf.objArray = new object[nSaves];
592 stackFrames = sf;
593 return sf.objArray;
594 }
595
596 /**
597 * @brief Called during CallMode_RESTORE to pop a stackframe object to restore
598 * local variables and calling point within the function.
599 * @param funcName = name of function whose frame is being restored
600 * @returns the object[nSaves] where function can retrieve variables
601 * callNo = as passed to CaptureStackFrame() indicating restart point
602 */
603 public object[] RestoreStackFrame(string funcName, out int callNo)
604 {
605 XMRStackFrame sf = stackFrames;
606 if(sf.funcName != funcName)
607 throw new Exception("frame mismatch " + sf.funcName + " vs " + funcName);
608
609 callNo = sf.callNo;
610 stackFrames = sf.nextSF;
611 return sf.objArray;
612 }
613
614 /**
615 * @brief Convert all LSL_Integers in a list to System.Int32s,
616 * as required by llParcelMediaQuery().
617 */
618 public static LSL_List FixLLParcelMediaQuery(LSL_List oldlist)
619 {
620 object[] oldarray = oldlist.Data;
621 int len = oldarray.Length;
622 object[] newarray = new object[len];
623 for(int i = 0; i < len; i++)
624 {
625 object obj = oldarray[i];
626 if(obj is LSL_Integer)
627 obj = (int)(LSL_Integer)obj;
628 newarray[i] = obj;
629 }
630 return new LSL_List(newarray);
631 }
632
633 /**
634 * @brief Convert *SOME* LSL_Integers in a list to System.Int32s,
635 * as required by llParcelMediaCommandList().
636 */
637 public static LSL_List FixLLParcelMediaCommandList(LSL_List oldlist)
638 {
639 object[] oldarray = oldlist.Data;
640 int len = oldarray.Length;
641 object[] newarray = new object[len];
642 int verbatim = 0;
643 for(int i = 0; i < len; i++)
644 {
645 object obj = oldarray[i];
646 if(--verbatim < 0)
647 {
648 if(obj is LSL_Integer)
649 obj = (int)(LSL_Integer)obj;
650 if(obj is int)
651 {
652 switch((int)obj)
653 {
654 case ScriptBaseClass.PARCEL_MEDIA_COMMAND_AUTO_ALIGN:
655 // leave next integer as LSL_Integer
656 verbatim = 1;
657 break;
658
659 case ScriptBaseClass.PARCEL_MEDIA_COMMAND_SIZE:
660 // leave next two integers as LSL_Integer
661 verbatim = 2;
662 break;
663
664 }
665 }
666 }
667 newarray[i] = obj;
668 }
669 return new LSL_List(newarray);
670 }
671
672 public static int xmrHashCode(int i)
673 {
674 return i.GetHashCode();
675 }
676
677 public static int xmrHashCode(double f)
678 {
679 return f.GetHashCode();
680 }
681
682 public static int xmrHashCode(object o)
683 {
684 return o.GetHashCode();
685 }
686
687 public static int xmrHashCode(string s)
688 {
689 return s.GetHashCode();
690 }
691
692 public string xmrTypeName(object o)
693 {
694 /*
695 * Basic types return constant strings of the script-visible type name.
696 */
697 if(o is XMR_Array)
698 return "array";
699 if(o is bool)
700 return "bool";
701 if(o is char)
702 return "char";
703 if(o is Exception)
704 return "exception";
705 if(o is double)
706 return "float";
707 if(o is float)
708 return "float";
709 if(o is LSL_Float)
710 return "float";
711 if(o is int)
712 return "integer";
713 if(o is LSL_Integer)
714 return "integer";
715 if(o is LSL_List)
716 return "list";
717 if(o is LSL_Rotation)
718 return "rotation";
719 if(o is LSL_String)
720 return "string";
721 if(o is string)
722 return "string";
723 if(o is LSL_Vector)
724 return "vector";
725
726 /*
727 * A script-defined interface is represented as an array of delegates.
728 * If that is the case, convert it to the object of the script-defined
729 * class that is implementing the interface. This should let the next
730 * step get the script-defined type name of the object.
731 */
732 if(o is Delegate[])
733 o = ((Delegate[])o)[0].Target;
734
735 /*
736 * If script-defined class instance, get the script-defined
737 * type name.
738 */
739 if(o is XMRSDTypeClObj)
740 return ((XMRSDTypeClObj)o).sdtcClass.longName.val;
741
742 /*
743 * If it's a delegate, maybe we can look up its script-defined type name.
744 */
745 Type ot = o.GetType();
746 if(o is Delegate)
747 {
748 String os;
749 if(m_ObjCode.sdDelTypes.TryGetValue(ot, out os))
750 return os;
751 }
752
753 /*
754 * Don't know what it is, get the C#-level type name.
755 */
756 return ot.ToString();
757 }
758
759 /**
760 * @brief Call the current state's event handler.
761 * @param ev = as returned by xmrEventDequeue saying which event handler to call
762 * and what argument list to pass to it. The llDetect...() parameters
763 * are as currently set for the script (use xmrEventLoadDets to set how
764 * you want them to be different).
765 */
766 public void xmrEventCallHandler(LSL_List ev)
767 {
768 object[] data = ev.Data;
769 int evc = (int)(ev.GetLSLIntegerItem(0).value & 0xFFFFFFFF);
770 ScriptEventHandler seh = m_ObjCode.scriptEventHandlerTable[stateCode, evc];
771 if(seh != null)
772 {
773 int nargs = data.Length - 1;
774 object[] args = new object[nargs];
775 Array.Copy(data, 1, args, 0, nargs);
776
777 object[] saveEHArgs = this.ehArgs;
778 ScriptEventCode saveEventCode = this.eventCode;
779
780 this.ehArgs = args;
781 this.eventCode = (ScriptEventCode)evc;
782
783 seh(this);
784
785 this.ehArgs = saveEHArgs;
786 this.eventCode = saveEventCode;
787 }
788 }
789
790 /**
791 * @brief Sane substring functions.
792 */
793 public string xmrSubstring(string s, int offset)
794 {
795 if(offset >= s.Length)
796 return "";
797 return s.Substring(offset);
798 }
799
800 // C# style
801 public string xmrSubstring(string s, int offset, int length)
802 {
803 if(length <= 0)
804 return "";
805 if(offset >= s.Length)
806 return "";
807 if(length > s.Length - offset)
808 length = s.Length - offset;
809 return s.Substring(offset, length);
810 }
811
812 // java style
813 public string xmrJSubstring(string s, int beg, int end)
814 {
815 if(end <= beg)
816 return "";
817 if(beg >= s.Length)
818 return "";
819 if(end > s.Length)
820 end = s.Length;
821 return s.Substring(beg, end - beg);
822 }
823
824 /**
825 * @brief String begins and ends with test.
826 */
827 public bool xmrStringStartsWith(string s, string t)
828 {
829 return s.StartsWith(t);
830 }
831
832 public bool xmrStringEndsWith(string s, string t)
833 {
834 return s.EndsWith(t);
835 }
836
837 /**
838 * @brief [Last]IndexOf with starting position (just like C#)
839 */
840 public int xmrStringIndexOf(string haystack, string needle)
841 {
842 return haystack.IndexOf(needle);
843 }
844
845 public int xmrStringIndexOf(string haystack, string needle, int startat)
846 {
847 return haystack.IndexOf(needle, startat);
848 }
849
850 public int xmrStringLastIndexOf(string haystack, string needle)
851 {
852 return haystack.LastIndexOf(needle);
853 }
854
855 public int xmrStringLastIndexOf(string haystack, string needle, int startat)
856 {
857 return haystack.LastIndexOf(needle, startat);
858 }
859
860 /**
861 * @brief These conversions throw exceptions if there is anything stinky...
862 */
863 public double xmrString2Float(string s)
864 {
865 return double.Parse(s, CultureInfo.InvariantCulture);
866 }
867
868 public int xmrString2Integer(string s)
869 {
870 s = s.Trim();
871 if(s.StartsWith("0x") || s.StartsWith("0X"))
872 return int.Parse(s.Substring(2), NumberStyles.HexNumber);
873
874 return int.Parse(s, CultureInfo.InvariantCulture);
875 }
876
877 public LSL_Rotation xmrString2Rotation(string s)
878 {
879 s = s.Trim();
880 if(!s.StartsWith("<") || !s.EndsWith(">"))
881 throw new FormatException("doesn't begin with < and end with >");
882
883 s = s.Substring(1, s.Length - 2);
884 string[] splitup = s.Split(justacomma, 5);
885 if(splitup.Length != 4)
886 throw new FormatException("doesn't have exactly 3 commas");
887
888 double x = double.Parse(splitup[0], CultureInfo.InvariantCulture);
889 double y = double.Parse(splitup[1], CultureInfo.InvariantCulture);
890 double z = double.Parse(splitup[2], CultureInfo.InvariantCulture);
891 double w = double.Parse(splitup[3], CultureInfo.InvariantCulture);
892 return new LSL_Rotation(x, y, z, w);
893 }
894
895 public LSL_Vector xmrString2Vector(string s)
896 {
897 s = s.Trim();
898 if(!s.StartsWith("<") || !s.EndsWith(">"))
899 throw new FormatException("doesn't begin with < and end with >");
900
901 s = s.Substring(1, s.Length - 2);
902 string[] splitup = s.Split(justacomma, 4);
903 if(splitup.Length != 3)
904 throw new FormatException("doesn't have exactly 2 commas");
905
906 double x = double.Parse(splitup[0], CultureInfo.InvariantCulture);
907 double y = double.Parse(splitup[1], CultureInfo.InvariantCulture);
908 double z = double.Parse(splitup[2], CultureInfo.InvariantCulture);
909 return new LSL_Vector(x, y, z);
910 }
911
912 /**
913 * @brief Access C#-style formatted numeric conversions.
914 */
915 public string xmrFloat2String(double val, string fmt)
916 {
917 return val.ToString(fmt, CultureInfo.InvariantCulture);
918 }
919
920 public string xmrInteger2String(int val, string fmt)
921 {
922 return val.ToString(fmt, CultureInfo.InvariantCulture);
923 }
924
925 public string xmrRotation2String(LSL_Rotation val, string fmt)
926 {
927 return "<" + val.x.ToString(fmt, CultureInfo.InvariantCulture) + "," +
928 val.y.ToString(fmt, CultureInfo.InvariantCulture) + "," +
929 val.z.ToString(fmt, CultureInfo.InvariantCulture) + "," +
930 val.s.ToString(fmt, CultureInfo.InvariantCulture) + ">";
931 }
932
933 public string xmrVector2String(LSL_Vector val, string fmt)
934 {
935 return "<" + val.x.ToString(fmt, CultureInfo.InvariantCulture) + "," +
936 val.y.ToString(fmt, CultureInfo.InvariantCulture) + "," +
937 val.z.ToString(fmt, CultureInfo.InvariantCulture) + ">";
938 }
939
940 /**
941 * @brief Get a delegate for a script-defined function.
942 * @param name = name of the function including arg types, eg,
943 * "Verify(array,list,string)"
944 * @param sig = script-defined type name
945 * @param targ = function's 'this' pointer or null if static
946 * @returns delegate for the script-defined function
947 */
948 public Delegate GetScriptMethodDelegate(string name, string sig, object targ)
949 {
950 DynamicMethod dm = m_ObjCode.dynamicMethods[name];
951 TokenDeclSDTypeDelegate dt = (TokenDeclSDTypeDelegate)m_ObjCode.sdObjTypesName[sig];
952 return dm.CreateDelegate(dt.GetSysType(), targ);
953 }
954
955 /**
956 * @brief Try to cast the thrown object to the given script-defined type.
957 * @param thrown = what object was thrown
958 * @param inst = what script instance we are running in
959 * @param sdtypeindex = script-defined type to try to cast it to
960 * @returns null: thrown is not castable to sdtypename
961 * else: an object casted to sdtypename
962 */
963 public static object XMRSDTypeCatchTryCastToSDType(object thrown, XMRInstAbstract inst, int sdtypeindex)
964 {
965 TokenDeclSDType sdType = inst.m_ObjCode.sdObjTypesIndx[sdtypeindex];
966
967 /*
968 * If it is a script-defined interface object, convert to the original XMRSDTypeClObj.
969 */
970 if(thrown is Delegate[])
971 {
972 thrown = ((Delegate[])thrown)[0].Target;
973 }
974
975 /*
976 * If it is a script-defined delegate object, make sure it is an instance of the expected type.
977 */
978 if(thrown is Delegate)
979 {
980 Type ot = thrown.GetType();
981 Type tt = sdType.GetSysType();
982 return (ot == tt) ? thrown : null;
983 }
984
985 /*
986 * If it is a script-defined class object, make sure it is an instance of the expected class.
987 */
988 if(thrown is XMRSDTypeClObj)
989 {
990
991 /*
992 * Step from the object's actual class rootward.
993 * If we find the requested class along the way, the cast is valid.
994 * If we run off the end of the root, the cast is not valid.
995 */
996 for(TokenDeclSDTypeClass ac = ((XMRSDTypeClObj)thrown).sdtcClass; ac != null; ac = ac.extends)
997 {
998 if(ac == sdType)
999 return thrown;
1000 }
1001 }
1002
1003 /*
1004 * Don't know what it is, assume it is not what caller wants.
1005 */
1006 return null;
1007 }
1008
1009 /**
1010 * @brief Allocate and access fixed-dimension arrays.
1011 */
1012 public static object xmrFixedArrayAllocC(int len)
1013 {
1014 return new char[len];
1015 }
1016 public static object xmrFixedArrayAllocF(int len)
1017 {
1018 return new double[len];
1019 }
1020 public static object xmrFixedArrayAllocI(int len)
1021 {
1022 return new int[len];
1023 }
1024 public static object xmrFixedArrayAllocO(int len)
1025 {
1026 return new object[len];
1027 }
1028
1029 public static char xmrFixedArrayGetC(object arr, int idx)
1030 {
1031 return ((char[])arr)[idx];
1032 }
1033 public static double xmrFixedArrayGetF(object arr, int idx)
1034 {
1035 return ((double[])arr)[idx];
1036 }
1037 public static int xmrFixedArrayGetI(object arr, int idx)
1038 {
1039 return ((int[])arr)[idx];
1040 }
1041 public static object xmrFixedArrayGetO(object arr, int idx)
1042 {
1043 return ((object[])arr)[idx];
1044 }
1045
1046 public static void xmrFixedArraySetC(object arr, int idx, char val)
1047 {
1048 ((char[])arr)[idx] = val;
1049 }
1050 public static void xmrFixedArraySetF(object arr, int idx, double val)
1051 {
1052 ((double[])arr)[idx] = val;
1053 }
1054 public static void xmrFixedArraySetI(object arr, int idx, int val)
1055 {
1056 ((int[])arr)[idx] = val;
1057 }
1058 public static void xmrFixedArraySetO(object arr, int idx, object val)
1059 {
1060 ((object[])arr)[idx] = val;
1061 }
1062
1063 /**
1064 * @brief Copy from one script-defined array to another.
1065 * @param srcobj = source script-defined array class object pointer
1066 * @param srcstart = offset in source array to start copying from
1067 * @param dstobj = destination script-defined array class object pointer
1068 * @param dststart = offset in destination arry to start copying to
1069 * @param count = number of elements to copy
1070 */
1071 public static void xmrArrayCopy(object srcobj, int srcstart, object dstobj, int dststart, int count)
1072 {
1073 /*
1074 * The script writer should only pass us script-defined class objects.
1075 * Throw exception otherwise.
1076 */
1077 XMRSDTypeClObj srcsdt = (XMRSDTypeClObj)srcobj;
1078 XMRSDTypeClObj dstsdt = (XMRSDTypeClObj)dstobj;
1079
1080 /*
1081 * Get the script-visible type name of the arrays, brackets and all.
1082 */
1083 string srctypename = srcsdt.sdtcClass.longName.val;
1084 string dsttypename = dstsdt.sdtcClass.longName.val;
1085
1086 /*
1087 * The part before the first '[' of each should match exactly,
1088 * meaning the basic data type (eg, float, List<string>) is the same.
1089 * And there must be a '[' in each meaning that it is a script-defined array type.
1090 */
1091 int i = srctypename.IndexOf('[');
1092 int j = dsttypename.IndexOf('[');
1093 if((i < 0) || (j < 0))
1094 throw new InvalidCastException("non-array passed: " + srctypename + " and/or " + dsttypename);
1095 if((i != j) || !srctypename.StartsWith(dsttypename.Substring(0, j)))
1096 throw new ArrayTypeMismatchException(srctypename + " vs " + dsttypename);
1097
1098 /*
1099 * The number of brackets must match exactly.
1100 * This permits copying from something like a float[,][] to something like a float[][].
1101 * But you cannot copy from a float[][] to a float[] or wisa wersa.
1102 * Counting either '[' or ']' would work equally well.
1103 */
1104 int srclen = srctypename.Length;
1105 int dstlen = dsttypename.Length;
1106 int srcjags = 0;
1107 int dstjags = 0;
1108 while(++i < srclen)
1109 if(srctypename[i] == ']')
1110 srcjags++;
1111 while(++j < dstlen)
1112 if(dsttypename[j] == ']')
1113 dstjags++;
1114 if(dstjags != srcjags)
1115 throw new ArrayTypeMismatchException(srctypename + " vs " + dsttypename);
1116
1117 /*
1118 * Perform the copy.
1119 */
1120 Array srcarray = (Array)srcsdt.instVars.iarObjects[0];
1121 Array dstarray = (Array)dstsdt.instVars.iarObjects[0];
1122 Array.Copy(srcarray, srcstart, dstarray, dststart, count);
1123 }
1124
1125 /**
1126 * @brief Copy from an array to a list.
1127 * @param srcar = the array to copy from
1128 * @param start = where to start in the array
1129 * @param count = number of elements
1130 * @returns the list
1131 */
1132 public static LSL_List xmrArray2List(object srcar, int start, int count)
1133 {
1134 /*
1135 * Get the script-visible type of the array.
1136 * We only do arrays.
1137 */
1138 XMRSDTypeClObj array = (XMRSDTypeClObj)srcar;
1139 TokenDeclSDTypeClass sdtClass = array.sdtcClass;
1140 if(sdtClass.arrayOfRank == 0)
1141 throw new InvalidCastException("only do arrays not " + sdtClass.longName.val);
1142
1143 /*
1144 * Validate objects they want to put in the list.
1145 * We can't allow anything funky that OpenSim runtime doesn't expect.
1146 */
1147 Array srcarray = (Array)array.instVars.iarObjects[0];
1148 object[] output = new object[count];
1149 for(int i = 0; i < count; i++)
1150 {
1151 object src = srcarray.GetValue(i + start);
1152 if(src == null)
1153 throw new NullReferenceException("null element " + i);
1154 if(src is double)
1155 {
1156 output[i] = new LSL_Float((double)src);
1157 continue;
1158 }
1159 if(src is int)
1160 {
1161 output[i] = new LSL_Integer((int)src);
1162 continue;
1163 }
1164 if(src is LSL_Rotation)
1165 {
1166 output[i] = src;
1167 continue;
1168 }
1169 if(src is LSL_Vector)
1170 {
1171 output[i] = src;
1172 continue;
1173 }
1174 if(src is string)
1175 {
1176 output[i] = new LSL_String((string)src);
1177 continue;
1178 }
1179 throw new InvalidCastException("invalid element " + i + " type " + src.GetType().Name);
1180 }
1181
1182 /*
1183 * Make a list out of that now immutable array.
1184 */
1185 return new LSL_List(output);
1186 }
1187
1188 /**
1189 * @brief Copy from a list to an array.
1190 * @param srclist = list to copy from
1191 * @param srcstart = where to start in the list
1192 * @param dstobj = array to copy to
1193 * @param dststart = where to start in the array
1194 * @param count = number of elements
1195 */
1196 public static void xmrList2Array(LSL_List srclist, int srcstart, object dstobj, int dststart, int count)
1197 {
1198 /*
1199 * Get the script-visible type of the destination.
1200 * We only do arrays.
1201 */
1202 XMRSDTypeClObj dstarray = (XMRSDTypeClObj)dstobj;
1203 TokenDeclSDTypeClass sdtClass = dstarray.sdtcClass;
1204 if(sdtClass.arrayOfType == null)
1205 throw new InvalidCastException("only do arrays not " + sdtClass.longName.val);
1206
1207 /*
1208 * Copy from the immutable array to the mutable array.
1209 * Strip off any LSL wrappers as the script code doesn't expect any.
1210 */
1211 object[] srcarr = srclist.Data;
1212 Array dstarr = (Array)dstarray.instVars.iarObjects[0];
1213
1214 for(int i = 0; i < count; i++)
1215 {
1216 object obj = srcarr[i + srcstart];
1217 if(obj is LSL_Float)
1218 obj = ((LSL_Float)obj).value;
1219 else if(obj is LSL_Integer)
1220 obj = ((LSL_Integer)obj).value;
1221 else if(obj is LSL_String)
1222 obj = ((LSL_String)obj).m_string;
1223 dstarr.SetValue(obj, i + dststart);
1224 }
1225 }
1226
1227 /**
1228 * @brief Copy from an array of characters to a string.
1229 * @param srcar = the array to copy from
1230 * @param start = where to start in the array
1231 * @param count = number of elements
1232 * @returns the string
1233 */
1234 public static string xmrChars2String(object srcar, int start, int count)
1235 {
1236 /*
1237 * Make sure they gave us a script-defined array object.
1238 */
1239 XMRSDTypeClObj array = (XMRSDTypeClObj)srcar;
1240 TokenDeclSDTypeClass sdtClass = array.sdtcClass;
1241 if(sdtClass.arrayOfRank == 0)
1242 throw new InvalidCastException("only do arrays not " + sdtClass.longName.val);
1243
1244 /*
1245 * We get a type cast error from mono if they didn't give us a character array.
1246 * But if it is ok, create a string from the requested characters.
1247 */
1248 char[] srcarray = (char[])array.instVars.iarObjects[0];
1249 return new string(srcarray, start, count);
1250 }
1251
1252 /**
1253 * @brief Copy from a string to a character array.
1254 * @param srcstr = string to copy from
1255 * @param srcstart = where to start in the string
1256 * @param dstobj = array to copy to
1257 * @param dststart = where to start in the array
1258 * @param count = number of elements
1259 */
1260 public static void xmrString2Chars(string srcstr, int srcstart, object dstobj, int dststart, int count)
1261 {
1262 /*
1263 * Make sure they gave us a script-defined array object.
1264 */
1265 XMRSDTypeClObj dstarray = (XMRSDTypeClObj)dstobj;
1266 TokenDeclSDTypeClass sdtClass = dstarray.sdtcClass;
1267 if(sdtClass.arrayOfType == null)
1268 throw new InvalidCastException("only do arrays not " + sdtClass.longName.val);
1269
1270 /*
1271 * We get a type cast error from mono if they didn't give us a character array.
1272 * But if it is ok, copy from the string to the character array.
1273 */
1274 char[] dstarr = (char[])dstarray.instVars.iarObjects[0];
1275 for(int i = 0; i < count; i++)
1276 dstarr[i + dststart] = srcstr[i + srcstart];
1277 }
1278
1279 /**
1280 * @brief Implement osParseJSON() so we return an array to the script.
1281 * No coherent example of its use in scripts on web found.
1282 * see http://www.json.org/ for more details on JSON
1283 */
1284 private static LSL_List nullList = new LSL_List(new object[0]);
1285 public new XMR_Array osParseJSON(string json)
1286 {
1287 XMR_Array dict = new XMR_Array(this);
1288 int idx = ParseJSON(dict, nullList, json, 0);
1289 while(idx < json.Length)
1290 {
1291 if(json[idx] > ' ')
1292 throw new Exception("left-over json " + json);
1293 idx++;
1294 }
1295 return dict;
1296 }
1297
1298 private static int ParseJSON(XMR_Array dict, LSL_List keys, string json, int idx)
1299 {
1300 char c;
1301
1302 while((c = json[idx++]) <= ' ')
1303 {
1304 }
1305 switch(c)
1306 {
1307
1308 // '{' <keystring> ':' <value> [ ',' <keystring> ':' <value> ... ] '}'
1309 case '{':
1310 do
1311 {
1312 string key = ParseJSONString(json, ref idx);
1313 while((c = json[idx++]) <= ' ')
1314 {
1315 }
1316 if(c != ':')
1317 throw new Exception("missing : after key");
1318 idx = ParseJSON(dict, ParseJSONKeyAdd(keys, key), json, idx);
1319 while((c = json[idx++]) <= ' ')
1320 {
1321 }
1322 } while(c == ',');
1323 if(c != '}')
1324 throw new Exception("missing , or } after value");
1325 break;
1326
1327
1328 // '[' <value> [ ',' <value> ... ] ']'
1329 case '[':
1330 int index = 0;
1331 do
1332 {
1333 object key = index++;
1334 idx = ParseJSON(dict, ParseJSONKeyAdd(keys, key), json, idx);
1335 while((c = json[idx++]) <= ' ')
1336 {
1337 }
1338 } while(c == ',');
1339 if(c != ']')
1340 throw new Exception("missing , or ] after value");
1341 break;
1342
1343
1344 // '"'<string>'"'
1345 case '"':
1346 {
1347 --idx;
1348 string val = ParseJSONString(json, ref idx);
1349 dict.SetByKey(keys, val);
1350 break;
1351 }
1352 // true false null
1353 case 't':
1354 if(json.Substring(idx, 3) != "rue")
1355 throw new Exception("bad true in json");
1356 idx += 3;
1357 dict.SetByKey(keys, 1);
1358 break;
1359
1360 case 'f':
1361 if(json.Substring(idx, 4) != "alse")
1362 throw new Exception("bad false in json");
1363 idx += 4;
1364 dict.SetByKey(keys, 0);
1365 break;
1366
1367 case 'n':
1368 if(json.Substring(idx, 3) != "ull")
1369 throw new Exception("bad null in json");
1370 idx += 3;
1371 dict.SetByKey(keys, null);
1372 break;
1373
1374 // otherwise assume it's a number
1375 default:
1376 {
1377 --idx;
1378 object val = ParseJSONNumber(json, ref idx);
1379 dict.SetByKey(keys, val);
1380 break;
1381 }
1382 }
1383 return idx;
1384 }
1385
1386 // Given the key for a whole array, create a key for a given element of the array
1387 private static LSL_List ParseJSONKeyAdd(LSL_List oldkeys, object key)
1388 {
1389 int oldkeyslen = oldkeys.Length;
1390 object[] array = oldkeys.Data;
1391 Array.Resize<object>(ref array, oldkeyslen + 1);
1392 array[oldkeyslen] = key;
1393 return new LSL_List(array);
1394 }
1395
1396 // Parse out a JSON string
1397 private static string ParseJSONString(string json, ref int idx)
1398 {
1399 char c;
1400
1401 while((c = json[idx++]) <= ' ')
1402 {
1403 }
1404 if(c != '"')
1405 throw new Exception("bad start of json string");
1406
1407 StringBuilder sb = new StringBuilder();
1408 while((c = json[idx++]) != '"')
1409 {
1410 if(c == '\\')
1411 {
1412 c = json[idx++];
1413 switch(c)
1414 {
1415 case 'b':
1416 c = '\b';
1417 break;
1418
1419 case 'f':
1420 c = '\f';
1421 break;
1422
1423 case 'n':
1424 c = '\n';
1425 break;
1426
1427 case 'r':
1428 c = '\r';
1429 break;
1430
1431 case 't':
1432 c = '\t';
1433 break;
1434
1435 case 'u':
1436 c = (char)Int32.Parse(json.Substring(idx, 4),
1437 System.Globalization.NumberStyles.HexNumber);
1438 idx += 4;
1439 break;
1440
1441 default:
1442 break;
1443 }
1444 }
1445 sb.Append(c);
1446 }
1447 return sb.ToString();
1448 }
1449
1450 // Parse out a JSON number
1451 private static object ParseJSONNumber(string json, ref int idx)
1452 {
1453 char c;
1454
1455 while((c = json[idx++]) <= ' ')
1456 {
1457 }
1458
1459 bool expneg = false;
1460 bool isneg = false;
1461 int decpt = -1;
1462 int expon = 0;
1463 int ival = 0;
1464 double dval = 0;
1465
1466 if(c == '-')
1467 {
1468 isneg = true;
1469 c = json[idx++];
1470 }
1471 if((c < '0') || (c > '9'))
1472 throw new Exception("bad json number");
1473
1474 while((c >= '0') && (c <= '9'))
1475 {
1476 dval *= 10;
1477 ival *= 10;
1478 dval += c - '0';
1479 ival += c - '0';
1480 c = '\0';
1481 if(idx < json.Length)
1482 c = json[idx++];
1483 }
1484 if(c == '.')
1485 {
1486 decpt = 0;
1487 c = '\0';
1488 if(idx < json.Length)
1489 c = json[idx++];
1490 while((c >= '0') && (c <= '9'))
1491 {
1492 dval *= 10;
1493 dval += c - '0';
1494 decpt++;
1495 c = '\0';
1496 if(idx < json.Length)
1497 c = json[idx++];
1498 }
1499 }
1500 if((c == 'e') || (c == 'E'))
1501 {
1502 if(decpt < 0)
1503 decpt = 0;
1504 c = json[idx++];
1505 if(c == '-')
1506 expneg = true;
1507 if((c == '-') || (c == '+'))
1508 c = json[idx++];
1509 while((c >= '0') && (c <= '9'))
1510 {
1511 expon *= 10;
1512 expon += c - '0';
1513 c = '\0';
1514 if(idx < json.Length)
1515 c = json[idx++];
1516 }
1517 if(expneg)
1518 expon = -expon;
1519 }
1520
1521 if(c != 0)
1522 --idx;
1523 if(decpt < 0)
1524 {
1525 if(isneg)
1526 ival = -ival;
1527 return ival;
1528 }
1529 else
1530 {
1531 if(isneg)
1532 dval = -dval;
1533 dval *= Math.Pow(10, expon - decpt);
1534 return dval;
1535 }
1536 }
1537
1538 /**
1539 * @brief Exception-related runtime calls.
1540 */
1541 // Return exception message (no type information just the message)
1542 public static string xmrExceptionMessage(Exception ex)
1543 {
1544 return ex.Message;
1545 }
1546
1547 // Return stack trace (no type or message, just stack trace lines: at ... \n)
1548 public string xmrExceptionStackTrace(Exception ex)
1549 {
1550 return XMRExceptionStackString(ex);
1551 }
1552
1553 // Return value thrown by a throw statement
1554 public static object xmrExceptionThrownValue(Exception ex)
1555 {
1556 return ((ScriptThrownException)ex).thrown;
1557 }
1558
1559 // Return exception's short type name, eg, NullReferenceException, ScriptThrownException, etc.
1560 public static string xmrExceptionTypeName(Exception ex)
1561 {
1562 return ex.GetType().Name;
1563 }
1564
1565 // internal use only: converts any IL addresses in script-defined methods to source location equivalent
1566 // Mono ex.StackTrace:
1567 // at OpenSim.Region.ScriptEngine.YEngine.TypeCast.ObjectToInteger (System.Object x) [0x0005e] in /home/kunta/opensim-0.9/addon-modules/YEngine/Module/MMRScriptTypeCast.cs:750
1568 // at (wrapper dynamic-method) System.Object:default state_entry (OpenSim.Region.ScriptEngine.YEngine.XMRInstAbstract) [0x00196]
1569
1570 // Microsoft ex.StackTrace:
1571 // at OpenSim.Region.ScriptEngine.YEngine.TypeCast.ObjectToInteger(Object x) in C:\Users\mrieker\opensim-0.9-source\addon-modules\YEngine\Module\MMRScriptTypeCast.cs:line 750
1572 // at default state_entry (XMRInstAbstract )
1573 public string XMRExceptionStackString(Exception ex)
1574 {
1575 string stwhole = ex.StackTrace;
1576 string[] stlines = stwhole.Split(new char[] { '\n' });
1577 StringBuilder sb = new StringBuilder();
1578 foreach(string st in stlines)
1579 {
1580 string stline = st.Trim();
1581 if(stline == "")
1582 continue;
1583
1584 // strip 'at' off the front of line
1585 if(stline.StartsWith("at "))
1586 {
1587 stline = stline.Substring(3);
1588 }
1589
1590 // strip '(wrapper ...' off front of line
1591 if(stline.StartsWith("(wrapper dynamic-method) System.Object:"))
1592 {
1593 stline = stline.Substring(39);
1594 }
1595
1596 // strip the (systemargtypes...) from our dynamic method names cuz it's messy
1597 // 'default state_entry (XMRInstAbstract )'
1598 // => 'default state_entry'
1599 // 'CallSomethingThatThrows(string) (OpenSim.Region.ScriptEngine.YEngine.XMRInstance,string)'
1600 // => 'CallSomethingThatThrows(string)'
1601 int kwin = stline.IndexOf(" in ");
1602 int br0x = stline.IndexOf(" [0x");
1603 int pastCloseParen = stline.Length;
1604 if((kwin >= 0) && (br0x >= 0))
1605 pastCloseParen = Math.Min(kwin, br0x);
1606 else if(kwin >= 0)
1607 pastCloseParen = kwin;
1608 else if(br0x >= 0)
1609 pastCloseParen = br0x;
1610 else
1611 pastCloseParen = stline.Length;
1612 int endFuncName = pastCloseParen;
1613 while(endFuncName > 0)
1614 {
1615 if(stline[--endFuncName] == '(')
1616 break;
1617 }
1618 while(endFuncName > 0)
1619 {
1620 if(stline[endFuncName - 1] != ' ')
1621 break;
1622 --endFuncName;
1623 }
1624 string funcName = stline.Substring(0, endFuncName);
1625 KeyValuePair<int, ScriptSrcLoc>[] srcLocs;
1626 if(m_ObjCode.scriptSrcLocss.TryGetValue(funcName, out srcLocs))
1627 {
1628 stline = stline.Substring(0, endFuncName) + stline.Substring(pastCloseParen);
1629 kwin = stline.IndexOf(" in ");
1630 br0x = stline.IndexOf(" [0x");
1631 }
1632
1633 // keyword 'in' is just before filename:linenumber that goes to end of line
1634 // trim up the corresponding filename (ie, remove useless path info)
1635 if(kwin >= 0)
1636 {
1637 int begfn = kwin + 4;
1638 int slash = begfn;
1639 for(int i = begfn; i < stline.Length; i++)
1640 {
1641 char c = stline[i];
1642 if((c == '/') || (c == '\\'))
1643 slash = i + 1;
1644 }
1645 stline = stline.Substring(0, begfn) + stline.Substring(slash);
1646 }
1647 else if(srcLocs != null)
1648 {
1649
1650 // no filename:linenumber info, try to convert IL offset
1651 if(br0x >= 0)
1652 {
1653 try
1654 {
1655 int begiloffs = br0x + 4;
1656 int endiloffs = stline.IndexOf("]", begiloffs);
1657 int iloffset = int.Parse(stline.Substring(begiloffs, endiloffs - begiloffs),
1658 System.Globalization.NumberStyles.HexNumber);
1659
1660 int srcLocIdx;
1661 int srcLocLen = srcLocs.Length;
1662 for(srcLocIdx = 0; ++srcLocIdx < srcLocLen;)
1663 {
1664 if(iloffset < srcLocs[srcLocIdx].Key)
1665 break;
1666 }
1667 ScriptSrcLoc srcLoc = srcLocs[--srcLocIdx].Value;
1668
1669 stline = stline.Substring(0, br0x) + " <" +
1670 srcLoc.file + '(' + srcLoc.line + ',' + srcLoc.posn + ")>";
1671 }
1672 catch
1673 {
1674 }
1675 }
1676 }
1677
1678 // put edited line in output string
1679 if(sb.Length > 0)
1680 sb.AppendLine();
1681 sb.Append(" at ");
1682 sb.Append(stline);
1683 }
1684 return sb.ToString();
1685 }
1686
1687 /**
1688 * @brief List fonts available.
1689 */
1690 public LSL_List xmrFontsAvailable()
1691 {
1692 System.Drawing.FontFamily[] families = System.Drawing.FontFamily.Families;
1693 object[] output = new object[families.Length];
1694 for(int i = 0; i < families.Length; i++)
1695 output[i] = new LSL_String(families[i].Name);
1696
1697 return new LSL_List(output);
1698 }
1699
1700 /************************\
1701 * Used by decompiler *
1702 \************************/
1703
1704 public bool xmrRotationToBool(LSL_Rotation x)
1705 {
1706 return TypeCast.RotationToBool(x);
1707 }
1708 public bool xmrStringToBool(string x)
1709 {
1710 return TypeCast.StringToBool(x);
1711 }
1712 public bool xmrVectorToBool(LSL_Vector x)
1713 {
1714 return TypeCast.VectorToBool(x);
1715 }
1716 public bool xmrKeyToBool(string x)
1717 {
1718 return TypeCast.KeyToBool(x);
1719 }
1720 public bool xmrListToBool(LSL_List x)
1721 {
1722 return TypeCast.ListToBool(x);
1723 }
1724
1725 public int xmrStringCompare(string x, string y)
1726 {
1727 return string.Compare(x, y);
1728 }
1729
1730 /**
1731 * @brief types of data we serialize
1732 */
1733 private enum Ser: byte
1734 {
1735 NULL,
1736 EVENTCODE,
1737 LSLFLOAT,
1738 LSLINT,
1739 LSLKEY,
1740 LSLLIST,
1741 LSLROT,
1742 LSLSTR,
1743 LSLVEC,
1744 SYSARRAY,
1745 SYSDOUB,
1746 SYSFLOAT,
1747 SYSINT,
1748 SYSSTR,
1749 XMRARRAY,
1750 DUPREF,
1751 SYSBOOL,
1752 XMRINST,
1753 DELEGATE,
1754 SDTCLOBJ,
1755 SYSCHAR,
1756 SYSERIAL,
1757 THROWNEX
1758 }
1759
1760 /**
1761 * @brief Write state out to a stream.
1762 * Do not change script state.
1763 */
1764 public void MigrateOut(BinaryWriter mow)
1765 {
1766 try
1767 {
1768 this.migrateOutWriter = mow;
1769 this.migrateOutObjects = new Dictionary<object, int>();
1770 this.migrateOutLists = new Dictionary<object[], ObjLslList>();
1771 this.SendObjValue(this.ehArgs);
1772 mow.Write(this.doGblInit);
1773 mow.Write(this.stateCode);
1774 mow.Write((int)this.eventCode);
1775 this.glblVars.SendArrays(this.SendObjValue);
1776 if(this.newStateCode >= 0)
1777 {
1778 mow.Write("**newStateCode**");
1779 mow.Write(this.newStateCode);
1780 }
1781 for(XMRStackFrame thisSF = this.stackFrames; thisSF != null; thisSF = thisSF.nextSF)
1782 {
1783 mow.Write(thisSF.funcName);
1784 mow.Write(thisSF.callNo);
1785 this.SendObjValue(thisSF.objArray);
1786 }
1787 mow.Write("");
1788 }
1789 finally
1790 {
1791 this.migrateOutWriter = null;
1792 this.migrateOutObjects = null;
1793 this.migrateOutLists = null;
1794 }
1795 }
1796
1797 /**
1798 * @brief Write an object to the output stream.
1799 * @param graph = object to send
1800 */
1801 private BinaryWriter migrateOutWriter;
1802 private Dictionary<object, int> migrateOutObjects;
1803 private Dictionary<object[], ObjLslList> migrateOutLists;
1804 public void SendObjValue(object graph)
1805 {
1806 BinaryWriter mow = this.migrateOutWriter;
1807
1808 /*
1809 * Value types (including nulls) are always output directly.
1810 */
1811 if(graph == null)
1812 {
1813 mow.Write((byte)Ser.NULL);
1814 return;
1815 }
1816 if(graph is ScriptEventCode)
1817 {
1818 mow.Write((byte)Ser.EVENTCODE);
1819 mow.Write((int)graph);
1820 return;
1821 }
1822 if(graph is LSL_Float)
1823 {
1824 mow.Write((byte)Ser.LSLFLOAT);
1825 mow.Write((double)((LSL_Float)graph).value);
1826 return;
1827 }
1828 if(graph is LSL_Integer)
1829 {
1830 mow.Write((byte)Ser.LSLINT);
1831 mow.Write((int)((LSL_Integer)graph).value);
1832 return;
1833 }
1834 if(graph is LSL_Key)
1835 {
1836 mow.Write((byte)Ser.LSLKEY);
1837 LSL_Key key = (LSL_Key)graph;
1838 SendObjValue(key.m_string); // m_string can be null
1839 return;
1840 }
1841 if(graph is LSL_Rotation)
1842 {
1843 mow.Write((byte)Ser.LSLROT);
1844 mow.Write((double)((LSL_Rotation)graph).x);
1845 mow.Write((double)((LSL_Rotation)graph).y);
1846 mow.Write((double)((LSL_Rotation)graph).z);
1847 mow.Write((double)((LSL_Rotation)graph).s);
1848 return;
1849 }
1850 if(graph is LSL_String)
1851 {
1852 mow.Write((byte)Ser.LSLSTR);
1853 LSL_String str = (LSL_String)graph;
1854 SendObjValue(str.m_string); // m_string can be null
1855 return;
1856 }
1857 if(graph is LSL_Vector)
1858 {
1859 mow.Write((byte)Ser.LSLVEC);
1860 mow.Write((double)((LSL_Vector)graph).x);
1861 mow.Write((double)((LSL_Vector)graph).y);
1862 mow.Write((double)((LSL_Vector)graph).z);
1863 return;
1864 }
1865 if(graph is bool)
1866 {
1867 mow.Write((byte)Ser.SYSBOOL);
1868 mow.Write((bool)graph);
1869 return;
1870 }
1871 if(graph is double)
1872 {
1873 mow.Write((byte)Ser.SYSDOUB);
1874 mow.Write((double)graph);
1875 return;
1876 }
1877 if(graph is float)
1878 {
1879 mow.Write((byte)Ser.SYSFLOAT);
1880 mow.Write((float)graph);
1881 return;
1882 }
1883 if(graph is int)
1884 {
1885 mow.Write((byte)Ser.SYSINT);
1886 mow.Write((int)graph);
1887 return;
1888 }
1889 if(graph is char)
1890 {
1891 mow.Write((byte)Ser.SYSCHAR);
1892 mow.Write((char)graph);
1893 return;
1894 }
1895
1896 /*
1897 * Script instance pointer is always just that.
1898 */
1899 if(graph == this)
1900 {
1901 mow.Write((byte)Ser.XMRINST);
1902 return;
1903 }
1904
1905 /*
1906 * Convert lists to object type.
1907 * This is compatible with old migration data and also
1908 * two vars pointing to same list won't duplicate it.
1909 */
1910 if(graph is LSL_List)
1911 {
1912 object[] data = ((LSL_List)graph).Data;
1913 ObjLslList oll;
1914 if(!this.migrateOutLists.TryGetValue(data, out oll))
1915 {
1916 oll = new ObjLslList();
1917 oll.objarray = data;
1918 this.migrateOutLists[data] = oll;
1919 }
1920 graph = oll;
1921 }
1922
1923 /*
1924 * If this same exact object was already serialized,
1925 * just output an index telling the receiver to use
1926 * that same old object, rather than creating a whole
1927 * new object with the same values. Also this prevents
1928 * self-referencing objects (like arrays) from causing
1929 * an infinite loop.
1930 */
1931 int ident;
1932 if(this.migrateOutObjects.TryGetValue(graph, out ident))
1933 {
1934 mow.Write((byte)Ser.DUPREF);
1935 mow.Write(ident);
1936 return;
1937 }
1938
1939 /*
1940 * Object not seen before, save its address with an unique
1941 * ident number that the receiver can easily regenerate.
1942 */
1943 ident = this.migrateOutObjects.Count;
1944 this.migrateOutObjects.Add(graph, ident);
1945
1946 /*
1947 * Now output the object's value(s).
1948 * If the object self-references, the object is alreay entered
1949 * in the dictionary and so the self-reference will just emit
1950 * a DUPREF tag instead of trying to output the whole object
1951 * again.
1952 */
1953 if(graph is ObjLslList)
1954 {
1955 mow.Write((byte)Ser.LSLLIST);
1956 ObjLslList oll = (ObjLslList)graph;
1957 SendObjValue(oll.objarray);
1958 }
1959 else if(graph is XMR_Array)
1960 {
1961 mow.Write((byte)Ser.XMRARRAY);
1962 ((XMR_Array)graph).SendArrayObj(this.SendObjValue);
1963 }
1964 else if(graph is Array)
1965 {
1966 Array array = (Array)graph;
1967 mow.Write((byte)Ser.SYSARRAY);
1968 mow.Write(SysType2String(array.GetType().GetElementType()));
1969 mow.Write((int)array.Length);
1970 for(int i = 0; i < array.Length; i++)
1971 this.SendObjValue(array.GetValue(i));
1972 }
1973 else if(graph is string)
1974 {
1975 mow.Write((byte)Ser.SYSSTR);
1976 mow.Write((string)graph);
1977 }
1978 else if(graph is Delegate)
1979 {
1980 Delegate del = (Delegate)graph;
1981 mow.Write((byte)Ser.DELEGATE);
1982 mow.Write(del.Method.Name);
1983 Type delType = del.GetType();
1984 foreach(KeyValuePair<string, TokenDeclSDType> kvp in m_ObjCode.sdObjTypesName)
1985 {
1986 TokenDeclSDType sdt = kvp.Value;
1987 if(sdt is TokenDeclSDTypeDelegate)
1988 {
1989 TokenDeclSDTypeDelegate sdtd = (TokenDeclSDTypeDelegate)sdt;
1990 if(sdtd.GetSysType() == delType)
1991 {
1992 mow.Write(kvp.Key);
1993 goto found;
1994 }
1995 }
1996 }
1997 throw new Exception("cant find script-defined delegate for " + del.Method.Name + " type " + del.GetType());
1998 found:
1999 SendObjValue(del.Target);
2000 }
2001 else if(graph is XMRSDTypeClObj)
2002 {
2003 mow.Write((byte)Ser.SDTCLOBJ);
2004 ((XMRSDTypeClObj)graph).Capture(this.SendObjValue);
2005 }
2006 else if(graph is ScriptThrownException)
2007 {
2008 MemoryStream memoryStream = new MemoryStream();
2009 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter =
2010 new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
2011 bformatter.Serialize(memoryStream, graph);
2012 byte[] rawBytes = memoryStream.ToArray();
2013 mow.Write((byte)Ser.THROWNEX);
2014 mow.Write((int)rawBytes.Length);
2015 mow.Write(rawBytes);
2016 SendObjValue(((ScriptThrownException)graph).thrown);
2017 }
2018 else
2019 {
2020 MemoryStream memoryStream = new MemoryStream();
2021 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter =
2022 new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
2023 bformatter.Serialize(memoryStream, graph);
2024 byte[] rawBytes = memoryStream.ToArray();
2025 mow.Write((byte)Ser.SYSERIAL);
2026 mow.Write((int)rawBytes.Length);
2027 mow.Write(rawBytes);
2028 }
2029 }
2030
2031 /**
2032 * @brief Use short strings for known type names.
2033 */
2034 private static string SysType2String(Type type)
2035 {
2036 if(type.IsArray && (type.GetArrayRank() == 1))
2037 {
2038 string str = KnownSysType2String(type.GetElementType());
2039 if(str != null)
2040 return str + "[]";
2041 }
2042 else
2043 {
2044 string str = KnownSysType2String(type);
2045 if(str != null)
2046 return str;
2047 }
2048 return type.ToString();
2049 }
2050 private static string KnownSysType2String(Type type)
2051 {
2052 if(type == typeof(bool))
2053 return "bo";
2054 if(type == typeof(char))
2055 return "ch";
2056 if(type == typeof(Delegate))
2057 return "de";
2058 if(type == typeof(double))
2059 return "do";
2060 if(type == typeof(float))
2061 return "fl";
2062 if(type == typeof(int))
2063 return "in";
2064 if(type == typeof(LSL_List))
2065 return "li";
2066 if(type == typeof(object))
2067 return "ob";
2068 if(type == typeof(LSL_Rotation))
2069 return "ro";
2070 if(type == typeof(XMRSDTypeClObj))
2071 return "sc";
2072 if(type == typeof(string))
2073 return "st";
2074 if(type == typeof(LSL_Vector))
2075 return "ve";
2076 if(type == typeof(XMR_Array))
2077 return "xa";
2078 return null;
2079 }
2080 private static Type String2SysType(string str)
2081 {
2082 if(str.EndsWith("[]"))
2083 return String2SysType(str.Substring(0, str.Length - 2)).MakeArrayType();
2084
2085 if(str == "bo")
2086 return typeof(bool);
2087 if(str == "ch")
2088 return typeof(char);
2089 if(str == "de")
2090 return typeof(Delegate);
2091 if(str == "do")
2092 return typeof(double);
2093 if(str == "fl")
2094 return typeof(float);
2095 if(str == "in")
2096 return typeof(int);
2097 if(str == "li")
2098 return typeof(LSL_List);
2099 if(str == "ob")
2100 return typeof(object);
2101 if(str == "ro")
2102 return typeof(LSL_Rotation);
2103 if(str == "sc")
2104 return typeof(XMRSDTypeClObj);
2105 if(str == "st")
2106 return typeof(string);
2107 if(str == "ve")
2108 return typeof(LSL_Vector);
2109 if(str == "xa")
2110 return typeof(XMR_Array);
2111 return Type.GetType(str, true);
2112 }
2113
2114 /**
2115 * @brief Read state in from a stream.
2116 */
2117 public void MigrateIn(BinaryReader mir)
2118 {
2119 try
2120 {
2121 this.migrateInReader = mir;
2122 this.migrateInObjects = new Dictionary<int, object>();
2123 this.ehArgs = (object[])this.RecvObjValue();
2124 this.doGblInit = mir.ReadBoolean();
2125 this.stateCode = mir.ReadInt32();
2126 this.eventCode = (ScriptEventCode)mir.ReadInt32();
2127 this.newStateCode = -1;
2128 this.glblVars.RecvArrays(this.RecvObjValue);
2129 XMRStackFrame lastSF = null;
2130 string funcName;
2131 while((funcName = mir.ReadString()) != "")
2132 {
2133 if(funcName == "**newStateCode**")
2134 {
2135 this.newStateCode = mir.ReadInt32();
2136 continue;
2137 }
2138 XMRStackFrame thisSF = new XMRStackFrame();
2139 thisSF.funcName = funcName;
2140 thisSF.callNo = mir.ReadInt32();
2141 thisSF.objArray = (object[])this.RecvObjValue();
2142 if(lastSF == null)
2143 this.stackFrames = thisSF;
2144 else
2145 lastSF.nextSF = thisSF;
2146 lastSF = thisSF;
2147 }
2148 }
2149 finally
2150 {
2151 this.migrateInReader = null;
2152 this.migrateInObjects = null;
2153 }
2154 }
2155
2156 /**
2157 * @brief Read a single value from the stream.
2158 * @returns value (boxed as needed)
2159 */
2160 private BinaryReader migrateInReader;
2161 private Dictionary<int, object> migrateInObjects;
2162 public object RecvObjValue()
2163 {
2164 BinaryReader mir = this.migrateInReader;
2165 int ident = this.migrateInObjects.Count;
2166 Ser code = (Ser)mir.ReadByte();
2167 switch(code)
2168 {
2169 case Ser.NULL:
2170 return null;
2171
2172 case Ser.EVENTCODE:
2173 return (ScriptEventCode)mir.ReadInt32();
2174
2175 case Ser.LSLFLOAT:
2176 return new LSL_Float(mir.ReadDouble());
2177
2178 case Ser.LSLINT:
2179 return new LSL_Integer(mir.ReadInt32());
2180
2181 case Ser.LSLKEY:
2182 return new LSL_Key((string)RecvObjValue());
2183
2184 case Ser.LSLLIST:
2185 {
2186 this.migrateInObjects.Add(ident, null); // placeholder
2187 object[] data = (object[])RecvObjValue(); // read data, maybe using another index
2188 LSL_List list = new LSL_List(data); // make LSL-level list
2189 this.migrateInObjects[ident] = list; // fill in slot
2190 return list;
2191 }
2192
2193 case Ser.LSLROT:
2194 {
2195 double x = mir.ReadDouble();
2196 double y = mir.ReadDouble();
2197 double z = mir.ReadDouble();
2198 double w = mir.ReadDouble();
2199 return new LSL_Rotation(x, y, z, w);
2200 }
2201 case Ser.LSLSTR:
2202 return new LSL_String((string)RecvObjValue());
2203
2204 case Ser.LSLVEC:
2205 {
2206 double x = mir.ReadDouble();
2207 double y = mir.ReadDouble();
2208 double z = mir.ReadDouble();
2209 return new LSL_Vector(x, y, z);
2210 }
2211
2212 case Ser.SYSARRAY:
2213 {
2214 Type eletype = String2SysType(mir.ReadString());
2215 int length = mir.ReadInt32();
2216 Array array = Array.CreateInstance(eletype, length);
2217 this.migrateInObjects.Add(ident, array);
2218 for(int i = 0; i < length; i++)
2219 array.SetValue(RecvObjValue(), i);
2220 return array;
2221 }
2222
2223 case Ser.SYSBOOL:
2224 return mir.ReadBoolean();
2225
2226 case Ser.SYSDOUB:
2227 return mir.ReadDouble();
2228
2229 case Ser.SYSFLOAT:
2230 return mir.ReadSingle();
2231
2232 case Ser.SYSINT:
2233 return mir.ReadInt32();
2234
2235 case Ser.SYSCHAR:
2236 return mir.ReadChar();
2237
2238 case Ser.SYSSTR:
2239 string s = mir.ReadString();
2240 this.migrateInObjects.Add(ident, s);
2241 return s;
2242
2243 case Ser.XMRARRAY:
2244 {
2245 XMR_Array array = new XMR_Array(this);
2246 this.migrateInObjects.Add(ident, array);
2247 array.RecvArrayObj(this.RecvObjValue);
2248 return array;
2249 }
2250
2251 case Ser.DUPREF:
2252 {
2253 ident = mir.ReadInt32();
2254 object obj = this.migrateInObjects[ident];
2255 if(obj is ObjLslList)
2256 obj = new LSL_List(((ObjLslList)obj).objarray);
2257 return obj;
2258 }
2259
2260 case Ser.XMRINST:
2261 return this;
2262
2263 case Ser.DELEGATE:
2264 this.migrateInObjects.Add(ident, null); // placeholder
2265 string name = mir.ReadString(); // function name
2266 string sig = mir.ReadString(); // delegate type
2267 object targ = this.RecvObjValue(); // 'this' object
2268 Delegate del = this.GetScriptMethodDelegate(name, sig, targ);
2269 this.migrateInObjects[ident] = del; // actual value
2270 return del;
2271
2272 case Ser.SDTCLOBJ:
2273 XMRSDTypeClObj clobj = new XMRSDTypeClObj();
2274 this.migrateInObjects.Add(ident, clobj);
2275 clobj.Restore(this, this.RecvObjValue);
2276 return clobj;
2277
2278 case Ser.SYSERIAL:
2279 {
2280 int rawLength = mir.ReadInt32();
2281 byte[] rawBytes = mir.ReadBytes(rawLength);
2282 MemoryStream memoryStream = new MemoryStream(rawBytes);
2283 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter =
2284 new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
2285 object graph = bformatter.Deserialize(memoryStream);
2286 this.migrateInObjects.Add(ident, graph);
2287 return graph;
2288 }
2289
2290 case Ser.THROWNEX:
2291 {
2292 int rawLength = mir.ReadInt32();
2293 byte[] rawBytes = mir.ReadBytes(rawLength);
2294 MemoryStream memoryStream = new MemoryStream(rawBytes);
2295 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter =
2296 new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
2297 object graph = bformatter.Deserialize(memoryStream);
2298 this.migrateInObjects.Add(ident, graph);
2299 ((ScriptThrownException)graph).thrown = RecvObjValue();
2300 return graph;
2301 }
2302
2303 default:
2304 throw new Exception("bad stream code " + code.ToString());
2305 }
2306 }
2307
2308 // wrapper around list object arrays to make sure they are always object types for migration purposes
2309 private class ObjLslList
2310 {
2311 public object[] objarray;
2312 }
2313 }
2314
2315 // Any xmr...() methods that call CheckRun() must be tagged with this attribute
2316 // so the ScriptCodeGen will know the method is non-trivial.
2317 public class xmrMethodCallsCheckRunAttribute: Attribute
2318 {
2319 }
2320
2321 // Any xmr...() methods in xmrengtest that call Stub<somethingorother>() must be
2322 // tagged with this attribute so the -builtins option will tell the user that
2323 // they are a stub function.
2324 public class xmrMethodIsNoisyAttribute: Attribute
2325 {
2326 }
2327
2328 // Any script callable methods that really return a key not a string should be
2329 // tagged with this attribute so the compiler will know they return type key and
2330 // not type string.
2331 public class xmrMethodReturnsKeyAttribute: Attribute
2332 {
2333 }
2334
2335 [SerializableAttribute]
2336 public class OutOfHeapException: Exception
2337 {
2338 public OutOfHeapException(int oldtotal, int newtotal, int limit)
2339 : base("oldtotal=" + oldtotal + ", newtotal=" + newtotal + ", limit=" + limit)
2340 {
2341 }
2342 }
2343
2344 [SerializableAttribute]
2345 public class OutOfStackException: Exception
2346 {
2347 }
2348}