LSO_Parser.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  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 OpenSim 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. /* Original code: Tedd Hansen */
  28. using System;
  29. using System.Collections;
  30. using System.Collections.Generic;
  31. using System.IO;
  32. using System.Reflection;
  33. using System.Reflection.Emit;
  34. using System.Text;
  35. namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO
  36. {
  37. internal partial class LSO_Parser
  38. {
  39. private string FileName;
  40. private FileStream fs;
  41. private BinaryReader br;
  42. internal LSO_Struct.Header myHeader;
  43. internal Dictionary<long, LSO_Struct.StaticBlock> StaticBlocks = new Dictionary<long, LSO_Struct.StaticBlock>();
  44. //private System.Collections.Hashtable StaticBlocks = new System.Collections.Hashtable();
  45. private TypeBuilder typeBuilder;
  46. private List<string> EventList = new List<string>();
  47. public LSO_Parser(string _FileName, TypeBuilder _typeBuilder)
  48. {
  49. FileName = _FileName;
  50. typeBuilder = _typeBuilder;
  51. }
  52. internal void OpenFile()
  53. {
  54. // Open
  55. Common.SendToDebug("Opening filename: " + FileName);
  56. fs = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
  57. br = new BinaryReader(fs, Encoding.BigEndianUnicode);
  58. }
  59. internal void CloseFile()
  60. {
  61. // Close
  62. br.Close();
  63. fs.Close();
  64. }
  65. /// <summary>
  66. /// Parse LSO file.
  67. /// </summary>
  68. public void Parse()
  69. {
  70. // The LSO Format consist of 6 major blocks: header, statics, functions, states, heap, and stack.
  71. // HEADER BLOCK
  72. Common.SendToDebug("Reading HEADER BLOCK at: 0");
  73. fs.Seek(0, SeekOrigin.Begin);
  74. myHeader = new LSO_Struct.Header();
  75. myHeader.TM = BitConverter.ToUInt32(br_read(4), 0);
  76. myHeader.IP = BitConverter.ToUInt32(br_read(4), 0);
  77. myHeader.VN = BitConverter.ToUInt32(br_read(4), 0);
  78. myHeader.BP = BitConverter.ToUInt32(br_read(4), 0);
  79. myHeader.SP = BitConverter.ToUInt32(br_read(4), 0);
  80. myHeader.HR = BitConverter.ToUInt32(br_read(4), 0);
  81. myHeader.HP = BitConverter.ToUInt32(br_read(4), 0);
  82. myHeader.CS = BitConverter.ToUInt32(br_read(4), 0);
  83. myHeader.NS = BitConverter.ToUInt32(br_read(4), 0);
  84. myHeader.CE = BitConverter.ToUInt32(br_read(4), 0);
  85. myHeader.IE = BitConverter.ToUInt32(br_read(4), 0);
  86. myHeader.ER = BitConverter.ToUInt32(br_read(4), 0);
  87. myHeader.FR = BitConverter.ToUInt32(br_read(4), 0);
  88. myHeader.SLR = BitConverter.ToUInt32(br_read(4), 0);
  89. myHeader.GVR = BitConverter.ToUInt32(br_read(4), 0);
  90. myHeader.GFR = BitConverter.ToUInt32(br_read(4), 0);
  91. myHeader.PR = BitConverter.ToUInt32(br_read(4), 0);
  92. myHeader.ESR = BitConverter.ToUInt32(br_read(4), 0);
  93. myHeader.SR = BitConverter.ToUInt32(br_read(4), 0);
  94. myHeader.NCE = BitConverter.ToUInt64(br_read(8), 0);
  95. myHeader.NIE = BitConverter.ToUInt64(br_read(8), 0);
  96. myHeader.NER = BitConverter.ToUInt64(br_read(8), 0);
  97. // Print Header Block to debug
  98. Common.SendToDebug("TM - Top of memory (size): " + myHeader.TM);
  99. Common.SendToDebug("IP - Instruction Pointer (0=not running): " + myHeader.IP);
  100. Common.SendToDebug("VN - Version number: " + myHeader.VN);
  101. Common.SendToDebug("BP - Local Frame Pointer: " + myHeader.BP);
  102. Common.SendToDebug("SP - Stack Pointer: " + myHeader.SP);
  103. Common.SendToDebug("HR - Heap Register: " + myHeader.HR);
  104. Common.SendToDebug("HP - Heap Pointer: " + myHeader.HP);
  105. Common.SendToDebug("CS - Current State: " + myHeader.CS);
  106. Common.SendToDebug("NS - Next State: " + myHeader.NS);
  107. Common.SendToDebug("CE - Current Events: " + myHeader.CE);
  108. Common.SendToDebug("IE - In Event: " + myHeader.IE);
  109. Common.SendToDebug("ER - Event Register: " + myHeader.ER);
  110. Common.SendToDebug("FR - Fault Register: " + myHeader.FR);
  111. Common.SendToDebug("SLR - Sleep Register: " + myHeader.SLR);
  112. Common.SendToDebug("GVR - Global Variable Register: " + myHeader.GVR);
  113. Common.SendToDebug("GFR - Global Function Register: " + myHeader.GFR);
  114. Common.SendToDebug("PR - Parameter Register: " + myHeader.PR);
  115. Common.SendToDebug("ESR - Energy Supply Register: " + myHeader.ESR);
  116. Common.SendToDebug("SR - State Register: " + myHeader.SR);
  117. Common.SendToDebug("NCE - 64-bit Current Events: " + myHeader.NCE);
  118. Common.SendToDebug("NIE - 64-bit In Events: " + myHeader.NIE);
  119. Common.SendToDebug("NER - 64-bit Event Register: " + myHeader.NER);
  120. Common.SendToDebug("Read position when exiting HEADER BLOCK: " + fs.Position);
  121. // STATIC BLOCK
  122. Common.SendToDebug("Reading STATIC BLOCK at: " + myHeader.GVR);
  123. fs.Seek(myHeader.GVR, SeekOrigin.Begin);
  124. int StaticBlockCount = 0;
  125. // Read function blocks until we hit GFR
  126. while (fs.Position < myHeader.GFR)
  127. {
  128. StaticBlockCount++;
  129. long startReadPos = fs.Position;
  130. Common.SendToDebug("Reading Static Block " + StaticBlockCount + " at: " + startReadPos);
  131. //fs.Seek(myHeader.GVR, SeekOrigin.Begin);
  132. LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock();
  133. myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0);
  134. myStaticBlock.ObjectType = br_read(1)[0];
  135. Common.SendToDebug("Static Block ObjectType: " +
  136. ((LSO_Enums.Variable_Type_Codes) myStaticBlock.ObjectType).ToString());
  137. myStaticBlock.Unknown = br_read(1)[0];
  138. // Size of datatype varies -- what about strings?
  139. if (myStaticBlock.ObjectType != 0)
  140. myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType));
  141. StaticBlocks.Add((UInt32) startReadPos, myStaticBlock);
  142. }
  143. Common.SendToDebug("Number of Static Blocks read: " + StaticBlockCount);
  144. // FUNCTION BLOCK
  145. // Always right after STATIC BLOCK
  146. LSO_Struct.FunctionBlock myFunctionBlock = new LSO_Struct.FunctionBlock();
  147. if (myHeader.GFR == myHeader.SR)
  148. {
  149. // If GFR and SR are at same position then there is no fuction block
  150. Common.SendToDebug("No FUNCTION BLOCK found");
  151. }
  152. else
  153. {
  154. Common.SendToDebug("Reading FUNCTION BLOCK at: " + myHeader.GFR);
  155. fs.Seek(myHeader.GFR, SeekOrigin.Begin);
  156. myFunctionBlock.FunctionCount = BitConverter.ToUInt32(br_read(4), 0);
  157. Common.SendToDebug("Number of functions in Fuction Block: " + myFunctionBlock.FunctionCount);
  158. if (myFunctionBlock.FunctionCount > 0)
  159. {
  160. myFunctionBlock.CodeChunkPointer = new UInt32[myFunctionBlock.FunctionCount];
  161. for (int i = 0; i < myFunctionBlock.FunctionCount; i++)
  162. {
  163. Common.SendToDebug("Reading function " + i + " at: " + fs.Position);
  164. // TODO: ADD TO FUNCTION LIST (How do we identify it later?)
  165. // Note! Absolute position
  166. myFunctionBlock.CodeChunkPointer[i] = BitConverter.ToUInt32(br_read(4), 0) + myHeader.GFR;
  167. Common.SendToDebug("Fuction " + i + " code chunk position: " +
  168. myFunctionBlock.CodeChunkPointer[i]);
  169. }
  170. }
  171. }
  172. // STATE FRAME BLOCK
  173. // Always right after FUNCTION BLOCK
  174. Common.SendToDebug("Reading STATE BLOCK at: " + myHeader.SR);
  175. fs.Seek(myHeader.SR, SeekOrigin.Begin);
  176. LSO_Struct.StateFrameBlock myStateFrameBlock = new LSO_Struct.StateFrameBlock();
  177. myStateFrameBlock.StateCount = BitConverter.ToUInt32(br_read(4), 0);
  178. if (myStateFrameBlock.StateCount > 0)
  179. {
  180. // Initialize array
  181. myStateFrameBlock.StatePointer = new LSO_Struct.StatePointerBlock[myStateFrameBlock.StateCount];
  182. for (int i = 0; i < myStateFrameBlock.StateCount; i++)
  183. {
  184. Common.SendToDebug("Reading STATE POINTER BLOCK " + (i + 1) + " at: " + fs.Position);
  185. // Position is relative to state frame
  186. myStateFrameBlock.StatePointer[i].Location = myHeader.SR + BitConverter.ToUInt32(br_read(4), 0);
  187. myStateFrameBlock.StatePointer[i].EventMask = new BitArray(br_read(8));
  188. Common.SendToDebug("Pointer: " + myStateFrameBlock.StatePointer[i].Location);
  189. Common.SendToDebug("Total potential EventMask bits: " +
  190. myStateFrameBlock.StatePointer[i].EventMask.Count);
  191. //// Read STATE BLOCK
  192. //long CurPos = fs.Position;
  193. //fs.Seek(CurPos, SeekOrigin.Begin);
  194. }
  195. }
  196. // STATE BLOCK
  197. // For each StateFrameBlock there is one StateBlock with multiple event handlers
  198. if (myStateFrameBlock.StateCount > 0)
  199. {
  200. // Go through all State Frame Pointers found
  201. for (int i = 0; i < myStateFrameBlock.StateCount; i++)
  202. {
  203. fs.Seek(myStateFrameBlock.StatePointer[i].Location, SeekOrigin.Begin);
  204. Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " at: " + fs.Position);
  205. // READ: STATE BLOCK HEADER
  206. myStateFrameBlock.StatePointer[i].StateBlock = new LSO_Struct.StateBlock();
  207. myStateFrameBlock.StatePointer[i].StateBlock.StartPos = (UInt32) fs.Position; // Note
  208. myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize = BitConverter.ToUInt32(br_read(4), 0);
  209. myStateFrameBlock.StatePointer[i].StateBlock.Unknown = br_read(1)[0];
  210. myStateFrameBlock.StatePointer[i].StateBlock.EndPos = (UInt32) fs.Position; // Note
  211. Common.SendToDebug("State block Start Pos: " + myStateFrameBlock.StatePointer[i].StateBlock.StartPos);
  212. Common.SendToDebug("State block Header Size: " +
  213. myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize);
  214. Common.SendToDebug("State block Header End Pos: " +
  215. myStateFrameBlock.StatePointer[i].StateBlock.EndPos);
  216. // We need to count number of bits flagged in EventMask?
  217. // for each bit in myStateFrameBlock.StatePointer[i].EventMask
  218. // ADDING TO ALL RIGHT NOW, SHOULD LIMIT TO ONLY THE ONES IN USE
  219. //TODO: Create event hooks
  220. myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers =
  221. new LSO_Struct.StateBlockHandler[myStateFrameBlock.StatePointer[i].EventMask.Count - 1];
  222. for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++)
  223. {
  224. if (myStateFrameBlock.StatePointer[i].EventMask.Get(ii) == true)
  225. {
  226. // We got an event
  227. // READ: STATE BLOCK HANDLER
  228. Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER matching EVENT MASK " + ii +
  229. " (" + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") at: " +
  230. fs.Position);
  231. myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer =
  232. myStateFrameBlock.StatePointer[i].StateBlock.EndPos +
  233. BitConverter.ToUInt32(br_read(4), 0);
  234. myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CallFrameSize =
  235. BitConverter.ToUInt32(br_read(4), 0);
  236. Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" +
  237. ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") Code Chunk Pointer: " +
  238. myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].
  239. CodeChunkPointer);
  240. Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" +
  241. ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") Call Frame Size: " +
  242. myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].
  243. CallFrameSize);
  244. }
  245. }
  246. }
  247. }
  248. //// READ FUNCTION CODE CHUNKS
  249. //// Functions + Function start pos (GFR)
  250. //// TODO: Somehow be able to identify and reference this
  251. //LSO_Struct.CodeChunk[] myFunctionCodeChunk;
  252. //if (myFunctionBlock.FunctionCount > 0)
  253. //{
  254. // myFunctionCodeChunk = new LSO_Struct.CodeChunk[myFunctionBlock.FunctionCount];
  255. // for (int i = 0; i < myFunctionBlock.FunctionCount; i++)
  256. // {
  257. // Common.SendToDebug("Reading Function Code Chunk " + i);
  258. // myFunctionCodeChunk[i] = GetCodeChunk((UInt32)myFunctionBlock.CodeChunkPointer[i]);
  259. // }
  260. //}
  261. // READ EVENT CODE CHUNKS
  262. LSO_Struct.CodeChunk[] myEventCodeChunk;
  263. if (myStateFrameBlock.StateCount > 0)
  264. {
  265. myEventCodeChunk = new LSO_Struct.CodeChunk[myStateFrameBlock.StateCount];
  266. for (int i = 0; i < myStateFrameBlock.StateCount; i++)
  267. {
  268. // TODO: Somehow organize events and functions so they can be found again,
  269. // two level search ain't no good
  270. for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++)
  271. {
  272. if (myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer > 0)
  273. {
  274. Common.SendToDebug("Reading Event Code Chunk state " + i + ", event " +
  275. (LSO_Enums.Event_Mask_Values) ii);
  276. // Override a Method / Function
  277. string eventname = i + "_event_" + (LSO_Enums.Event_Mask_Values) ii;
  278. Common.SendToDebug("Event Name: " + eventname);
  279. if (Common.IL_ProcessCodeChunks)
  280. {
  281. EventList.Add(eventname);
  282. // JUMP TO CODE PROCESSOR
  283. ProcessCodeChunk(
  284. myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer,
  285. typeBuilder, eventname);
  286. }
  287. }
  288. }
  289. }
  290. }
  291. if (Common.IL_CreateFunctionList)
  292. IL_INSERT_FUNCTIONLIST();
  293. }
  294. internal LSO_Struct.HeapBlock GetHeap(UInt32 pos)
  295. {
  296. // HEAP BLOCK
  297. // TODO:? Special read for strings/keys (null terminated) and lists (pointers to other HEAP entries)
  298. Common.SendToDebug("Reading HEAP BLOCK at: " + pos);
  299. fs.Seek(pos, SeekOrigin.Begin);
  300. LSO_Struct.HeapBlock myHeapBlock = new LSO_Struct.HeapBlock();
  301. myHeapBlock.DataBlockSize = BitConverter.ToInt32(br_read(4), 0);
  302. myHeapBlock.ObjectType = br_read(1)[0];
  303. myHeapBlock.ReferenceCount = BitConverter.ToUInt16(br_read(2), 0);
  304. //myHeapBlock.Data = br_read(getObjectSize(myHeapBlock.ObjectType));
  305. // Don't read it reversed
  306. myHeapBlock.Data = new byte[myHeapBlock.DataBlockSize - 1];
  307. br.Read(myHeapBlock.Data, 0, myHeapBlock.DataBlockSize - 1);
  308. Common.SendToDebug("Heap Block Data Block Size: " + myHeapBlock.DataBlockSize);
  309. Common.SendToDebug("Heap Block ObjectType: " +
  310. ((LSO_Enums.Variable_Type_Codes) myHeapBlock.ObjectType).ToString());
  311. Common.SendToDebug("Heap Block Reference Count: " + myHeapBlock.ReferenceCount);
  312. return myHeapBlock;
  313. }
  314. private byte[] br_read(int len)
  315. {
  316. if (len <= 0)
  317. return null;
  318. try
  319. {
  320. byte[] bytes = new byte[len];
  321. for (int i = len - 1; i > -1; i--)
  322. bytes[i] = br.ReadByte();
  323. return bytes;
  324. }
  325. catch (Exception e)
  326. {
  327. Common.SendToDebug("Exception: " + e.ToString());
  328. throw (e);
  329. }
  330. }
  331. //private byte[] br_read_smallendian(int len)
  332. //{
  333. // byte[] bytes = new byte[len];
  334. // br.Read(bytes,0, len);
  335. // return bytes;
  336. //}
  337. private Type getLLObjectType(byte objectCode)
  338. {
  339. switch ((LSO_Enums.Variable_Type_Codes) objectCode)
  340. {
  341. case LSO_Enums.Variable_Type_Codes.Void:
  342. return typeof (void);
  343. case LSO_Enums.Variable_Type_Codes.Integer:
  344. return typeof (UInt32);
  345. case LSO_Enums.Variable_Type_Codes.Float:
  346. return typeof (float);
  347. case LSO_Enums.Variable_Type_Codes.String:
  348. return typeof (string);
  349. case LSO_Enums.Variable_Type_Codes.Key:
  350. return typeof (string);
  351. case LSO_Enums.Variable_Type_Codes.Vector:
  352. return typeof (LSO_Enums.Vector);
  353. case LSO_Enums.Variable_Type_Codes.Rotation:
  354. return typeof (LSO_Enums.Rotation);
  355. case LSO_Enums.Variable_Type_Codes.List:
  356. Common.SendToDebug("TODO: List datatype not implemented yet!");
  357. return typeof (ArrayList);
  358. case LSO_Enums.Variable_Type_Codes.Null:
  359. Common.SendToDebug("TODO: Datatype null is not implemented, using string instead.!");
  360. return typeof (string);
  361. default:
  362. Common.SendToDebug("Lookup of LSL datatype " + objectCode +
  363. " to .Net datatype failed: Unknown LSL datatype. Defaulting to object.");
  364. return typeof (object);
  365. }
  366. }
  367. private int getObjectSize(byte ObjectType)
  368. {
  369. switch ((LSO_Enums.Variable_Type_Codes) ObjectType)
  370. {
  371. case LSO_Enums.Variable_Type_Codes.Integer:
  372. case LSO_Enums.Variable_Type_Codes.Float:
  373. case LSO_Enums.Variable_Type_Codes.String:
  374. case LSO_Enums.Variable_Type_Codes.Key:
  375. case LSO_Enums.Variable_Type_Codes.List:
  376. return 4;
  377. case LSO_Enums.Variable_Type_Codes.Vector:
  378. return 12;
  379. case LSO_Enums.Variable_Type_Codes.Rotation:
  380. return 16;
  381. default:
  382. return 0;
  383. }
  384. }
  385. private string Read_String()
  386. {
  387. string ret = "";
  388. byte reader = br_read(1)[0];
  389. while (reader != 0x000)
  390. {
  391. ret += (char) reader;
  392. reader = br_read(1)[0];
  393. }
  394. return ret;
  395. }
  396. /// <summary>
  397. /// Reads a code chunk and creates IL
  398. /// </summary>
  399. /// <param name="pos">Absolute position in file. REMEMBER TO ADD myHeader.GFR!</param>
  400. /// <param name="typeBuilder">TypeBuilder for assembly</param>
  401. /// <param name="eventname">Name of event (function) to generate</param>
  402. private void ProcessCodeChunk(UInt32 pos, TypeBuilder typeBuilder, string eventname)
  403. {
  404. LSO_Struct.CodeChunk myCodeChunk = new LSO_Struct.CodeChunk();
  405. Common.SendToDebug("Reading Function Code Chunk at: " + pos);
  406. fs.Seek(pos, SeekOrigin.Begin);
  407. myCodeChunk.CodeChunkHeaderSize = BitConverter.ToUInt32(br_read(4), 0);
  408. Common.SendToDebug("CodeChunk Header Size: " + myCodeChunk.CodeChunkHeaderSize);
  409. // Read until null
  410. myCodeChunk.Comment = Read_String();
  411. Common.SendToDebug("Function comment: " + myCodeChunk.Comment);
  412. myCodeChunk.ReturnTypePos = br_read(1)[0];
  413. myCodeChunk.ReturnType = GetStaticBlock((long) myCodeChunk.ReturnTypePos + (long) myHeader.GVR);
  414. Common.SendToDebug("Return type #" + myCodeChunk.ReturnType.ObjectType + ": " +
  415. ((LSO_Enums.Variable_Type_Codes) myCodeChunk.ReturnType.ObjectType).ToString());
  416. // TODO: How to determine number of codechunks -- does this method work?
  417. myCodeChunk.CodeChunkArguments = new List<LSO_Struct.CodeChunkArgument>();
  418. byte reader = br_read(1)[0];
  419. reader = br_read(1)[0];
  420. // NOTE ON CODE CHUNK ARGUMENTS
  421. // This determins type definition
  422. int ccount = 0;
  423. while (reader != 0x000)
  424. {
  425. ccount++;
  426. Common.SendToDebug("Reading Code Chunk Argument " + ccount);
  427. LSO_Struct.CodeChunkArgument CCA = new LSO_Struct.CodeChunkArgument();
  428. CCA.FunctionReturnTypePos = reader;
  429. reader = br_read(1)[0];
  430. CCA.NullString = reader;
  431. CCA.FunctionReturnType = GetStaticBlock(CCA.FunctionReturnTypePos + myHeader.GVR);
  432. myCodeChunk.CodeChunkArguments.Add(CCA);
  433. Common.SendToDebug("Code Chunk Argument " + ccount + " type #" + CCA.FunctionReturnType.ObjectType +
  434. ": " + (LSO_Enums.Variable_Type_Codes) CCA.FunctionReturnType.ObjectType);
  435. }
  436. // Create string array
  437. Type[] MethodArgs = new Type[myCodeChunk.CodeChunkArguments.Count];
  438. for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++)
  439. {
  440. MethodArgs[_ic] = getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType);
  441. Common.SendToDebug("Method argument " + _ic + ": " +
  442. getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType).
  443. ToString());
  444. }
  445. // End marker is 0x000
  446. myCodeChunk.EndMarker = reader;
  447. //
  448. // Emit: START OF METHOD (FUNCTION)
  449. //
  450. Common.SendToDebug("CLR:" + eventname + ":MethodBuilder methodBuilder = typeBuilder.DefineMethod...");
  451. MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname,
  452. MethodAttributes.Public,
  453. typeof (void),
  454. new Type[] {typeof (object)});
  455. //MethodArgs);
  456. //typeof(void), //getLLObjectType(myCodeChunk.ReturnType),
  457. // new Type[] { typeof(object) }, //);
  458. //Common.SendToDebug("CLR:" + eventname + ":typeBuilder.DefineMethodOverride(methodBuilder...");
  459. //typeBuilder.DefineMethodOverride(methodBuilder,
  460. // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname));
  461. // Create the IL generator
  462. Common.SendToDebug("CLR:" + eventname + ":ILGenerator il = methodBuilder.GetILGenerator();");
  463. ILGenerator il = methodBuilder.GetILGenerator();
  464. if (Common.IL_UseTryCatch)
  465. IL_INSERT_TRY(il, eventname);
  466. // Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!");
  467. //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call...");
  468. //il.Emit(OpCodes.Call, typeof(Console).GetMethod
  469. // ("WriteLine", new Type[] { typeof(string) }));
  470. //Common.SendToDebug("STARTUP: il.Emit(OpCodes.Ldc_I4_S, 0);");
  471. //il.Emit(OpCodes.Ldc_I4_S, 0);
  472. for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++)
  473. {
  474. Common.SendToDebug("PARAMS: il.Emit(OpCodes.Ldarg, " + _ic + ");");
  475. il.Emit(OpCodes.Ldarg, _ic);
  476. }
  477. //
  478. // CALLING OPCODE PROCESSOR, one command at the time TO GENERATE IL
  479. //
  480. bool FoundRet = false;
  481. while (FoundRet == false)
  482. {
  483. FoundRet = LSL_PROCESS_OPCODE(il);
  484. }
  485. if (Common.IL_UseTryCatch)
  486. IL_INSERT_END_TRY(il, eventname);
  487. // Emit: RETURN FROM METHOD
  488. il.Emit(OpCodes.Ret);
  489. return;
  490. }
  491. private void IL_INSERT_FUNCTIONLIST()
  492. {
  493. Common.SendToDebug("Creating function list");
  494. string eventname = "GetFunctions";
  495. Common.SendToDebug("Creating IL " + eventname);
  496. // Define a private String field.
  497. //FieldBuilder myField = myTypeBuilder.DefineField("EventList", typeof(String[]), FieldAttributes.Public);
  498. //FieldBuilder mem = typeBuilder.DefineField("mem", typeof(Array), FieldAttributes.Private);
  499. MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname,
  500. MethodAttributes.Public,
  501. typeof (string[]),
  502. null);
  503. //typeBuilder.DefineMethodOverride(methodBuilder,
  504. // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname));
  505. ILGenerator il = methodBuilder.GetILGenerator();
  506. // IL_INSERT_TRY(il, eventname);
  507. // // Push string to stack
  508. // il.Emit(OpCodes.Ldstr, "Inside " + eventname);
  509. //// Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!");
  510. //il.Emit(OpCodes.Call, typeof(Console).GetMethod
  511. // ("WriteLine", new Type[] { typeof(string) }));
  512. //initIL.Emit(OpCodes.Newobj, typeof(string[]));
  513. //string[] MyArray = new string[2] { "TestItem1" , "TestItem2" };
  514. ////il.Emit(OpCodes.Ldarg_0);
  515. il.DeclareLocal(typeof (string[]));
  516. ////il.Emit(OpCodes.Ldarg_0);
  517. il.Emit(OpCodes.Ldc_I4, EventList.Count); // Specify array length
  518. il.Emit(OpCodes.Newarr, typeof (String)); // create new string array
  519. il.Emit(OpCodes.Stloc_0); // Store array as local variable 0 in stack
  520. ////SetFunctionList
  521. for (int lv = 0; lv < EventList.Count; lv++)
  522. {
  523. il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack
  524. il.Emit(OpCodes.Ldc_I4, lv); // Push index position
  525. il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value
  526. il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value
  527. //il.Emit(OpCodes.Ldarg_0);
  528. //il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value
  529. //il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("AddFunction", new Type[] { typeof(string) }));
  530. }
  531. // IL_INSERT_END_TRY(il, eventname);
  532. il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack
  533. // il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("SetFunctionList", new Type[] { typeof(Array) }));
  534. il.Emit(OpCodes.Ret); // Return
  535. }
  536. private void IL_INSERT_TRY(ILGenerator il, string eventname)
  537. {
  538. /*
  539. * CLR TRY
  540. */
  541. //Common.SendToDebug("CLR:" + eventname + ":il.BeginExceptionBlock()");
  542. il.BeginExceptionBlock();
  543. // Push "Hello World!" string to stack
  544. //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr...");
  545. //il.Emit(OpCodes.Ldstr, "Starting CLR dynamic execution of: " + eventname);
  546. }
  547. private void IL_INSERT_END_TRY(ILGenerator il, string eventname)
  548. {
  549. /*
  550. * CATCH
  551. */
  552. Common.SendToDebug("CLR:" + eventname + ":il.BeginCatchBlock(typeof(Exception));");
  553. il.BeginCatchBlock(typeof (Exception));
  554. // Push "Hello World!" string to stack
  555. Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr...");
  556. il.Emit(OpCodes.Ldstr, "Execption executing dynamic CLR function " + eventname + ": ");
  557. //call void [mscorlib]System.Console::WriteLine(string)
  558. Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call...");
  559. il.Emit(OpCodes.Call, typeof (Console).GetMethod
  560. ("Write", new Type[] {typeof (string)}));
  561. //callvirt instance string [mscorlib]System.Exception::get_Message()
  562. Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Callvirt...");
  563. il.Emit(OpCodes.Callvirt, typeof (Exception).GetMethod
  564. ("get_Message"));
  565. //call void [mscorlib]System.Console::WriteLine(string)
  566. Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call...");
  567. il.Emit(OpCodes.Call, typeof (Console).GetMethod
  568. ("WriteLine", new Type[] {typeof (string)}));
  569. /*
  570. * CLR END TRY
  571. */
  572. //Common.SendToDebug("CLR:" + eventname + ":il.EndExceptionBlock();");
  573. il.EndExceptionBlock();
  574. }
  575. private LSO_Struct.StaticBlock GetStaticBlock(long pos)
  576. {
  577. long FirstPos = fs.Position;
  578. try
  579. {
  580. UInt32 position = (UInt32) pos;
  581. // STATIC BLOCK
  582. Common.SendToDebug("Reading STATIC BLOCK at: " + position);
  583. fs.Seek(position, SeekOrigin.Begin);
  584. if (StaticBlocks.ContainsKey(position) == true)
  585. {
  586. Common.SendToDebug("Found cached STATIC BLOCK");
  587. return StaticBlocks[pos];
  588. }
  589. //int StaticBlockCount = 0;
  590. // Read function blocks until we hit GFR
  591. //while (fs.Position < myHeader.GFR)
  592. //{
  593. //StaticBlockCount++;
  594. //Common.SendToDebug("Reading Static Block at: " + position);
  595. //fs.Seek(myHeader.GVR, SeekOrigin.Begin);
  596. LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock();
  597. myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0);
  598. myStaticBlock.ObjectType = br_read(1)[0];
  599. Common.SendToDebug("Static Block ObjectType: " +
  600. ((LSO_Enums.Variable_Type_Codes) myStaticBlock.ObjectType).ToString());
  601. myStaticBlock.Unknown = br_read(1)[0];
  602. // Size of datatype varies
  603. if (myStaticBlock.ObjectType != 0)
  604. myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType));
  605. StaticBlocks.Add(position, myStaticBlock);
  606. //}
  607. Common.SendToDebug("Done reading Static Block.");
  608. return myStaticBlock;
  609. }
  610. finally
  611. {
  612. // Go back to original read pos
  613. fs.Seek(FirstPos, SeekOrigin.Begin);
  614. }
  615. }
  616. }
  617. }