Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
413aa9b5f0 | ||
|
|
5da1e26835 | ||
|
|
53a4173fd3 | ||
|
|
5737243606 | ||
|
|
be727e67c6 | ||
|
|
9d67c46835 | ||
|
|
756a2fd060 | ||
|
|
8ad1f85a45 | ||
|
|
ad6ae5d087 | ||
|
|
580a1364d0 | ||
|
|
d4f90f9c01 | ||
|
|
cecff913f1 | ||
|
|
7a4c78dac3 | ||
|
|
ee47075fda | ||
|
|
100f6b6bf4 |
+10
-1
@@ -1,9 +1,18 @@
|
||||
RABCDAsm Changelog
|
||||
==================
|
||||
|
||||
RABCDAsm v1.4 (2011.02.xx)
|
||||
RABCDAsm v1.5 (2011.04.14)
|
||||
--------------------------
|
||||
|
||||
* Fixed v1.4 constant pool regression
|
||||
* Added support for memory-access and sign-extend opcodes
|
||||
* Speed optimizations
|
||||
* Documentation updates
|
||||
|
||||
RABCDAsm v1.4 (2011.03.07)
|
||||
--------------------------
|
||||
|
||||
* Source code ported to D2
|
||||
* Add support for forward-references for TypeName-kind Multinames
|
||||
* Correctly order classes by dependencies (extends/implements) and reference
|
||||
count
|
||||
|
||||
@@ -48,27 +48,23 @@ bytecode with the following properties:
|
||||
Compiling from source
|
||||
---------------------
|
||||
|
||||
RABCDAsm is written in the [D programming language, version 1][d1]. It uses one
|
||||
third-party library, [std2][] (for some fancy template stuff).
|
||||
RABCDAsm is written in the [D programming language, version 2][d2].
|
||||
|
||||
Assuming you have [dmd][], [git][] and [svn][] installed, compiling should be
|
||||
as straight-forward as:
|
||||
Assuming you have [dmd][] and [git][] installed, compiling should be as
|
||||
straight-forward as:
|
||||
|
||||
git clone git://github.com/CyberShadow/RABCDAsm.git
|
||||
cd RABCDAsm
|
||||
svn co http://svn.dsource.org/projects/std2/trunk/std2/std2
|
||||
dmd rabcdasm abcfile asprogram disassembler autodata murmurhash2a
|
||||
dmd rabcasm abcfile asprogram assembler autodata murmurhash2a
|
||||
dmd abcexport swffile zlibx
|
||||
dmd abcreplace swffile zlibx
|
||||
dmd swfdecompress swffile zlibx
|
||||
dmd swf7zcompress swffile zlibx
|
||||
dmd -O -inline rabcdasm abcfile asprogram disassembler autodata murmurhash2a
|
||||
dmd -O -inline rabcasm abcfile asprogram assembler autodata murmurhash2a
|
||||
dmd -O -inline abcexport swffile zlibx
|
||||
dmd -O -inline abcreplace swffile zlibx
|
||||
dmd -O -inline swfdecompress swffile zlibx
|
||||
dmd -O -inline swf7zcompress swffile zlibx
|
||||
|
||||
[d1]: http://www.digitalmars.com/d/1.0/
|
||||
[std2]: http://dsource.org/projects/std2
|
||||
[d2]: http://www.digitalmars.com/d/2.0/
|
||||
[dmd]: http://www.digitalmars.com/d/download.html
|
||||
[git]: http://git-scm.com/
|
||||
[svn]: http://subversion.apache.org/
|
||||
|
||||
Pre-compiled binaries
|
||||
---------------------
|
||||
|
||||
+4
-4
@@ -20,7 +20,7 @@ module abcexport;
|
||||
|
||||
import std.file;
|
||||
import std.path;
|
||||
import std.string;
|
||||
import std.conv;
|
||||
import std.stdio;
|
||||
import swffile;
|
||||
|
||||
@@ -45,11 +45,11 @@ void main(string[] args)
|
||||
while (*p++) {} // skip name
|
||||
abc = tag.data[p-tag.data.ptr..$];
|
||||
}
|
||||
write(getName(arg) ~ .toString(count++) ~ ".abc", abc);
|
||||
std.file.write(getName(arg) ~ to!string(count++) ~ ".abc", abc);
|
||||
}
|
||||
if (count == 0)
|
||||
throw new Exception("No DoABC tags found");
|
||||
}
|
||||
catch (Object o)
|
||||
writefln("Error while processing %s: %s", arg, o);
|
||||
catch (Exception e)
|
||||
writefln("Error while processing %s: %s", arg, e);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
module abcfile;
|
||||
|
||||
import std.string : format; // exception formatting
|
||||
import std.exception;
|
||||
|
||||
/**
|
||||
* Implements a shallow representation of an .abc file.
|
||||
@@ -181,7 +182,7 @@ class ABCFile
|
||||
|
||||
// TraitAttributes bitmask
|
||||
ubyte attr() { return cast(ubyte)(kindAttr >> 4); }
|
||||
void attr(ubyte value) { kindAttr = (kindAttr&0xF) | (value<<4); }
|
||||
void attr(ubyte value) { kindAttr = cast(ubyte)((kindAttr&0xF) | (value<<4)); }
|
||||
}
|
||||
|
||||
struct Class
|
||||
@@ -708,16 +709,16 @@ const OpcodeInfo[256] opcodeInfo = [
|
||||
/* 0x32 */ {"hasnext2", [OpcodeArgumentType.UIntLiteral, OpcodeArgumentType.UIntLiteral]},
|
||||
/* 0x33 */ {"pushdecimal", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x34 */ {"pushdnan", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x35 */ {"li8", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x36 */ {"li16", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x37 */ {"li32", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x38 */ {"lf32", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x39 */ {"lf64", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3A */ {"si8", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3B */ {"si16", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3C */ {"si32", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3D */ {"sf32", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3E */ {"sf64", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x35 */ {"li8", []},
|
||||
/* 0x36 */ {"li16", []},
|
||||
/* 0x37 */ {"li32", []},
|
||||
/* 0x38 */ {"lf32", []},
|
||||
/* 0x39 */ {"lf64", []},
|
||||
/* 0x3A */ {"si8", []},
|
||||
/* 0x3B */ {"si16", []},
|
||||
/* 0x3C */ {"si32", []},
|
||||
/* 0x3D */ {"sf32", []},
|
||||
/* 0x3E */ {"sf64", []},
|
||||
/* 0x3F */ {"0x3F", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x40 */ {"newfunction", [OpcodeArgumentType.Method]},
|
||||
/* 0x41 */ {"call", [OpcodeArgumentType.UIntLiteral]},
|
||||
@@ -735,9 +736,9 @@ const OpcodeInfo[256] opcodeInfo = [
|
||||
/* 0x4D */ {"callinterface", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x4E */ {"callsupervoid", [OpcodeArgumentType.Multiname, OpcodeArgumentType.UIntLiteral]},
|
||||
/* 0x4F */ {"callpropvoid", [OpcodeArgumentType.Multiname, OpcodeArgumentType.UIntLiteral]},
|
||||
/* 0x50 */ {"sxi1", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x51 */ {"sxi8", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x52 */ {"sxi16", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x50 */ {"sxi1", []},
|
||||
/* 0x51 */ {"sxi8", []},
|
||||
/* 0x52 */ {"sxi16", []},
|
||||
/* 0x53 */ {"applytype", [OpcodeArgumentType.UIntLiteral]},
|
||||
/* 0x54 */ {"0x54", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x55 */ {"newobject", [OpcodeArgumentType.UIntLiteral]},
|
||||
@@ -992,13 +993,13 @@ private final class ABCReader
|
||||
foreach (ref value; abc.bodies)
|
||||
value = readMethodBody();
|
||||
}
|
||||
catch (Object o)
|
||||
throw new Exception(format("Error at %d (0x%X): %s", pos, pos, o));
|
||||
catch (Exception e)
|
||||
throw new Exception(format("Error at %d (0x%X):", pos, pos), e);
|
||||
}
|
||||
|
||||
ubyte readU8()
|
||||
{
|
||||
assert(pos < buf.length);
|
||||
enforce(pos < buf.length, "End of file reached");
|
||||
return buf[pos++];
|
||||
}
|
||||
|
||||
@@ -1046,7 +1047,7 @@ private final class ABCReader
|
||||
|
||||
void readExact(void* ptr, size_t len)
|
||||
{
|
||||
assert(pos+len <= buf.length);
|
||||
enforce(pos+len <= buf.length, "End of file reached");
|
||||
(cast(ubyte*)ptr)[0..len] = buf[pos..pos+len];
|
||||
pos += len;
|
||||
}
|
||||
@@ -1061,8 +1062,9 @@ private final class ABCReader
|
||||
|
||||
string readString()
|
||||
{
|
||||
string s = new char[readU30()];
|
||||
readExact(s.ptr, s.length);
|
||||
char[] buf = new char[readU30()];
|
||||
readExact(buf.ptr, buf.length);
|
||||
string s = assumeUnique(buf);
|
||||
if (s.length == 0)
|
||||
s = ""; // not null!
|
||||
return s;
|
||||
@@ -1471,7 +1473,7 @@ private final class ABCWriter
|
||||
foreach (ref value; abc.instances)
|
||||
writeInstance(value);
|
||||
|
||||
assert(abc.classes.length == abc.instances.length);
|
||||
assert(abc.classes.length == abc.instances.length, "Number of classes and instances differs");
|
||||
foreach (ref value; abc.classes)
|
||||
writeClass(value);
|
||||
|
||||
@@ -1551,7 +1553,7 @@ private final class ABCWriter
|
||||
writeU32(v);
|
||||
}
|
||||
|
||||
void writeExact(void* ptr, size_t len)
|
||||
void writeExact(const(void)* ptr, size_t len)
|
||||
{
|
||||
while (pos+len > buf.length)
|
||||
buf.length = buf.length * 2;
|
||||
@@ -1643,7 +1645,7 @@ private final class ABCWriter
|
||||
}
|
||||
if (v.flags & MethodFlags.HAS_PARAM_NAMES)
|
||||
{
|
||||
assert(v.paramNames.length == v.paramTypes.length);
|
||||
assert(v.paramNames.length == v.paramTypes.length, "Mismatching number of parameter names and types");
|
||||
foreach (value; v.paramNames)
|
||||
writeU30(value);
|
||||
}
|
||||
@@ -1753,7 +1755,8 @@ private final class ABCWriter
|
||||
// we don't know the length before writing all the instructions - swap buffer with a temporary one
|
||||
auto globalBuf = buf;
|
||||
auto globalPos = pos;
|
||||
buf = new ubyte[1024];
|
||||
static ubyte[1024*16] methodBuf;
|
||||
buf = methodBuf[];
|
||||
pos = 0;
|
||||
|
||||
struct Fixup { ABCFile.Label target; uint pos, base; }
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ void main(string[] args)
|
||||
if (args.length != 4)
|
||||
throw new Exception("Bad arguments. Usage: abcreplace file.swf index code.abc");
|
||||
auto swf = SWFFile.read(cast(ubyte[])read(args[1]));
|
||||
auto index = toUint(args[2]);
|
||||
auto index = to!uint(args[2]);
|
||||
uint count;
|
||||
foreach (ref tag; swf.tags)
|
||||
if ((tag.type == TagType.DoABC || tag.type == TagType.DoABC2) && count++ == index)
|
||||
|
||||
+55
-77
@@ -18,6 +18,8 @@
|
||||
|
||||
module asprogram;
|
||||
|
||||
import std.algorithm;
|
||||
import core.stdc.string;
|
||||
import abcfile;
|
||||
import autodata;
|
||||
|
||||
@@ -41,16 +43,7 @@ final class ASProgram
|
||||
uint privateIndex; // unique index for private namespaces
|
||||
|
||||
mixin AutoCompare;
|
||||
//mixin ProcessAllData;
|
||||
|
||||
R processData(R, string prolog, string epilog, H)(ref H handler)
|
||||
{
|
||||
mixin(prolog);
|
||||
mixin(addAutoField("kind"));
|
||||
mixin(addAutoField("name"));
|
||||
mixin(addAutoField("privateIndex"));
|
||||
mixin(epilog);
|
||||
}
|
||||
mixin ProcessAllData;
|
||||
}
|
||||
|
||||
static class Multiname
|
||||
@@ -89,7 +82,7 @@ final class ASProgram
|
||||
mixin AutoCompare;
|
||||
mixin AutoToString;
|
||||
|
||||
R processData(R, string prolog, string epilog, H)(ref H handler)
|
||||
R processData(R, string prolog, string epilog, H)(ref H handler) const
|
||||
{
|
||||
mixin(prolog);
|
||||
mixin(addAutoField("kind"));
|
||||
@@ -244,7 +237,7 @@ final class ASProgram
|
||||
|
||||
Instance instance;
|
||||
|
||||
string toString()
|
||||
override string toString()
|
||||
{
|
||||
return instance.name.toString();
|
||||
}
|
||||
@@ -732,9 +725,24 @@ private final class AStoABC
|
||||
return value == T.init;
|
||||
}
|
||||
|
||||
static void move(T)(T[] array, size_t from, size_t to)
|
||||
{
|
||||
assert(from<array.length && to<array.length);
|
||||
if (from == to)
|
||||
return;
|
||||
T t = array[from];
|
||||
if (from < to)
|
||||
memmove(array.ptr+from, array.ptr+from+1, (to-from)*T.sizeof);
|
||||
else
|
||||
memmove(array.ptr+to+1, array.ptr+to, (from-to)*T.sizeof);
|
||||
array[to] = t;
|
||||
}
|
||||
|
||||
/// Maintain an unordered set of values; sort/index by usage count
|
||||
struct ConstantPool(T, bool haveNull = true)
|
||||
{
|
||||
alias immutable(T) I;
|
||||
|
||||
struct Entry
|
||||
{
|
||||
uint hits;
|
||||
@@ -743,7 +751,7 @@ private final class AStoABC
|
||||
|
||||
mixin AutoCompare;
|
||||
|
||||
R processData(R, string prolog, string epilog, H)(ref H handler)
|
||||
R processData(R, string prolog, string epilog, H)(ref H handler) const
|
||||
{
|
||||
mixin(prolog);
|
||||
mixin(addAutoField("hits", true));
|
||||
@@ -752,17 +760,18 @@ private final class AStoABC
|
||||
}
|
||||
}
|
||||
|
||||
Entry[T] pool;
|
||||
Entry[immutable(T)] pool;
|
||||
T[] values;
|
||||
|
||||
bool add(T value) // return true if added
|
||||
{
|
||||
enum ivalue = cast(I)value;
|
||||
if (haveNull && isNull(value))
|
||||
return false;
|
||||
auto cp = value in pool;
|
||||
auto cp = ivalue in pool;
|
||||
if (cp is null)
|
||||
{
|
||||
pool[value] = Entry(1, value);
|
||||
pool[ivalue] = Entry(1, value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -774,7 +783,8 @@ private final class AStoABC
|
||||
|
||||
bool notAdded(T value)
|
||||
{
|
||||
auto ep = value in pool;
|
||||
enum ivalue = cast(I)value;
|
||||
auto ep = ivalue in pool;
|
||||
if (ep)
|
||||
ep.hits++;
|
||||
return !((haveNull && isNull(value)) || ep);
|
||||
@@ -788,16 +798,17 @@ private final class AStoABC
|
||||
values.length = all.length + NullOffset;
|
||||
foreach (i, ref c; all)
|
||||
{
|
||||
pool[c.value].index = i + NullOffset;
|
||||
pool[cast(I)c.value].index = i + NullOffset;
|
||||
values[i + NullOffset] = c.value;
|
||||
}
|
||||
}
|
||||
|
||||
uint get(T value)
|
||||
{
|
||||
enum ivalue = cast(I)value;
|
||||
if (haveNull && isNull(value))
|
||||
return 0;
|
||||
return pool[value].index;
|
||||
return pool[ivalue].index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -811,17 +822,8 @@ private final class AStoABC
|
||||
uint addIndex, index;
|
||||
void*[] parents;
|
||||
|
||||
int opCmp(Entry* o)
|
||||
{
|
||||
if (this.parents.contains(o.object))
|
||||
return 1;
|
||||
if (o.parents.contains(this.object))
|
||||
return -1;
|
||||
if (o.hits==hits)
|
||||
return addIndex-o.addIndex;
|
||||
else
|
||||
return o.hits-hits;
|
||||
}
|
||||
mixin AutoToString;
|
||||
mixin ProcessAllData;
|
||||
}
|
||||
|
||||
Entry[void*] pool;
|
||||
@@ -871,61 +873,37 @@ private final class AStoABC
|
||||
|
||||
void finalize()
|
||||
{
|
||||
// assign unique index
|
||||
// create array
|
||||
auto all = new Entry*[pool.length];
|
||||
int i=0;
|
||||
foreach (ref e; pool)
|
||||
e.index = i++;
|
||||
|
||||
// topographical sort
|
||||
bool done;
|
||||
while (!done)
|
||||
{
|
||||
done = true;
|
||||
|
||||
foreach (ref a; pool)
|
||||
foreach (parent; a.parents)
|
||||
{
|
||||
auto pb = parent in pool;
|
||||
assert(pb !is null, "Can't find referenced object");
|
||||
if (pb.index > a.index)
|
||||
{
|
||||
auto t = pb.index;
|
||||
pb.index = a.index;
|
||||
a.index = t;
|
||||
done = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy to array
|
||||
auto all = new Entry[i];
|
||||
foreach (ref e; pool)
|
||||
all[e.index] = e;
|
||||
all[i++] = &e;
|
||||
|
||||
// sort
|
||||
//all.sort; // sort preserving topological integrity demands compared items to always be adjacent
|
||||
done = false;
|
||||
while (!done)
|
||||
{
|
||||
done = true;
|
||||
sort!q{a.hits > b.hits || (a.hits == b.hits && a.addIndex < b.addIndex)}(all);
|
||||
|
||||
for (int j=0; j<all.length-1; j++)
|
||||
if (all[j] > &all[j+1])
|
||||
// topographical sort
|
||||
topSort:
|
||||
|
||||
// update indices
|
||||
foreach (j, e; all)
|
||||
e.index = j;
|
||||
|
||||
foreach (ref a; pool)
|
||||
foreach (parent; a.parents)
|
||||
{
|
||||
auto pb = parent in pool;
|
||||
assert(pb !is null, "Can't find referenced object");
|
||||
if (pb.index > a.index)
|
||||
{
|
||||
auto t = all[j];
|
||||
all[j] = all[j+1];
|
||||
all[j+1] = t;
|
||||
done = false;
|
||||
move(all, pb.index, a.index);
|
||||
goto topSort;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
objects.length = i;
|
||||
foreach (j, ref e; all)
|
||||
{
|
||||
pool[e.object].index = j;
|
||||
foreach (j, e; all)
|
||||
objects[j] = cast(T)e.object;
|
||||
}
|
||||
}
|
||||
|
||||
uint get(T obj)
|
||||
@@ -996,7 +974,7 @@ private final class AStoABC
|
||||
throw new .Exception("Unknown Multiname kind");
|
||||
}
|
||||
bool r = multinames.add(multiname);
|
||||
assert(r);
|
||||
assert(r, "Recursive multiname reference");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1095,7 +1073,7 @@ private final class AStoABC
|
||||
visitInstance(vclass.instance);
|
||||
|
||||
bool r = classes.add(vclass);
|
||||
assert(r);
|
||||
assert(r, "Recursive class reference");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-40
@@ -22,6 +22,7 @@ import std.file;
|
||||
import std.string;
|
||||
import std.conv;
|
||||
import std.path;
|
||||
import std.exception;
|
||||
import abcfile;
|
||||
import asprogram;
|
||||
|
||||
@@ -44,8 +45,8 @@ final class Assembler
|
||||
{
|
||||
string filename;
|
||||
string buf;
|
||||
char* pos;
|
||||
char* end;
|
||||
immutable(char)* pos;
|
||||
immutable(char)* end;
|
||||
string[] arguments;
|
||||
string basePath;
|
||||
|
||||
@@ -61,7 +62,7 @@ final class Assembler
|
||||
|
||||
static File fromData(string name, string data, string[] arguments = null, string basePath = null)
|
||||
{
|
||||
data ~= \0; data = data[0..$-1]; // hack to prevent readWord etc. from checking for end-of-file on every character
|
||||
data ~= "\0"; data = data[0..$-1]; // hack to prevent readWord etc. from checking for end-of-file on every character
|
||||
return File(name, data, data.ptr, data.ptr + data.length, arguments, basePath);
|
||||
}
|
||||
|
||||
@@ -98,11 +99,11 @@ final class Assembler
|
||||
{
|
||||
if (filename.length == 0)
|
||||
throw new Exception("Empty filename");
|
||||
filename = filename.dup;
|
||||
foreach (ref c; filename)
|
||||
auto buf = filename.dup;
|
||||
foreach (ref c; buf)
|
||||
if (c == '\\')
|
||||
c = '/';
|
||||
return std.path.join(getBasePath, filename);
|
||||
return std.path.join(getBasePath, assumeUnique(buf));
|
||||
}
|
||||
|
||||
void skipWhitespace()
|
||||
@@ -190,7 +191,7 @@ final class Assembler
|
||||
foreach (ref file; files[0..fileCount])
|
||||
if (file.arguments.length)
|
||||
{
|
||||
uint index = .toUint(name)-1;
|
||||
uint index = .to!uint(name)-1;
|
||||
if (index >= file.arguments.length)
|
||||
throw new Exception("Argument index out-of-bounds");
|
||||
string value = file.arguments[index];
|
||||
@@ -211,7 +212,7 @@ final class Assembler
|
||||
|
||||
static bool isWordChar(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.'; // TODO: use lookup table?
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.';
|
||||
}
|
||||
|
||||
string readWord()
|
||||
@@ -254,7 +255,7 @@ final class Assembler
|
||||
}
|
||||
}
|
||||
|
||||
void pushFile(ref File file)
|
||||
void pushFile(File file)
|
||||
{
|
||||
if (fileCount == files.length)
|
||||
throw new Exception("Recursion limit exceeded");
|
||||
@@ -264,7 +265,7 @@ final class Assembler
|
||||
}
|
||||
|
||||
/// For restoring the position of an error
|
||||
void setFile(ref File file)
|
||||
void setFile(File file)
|
||||
{
|
||||
files[0] = file;
|
||||
fileCount = -1;
|
||||
@@ -357,7 +358,7 @@ final class Assembler
|
||||
static const char[16] hexDigits = "0123456789ABCDEF";
|
||||
|
||||
// TODO: optimize
|
||||
string s = \";
|
||||
string s = "\"";
|
||||
foreach (c; str)
|
||||
if (c == 0x0A)
|
||||
s ~= `\n`;
|
||||
@@ -422,7 +423,7 @@ final class Assembler
|
||||
return v;
|
||||
}
|
||||
|
||||
ubyte readFlag(string[] names)
|
||||
ubyte readFlag(const string[] names)
|
||||
{
|
||||
auto word = readWord();
|
||||
ubyte f = 1;
|
||||
@@ -490,7 +491,7 @@ final class Assembler
|
||||
string w = readWord();
|
||||
if (w == "null")
|
||||
return ABCFile.NULL_INT;
|
||||
return toInt(w);
|
||||
return to!int(w);
|
||||
}
|
||||
|
||||
ulong readUInt()
|
||||
@@ -498,7 +499,7 @@ final class Assembler
|
||||
string w = readWord();
|
||||
if (w == "null")
|
||||
return ABCFile.NULL_UINT;
|
||||
return toUint(w);
|
||||
return to!uint(w);
|
||||
}
|
||||
|
||||
double readDouble()
|
||||
@@ -506,7 +507,7 @@ final class Assembler
|
||||
string w = readWord();
|
||||
if (w == "null")
|
||||
return ABCFile.NULL_DOUBLE;
|
||||
return toDouble(w);
|
||||
return to!double(w);
|
||||
}
|
||||
|
||||
string readString()
|
||||
@@ -967,7 +968,7 @@ final class Assembler
|
||||
if (c=='-' || c=='+')
|
||||
{
|
||||
name = label[0..i];
|
||||
offset = .toInt(label[i..$]);
|
||||
offset = to!int(label[i..$]);
|
||||
break;
|
||||
}
|
||||
auto lp = name in labels;
|
||||
@@ -1073,24 +1074,14 @@ final class Assembler
|
||||
|
||||
foreach (ref f; jumpFixups)
|
||||
{
|
||||
try
|
||||
instructions[f.ii].arguments[f.ai].jumpTarget = parseLabel(f.name, labels);
|
||||
catch (Object o)
|
||||
{
|
||||
setFile(f.where.load);
|
||||
throw o;
|
||||
}
|
||||
scope(failure) setFile(f.where.load);
|
||||
instructions[f.ii].arguments[f.ai].jumpTarget = parseLabel(f.name, labels);
|
||||
}
|
||||
|
||||
foreach (ref f; switchFixups)
|
||||
{
|
||||
try
|
||||
instructions[f.ii].arguments[f.ai].switchTargets[f.si] = parseLabel(f.name, labels);
|
||||
catch (Object o)
|
||||
{
|
||||
setFile(f.where.load);
|
||||
throw o;
|
||||
}
|
||||
scope(failure) setFile(f.where.load);
|
||||
instructions[f.ii].arguments[f.ai].switchTargets[f.si] = parseLabel(f.name, labels);
|
||||
}
|
||||
|
||||
foreach (ref f; localClassFixups)
|
||||
@@ -1107,13 +1098,8 @@ final class Assembler
|
||||
ABCFile.Label readLabel()
|
||||
{
|
||||
auto word = readWord();
|
||||
try
|
||||
return parseLabel(word, labels);
|
||||
catch (Object o)
|
||||
{
|
||||
backpedal(word.length);
|
||||
throw o;
|
||||
}
|
||||
scope(failure) backpedal(word.length);
|
||||
return parseLabel(word, labels);
|
||||
}
|
||||
|
||||
ASProgram.Exception e;
|
||||
@@ -1213,15 +1199,15 @@ final class Assembler
|
||||
*f.ptr = *mp;
|
||||
}
|
||||
}
|
||||
catch (Object o)
|
||||
catch (Exception e)
|
||||
{
|
||||
string s = files[0].positionStr ~ ": " ~ o.toString();
|
||||
string s = files[0].positionStr ~ ": ";
|
||||
if (fileCount == -1)
|
||||
s ~= "\n\t(inclusion context unavailable)";
|
||||
else
|
||||
foreach (ref f; files[1..fileCount])
|
||||
s ~= "\n\t(included from " ~ f.positionStr ~ ")";
|
||||
throw new Exception(s);
|
||||
throw new Exception(s, e);
|
||||
}
|
||||
|
||||
classFixups = null;
|
||||
|
||||
+84
-79
@@ -19,61 +19,67 @@
|
||||
module autodata;
|
||||
|
||||
import murmurhash2a;
|
||||
import std2.traits;
|
||||
import std.traits;
|
||||
|
||||
string addAutoField(string name, bool reverseSort = false)
|
||||
{
|
||||
//return `mixin(handler.process!(typeof(` ~ name ~ `), "` ~ name ~ `")());`; // doesn't work due to DMD bug 3959
|
||||
return `{ static const _AutoDataStr = handler.process!(typeof(this.` ~ name ~ `), "` ~ name ~ `", ` ~ (reverseSort ? "true" : "false") ~`)(); mixin(_AutoDataStr); }`;
|
||||
return `mixin(typeof(handler).getMixin!(typeof(` ~ name ~ `), "` ~ name ~ `", ` ~ (reverseSort ? "true" : "false") ~`));`;
|
||||
}
|
||||
|
||||
template AutoCompare()
|
||||
{
|
||||
hash_t toHash()
|
||||
static if (is(typeof(this)==class))
|
||||
{
|
||||
alias typeof(this) _AutoDataTypeReference;
|
||||
alias Object _AutoDataOtherTypeReference;
|
||||
|
||||
override hash_t toHash() const { return _AutoDataHash(); }
|
||||
override bool opEquals(Object o) const { return _AutoDataEquals(o); }
|
||||
override int opCmp(Object o) const { return _AutoDataCmp(o); }
|
||||
}
|
||||
else // struct
|
||||
{
|
||||
alias const(typeof(this)*) _AutoDataTypeReference;
|
||||
alias const(typeof(this)*) _AutoDataOtherTypeReference;
|
||||
|
||||
hash_t toHash() const { return _AutoDataHash(); }
|
||||
bool opEquals(ref const typeof(this) s) const { return _AutoDataEquals(&s); }
|
||||
int opCmp(ref const typeof(this) s) const { return _AutoDataCmp(&s); }
|
||||
}
|
||||
|
||||
private hash_t _AutoDataHash() const
|
||||
{
|
||||
HashDataHandler handler;
|
||||
handler.hasher.Begin();
|
||||
processData!(void, "", "")(handler);
|
||||
processData!(void, q{}, q{})(handler);
|
||||
return handler.hasher.End();
|
||||
}
|
||||
|
||||
static if (is(typeof(this)==class))
|
||||
alias Object _AutoDataOtherType;
|
||||
else
|
||||
alias typeof(this) _AutoDataOtherType;
|
||||
|
||||
int opEquals(_AutoDataOtherType other)
|
||||
private bool _AutoDataEquals(_AutoDataOtherTypeReference other) const
|
||||
{
|
||||
EqualsDataHandler!(typeof(this)) handler;
|
||||
static if (is(typeof(this)==class))
|
||||
{
|
||||
handler.other = cast(typeof(this)) other;
|
||||
if (handler.other is null)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
handler.other = other;
|
||||
return processData!(bool, "auto _AutoDataOther = handler.other;", "return true;")(handler);
|
||||
auto handler = EqualsDataHandler!_AutoDataTypeReference(cast(_AutoDataTypeReference) other);
|
||||
if (handler.other is null)
|
||||
return false;
|
||||
return processData!(bool, q{auto _AutoDataOther = handler.other;}, q{return true;})(handler);
|
||||
}
|
||||
|
||||
int opCmp(_AutoDataOtherType other)
|
||||
private int _AutoDataCmp(_AutoDataOtherTypeReference other) const
|
||||
{
|
||||
CmpDataHandler!(typeof(this)) handler;
|
||||
static if (is(typeof(this)==class))
|
||||
{
|
||||
handler.other = cast(typeof(this)) other;
|
||||
if (handler.other is null)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
handler.other = other;
|
||||
return processData!(int, "auto _AutoDataOther = handler.other;", "return 0;")(handler);
|
||||
auto handler = CmpDataHandler!_AutoDataTypeReference(cast(_AutoDataTypeReference) other);
|
||||
if (handler.other is null)
|
||||
return false;
|
||||
return processData!(int, q{auto _AutoDataOther = handler.other;}, "return 0;")(handler);
|
||||
}
|
||||
}
|
||||
|
||||
template AutoToString()
|
||||
{
|
||||
string toString()
|
||||
static if (is(typeof(this)==class))
|
||||
override string toString() { return _AutoDataToString(); }
|
||||
else // struct
|
||||
string toString() const { return _AutoDataToString(); }
|
||||
|
||||
string _AutoDataToString() const
|
||||
{
|
||||
ToStringDataHandler handler;
|
||||
return processData!(string, "string _AutoDataResult;", "return _AutoDataResult;")(handler);
|
||||
@@ -82,20 +88,11 @@ template AutoToString()
|
||||
|
||||
template ProcessAllData()
|
||||
{
|
||||
R processData(R, string prolog, string epilog, H)(ref H handler)
|
||||
R processData(R, string prolog, string epilog, H)(ref H handler) const
|
||||
{
|
||||
mixin(prolog);
|
||||
foreach (i, T; this.tupleof)
|
||||
{
|
||||
//mixin(addAutoField(T.stringof)); // doesn't work
|
||||
static if (this.tupleof[i].stringof == typeof(this.tupleof[i]).stringof)
|
||||
static assert(0, "DMD bug 2881 detected - can't use enums with ProcessAllData");
|
||||
else
|
||||
static if (is (typeof(this) == class))
|
||||
mixin(addAutoField(this.tupleof[i].stringof[5..$])); // remove "this."
|
||||
else
|
||||
mixin(addAutoField(this.tupleof[i].stringof[8..$])); // remove "(*this)."
|
||||
}
|
||||
mixin(addAutoField(this.tupleof[i].stringof[5..$])); // remove "this."
|
||||
mixin(epilog);
|
||||
}
|
||||
}
|
||||
@@ -103,29 +100,27 @@ template ProcessAllData()
|
||||
/// For data handlers that only need to look at the raw data (currently only HashDataHandler)
|
||||
template RawDataHandlerWrapper()
|
||||
{
|
||||
static string process(T, string name, bool reverseSort)()
|
||||
template getMixin(T, string name, bool reverseSort)
|
||||
{
|
||||
return processRecursive!(T, "this." ~ name, "");
|
||||
enum getMixin = getMixinRecursive!(T, "this." ~ name, "");
|
||||
}
|
||||
|
||||
static string processRecursive(T, string name, string loopDepth)()
|
||||
template getMixinRecursive(T, string name, string loopDepth)
|
||||
{
|
||||
static if (!hasAliasing!(T))
|
||||
return processRaw("&" ~ name, name ~ ".sizeof");
|
||||
else
|
||||
static if (is(T U : U[]))
|
||||
{
|
||||
string s = "{ bool _AutoDataNullTest = " ~ name ~ " is null; " ~ processRaw("&_AutoDataNullTest", "bool.sizeof") ~ "}";
|
||||
static if (!hasAliasing!(U))
|
||||
s ~= processRaw(name ~ ".ptr", name ~ ".length");
|
||||
else
|
||||
s ~= "foreach (ref _AutoDataArrayItem" ~ loopDepth ~ "; " ~ name ~ ") {" ~ processRecursive!(U, "_AutoDataArrayItem" ~ loopDepth, loopDepth~"Item")() ~ "}";
|
||||
return s;
|
||||
}
|
||||
enum getMixinRecursive =
|
||||
"{ bool _AutoDataNullTest = " ~ name ~ " is null; " ~ getRawMixin!("&_AutoDataNullTest", "bool.sizeof") ~ "}" ~
|
||||
(!hasAliasing!(U) ?
|
||||
getRawMixin!(name ~ ".ptr", name ~ ".length")
|
||||
:
|
||||
"foreach (ref _AutoDataArrayItem" ~ loopDepth ~ "; " ~ name ~ ") {" ~ getMixinRecursive!(U, "_AutoDataArrayItem" ~ loopDepth, loopDepth~"Item") ~ "}"
|
||||
);
|
||||
else
|
||||
static if (!hasAliasing!(T))
|
||||
enum getMixinRecursive = getRawMixin!("&" ~ name, name ~ ".sizeof");
|
||||
else
|
||||
static if (is(typeof((new T).toHash())))
|
||||
//static assert(0, "aoeu: " ~ T.stringof);
|
||||
return name ~ ".processData!(void, ``, ``)(handler);";
|
||||
enum getMixinRecursive = name ~ ".processData!(void, ``, ``)(handler);";
|
||||
else
|
||||
static assert(0, "Don't know how to process type: " ~ T.stringof);
|
||||
}
|
||||
@@ -137,9 +132,9 @@ struct HashDataHandler
|
||||
|
||||
MurmurHash2A hasher;
|
||||
|
||||
static string processRaw(string ptr, string len)
|
||||
template getRawMixin(string ptr, string len)
|
||||
{
|
||||
return "handler.hasher.Add(" ~ ptr ~ ", " ~ len ~ ");";
|
||||
enum getRawMixin = "handler.hasher.Add(" ~ ptr ~ ", " ~ len ~ ");";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,13 +142,17 @@ struct EqualsDataHandler(O)
|
||||
{
|
||||
O other;
|
||||
|
||||
static string process(T, string name, bool reverseSort)()
|
||||
template nullCheck(T, string name)
|
||||
{
|
||||
string s;
|
||||
static if (is(T U : U[]))
|
||||
s ~= " if ((this." ~ name ~ " is null) != (_AutoDataOther." ~ name ~ " is null)) return false;";
|
||||
s ~= "if (this." ~ name ~ " != _AutoDataOther." ~ name ~ ") return false;";
|
||||
return s;
|
||||
enum nullCheck = "if ((this." ~ name ~ " is null) != (_AutoDataOther." ~ name ~ " is null)) return false;";
|
||||
else
|
||||
enum nullCheck = "";
|
||||
}
|
||||
|
||||
template getMixin(T, string name, bool reverseSort)
|
||||
{
|
||||
enum getMixin = nullCheck!(T, name) ~ "if (this." ~ name ~ " != _AutoDataOther." ~ name ~ ") return false;";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,32 +160,38 @@ struct CmpDataHandler(O)
|
||||
{
|
||||
O other;
|
||||
|
||||
static string process(T, string name, bool reverseSort)()
|
||||
template getMixin(T, string name, bool reverseSort)
|
||||
{
|
||||
string reverseStr = reverseSort ? "-" : "";
|
||||
string s;
|
||||
enum getMixin = getMixinComposite!(T, name, reverseSort).code;
|
||||
}
|
||||
|
||||
template getMixinComposite(T, string name, bool reverseSort)
|
||||
{
|
||||
enum reverseStr = reverseSort ? "-" : "";
|
||||
static if (is(T U : U[]))
|
||||
s ~= "{ int _AutoDataCmp = cast(int)(this." ~ name ~ " !is null) - cast(int)(_AutoDataOther." ~ name ~ " !is null); if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }";
|
||||
enum arrCode = "{ int _AutoDataCmp = cast(int)(this." ~ name ~ " !is null) - cast(int)(_AutoDataOther." ~ name ~ " !is null); if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }";
|
||||
else
|
||||
enum arrCode = "";
|
||||
|
||||
static if (is(T == string) && is(std.string.cmp))
|
||||
s ~= "{ int _AutoDataCmp = std.string.cmp(this." ~ name ~ ", _AutoDataOther." ~ name ~ "); if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }";
|
||||
enum dataCode = "{ int _AutoDataCmp = std.string.cmp(this." ~ name ~ ", _AutoDataOther." ~ name ~ "); if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }";
|
||||
else
|
||||
static if (is(T == int))
|
||||
s ~= "{ int _AutoDataCmp = this." ~ name ~ " - _AutoDataOther." ~ name ~ "; if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }"; // TODO: use long?
|
||||
enum dataCode = "{ int _AutoDataCmp = this." ~ name ~ " - _AutoDataOther." ~ name ~ "; if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }"; // TODO: use long?
|
||||
else
|
||||
static if (is(typeof(T.opCmp)))
|
||||
s ~= "{ int _AutoDataCmp = this." ~ name ~ ".opCmp(_AutoDataOther." ~ name ~ "); if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }";
|
||||
enum dataCode = "{ int _AutoDataCmp = this." ~ name ~ ".opCmp(_AutoDataOther." ~ name ~ "); if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }";
|
||||
else
|
||||
s ~= "if (this." ~ name ~ " < _AutoDataOther." ~ name ~ ") return " ~ reverseStr ~ "(-1);" ~
|
||||
"if (this." ~ name ~ " > _AutoDataOther." ~ name ~ ") return " ~ reverseStr ~ "( 1);";
|
||||
return s;
|
||||
enum dataCode = "if (this." ~ name ~ " < _AutoDataOther." ~ name ~ ") return " ~ reverseStr ~ "(-1);" ~
|
||||
"if (this." ~ name ~ " > _AutoDataOther." ~ name ~ ") return " ~ reverseStr ~ "( 1);";
|
||||
enum code = arrCode ~ dataCode;
|
||||
}
|
||||
}
|
||||
|
||||
struct ToStringDataHandler
|
||||
{
|
||||
static string process(T, string name, bool reverseSort)()
|
||||
template getMixin(T, string name, bool reverseSort)
|
||||
{
|
||||
return "_AutoDataResult ~= format(`%s = %s `, `" ~ name ~ "`, this." ~ name ~ ");";
|
||||
enum getMixin = "_AutoDataResult ~= format(`%s = %s `, `" ~ name ~ "`, this." ~ name ~ ");";
|
||||
}
|
||||
}
|
||||
|
||||
+25
-22
@@ -20,12 +20,14 @@ module disassembler;
|
||||
|
||||
import std.file;
|
||||
import std.string;
|
||||
import std.conv;
|
||||
import std.exception;
|
||||
import abcfile;
|
||||
import asprogram;
|
||||
|
||||
final class StringBuilder
|
||||
{
|
||||
string buf;
|
||||
char[] buf;
|
||||
size_t pos;
|
||||
string filename;
|
||||
|
||||
@@ -108,7 +110,7 @@ final class RefBuilder : ASTraitsVisitor
|
||||
override void run()
|
||||
{
|
||||
foreach (i, ref v; as.scripts)
|
||||
addMethod(v.sinit, "script" ~ .toString(i) ~ "_sinit");
|
||||
addMethod(v.sinit, "script" ~ to!string(i) ~ "_sinit");
|
||||
foreach (vclass; as.orphanClasses)
|
||||
addClass(vclass, "orphan");
|
||||
foreach (method; as.orphanMethods)
|
||||
@@ -157,7 +159,7 @@ final class RefBuilder : ASTraitsVisitor
|
||||
int n = 0;
|
||||
uint* pindex;
|
||||
while ((pindex = name in privateNamespaceByName) !is null && *pindex != index)
|
||||
name = bname ~ .toString(++n);
|
||||
name = bname ~ to!string(++n);
|
||||
}
|
||||
auto pname = index in privateNamespaceNames;
|
||||
if (pname)
|
||||
@@ -242,11 +244,11 @@ final class RefBuilder : ASTraitsVisitor
|
||||
strings[i] = qNameToString(m);
|
||||
if (field)
|
||||
strings[$-1] = field;
|
||||
string s = join(strings, "/");
|
||||
char[] s = join(strings, "/").dup;
|
||||
foreach (ref c; s)
|
||||
if (c < 0x20 || c == '"')
|
||||
c = '_';
|
||||
return s;
|
||||
return assumeUnique(s);
|
||||
}
|
||||
|
||||
string addObject(T)(T obj, ref T[string] objByName, string field)
|
||||
@@ -255,7 +257,7 @@ final class RefBuilder : ASTraitsVisitor
|
||||
auto uniqueName = name;
|
||||
int i = 1;
|
||||
while (uniqueName in objByName)
|
||||
uniqueName = name ~ "_" ~ .toString(++i);
|
||||
uniqueName = name ~ "_" ~ to!string(++i);
|
||||
objByName[uniqueName] = obj;
|
||||
objName[cast(void*)obj] = uniqueName;
|
||||
return uniqueName;
|
||||
@@ -300,7 +302,7 @@ final class RefBuilder : ASTraitsVisitor
|
||||
if (pname)
|
||||
return *pname;
|
||||
else
|
||||
//throw new Exception("Nameless private namespace: " ~ .toString(index));
|
||||
//throw new Exception("Nameless private namespace: " ~ to!string(index));
|
||||
return addPrivateNamespace(index, "OrphanPrivateNamespace");
|
||||
}
|
||||
}
|
||||
@@ -335,10 +337,10 @@ final class Disassembler
|
||||
sb.indent++; sb.newLine();
|
||||
|
||||
sb ~= "minorversion ";
|
||||
sb ~= .toString(as.minorVersion);
|
||||
sb ~= to!string(as.minorVersion);
|
||||
sb.newLine();
|
||||
sb ~= "majorversion ";
|
||||
sb ~= .toString(as.majorVersion);
|
||||
sb ~= to!string(as.majorVersion);
|
||||
sb.newLine();
|
||||
sb.newLine();
|
||||
|
||||
@@ -388,7 +390,7 @@ final class Disassembler
|
||||
uint[] indices = refs.privateNamespaceNames.keys.sort;
|
||||
foreach (index; indices)
|
||||
{
|
||||
sb ~= "#privatens " ~ .toString(index) ~ " ";
|
||||
sb ~= "#privatens " ~ to!string(index) ~ " ";
|
||||
dumpString(sb, refs.privateNamespaceNames[index]);
|
||||
sb.newLine();
|
||||
}
|
||||
@@ -400,7 +402,7 @@ final class Disassembler
|
||||
if (v == ABCFile.NULL_INT)
|
||||
sb ~= "null";
|
||||
else
|
||||
sb ~= .toString(v);
|
||||
sb ~= to!string(v);
|
||||
}
|
||||
|
||||
void dumpUInt(StringBuilder sb, ulong v)
|
||||
@@ -408,7 +410,7 @@ final class Disassembler
|
||||
if (v == ABCFile.NULL_UINT)
|
||||
sb ~= "null";
|
||||
else
|
||||
sb ~= .toString(v);
|
||||
sb ~= to!string(v);
|
||||
}
|
||||
|
||||
void dumpDouble(StringBuilder sb, double v)
|
||||
@@ -642,7 +644,7 @@ final class Disassembler
|
||||
sb.indent--; sb ~= "end ; metadata"; sb.newLine();
|
||||
}
|
||||
|
||||
void dumpFlags(bool oneLine = false)(StringBuilder sb, ubyte flags, string[] names)
|
||||
void dumpFlags(bool oneLine = false)(StringBuilder sb, ubyte flags, const string[] names)
|
||||
{
|
||||
for (int i=0; flags; i++, flags>>=1)
|
||||
if (flags & 1)
|
||||
@@ -747,13 +749,14 @@ final class Disassembler
|
||||
|
||||
string toFileName(string refid)
|
||||
{
|
||||
string filename = refid.dup;
|
||||
foreach (ref c; filename)
|
||||
char[] buf = refid.dup;
|
||||
foreach (ref c; buf)
|
||||
if (c == '.' || c == ':')
|
||||
c = '/';
|
||||
else
|
||||
if (c == '\\' || c == '*' || c == '?' || c == '"' || c == '<' || c == '>' || c == '|')
|
||||
c = '_';
|
||||
string filename = assumeUnique(buf);
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
@@ -835,7 +838,7 @@ final class Disassembler
|
||||
void dumpScript(StringBuilder sb, ASProgram.Script script, uint index)
|
||||
{
|
||||
sb ~= "script ; ";
|
||||
sb ~= .toString(index);
|
||||
sb ~= to!string(index);
|
||||
sb.indent++; sb.newLine();
|
||||
sb ~= "sinit"; dumpMethod(sb, script.sinit);
|
||||
dumpTraits(sb, script.traits);
|
||||
@@ -853,12 +856,12 @@ final class Disassembler
|
||||
void dumpLabel(StringBuilder sb, ref ABCFile.Label label)
|
||||
{
|
||||
sb ~= 'L';
|
||||
sb ~= .toString(label.index);
|
||||
sb ~= to!string(label.index);
|
||||
if (label.offset != 0)
|
||||
{
|
||||
if (label.offset > 0)
|
||||
sb ~= '+';
|
||||
sb ~= .toString(label.offset);
|
||||
sb ~= to!string(label.offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -925,7 +928,7 @@ final class Disassembler
|
||||
{
|
||||
sb.noIndent();
|
||||
sb ~= 'L';
|
||||
sb ~= .toString(ii);
|
||||
sb ~= to!string(ii);
|
||||
sb ~= ':';
|
||||
sb.newLine();
|
||||
}
|
||||
@@ -953,13 +956,13 @@ final class Disassembler
|
||||
throw new Exception("Don't know how to disassemble OP_" ~ opcodeInfo[instruction.opcode].name);
|
||||
|
||||
case OpcodeArgumentType.UByteLiteral:
|
||||
sb ~= .toString(instruction.arguments[i].ubytev);
|
||||
sb ~= to!string(instruction.arguments[i].ubytev);
|
||||
break;
|
||||
case OpcodeArgumentType.IntLiteral:
|
||||
sb ~= .toString(instruction.arguments[i].intv);
|
||||
sb ~= to!string(instruction.arguments[i].intv);
|
||||
break;
|
||||
case OpcodeArgumentType.UIntLiteral:
|
||||
sb ~= .toString(instruction.arguments[i].uintv);
|
||||
sb ~= to!string(instruction.arguments[i].uintv);
|
||||
break;
|
||||
|
||||
case OpcodeArgumentType.Int:
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public:
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void Add ( void * vdata, int len )
|
||||
void Add ( const(void) * vdata, int len )
|
||||
{
|
||||
ubyte * data = cast(ubyte*)vdata;
|
||||
m_size += len;
|
||||
|
||||
Reference in New Issue
Block a user