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