1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.IO;
- using System.Reflection.Emit;
- using System.Text;
- using System.Threading;
- using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
- using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
- using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
- using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
- using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
- using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
- using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
- namespace OpenSim.Region.ScriptEngine.Yengine
- {
- public class XMRInstArrays
- {
- public XMR_Array[] iarArrays;
- public char[] iarChars;
- public double[] iarFloats;
- public int[] iarIntegers;
- public LSL_List[] iarLists;
- public object[] iarObjects;
- public LSL_Rotation[] iarRotations;
- public string[] iarStrings;
- public LSL_Vector[] iarVectors;
- public XMRSDTypeClObj[] iarSDTClObjs;
- public Delegate[][] iarSDTIntfObjs;
- private XMRInstAbstract instance;
- public int arraysHeapUse;
- public static readonly XMR_Array[] noArrays = new XMR_Array[0];
- public static readonly char[] noChars = new char[0];
- public static readonly double[] noFloats = new double[0];
- public static readonly int[] noIntegers = new int[0];
- public static readonly LSL_List[] noLists = new LSL_List[0];
- public static readonly object[] noObjects = new object[0];
- public static readonly LSL_Rotation[] noRotations = new LSL_Rotation[0];
- public static readonly string[] noStrings = new string[0];
- public static readonly LSL_Vector[] noVectors = new LSL_Vector[0];
- public static readonly XMRSDTypeClObj[] noSDTClObjs = new XMRSDTypeClObj[0];
- public static readonly Delegate[][] noSDTIntfObjs = new Delegate[0][];
- public XMRInstArrays(XMRInstAbstract inst)
- {
- instance = inst;
- }
- /*
- ~XMRInstArrays()
- {
- arraysHeapUse = instance.UpdateArraysHeapUse(arraysHeapUse, 0);
- }
- */
- public void Clear()
- {
- int newheapUse = 0;
- if(iarArrays is not null)
- {
- foreach(XMR_Array xa in iarArrays)
- xa.__pub_clear();
- }
- if(iarChars is not null)
- iarChars = new char[iarChars.Length];
- if (iarLists is not null)
- iarLists = new LSL_List[iarLists.Length];
- if (iarObjects is not null)
- iarObjects = new object[iarObjects.Length];
- if(iarStrings is not null)
- iarStrings = new string[iarStrings.Length];
- if (iarFloats is not null)
- newheapUse += iarFloats.Length * HeapTrackerObject.HT_DOUB;
- if (iarIntegers is not null)
- newheapUse += iarIntegers.Length * HeapTrackerObject.HT_INT;
- if (iarRotations is not null)
- newheapUse += iarRotations.Length * HeapTrackerObject.HT_ROT;
- if (iarVectors != null)
- newheapUse += iarVectors.Length * HeapTrackerObject.HT_VEC;
- arraysHeapUse = instance.UpdateArraysHeapUse(0, newheapUse);
- }
- public void AllocVarArrays(XMRInstArSizes ars)
- {
- ClearOldArrays();
- int newuse = arraysHeapUse +
- ars.iasChars* HeapTrackerObject.HT_CHAR +
- ars.iasFloats * HeapTrackerObject.HT_DOUB +
- ars.iasIntegers * HeapTrackerObject.HT_INT +
- ars.iasRotations * HeapTrackerObject.HT_ROT +
- ars.iasVectors * HeapTrackerObject.HT_VEC +
- ars.iasSDTIntfObjs * HeapTrackerObject.HT_DELE;
- arraysHeapUse = instance.UpdateArraysHeapUse(arraysHeapUse, newuse);
- iarArrays = (ars.iasArrays > 0) ? new XMR_Array[ars.iasArrays] : noArrays;
- iarChars = (ars.iasChars > 0) ? new char[ars.iasChars] : noChars;
- iarFloats = (ars.iasFloats > 0) ? new double[ars.iasFloats] : noFloats;
- iarIntegers = (ars.iasIntegers > 0) ? new int[ars.iasIntegers] : noIntegers;
- iarLists = (ars.iasLists > 0) ? new LSL_List[ars.iasLists] : noLists;
- iarObjects = (ars.iasObjects > 0) ? new object[ars.iasObjects] : noObjects;
- iarRotations = (ars.iasRotations > 0) ? new LSL_Rotation[ars.iasRotations] : noRotations;
- iarStrings = (ars.iasStrings > 0) ? new string[ars.iasStrings] : noStrings;
- iarVectors = (ars.iasVectors > 0) ? new LSL_Vector[ars.iasVectors] : noVectors;
- iarSDTClObjs = (ars.iasSDTClObjs > 0) ? new XMRSDTypeClObj[ars.iasSDTClObjs] : noSDTClObjs;
- iarSDTIntfObjs = (ars.iasSDTIntfObjs > 0) ? new Delegate[ars.iasSDTIntfObjs][] : noSDTIntfObjs;
- }
- /**
- * @brief Do not write directly to iarLists[index], rather use this method.
- */
- public void PopList(int index, LSL_List lis)
- {
- int delta = HeapTrackerObject.Size(lis) - HeapTrackerObject.Size(iarLists[index]);
- instance.UpdateArraysHeapUse(0, delta);
- Interlocked.Add(ref arraysHeapUse, delta);
- iarLists[index] = lis;
- }
- /**
- * @brief Do not write directly to iarObjects[index], rather use this method.
- */
- public void PopObject(int index, object obj)
- {
- int delta = HeapTrackerObject.Size(obj) - HeapTrackerObject.Size(iarObjects[index]);
- instance.UpdateArraysHeapUse(0, delta);
- Interlocked.Add(ref arraysHeapUse, delta);
- iarObjects[index] = obj;
- }
- /**
- * @brief Do not write directly to iarStrings[index], rather use this method.
- */
- public void PopString(int index, string str)
- {
- int delta = HeapTrackerString.Size(str) - HeapTrackerString.Size(iarStrings[index]);
- instance.UpdateArraysHeapUse(0, delta);
- Interlocked.Add(ref arraysHeapUse, delta);
- iarStrings[index] = str;
- }
- /**
- * @brief Write all arrays out to a file.
- */
- public delegate void Sender(object value);
- public void SendArrays(Sender sender)
- {
- sender(iarArrays);
- sender(iarChars);
- sender(iarFloats);
- sender(iarIntegers);
- sender(iarLists);
- sender(iarObjects);
- sender(iarRotations);
- sender(iarStrings);
- sender(iarVectors);
- sender(iarSDTClObjs);
- sender(iarSDTIntfObjs);
- }
- /**
- * @brief Read all arrays in from a file.
- */
- public delegate object Recver();
- public void RecvArrays(Recver recver)
- {
- ClearOldArrays();
- iarArrays = (XMR_Array[])recver();
- if(iarArrays is null)
- iarArrays = noArrays;
- int newheapuse = arraysHeapUse;
- char[] chrs = (char[])recver();
- if (chrs is not null)
- {
- newheapuse += chrs.Length * HeapTrackerObject.HT_CHAR;
- iarChars = chrs;
- }
- else
- iarChars = noChars;
- double[] flts = (double[])recver();
- if (flts is not null)
- {
- newheapuse += flts.Length * HeapTrackerObject.HT_DOUB;
- iarFloats = flts;
- }
- else
- iarFloats = noFloats;
- int[] ints = (int[])recver();
- if (ints is not null)
- {
- newheapuse += ints.Length * HeapTrackerObject.HT_INT;
- iarIntegers = ints;
- }
- else
- iarIntegers = noIntegers;
- LSL_List[] liss = (LSL_List[])recver();
- if (liss is not null)
- {
- foreach (LSL_List lis in liss)
- {
- if(!(lis is null))
- newheapuse += lis.Size;
- }
- iarLists = liss;
- }
- else
- iarLists = noLists;
- object[] objs = (object[])recver();
- if (objs is not null)
- {
- foreach (object obj in objs)
- newheapuse += HeapTrackerObject.Size(obj);
- iarObjects = objs;
- }
- else
- iarObjects = noObjects;
- LSL_Rotation[] rots = (LSL_Rotation[])recver();
- if (rots is not null)
- {
- newheapuse += rots.Length * HeapTrackerObject.HT_ROT;
- iarRotations = rots;
- }
- else
- iarRotations = noRotations;
- string[] strs = (string[])recver();
- if (strs is not null)
- {
- foreach (string str in strs)
- newheapuse += HeapTrackerString.Size(str);
- iarStrings = strs;
- }
- else
- iarStrings = noStrings;
- LSL_Vector[] vecs = (LSL_Vector[])recver();
- if (vecs != null)
- {
- newheapuse += vecs.Length * HeapTrackerObject.HT_VEC;
- iarVectors = vecs;
- }
- else
- iarVectors = noVectors;
- iarSDTClObjs = (XMRSDTypeClObj[])recver();
- if(iarSDTClObjs is null)
- iarSDTClObjs = noSDTClObjs;
- Delegate[][] dels = (Delegate[][])recver();
- if(dels is not null)
- {
- newheapuse += dels.Length * HeapTrackerObject.HT_DELE;
- iarSDTIntfObjs = dels;
- }
- else
- iarSDTIntfObjs = noSDTIntfObjs;
- // update script heap usage, throwing an exception before finalizing changes
- arraysHeapUse = instance.UpdateArraysHeapUse(arraysHeapUse, newheapuse);
- }
- private void ClearOldArrays()
- {
- int newheapuse = arraysHeapUse;
- iarArrays = null;
- if(iarChars is not null)
- {
- newheapuse -= iarChars.Length * HeapTrackerObject.HT_CHAR;
- iarChars = null;
- }
- if(iarFloats is not null)
- {
- newheapuse -= iarFloats.Length * HeapTrackerObject.HT_DOUB;
- iarFloats = null;
- }
- if(iarIntegers is not null)
- {
- newheapuse -= iarIntegers.Length * HeapTrackerObject.HT_INT;
- iarIntegers = null;
- }
- if(iarLists is not null)
- {
- foreach(LSL_List lis in iarLists)
- {
- if ((lis is not null))
- newheapuse += lis.Size;
- }
- iarLists = null;
- }
- if(iarObjects is not null)
- {
- foreach(object obj in iarObjects)
- newheapuse -= HeapTrackerObject.Size(obj);
- iarObjects = null;
- }
- if(iarRotations is not null)
- {
- newheapuse -= iarRotations.Length * HeapTrackerObject.HT_ROT;
- iarRotations = null;
- }
- if(iarStrings is not null)
- {
- foreach(string str in iarStrings)
- newheapuse -= HeapTrackerString.Size(str);
- iarStrings = null;
- }
- if(iarVectors is not null)
- {
- newheapuse -= iarVectors.Length * HeapTrackerObject.HT_VEC;
- iarVectors = null;
- }
- iarSDTClObjs = null;
- if(iarSDTIntfObjs is not null)
- {
- newheapuse -= iarSDTIntfObjs.Length * HeapTrackerObject.HT_DELE;
- iarSDTIntfObjs = null;
- }
- arraysHeapUse = instance.UpdateArraysHeapUse(arraysHeapUse, newheapuse);
- }
- }
- public class XMRInstArSizes
- {
- public int iasArrays;
- public int iasChars;
- public int iasFloats;
- public int iasIntegers;
- public int iasLists;
- public int iasObjects;
- public int iasRotations;
- public int iasStrings;
- public int iasVectors;
- public int iasSDTClObjs;
- public int iasSDTIntfObjs;
- public void WriteAsmFile(TextWriter asmFileWriter, string label)
- {
- asmFileWriter.WriteLine(" {0}Arrays {1}", label, iasArrays);
- asmFileWriter.WriteLine(" {0}Chars {1}", label, iasChars);
- asmFileWriter.WriteLine(" {0}Floats {1}", label, iasFloats);
- asmFileWriter.WriteLine(" {0}Integers {1}", label, iasIntegers);
- asmFileWriter.WriteLine(" {0}Lists {1}", label, iasLists);
- asmFileWriter.WriteLine(" {0}Objects {1}", label, iasObjects);
- asmFileWriter.WriteLine(" {0}Rotations {1}", label, iasRotations);
- asmFileWriter.WriteLine(" {0}Strings {1}", label, iasStrings);
- asmFileWriter.WriteLine(" {0}Vectors {1}", label, iasVectors);
- asmFileWriter.WriteLine(" {0}SDTClObjs {1}", label, iasSDTClObjs);
- asmFileWriter.WriteLine(" {0}SDTIntfObjs {1}", label, iasSDTIntfObjs);
- }
- public void WriteToFile(BinaryWriter objFileWriter)
- {
- objFileWriter.Write(iasArrays);
- objFileWriter.Write(iasChars);
- objFileWriter.Write(iasFloats);
- objFileWriter.Write(iasIntegers);
- objFileWriter.Write(iasLists);
- objFileWriter.Write(iasObjects);
- objFileWriter.Write(iasRotations);
- objFileWriter.Write(iasStrings);
- objFileWriter.Write(iasVectors);
- objFileWriter.Write(iasSDTClObjs);
- objFileWriter.Write(iasSDTIntfObjs);
- }
- public void ReadFromFile(BinaryReader objFileReader)
- {
- iasArrays = objFileReader.ReadInt32();
- iasChars = objFileReader.ReadInt32();
- iasFloats = objFileReader.ReadInt32();
- iasIntegers = objFileReader.ReadInt32();
- iasLists = objFileReader.ReadInt32();
- iasObjects = objFileReader.ReadInt32();
- iasRotations = objFileReader.ReadInt32();
- iasStrings = objFileReader.ReadInt32();
- iasVectors = objFileReader.ReadInt32();
- iasSDTClObjs = objFileReader.ReadInt32();
- iasSDTIntfObjs = objFileReader.ReadInt32();
- }
- }
- public class XMRStackFrame
- {
- public XMRStackFrame nextSF;
- public string funcName;
- public int callNo;
- public object[] objArray;
- }
- /*
- * Contains only items required by the stand-alone compiler
- * so the compiler doesn't need to pull in all of OpenSim.
- *
- * Inherit from ScriptBaseClass so we can be used as 'this'
- * parameter for backend-API calls, eg llSay().
- */
- public abstract class XMRInstAbstract: ScriptBaseClass
- {
- public const int CallMode_NORMAL = 0; // when function is called, it proceeds normally
- public const int CallMode_SAVE = 1; // StackSaveException() was thrown, push args/locals to stackFrames
- public const int CallMode_RESTORE = 2; // when function is called, it pops state from stackFrames
- public bool suspendOnCheckRunHold; // suspend script execution until explicitly set false
- public bool suspendOnCheckRunTemp; // suspend script execution for single step only
- public int stackLimit; // stack must have at least this many bytes free on entry to functions
- public int m_StackLeft; // total number of stack bytes yet to be used (init to stacksize)
- public ScriptObjCode m_ObjCode; // script object code this instance was created from
- public object[] ehArgs; // event handler argument array
- public bool doGblInit = true; // default state_entry() needs to initialize global variables
- public int stateCode = 0; // state the script is in (0 = 'default')
- public int newStateCode = -1; // if >= 0, in the middle of exiting 'stateCode' and entering 'newStateCode'
- public ScriptEventCode eventCode = ScriptEventCode.None;
- // what event handler is executing (or None if not)
- public int callMode = CallMode_NORMAL;
- // to capture stack frames on stackFrames:
- // set to CallMode_SAVE just before throwing StackSaveException()
- // from within CheckRun() and cleared to CallMode_NORMAL when
- // the exception is caught
- // to restore stack frames from stackFrames:
- // set to CallMode_RESTORE just before calling CallSEH() and
- // cleared to CallMode_NORMAL by CheckRun()
- public XMRStackFrame stackFrames; // stack frames being saved/restored
- private static readonly char[] justacomma = { ',' };
- /*
- * These arrays hold the global variable values for the script instance.
- * The array lengths are determined by the script compilation,
- * and are found in ScriptObjCode.glblSizes.
- */
- public XMRInstArrays glblVars;
- public XMRInstAbstract()
- {
- glblVars = new XMRInstArrays(this);
- }
- /****************************************************************\
- * Abstract function prototypes. *
- * These functions require access to the OpenSim environment. *
- \****************************************************************/
- public abstract void CheckRunWork();
- public abstract void StateChange();
- [xmrMethodCallsCheckRunAttribute] // calls CheckRun()
- [xmrMethodIsNoisyAttribute] // calls Stub<somethingorother>()
- public abstract LSL_List xmrEventDequeue(double timeout, int returnMask1, int returnMask2,
- int backgroundMask1, int backgroundMask2);
- [xmrMethodIsNoisyAttribute] // calls Stub<somethingorother>()
- public abstract void xmrEventEnqueue(LSL_List ev);
- [xmrMethodIsNoisyAttribute] // calls Stub<somethingorother>()
- public abstract LSL_List xmrEventSaveDets();
- [xmrMethodIsNoisyAttribute] // calls Stub<somethingorother>()
- public abstract void xmrEventLoadDets(LSL_List dpList);
- /**************************************************\
- * Functions what don't require runtime support *
- * beyond what the compiler provides. *
- \**************************************************/
- protected int heapLimit;
- public int m_localsHeapUsed;
- public virtual int UpdateLocalsHeapUse(int olduse, int newuse)
- {
- int newtotal = Interlocked.Add(ref m_localsHeapUsed, newuse - olduse);
- if (newtotal + glblVars.arraysHeapUse > heapLimit)
- throw new OutOfHeapException(glblVars.arraysHeapUse + newtotal + olduse - newuse, newtotal + glblVars.arraysHeapUse, heapLimit);
- return newuse;
- }
- // not in use
- public virtual int UpdateArraysHeapUse(int olduse, int newuse)
- {
- if(newuse + glblVars.arraysHeapUse > heapLimit)
- throw new OutOfHeapException(glblVars.arraysHeapUse, glblVars.arraysHeapUse + newuse, heapLimit);
- return newuse;
- }
- public virtual void AddLocalsHeapUse(int delta)
- {
- Interlocked.Add(ref m_localsHeapUsed, delta);
- }
- public int xmrHeapLeft()
- {
- return heapLimit - m_localsHeapUsed - glblVars.arraysHeapUse;
- }
- public int xmrHeapUsed()
- {
- return m_localsHeapUsed + glblVars.arraysHeapUse;
- }
- /**
- * @brief Call script's event handler function from the very beginning.
- * @param instance.stateCode = which state the event is happening in
- * @param instance.eventCode = which event is happening in that state
- * @returns when event handler has completed or throws an exception
- * with instance.eventCode = ScriptEventCode.None
- */
- public void CallSEH()
- {
- ScriptEventHandler seh;
- // CallMode_NORMAL: run event handler from the beginning normally
- // CallMode_RESTORE: restore event handler stack from stackFrames
- callMode = (stackFrames is null) ? XMRInstAbstract.CallMode_NORMAL :
- XMRInstAbstract.CallMode_RESTORE;
- while(true)
- {
- if(newStateCode < 0)
- {
- // Process event given by 'stateCode' and 'eventCode'.
- // The event handler should call CheckRun() as often as convenient.
- int newState = stateCode;
- seh = m_ObjCode.scriptEventHandlerTable[newState, (int)eventCode];
- if(seh is not null)
- {
- try
- {
- seh(this);
- }
- catch(ScriptChangeStateException scse)
- {
- newState = scse.newState;
- }
- }
- ehArgs = null; // we are done with them and no args for
- // exit_state()/enter_state() anyway
- // The usual case is no state change.
- // Even a 'state <samestate>;' statement has no effect except to exit out.
- // It does not execute the state_exit() or state_entry() handlers.
- // See http://wiki.secondlife.com/wiki/State
- if(newState == stateCode)
- break;
- // Save new state in a more permanent location in case we
- // get serialized out while in the state_exit() handler.
- newStateCode = newState;
- }
- // Call old state's state_exit() handler.
- eventCode = ScriptEventCode.state_exit;
- seh = m_ObjCode.scriptEventHandlerTable[stateCode, (int)ScriptEventCode.state_exit];
- if(seh is not null)
- {
- try
- {
- seh(this);
- }
- catch(ScriptChangeStateException scse)
- {
- newStateCode = scse.newState;
- }
- }
- // Switch over to the new state's state_entry() handler.
- stateCode = newStateCode;
- eventCode = ScriptEventCode.state_entry;
- newStateCode = -1;
- // Now that the old state can't possibly start any more activity,
- // cancel any listening handlers, etc, of the old state.
- StateChange();
- // Loop back to execute new state's state_entry() handler.
- }
- // Event no longer being processed.
- stackFrames = null;
- eventCode = ScriptEventCode.None;
- }
- /**
- * @brief For compatibility with old code.
- */
- public void CheckRun(int line)
- {
- CheckRunStack();
- }
- /**
- * @brief Called at beginning of complex functions to see if they
- * are nested too deep possibly in a recursive loop.
- */
- public void CheckRunStack()
- {
- if(m_StackLeft < stackLimit)
- throw new OutOfStackException();
- CheckRunQuick();
- }
- /**
- * @brief Called in each iteration of a loop to see if running too long.
- */
- public void CheckRunQuick()
- {
- //if (suspendOnCheckRunHold || suspendOnCheckRunTemp)
- CheckRunWork();
- }
- /**
- * @brief Called during CallMode_SAVE to create a stackframe save object that saves
- * local variables and calling point within the function.
- * @param funcName = name of function whose frame is being saved
- * @param callNo = call number (ie, return address) within function to restart at
- * @param nSaves = number of variables the function will save
- * @returns an object[nSaves] where function can save variables
- */
- public object[] CaptureStackFrame(string funcName, int callNo, int nSaves)
- {
- XMRStackFrame sf = new XMRStackFrame();
- sf.nextSF = stackFrames;
- sf.funcName = funcName;
- sf.callNo = callNo;
- sf.objArray = new object[nSaves];
- stackFrames = sf;
- return sf.objArray;
- }
- /**
- * @brief Called during CallMode_RESTORE to pop a stackframe object to restore
- * local variables and calling point within the function.
- * @param funcName = name of function whose frame is being restored
- * @returns the object[nSaves] where function can retrieve variables
- * callNo = as passed to CaptureStackFrame() indicating restart point
- */
- public object[] RestoreStackFrame(string funcName, out int callNo)
- {
- XMRStackFrame sf = stackFrames;
- if(sf.funcName != funcName)
- throw new Exception("frame mismatch " + sf.funcName + " vs " + funcName);
- callNo = sf.callNo;
- stackFrames = sf.nextSF;
- sf.nextSF = null;
- return sf.objArray;
- }
- /**
- * @brief Convert all LSL_Integers in a list to System.Int32s,
- * as required by llParcelMediaQuery().
- */
- public static LSL_List FixLLParcelMediaQuery(LSL_List oldlist)
- {
- object[] oldarray = oldlist.Data;
- object[] newarray = new object[oldarray.Length];
- for(int i = 0; i < oldarray.Length; i++)
- {
- object obj = oldarray[i];
- if(obj is LSL_Integer io)
- obj = io.value;
- newarray[i] = obj;
- }
- return new LSL_List(newarray);
- }
- /**
- * @brief Convert *SOME* LSL_Integers in a list to System.Int32s,
- * as required by llParcelMediaCommandList().
- */
- public static LSL_List FixLLParcelMediaCommandList(LSL_List oldlist)
- {
- object[] oldarray = oldlist.Data;
- object[] newarray = new object[oldarray.Length];
- int verbatim = 0;
- for(int i = 0; i < oldarray.Length; i++)
- {
- object obj = oldarray[i];
- if(--verbatim < 0)
- {
- if(obj is LSL_Integer lio)
- obj = lio.value;
- if(obj is int io)
- {
- switch(io)
- {
- case ScriptBaseClass.PARCEL_MEDIA_COMMAND_AUTO_ALIGN:
- // leave next integer as LSL_Integer
- verbatim = 1;
- break;
- case ScriptBaseClass.PARCEL_MEDIA_COMMAND_SIZE:
- // leave next two integers as LSL_Integer
- verbatim = 2;
- break;
- }
- }
- }
- newarray[i] = obj;
- }
- return new LSL_List(newarray);
- }
- public static int xmrHashCode(int i)
- {
- return i.GetHashCode();
- }
- public static int xmrHashCode(double f)
- {
- return f.GetHashCode();
- }
- public static int xmrHashCode(object o)
- {
- return o.GetHashCode();
- }
- public static int xmrHashCode(string s)
- {
- return s.GetHashCode();
- }
- public string xmrTypeName(object o)
- {
- /*
- * Basic types return constant strings of the script-visible type name.
- */
- if(o is XMR_Array)
- return "array";
- if(o is bool)
- return "bool";
- if(o is char)
- return "char";
- if(o is Exception)
- return "exception";
- if(o is double)
- return "float";
- if(o is float)
- return "float";
- if(o is LSL_Float)
- return "float";
- if(o is int)
- return "integer";
- if(o is LSL_Integer)
- return "integer";
- if(o is LSL_List)
- return "list";
- if(o is LSL_Rotation)
- return "rotation";
- if(o is LSL_String)
- return "string";
- if(o is string)
- return "string";
- if(o is LSL_Vector)
- return "vector";
- // A script-defined interface is represented as an array of delegates.
- // If that is the case, convert it to the object of the script-defined
- // class that is implementing the interface. This should let the next
- // step get the script-defined type name of the object.
- if(o is Delegate[] dao)
- o = dao[0].Target;
- // If script-defined class instance, get the script-defined
- // type name.
- if(o is XMRSDTypeClObj XMRSDTypeClObjo)
- return XMRSDTypeClObjo.sdtcClass.longName.val;
- // If it's a delegate, maybe we can look up its script-defined type name.
- Type ot = o.GetType();
- if(o is Delegate)
- {
- if(m_ObjCode.sdDelTypes.TryGetValue(ot, out string os))
- return os;
- }
- // Don't know what it is, get the C#-level type name.
- return ot.ToString();
- }
- /**
- * @brief Call the current state's event handler.
- * @param ev = as returned by xmrEventDequeue saying which event handler to call
- * and what argument list to pass to it. The llDetect...() parameters
- * are as currently set for the script (use xmrEventLoadDets to set how
- * you want them to be different).
- */
- public void xmrEventCallHandler(LSL_List ev)
- {
- object[] data = ev.Data;
- int evc = ev.GetIntegerItem(0);
- ScriptEventHandler seh = m_ObjCode.scriptEventHandlerTable[stateCode, evc];
- if(seh is not null)
- {
- int nargs = data.Length - 1;
- object[] args = new object[nargs];
- Array.Copy(data, 1, args, 0, nargs);
- object[] saveEHArgs = this.ehArgs;
- ScriptEventCode saveEventCode = this.eventCode;
- ehArgs = args;
- eventCode = (ScriptEventCode)evc;
- seh(this);
- ehArgs = saveEHArgs;
- eventCode = saveEventCode;
- }
- }
- /**
- * @brief These conversions throw exceptions if there is anything stinky...
- */
- public double xmrString2Float(string s)
- {
- return double.Parse(s, CultureInfo.InvariantCulture);
- }
- public int xmrString2Integer(string s)
- {
- s = s.Trim();
- if(s.StartsWith("0x") || s.StartsWith("0X"))
- return int.Parse(s.Substring(2), NumberStyles.HexNumber);
- return int.Parse(s, CultureInfo.InvariantCulture);
- }
- public LSL_Rotation xmrString2Rotation(string s)
- {
- s = s.Trim();
- if(!s.StartsWith("<") || !s.EndsWith(">"))
- throw new FormatException("doesn't begin with < and end with >");
- s = s.Substring(1, s.Length - 2);
- string[] splitup = s.Split(justacomma, 5);
- if(splitup.Length != 4)
- throw new FormatException("doesn't have exactly 3 commas");
- double x = double.Parse(splitup[0], CultureInfo.InvariantCulture);
- double y = double.Parse(splitup[1], CultureInfo.InvariantCulture);
- double z = double.Parse(splitup[2], CultureInfo.InvariantCulture);
- double w = double.Parse(splitup[3], CultureInfo.InvariantCulture);
- return new LSL_Rotation(x, y, z, w);
- }
- public LSL_Vector xmrString2Vector(string s)
- {
- s = s.Trim();
- if(!s.StartsWith("<") || !s.EndsWith(">"))
- throw new FormatException("doesn't begin with < and end with >");
- s = s.Substring(1, s.Length - 2);
- string[] splitup = s.Split(justacomma, 4);
- if(splitup.Length != 3)
- throw new FormatException("doesn't have exactly 2 commas");
- double x = double.Parse(splitup[0], CultureInfo.InvariantCulture);
- double y = double.Parse(splitup[1], CultureInfo.InvariantCulture);
- double z = double.Parse(splitup[2], CultureInfo.InvariantCulture);
- return new LSL_Vector(x, y, z);
- }
- /**
- * @brief Access C#-style formatted numeric conversions.
- */
- public string xmrFloat2String(double val, string fmt)
- {
- return val.ToString(fmt, CultureInfo.InvariantCulture);
- }
- public string xmrInteger2String(int val, string fmt)
- {
- return val.ToString(fmt, CultureInfo.InvariantCulture);
- }
- public string xmrRotation2String(LSL_Rotation val, string fmt)
- {
- return "<" + val.x.ToString(fmt, CultureInfo.InvariantCulture) + "," +
- val.y.ToString(fmt, CultureInfo.InvariantCulture) + "," +
- val.z.ToString(fmt, CultureInfo.InvariantCulture) + "," +
- val.s.ToString(fmt, CultureInfo.InvariantCulture) + ">";
- }
- public string xmrVector2String(LSL_Vector val, string fmt)
- {
- return "<" + val.x.ToString(fmt, CultureInfo.InvariantCulture) + "," +
- val.y.ToString(fmt, CultureInfo.InvariantCulture) + "," +
- val.z.ToString(fmt, CultureInfo.InvariantCulture) + ">";
- }
- /**
- * @brief Get a delegate for a script-defined function.
- * @param name = name of the function including arg types, eg,
- * "Verify(array,list,string)"
- * @param sig = script-defined type name
- * @param targ = function's 'this' pointer or null if static
- * @returns delegate for the script-defined function
- */
- public Delegate GetScriptMethodDelegate(string name, string sig, object targ)
- {
- DynamicMethod dm = m_ObjCode.dynamicMethods[name];
- TokenDeclSDTypeDelegate dt = (TokenDeclSDTypeDelegate)m_ObjCode.sdObjTypesName[sig];
- return dm.CreateDelegate(dt.GetSysType(), targ);
- }
- /**
- * @brief Try to cast the thrown object to the given script-defined type.
- * @param thrown = what object was thrown
- * @param inst = what script instance we are running in
- * @param sdtypeindex = script-defined type to try to cast it to
- * @returns null: thrown is not castable to sdtypename
- * else: an object casted to sdtypename
- */
- public static object XMRSDTypeCatchTryCastToSDType(object thrown, XMRInstAbstract inst, int sdtypeindex)
- {
- TokenDeclSDType sdType = inst.m_ObjCode.sdObjTypesIndx[sdtypeindex];
- // If it is a script-defined interface object, convert to the original XMRSDTypeClObj.
- if(thrown is Delegate[] dt)
- {
- thrown = dt[0].Target;
- }
- // If it is a script-defined delegate object, make sure it is an instance of the expected type.
- if(thrown is Delegate)
- {
- Type ot = thrown.GetType();
- Type tt = sdType.GetSysType();
- return (ot == tt) ? thrown : null;
- }
- // If it is a script-defined class object, make sure it is an instance of the expected class.
- if(thrown is XMRSDTypeClObj XMRSDTypeClObjthrown)
- {
- // Step from the object's actual class rootward.
- // If we find the requested class along the way, the cast is valid.
- // If we run off the end of the root, the cast is not valid.
- for(TokenDeclSDTypeClass ac = XMRSDTypeClObjthrown.sdtcClass; ac is not null; ac = ac.extends)
- {
- if(ac == sdType)
- return thrown;
- }
- }
- // Don't know what it is, assume it is not what caller wants.
- return null;
- }
- /**
- * @brief Allocate and access fixed-dimension arrays.
- */
- public static object xmrFixedArrayAllocC(int len)
- {
- return new char[len];
- }
- public static object xmrFixedArrayAllocF(int len)
- {
- return new double[len];
- }
- public static object xmrFixedArrayAllocI(int len)
- {
- return new int[len];
- }
- public static object xmrFixedArrayAllocO(int len)
- {
- return new object[len];
- }
- public static char xmrFixedArrayGetC(object arr, int idx)
- {
- return ((char[])arr)[idx];
- }
- public static double xmrFixedArrayGetF(object arr, int idx)
- {
- return ((double[])arr)[idx];
- }
- public static int xmrFixedArrayGetI(object arr, int idx)
- {
- return ((int[])arr)[idx];
- }
- public static object xmrFixedArrayGetO(object arr, int idx)
- {
- return ((object[])arr)[idx];
- }
- public static void xmrFixedArraySetC(object arr, int idx, char val)
- {
- ((char[])arr)[idx] = val;
- }
- public static void xmrFixedArraySetF(object arr, int idx, double val)
- {
- ((double[])arr)[idx] = val;
- }
- public static void xmrFixedArraySetI(object arr, int idx, int val)
- {
- ((int[])arr)[idx] = val;
- }
- public static void xmrFixedArraySetO(object arr, int idx, object val)
- {
- ((object[])arr)[idx] = val;
- }
- /**
- * @brief Copy from one script-defined array to another.
- * @param srcobj = source script-defined array class object pointer
- * @param srcstart = offset in source array to start copying from
- * @param dstobj = destination script-defined array class object pointer
- * @param dststart = offset in destination arry to start copying to
- * @param count = number of elements to copy
- */
- public static void xmrArrayCopy(object srcobj, int srcstart, object dstobj, int dststart, int count)
- {
- // The script writer should only pass us script-defined class objects.
- // Throw exception otherwise.
- XMRSDTypeClObj srcsdt = (XMRSDTypeClObj)srcobj;
- XMRSDTypeClObj dstsdt = (XMRSDTypeClObj)dstobj;
- // Get the script-visible type name of the arrays, brackets and all.
- string srctypename = srcsdt.sdtcClass.longName.val;
- string dsttypename = dstsdt.sdtcClass.longName.val;
- // The part before the first '[' of each should match exactly,
- // meaning the basic data type (eg, float, List<string>) is the same.
- // And there must be a '[' in each meaning that it is a script-defined array type.
- int i = srctypename.IndexOf('[');
- int j = dsttypename.IndexOf('[');
- if((i < 0) || (j < 0))
- throw new InvalidCastException("non-array passed: " + srctypename + " and/or " + dsttypename);
- if((i != j) || !srctypename.StartsWith(dsttypename.Substring(0, j)))
- throw new ArrayTypeMismatchException(srctypename + " vs " + dsttypename);
- // The number of brackets must match exactly.
- // This permits copying from something like a float[,][] to something like a float[][].
- // But you cannot copy from a float[][] to a float[] or wisa wersa.
- // Counting either '[' or ']' would work equally well.
- int srclen = srctypename.Length;
- int dstlen = dsttypename.Length;
- int srcjags = 0;
- int dstjags = 0;
- while(++i < srclen)
- if(srctypename[i] == ']')
- srcjags++;
- while(++j < dstlen)
- if(dsttypename[j] == ']')
- dstjags++;
- if(dstjags != srcjags)
- throw new ArrayTypeMismatchException(srctypename + " vs " + dsttypename);
- // Perform the copy.
- Array srcarray = (Array)srcsdt.instVars.iarObjects[0];
- Array dstarray = (Array)dstsdt.instVars.iarObjects[0];
- Array.Copy(srcarray, srcstart, dstarray, dststart, count);
- }
- /**
- * @brief Copy from an array to a list.
- * @param srcar = the array to copy from
- * @param start = where to start in the array
- * @param count = number of elements
- * @returns the list
- */
- public static LSL_List xmrArray2List(object srcar, int start, int count)
- {
- // Get the script-visible type of the array.
- // We only do arrays.
- XMRSDTypeClObj array = (XMRSDTypeClObj)srcar;
- TokenDeclSDTypeClass sdtClass = array.sdtcClass;
- if(sdtClass.arrayOfRank == 0)
- throw new InvalidCastException("only do arrays not " + sdtClass.longName.val);
- // Validate objects they want to put in the list.
- // We can't allow anything funky that OpenSim runtime doesn't expect.
- Array srcarray = (Array)array.instVars.iarObjects[0];
- object[] output = new object[count];
- for(int i = 0; i < count; i++)
- {
- object src = srcarray.GetValue(i + start);
- if(src == null)
- throw new NullReferenceException("null element " + i);
- if(src is double dsrc)
- {
- output[i] = new LSL_Float(dsrc);
- continue;
- }
- if(src is int isrc)
- {
- output[i] = new LSL_Integer(isrc);
- continue;
- }
- if(src is LSL_Rotation)
- {
- output[i] = src;
- continue;
- }
- if(src is LSL_Vector)
- {
- output[i] = src;
- continue;
- }
- if(src is string ssrc)
- {
- output[i] = new LSL_String(ssrc);
- continue;
- }
- throw new InvalidCastException("invalid element " + i + " type " + src.GetType().Name);
- }
- // Make a list out of that now immutable array.
- return new LSL_List(output);
- }
- /**
- * @brief Copy from a list to an array.
- * @param srclist = list to copy from
- * @param srcstart = where to start in the list
- * @param dstobj = array to copy to
- * @param dststart = where to start in the array
- * @param count = number of elements
- */
- public static void xmrList2Array(LSL_List srclist, int srcstart, object dstobj, int dststart, int count)
- {
- // Get the script-visible type of the destination.
- // We only do arrays.
- XMRSDTypeClObj dstarray = (XMRSDTypeClObj)dstobj;
- TokenDeclSDTypeClass sdtClass = dstarray.sdtcClass;
- if(sdtClass.arrayOfType == null)
- throw new InvalidCastException("only do arrays not " + sdtClass.longName.val);
- // Copy from the immutable array to the mutable array.
- // Strip off any LSL wrappers as the script code doesn't expect any.
- object[] srcarr = srclist.Data;
- Array dstarr = (Array)dstarray.instVars.iarObjects[0];
- for(int i = 0; i < count; i++)
- {
- object obj = srcarr[i + srcstart];
- if(obj is LSL_Float lfo)
- obj = lfo.value;
- else if(obj is LSL_Integer lio)
- obj = lio.value;
- else if(obj is LSL_String lso)
- obj = lso.m_string;
- dstarr.SetValue(obj, i + dststart);
- }
- }
- /**
- * @brief Copy from an array of characters to a string.
- * @param srcar = the array to copy from
- * @param start = where to start in the array
- * @param count = number of elements
- * @returns the string
- */
- public static string xmrChars2String(object srcar, int start, int count)
- {
- // Make sure they gave us a script-defined array object.
- XMRSDTypeClObj array = (XMRSDTypeClObj)srcar;
- TokenDeclSDTypeClass sdtClass = array.sdtcClass;
- if(sdtClass.arrayOfRank == 0)
- throw new InvalidCastException("only do arrays not " + sdtClass.longName.val);
- // We get a type cast error from mono if they didn't give us a character array.
- // But if it is ok, create a string from the requested characters.
- char[] srcarray = (char[])array.instVars.iarObjects[0];
- return new string(srcarray, start, count);
- }
- /**
- * @brief Copy from a string to a character array.
- * @param srcstr = string to copy from
- * @param srcstart = where to start in the string
- * @param dstobj = array to copy to
- * @param dststart = where to start in the array
- * @param count = number of elements
- */
- public static void xmrString2Chars(string srcstr, int srcstart, object dstobj, int dststart, int count)
- {
- // Make sure they gave us a script-defined array object.
- XMRSDTypeClObj dstarray = (XMRSDTypeClObj)dstobj;
- TokenDeclSDTypeClass sdtClass = dstarray.sdtcClass;
- if(sdtClass.arrayOfType == null)
- throw new InvalidCastException("only do arrays not " + sdtClass.longName.val);
- // We get a type cast error from mono if they didn't give us a character array.
- // But if it is ok, copy from the string to the character array.
- char[] dstarr = (char[])dstarray.instVars.iarObjects[0];
- for(int i = 0; i < count; i++)
- dstarr[i + dststart] = srcstr[i + srcstart];
- }
- /**
- * @brief Exception-related runtime calls.
- */
- // Return exception message (no type information just the message)
- public static string xmrExceptionMessage(Exception ex)
- {
- return ex.Message;
- }
- public static string yExceptionMessage(Exception ex)
- {
- return ex.Message;
- }
- // Return stack trace (no type or message, just stack trace lines: at ... \n)
- public string xmrExceptionStackTrace(Exception ex)
- {
- return XMRExceptionStackString(ex);
- }
- public string yExceptionStackTrace(Exception ex)
- {
- return XMRExceptionStackString(ex);
- }
- // Return value thrown by a throw statement
- public static object xmrExceptionThrownValue(Exception ex)
- {
- return ((ScriptThrownException)ex).thrown;
- }
- public static object yExceptionThrownValue(Exception ex)
- {
- return ((ScriptThrownException)ex).thrown;
- }
- // Return exception's short type name, eg, NullReferenceException, ScriptThrownException, etc.
- public static string xmrExceptionTypeName(Exception ex)
- {
- return ex.GetType().Name;
- }
- public static string yExceptionTypeName(Exception ex)
- {
- return ex.GetType().Name;
- }
- // internal use only: converts any IL addresses in script-defined methods to source location equivalent
- // Mono ex.StackTrace:
- // at OpenSim.Region.ScriptEngine.YEngine.TypeCast.ObjectToInteger (System.Object x) [0x0005e] in /home/kunta/opensim-0.9/addon-modules/YEngine/Module/MMRScriptTypeCast.cs:750
- // at (wrapper dynamic-method) System.Object:default state_entry (OpenSim.Region.ScriptEngine.YEngine.XMRInstAbstract) [0x00196]
- // Microsoft ex.StackTrace:
- // 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
- // at default state_entry (XMRInstAbstract )
- public string XMRExceptionStackString(Exception ex)
- {
- string stwhole = ex.StackTrace;
- string[] stlines = stwhole.Split(new char[] { '\n' });
- StringBuilder sb = new StringBuilder();
- foreach(string st in stlines)
- {
- string stline = st.Trim();
- if(stline.Length == 0)
- continue;
- // strip 'at' off the front of line
- if(stline.StartsWith("at "))
- {
- stline = stline.Substring(3);
- }
- // strip '(wrapper ...' off front of line
- if(stline.StartsWith("(wrapper dynamic-method) System.Object:"))
- {
- stline = stline.Substring(39);
- }
- // strip the (systemargtypes...) from our dynamic method names cuz it's messy
- // 'default state_entry (XMRInstAbstract )'
- // => 'default state_entry'
- // 'CallSomethingThatThrows(string) (OpenSim.Region.ScriptEngine.YEngine.XMRInstance,string)'
- // => 'CallSomethingThatThrows(string)'
- int kwin = stline.IndexOf(" in ");
- int br0x = stline.IndexOf(" [0x");
- int pastCloseParen = stline.Length;
- if((kwin >= 0) && (br0x >= 0))
- pastCloseParen = Math.Min(kwin, br0x);
- else if(kwin >= 0)
- pastCloseParen = kwin;
- else if(br0x >= 0)
- pastCloseParen = br0x;
- else
- pastCloseParen = stline.Length;
- int endFuncName = pastCloseParen;
- while(endFuncName > 0)
- {
- if(stline[--endFuncName] == '(')
- break;
- }
- while(endFuncName > 0)
- {
- if(stline[endFuncName - 1] != ' ')
- break;
- --endFuncName;
- }
- string funcName = stline.Substring(0, endFuncName);
- KeyValuePair<int, ScriptSrcLoc>[] srcLocs;
- if(m_ObjCode.scriptSrcLocss.TryGetValue(funcName, out srcLocs))
- {
- stline = stline.Substring(0, endFuncName) + stline.Substring(pastCloseParen);
- kwin = stline.IndexOf(" in ");
- br0x = stline.IndexOf(" [0x");
- }
- // keyword 'in' is just before filename:linenumber that goes to end of line
- // trim up the corresponding filename (ie, remove useless path info)
- if(kwin >= 0)
- {
- int begfn = kwin + 4;
- int slash = begfn;
- for(int i = begfn; i < stline.Length; i++)
- {
- char c = stline[i];
- if((c == '/') || (c == '\\'))
- slash = i + 1;
- }
- stline = stline.Substring(0, begfn) + stline.Substring(slash);
- }
- else if(srcLocs != null)
- {
- // no filename:linenumber info, try to convert IL offset
- if(br0x >= 0)
- {
- try
- {
- int begiloffs = br0x + 4;
- int endiloffs = stline.IndexOf("]", begiloffs);
- int iloffset = int.Parse(stline.Substring(begiloffs, endiloffs - begiloffs),
- System.Globalization.NumberStyles.HexNumber);
- int srcLocIdx;
- int srcLocLen = srcLocs.Length;
- for(srcLocIdx = 0; ++srcLocIdx < srcLocLen;)
- {
- if(iloffset < srcLocs[srcLocIdx].Key)
- break;
- }
- ScriptSrcLoc srcLoc = srcLocs[--srcLocIdx].Value;
- stline = stline.Substring(0, br0x) + " <" +
- srcLoc.file + '(' + srcLoc.line + ',' + srcLoc.posn + ")>";
- }
- catch
- {
- }
- }
- }
- // put edited line in output string
- if(sb.Length > 0)
- sb.AppendLine();
- sb.Append(" at ");
- sb.Append(stline);
- }
- return sb.ToString();
- }
- /**
- * @brief List fonts available.
- */
- public LSL_List xmrFontsAvailable()
- {
- System.Drawing.FontFamily[] families = System.Drawing.FontFamily.Families;
- object[] output = new object[families.Length];
- for(int i = 0; i < families.Length; i++)
- output[i] = new LSL_String(families[i].Name);
- return new LSL_List(output);
- }
- /************************\
- * Used by decompiler *
- \************************/
- public bool xmrRotationToBool(LSL_Rotation x)
- {
- return TypeCast.RotationToBool(x);
- }
- public bool xmrStringToBool(string x)
- {
- return TypeCast.StringToBool(x);
- }
- public bool xmrVectorToBool(LSL_Vector x)
- {
- return TypeCast.VectorToBool(x);
- }
- public bool xmrKeyToBool(string x)
- {
- return TypeCast.KeyToBool(x);
- }
- public bool xmrListToBool(LSL_List x)
- {
- return TypeCast.ListToBool(x);
- }
- public int xmrStringCompare(string x, string y)
- {
- return string.Compare(x, y);
- }
- /**
- * @brief types of data we serialize
- */
- private enum Ser: byte
- {
- NULL,
- EVENTCODE,
- LSLFLOAT,
- LSLINT,
- LSLKEY,
- LSLLIST,
- LSLROT,
- LSLSTR,
- LSLVEC,
- SYSARRAY,
- SYSDOUB,
- SYSFLOAT,
- SYSINT,
- SYSSTR,
- XMRARRAY,
- DUPREF,
- SYSBOOL,
- XMRINST,
- DELEGATE,
- SDTCLOBJ,
- SYSCHAR,
- SYSERIAL,
- THROWNEX
- }
- /**
- * @brief Write state out to a stream.
- * Do not change script state.
- */
- public void MigrateOut(BinaryWriter mow)
- {
- try
- {
- migrateOutWriter = mow;
- migrateOutObjects = new Dictionary<object, int>();
- migrateOutLists = new Dictionary<object[], ObjLslList>();
- SendObjValue(ehArgs);
- mow.Write(doGblInit);
- mow.Write(stateCode);
- mow.Write((int)eventCode);
- glblVars.SendArrays(SendObjValue);
- if(newStateCode >= 0)
- {
- mow.Write("**newStateCode**");
- mow.Write(newStateCode);
- }
- for(XMRStackFrame thisSF = stackFrames; thisSF is not null; thisSF = thisSF.nextSF)
- {
- mow.Write(thisSF.funcName);
- mow.Write(thisSF.callNo);
- SendObjValue(thisSF.objArray);
- }
- mow.Write("");
- }
- finally
- {
- migrateOutWriter = null;
- migrateOutObjects = null;
- migrateOutLists = null;
- }
- }
- /**
- * @brief Write an object to the output stream.
- * @param graph = object to send
- */
- private BinaryWriter migrateOutWriter;
- private Dictionary<object, int> migrateOutObjects;
- private Dictionary<object[], ObjLslList> migrateOutLists;
- public void SendObjValue(object graph)
- {
- BinaryWriter mow = migrateOutWriter;
- // Value types (including nulls) are always output directly.
- if(graph is null)
- {
- mow.Write((byte)Ser.NULL);
- return;
- }
- if(graph is ScriptEventCode)
- {
- mow.Write((byte)Ser.EVENTCODE);
- mow.Write((int)graph);
- return;
- }
- if(graph is LSL_Float lfg)
- {
- mow.Write((byte)Ser.LSLFLOAT);
- mow.Write(lfg.value);
- return;
- }
- if(graph is LSL_Integer lig)
- {
- mow.Write((byte)Ser.LSLINT);
- mow.Write(lig.value);
- return;
- }
- if(graph is LSL_Key lkg)
- {
- mow.Write((byte)Ser.LSLKEY);
- SendObjValue(lkg.m_string); // m_string can be null
- return;
- }
- if(graph is LSL_Rotation lrg)
- {
- mow.Write((byte)Ser.LSLROT);
- mow.Write(lrg.x);
- mow.Write(lrg.y);
- mow.Write(lrg.z);
- mow.Write(lrg.s);
- return;
- }
- if(graph is LSL_String lsg)
- {
- mow.Write((byte)Ser.LSLSTR);
- SendObjValue(lsg.m_string); // m_string can be null
- return;
- }
- if(graph is LSL_Vector lvg)
- {
- mow.Write((byte)Ser.LSLVEC);
- mow.Write(lvg.x);
- mow.Write(lvg.y);
- mow.Write(lvg.z);
- return;
- }
- if(graph is bool)
- {
- mow.Write((byte)Ser.SYSBOOL);
- mow.Write((bool)graph);
- return;
- }
- if(graph is double dg)
- {
- mow.Write((byte)Ser.SYSDOUB);
- mow.Write((double)graph);
- return;
- }
- if(graph is float fg)
- {
- mow.Write((byte)Ser.SYSFLOAT);
- mow.Write(fg);
- return;
- }
- if(graph is int ig)
- {
- mow.Write((byte)Ser.SYSINT);
- mow.Write((int)graph);
- return;
- }
- if(graph is char cg)
- {
- mow.Write((byte)Ser.SYSCHAR);
- mow.Write(cg);
- return;
- }
- // Script instance pointer is always just that.
- if(graph == this)
- {
- mow.Write((byte)Ser.XMRINST);
- return;
- }
- // Convert lists to object type.
- // This is compatible with old migration data and also
- // two vars pointing to same list won't duplicate it.
- if(graph is LSL_List llg)
- {
- object[] data = llg.Data;
- if(!migrateOutLists.TryGetValue(data, out ObjLslList ollg))
- {
- ollg = new ObjLslList();
- ollg.objarray = data;
- migrateOutLists[data] = ollg;
- }
- graph = ollg;
- }
- // If this same exact object was already serialized,
- // just output an index telling the receiver to use
- // that same old object, rather than creating a whole
- // new object with the same values. Also this prevents
- // self-referencing objects (like arrays) from causing
- // an infinite loop.
- if(migrateOutObjects.TryGetValue(graph, out int ident))
- {
- mow.Write((byte)Ser.DUPREF);
- mow.Write(ident);
- return;
- }
- // Object not seen before, save its address with an unique
- // ident number that the receiver can easily regenerate.
- ident = migrateOutObjects.Count;
- migrateOutObjects.Add(graph, ident);
- // Now output the object's value(s).
- // If the object self-references, the object is alreay entered
- // in the dictionary and so the self-reference will just emit
- // a DUPREF tag instead of trying to output the whole object
- // again.
- if(graph is ObjLslList oll)
- {
- mow.Write((byte)Ser.LSLLIST);
- SendObjValue(oll.objarray);
- }
- else if(graph is XMR_Array xg)
- {
- mow.Write((byte)Ser.XMRARRAY);
- xg.SendArrayObj(SendObjValue);
- }
- else if(graph is Array array)
- {
- mow.Write((byte)Ser.SYSARRAY);
- mow.Write(SysType2String(array.GetType().GetElementType()));
- mow.Write(array.Length);
- for(int i = 0; i < array.Length; i++)
- SendObjValue(array.GetValue(i));
- }
- else if(graph is string sg)
- {
- mow.Write((byte)Ser.SYSSTR);
- mow.Write(sg);
- }
- else if(graph is Delegate del)
- {
- mow.Write((byte)Ser.DELEGATE);
- mow.Write(del.Method.Name);
- Type delType = del.GetType();
- foreach(KeyValuePair<string, TokenDeclSDType> kvp in m_ObjCode.sdObjTypesName)
- {
- TokenDeclSDType sdt = kvp.Value;
- if(sdt is TokenDeclSDTypeDelegate sdtd)
- {
- if(sdtd.GetSysType() == delType)
- {
- mow.Write(kvp.Key);
- goto found;
- }
- }
- }
- throw new Exception("cant find script-defined delegate for " + del.Method.Name + " type " + del.GetType());
- found:
- SendObjValue(del.Target);
- }
- else if(graph is XMRSDTypeClObj XMRSDTypeClObjgraph)
- {
- mow.Write((byte)Ser.SDTCLOBJ);
- XMRSDTypeClObjgraph.Capture(this.SendObjValue);
- }
- else if(graph is ScriptThrownException ScriptThrownExceptiongraph)
- {
- MemoryStream memoryStream = new MemoryStream();
- System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter =
- new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
- bformatter.Serialize(memoryStream, graph);
- byte[] rawBytes = memoryStream.ToArray();
- mow.Write((byte)Ser.THROWNEX);
- mow.Write((int)rawBytes.Length);
- mow.Write(rawBytes);
- SendObjValue(ScriptThrownExceptiongraph.thrown);
- }
- else
- {
- MemoryStream memoryStream = new MemoryStream();
- System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter =
- new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
- bformatter.Serialize(memoryStream, graph);
- byte[] rawBytes = memoryStream.ToArray();
- mow.Write((byte)Ser.SYSERIAL);
- mow.Write(rawBytes.Length);
- mow.Write(rawBytes);
- }
- }
- /**
- * @brief Use short strings for known type names.
- */
- private static string SysType2String(Type type)
- {
- if(type.IsArray && (type.GetArrayRank() == 1))
- {
- string str = KnownSysType2String(type.GetElementType());
- if(str is not null)
- return str + "[]";
- }
- else
- {
- string str = KnownSysType2String(type);
- if(str is not null)
- return str;
- }
- return type.ToString();
- }
- private static string KnownSysType2String(Type type)
- {
- if(type == typeof(bool))
- return "bo";
- if(type == typeof(char))
- return "ch";
- if(type == typeof(Delegate))
- return "de";
- if(type == typeof(double))
- return "do";
- if(type == typeof(float))
- return "fl";
- if(type == typeof(int))
- return "in";
- if(type == typeof(LSL_List))
- return "li";
- if(type == typeof(object))
- return "ob";
- if(type == typeof(LSL_Rotation))
- return "ro";
- if(type == typeof(XMRSDTypeClObj))
- return "sc";
- if(type == typeof(string))
- return "st";
- if(type == typeof(LSL_Vector))
- return "ve";
- if(type == typeof(XMR_Array))
- return "xa";
- return null;
- }
- private static Type String2SysType(string str)
- {
- if(str.EndsWith("[]"))
- return String2SysType(str.Substring(0, str.Length - 2)).MakeArrayType();
- if(str == "bo")
- return typeof(bool);
- if(str == "ch")
- return typeof(char);
- if(str == "de")
- return typeof(Delegate);
- if(str == "do")
- return typeof(double);
- if(str == "fl")
- return typeof(float);
- if(str == "in")
- return typeof(int);
- if(str == "li")
- return typeof(LSL_List);
- if(str == "ob")
- return typeof(object);
- if(str == "ro")
- return typeof(LSL_Rotation);
- if(str == "sc")
- return typeof(XMRSDTypeClObj);
- if(str == "st")
- return typeof(string);
- if(str == "ve")
- return typeof(LSL_Vector);
- if(str == "xa")
- return typeof(XMR_Array);
- return Type.GetType(str, true);
- }
- /**
- * @brief Read state in from a stream.
- */
- public void MigrateIn(BinaryReader mir)
- {
- try
- {
- migrateInReader = mir;
- migrateInObjects = new Dictionary<int, object>();
- ehArgs = (object[])RecvObjValue();
- doGblInit = mir.ReadBoolean();
- stateCode = mir.ReadInt32();
- eventCode = (ScriptEventCode)mir.ReadInt32();
- newStateCode = -1;
- glblVars.RecvArrays(RecvObjValue);
- XMRStackFrame lastSF = null;
- string funcName;
- while((funcName = mir.ReadString()) != "")
- {
- if(funcName == "**newStateCode**")
- {
- newStateCode = mir.ReadInt32();
- continue;
- }
- XMRStackFrame thisSF = new XMRStackFrame();
- thisSF.funcName = funcName;
- thisSF.callNo = mir.ReadInt32();
- thisSF.objArray = (object[])RecvObjValue();
- if(lastSF == null)
- stackFrames = thisSF;
- else
- lastSF.nextSF = thisSF;
- lastSF = thisSF;
- }
- }
- finally
- {
- migrateInReader = null;
- migrateInObjects = null;
- }
- }
- /**
- * @brief Read a single value from the stream.
- * @returns value (boxed as needed)
- */
- private BinaryReader migrateInReader;
- private Dictionary<int, object> migrateInObjects;
- public object RecvObjValue()
- {
- BinaryReader mir = this.migrateInReader;
- int ident = this.migrateInObjects.Count;
- Ser code = (Ser)mir.ReadByte();
- switch(code)
- {
- case Ser.NULL:
- return null;
- case Ser.EVENTCODE:
- return (ScriptEventCode)mir.ReadInt32();
- case Ser.LSLFLOAT:
- return new LSL_Float(mir.ReadDouble());
- case Ser.LSLINT:
- return new LSL_Integer(mir.ReadInt32());
- case Ser.LSLKEY:
- return new LSL_Key((string)RecvObjValue());
- case Ser.LSLLIST:
- {
- this.migrateInObjects.Add(ident, null); // placeholder
- object[] data = (object[])RecvObjValue(); // read data, maybe using another index
- LSL_List list = new LSL_List(data); // make LSL-level list
- this.migrateInObjects[ident] = list; // fill in slot
- return list;
- }
- case Ser.LSLROT:
- {
- double x = mir.ReadDouble();
- double y = mir.ReadDouble();
- double z = mir.ReadDouble();
- double w = mir.ReadDouble();
- return new LSL_Rotation(x, y, z, w);
- }
- case Ser.LSLSTR:
- return new LSL_String((string)RecvObjValue());
- case Ser.LSLVEC:
- {
- double x = mir.ReadDouble();
- double y = mir.ReadDouble();
- double z = mir.ReadDouble();
- return new LSL_Vector(x, y, z);
- }
- case Ser.SYSARRAY:
- {
- Type eletype = String2SysType(mir.ReadString());
- int length = mir.ReadInt32();
- Array array = Array.CreateInstance(eletype, length);
- this.migrateInObjects.Add(ident, array);
- for(int i = 0; i < length; i++)
- array.SetValue(RecvObjValue(), i);
- return array;
- }
- case Ser.SYSBOOL:
- return mir.ReadBoolean();
- case Ser.SYSDOUB:
- return mir.ReadDouble();
- case Ser.SYSFLOAT:
- return mir.ReadSingle();
- case Ser.SYSINT:
- return mir.ReadInt32();
- case Ser.SYSCHAR:
- return mir.ReadChar();
- case Ser.SYSSTR:
- string s = mir.ReadString();
- this.migrateInObjects.Add(ident, s);
- return s;
- case Ser.XMRARRAY:
- {
- XMR_Array array = new XMR_Array(this);
- this.migrateInObjects.Add(ident, array);
- array.RecvArrayObj(this.RecvObjValue);
- return array;
- }
- case Ser.DUPREF:
- {
- ident = mir.ReadInt32();
- object obj = this.migrateInObjects[ident];
- if(obj is ObjLslList)
- obj = new LSL_List(((ObjLslList)obj).objarray);
- return obj;
- }
- case Ser.XMRINST:
- return this;
- case Ser.DELEGATE:
- this.migrateInObjects.Add(ident, null); // placeholder
- string name = mir.ReadString(); // function name
- string sig = mir.ReadString(); // delegate type
- object targ = this.RecvObjValue(); // 'this' object
- Delegate del = this.GetScriptMethodDelegate(name, sig, targ);
- this.migrateInObjects[ident] = del; // actual value
- return del;
- case Ser.SDTCLOBJ:
- XMRSDTypeClObj clobj = new XMRSDTypeClObj();
- this.migrateInObjects.Add(ident, clobj);
- clobj.Restore(this, this.RecvObjValue);
- return clobj;
- case Ser.SYSERIAL:
- {
- int rawLength = mir.ReadInt32();
- byte[] rawBytes = mir.ReadBytes(rawLength);
- MemoryStream memoryStream = new MemoryStream(rawBytes);
- System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter =
- new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
- object graph = bformatter.Deserialize(memoryStream);
- this.migrateInObjects.Add(ident, graph);
- return graph;
- }
- case Ser.THROWNEX:
- {
- int rawLength = mir.ReadInt32();
- byte[] rawBytes = mir.ReadBytes(rawLength);
- MemoryStream memoryStream = new MemoryStream(rawBytes);
- System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter =
- new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
- object graph = bformatter.Deserialize(memoryStream);
- this.migrateInObjects.Add(ident, graph);
- ((ScriptThrownException)graph).thrown = RecvObjValue();
- return graph;
- }
- default:
- throw new Exception("bad stream code " + code.ToString());
- }
- }
- // wrapper around list object arrays to make sure they are always object types for migration purposes
- private class ObjLslList
- {
- public object[] objarray;
- }
- }
- // Any xmr...() methods that call CheckRun() must be tagged with this attribute
- // so the ScriptCodeGen will know the method is non-trivial.
- public class xmrMethodCallsCheckRunAttribute: Attribute
- {
- }
- // Any xmr...() methods in xmrengtest that call Stub<somethingorother>() must be
- // tagged with this attribute so the -builtins option will tell the user that
- // they are a stub function.
- public class xmrMethodIsNoisyAttribute: Attribute
- {
- }
- // Any script callable methods that really return a key not a string should be
- // tagged with this attribute so the compiler will know they return type key and
- // not type string.
- public class xmrMethodReturnsKeyAttribute: Attribute
- {
- }
- [SerializableAttribute]
- public class OutOfHeapException: Exception
- {
- public OutOfHeapException(int oldtotal, int newtotal, int limit)
- : base("(OWNER)oldtotal=" + oldtotal + ", newtotal=" + newtotal + ", limit=" + limit)
- {
- }
- }
- [SerializableAttribute]
- public class OutOfStackException: Exception
- {
- }
- }
|