mirror of
https://github.com/Leonmmcoset/CMLeonOS.git
synced 2026-03-03 15:30:27 +00:00
377 lines
7.1 KiB
C#
377 lines
7.1 KiB
C#
|
|
// #define DEBUG_BINARY_READER
|
||
|
|
// #define DEBUG_UNDUMP
|
||
|
|
|
||
|
|
using System;
|
||
|
|
|
||
|
|
using ULDebug = UniLua.Tools.ULDebug;
|
||
|
|
|
||
|
|
namespace UniLua
|
||
|
|
{
|
||
|
|
public class BinaryBytesReader
|
||
|
|
{
|
||
|
|
private ILoadInfo LoadInfo;
|
||
|
|
public int SizeOfSizeT;
|
||
|
|
|
||
|
|
|
||
|
|
public BinaryBytesReader( ILoadInfo loadinfo )
|
||
|
|
{
|
||
|
|
LoadInfo = loadinfo;
|
||
|
|
SizeOfSizeT = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
public byte[] ReadBytes( int count )
|
||
|
|
{
|
||
|
|
byte[] ret = new byte[count];
|
||
|
|
for( int i=0; i<count; ++i )
|
||
|
|
{
|
||
|
|
var c = LoadInfo.ReadByte();
|
||
|
|
if( c == -1 )
|
||
|
|
throw new UndumpException("truncated");
|
||
|
|
ret[i] = (byte)c;
|
||
|
|
}
|
||
|
|
#if DEBUG_BINARY_READER
|
||
|
|
var sb = new System.Text.StringBuilder();
|
||
|
|
sb.Append("ReadBytes:");
|
||
|
|
for( var i=0; i<ret.Length; ++i )
|
||
|
|
{
|
||
|
|
sb.Append( string.Format(" {0:X02}", ret[i]) );
|
||
|
|
}
|
||
|
|
Console.WriteLine( sb.ToString() );
|
||
|
|
#endif
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
public int ReadInt()
|
||
|
|
{
|
||
|
|
var bytes = ReadBytes( 4 );
|
||
|
|
int ret = BitConverter.ToInt32( bytes, 0 );
|
||
|
|
#if DEBUG_BINARY_READER
|
||
|
|
Console.WriteLine( "ReadInt: " + ret );
|
||
|
|
#endif
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
public uint ReadUInt()
|
||
|
|
{
|
||
|
|
var bytes = ReadBytes( 4 );
|
||
|
|
uint ret = BitConverter.ToUInt32( bytes, 0 );
|
||
|
|
#if DEBUG_BINARY_READER
|
||
|
|
Console.WriteLine( "ReadUInt: " + ret );
|
||
|
|
#endif
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
public int ReadSizeT()
|
||
|
|
{
|
||
|
|
if( SizeOfSizeT <= 0) {
|
||
|
|
throw new Exception("sizeof(size_t) is not valid:" + SizeOfSizeT);
|
||
|
|
}
|
||
|
|
|
||
|
|
var bytes = ReadBytes( SizeOfSizeT );
|
||
|
|
UInt64 ret;
|
||
|
|
switch( SizeOfSizeT ) {
|
||
|
|
case 4:
|
||
|
|
ret = BitConverter.ToUInt32( bytes, 0 );
|
||
|
|
break;
|
||
|
|
case 8:
|
||
|
|
ret = BitConverter.ToUInt64( bytes, 0 );
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw new NotImplementedException();
|
||
|
|
}
|
||
|
|
|
||
|
|
#if DEBUG_BINARY_READER
|
||
|
|
Console.WriteLine( "ReadSizeT: " + ret );
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if( ret > Int32.MaxValue )
|
||
|
|
throw new NotImplementedException();
|
||
|
|
|
||
|
|
return (int)ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
public double ReadDouble()
|
||
|
|
{
|
||
|
|
var bytes = ReadBytes( 8 );
|
||
|
|
double ret = BitConverter.ToDouble( bytes, 0 );
|
||
|
|
#if DEBUG_BINARY_READER
|
||
|
|
Console.WriteLine( "ReadDouble: " + ret );
|
||
|
|
#endif
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
public byte ReadByte()
|
||
|
|
{
|
||
|
|
var c = LoadInfo.ReadByte();
|
||
|
|
if( c == -1 )
|
||
|
|
throw new UndumpException("truncated");
|
||
|
|
#if DEBUG_BINARY_READER
|
||
|
|
Console.WriteLine( "ReadBytes: " + c );
|
||
|
|
#endif
|
||
|
|
return (byte)c;
|
||
|
|
}
|
||
|
|
|
||
|
|
public string ReadString()
|
||
|
|
{
|
||
|
|
var n = ReadSizeT();
|
||
|
|
if( n == 0 )
|
||
|
|
return null;
|
||
|
|
|
||
|
|
var bytes = ReadBytes( n );
|
||
|
|
|
||
|
|
// n=1: removing trailing '\0'
|
||
|
|
string ret = System.Text.Encoding.ASCII.GetString( bytes, 0, n-1 );
|
||
|
|
#if DEBUG_BINARY_READER
|
||
|
|
Console.WriteLine( "ReadString n:" + n + " ret:" + ret );
|
||
|
|
#endif
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class UndumpException : Exception
|
||
|
|
{
|
||
|
|
public string Why;
|
||
|
|
|
||
|
|
public UndumpException( string why )
|
||
|
|
{
|
||
|
|
Why = why;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public class Undump
|
||
|
|
{
|
||
|
|
private BinaryBytesReader Reader;
|
||
|
|
|
||
|
|
|
||
|
|
public static LuaProto LoadBinary( ILuaState lua,
|
||
|
|
ILoadInfo loadinfo, string name )
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var reader = new BinaryBytesReader( loadinfo );
|
||
|
|
var undump = new Undump( reader );
|
||
|
|
undump.LoadHeader();
|
||
|
|
return undump.LoadFunction();
|
||
|
|
}
|
||
|
|
catch( UndumpException e )
|
||
|
|
{
|
||
|
|
var Lua = (LuaState)lua;
|
||
|
|
Lua.O_PushString( string.Format(
|
||
|
|
"{0}: {1} precompiled chunk", name, e.Why ) );
|
||
|
|
Lua.D_Throw( ThreadStatus.LUA_ERRSYNTAX );
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private Undump( BinaryBytesReader reader )
|
||
|
|
{
|
||
|
|
Reader = reader;
|
||
|
|
}
|
||
|
|
|
||
|
|
private int LoadInt()
|
||
|
|
{
|
||
|
|
return Reader.ReadInt();
|
||
|
|
}
|
||
|
|
|
||
|
|
private byte LoadByte()
|
||
|
|
{
|
||
|
|
return Reader.ReadByte();
|
||
|
|
}
|
||
|
|
|
||
|
|
private byte[] LoadBytes( int count )
|
||
|
|
{
|
||
|
|
return Reader.ReadBytes( count );
|
||
|
|
}
|
||
|
|
|
||
|
|
private string LoadString()
|
||
|
|
{
|
||
|
|
return Reader.ReadString();
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool LoadBoolean()
|
||
|
|
{
|
||
|
|
return LoadByte() != 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
private double LoadNumber()
|
||
|
|
{
|
||
|
|
return Reader.ReadDouble();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void LoadHeader()
|
||
|
|
{
|
||
|
|
byte[] header = LoadBytes( 4 // Signature
|
||
|
|
+ 8 // version, format version, size of int ... etc
|
||
|
|
+ 6 // Tail
|
||
|
|
);
|
||
|
|
byte v = header[ 4 /* skip signature */
|
||
|
|
+ 4 /* offset of sizeof(size_t) */
|
||
|
|
];
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine(string.Format("sizeof(size_t): {0}", v));
|
||
|
|
#endif
|
||
|
|
Reader.SizeOfSizeT = v ;
|
||
|
|
}
|
||
|
|
|
||
|
|
private Instruction LoadInstruction()
|
||
|
|
{
|
||
|
|
return (Instruction)Reader.ReadUInt();
|
||
|
|
}
|
||
|
|
|
||
|
|
private LuaProto LoadFunction()
|
||
|
|
{
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "LoadFunction enter" );
|
||
|
|
#endif
|
||
|
|
|
||
|
|
LuaProto proto = new LuaProto();
|
||
|
|
proto.LineDefined = LoadInt();
|
||
|
|
proto.LastLineDefined = LoadInt();
|
||
|
|
proto.NumParams = LoadByte();
|
||
|
|
proto.IsVarArg = LoadBoolean();
|
||
|
|
proto.MaxStackSize = LoadByte();
|
||
|
|
|
||
|
|
LoadCode(proto);
|
||
|
|
LoadConstants(proto);
|
||
|
|
LoadUpvalues(proto);
|
||
|
|
LoadDebug(proto);
|
||
|
|
return proto;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void LoadCode( LuaProto proto )
|
||
|
|
{
|
||
|
|
var n = LoadInt();
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "LoadCode n:" + n );
|
||
|
|
#endif
|
||
|
|
proto.Code.Clear();
|
||
|
|
for( int i=0; i<n; ++i )
|
||
|
|
{
|
||
|
|
proto.Code.Add( LoadInstruction() );
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "Count:" + proto.Code.Count );
|
||
|
|
Console.WriteLine( "LoadInstruction:" + proto.Code[proto.Code.Count-1] );
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void LoadConstants( LuaProto proto )
|
||
|
|
{
|
||
|
|
var n = LoadInt();
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "Load Constants:" + n );
|
||
|
|
#endif
|
||
|
|
proto.K.Clear();
|
||
|
|
for( int i=0; i<n; ++i )
|
||
|
|
{
|
||
|
|
int t = (int)LoadByte();
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "Constant Type:" + t );
|
||
|
|
#endif
|
||
|
|
var v = new StkId();
|
||
|
|
switch( t )
|
||
|
|
{
|
||
|
|
case (int)LuaType.LUA_TNIL:
|
||
|
|
v.V.SetNilValue();
|
||
|
|
proto.K.Add( v );
|
||
|
|
break;
|
||
|
|
|
||
|
|
case (int)LuaType.LUA_TBOOLEAN:
|
||
|
|
v.V.SetBValue(LoadBoolean());
|
||
|
|
proto.K.Add( v );
|
||
|
|
break;
|
||
|
|
|
||
|
|
case (int)LuaType.LUA_TNUMBER:
|
||
|
|
v.V.SetNValue(LoadNumber());
|
||
|
|
proto.K.Add( v );
|
||
|
|
break;
|
||
|
|
|
||
|
|
case (int)LuaType.LUA_TSTRING:
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "LuaType.LUA_TSTRING" );
|
||
|
|
#endif
|
||
|
|
v.V.SetSValue(LoadString());
|
||
|
|
proto.K.Add( v );
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
throw new UndumpException(
|
||
|
|
"LoadConstants unknown type: " + t );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
n = LoadInt();
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "Load Functions:" + n );
|
||
|
|
#endif
|
||
|
|
proto.P.Clear();
|
||
|
|
for( int i=0; i<n; ++i )
|
||
|
|
{
|
||
|
|
proto.P.Add( LoadFunction() );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void LoadUpvalues( LuaProto proto )
|
||
|
|
{
|
||
|
|
var n = LoadInt();
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "Load Upvalues:" + n );
|
||
|
|
#endif
|
||
|
|
proto.Upvalues.Clear();
|
||
|
|
for( int i=0; i<n; ++i )
|
||
|
|
{
|
||
|
|
proto.Upvalues.Add(
|
||
|
|
new UpvalDesc()
|
||
|
|
{
|
||
|
|
Name = null,
|
||
|
|
InStack = LoadBoolean(),
|
||
|
|
Index = (int)LoadByte()
|
||
|
|
} );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void LoadDebug( LuaProto proto )
|
||
|
|
{
|
||
|
|
int n;
|
||
|
|
proto.Source = LoadString();
|
||
|
|
|
||
|
|
// LineInfo
|
||
|
|
n = LoadInt();
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "Load LineInfo:" + n );
|
||
|
|
#endif
|
||
|
|
proto.LineInfo.Clear();
|
||
|
|
for( int i=0; i<n; ++i )
|
||
|
|
{
|
||
|
|
proto.LineInfo.Add( LoadInt() );
|
||
|
|
}
|
||
|
|
|
||
|
|
// LocalVar
|
||
|
|
n = LoadInt();
|
||
|
|
#if DEBUG_UNDUMP
|
||
|
|
Console.WriteLine( "Load LocalVar:" + n );
|
||
|
|
#endif
|
||
|
|
proto.LocVars.Clear();
|
||
|
|
for( int i=0; i<n; ++i )
|
||
|
|
{
|
||
|
|
proto.LocVars.Add(
|
||
|
|
new LocVar()
|
||
|
|
{
|
||
|
|
VarName = LoadString(),
|
||
|
|
StartPc = LoadInt(),
|
||
|
|
EndPc = LoadInt(),
|
||
|
|
} );
|
||
|
|
}
|
||
|
|
|
||
|
|
// Upvalues' name
|
||
|
|
n = LoadInt();
|
||
|
|
for( int i=0; i<n; ++i )
|
||
|
|
{
|
||
|
|
proto.Upvalues[i].Name = LoadString();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|