Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cecff913f1 | ||
|
|
7a4c78dac3 | ||
|
|
ee47075fda | ||
|
|
100f6b6bf4 |
+2
-1
@@ -1,9 +1,10 @@
|
||||
RABCDAsm Changelog
|
||||
==================
|
||||
|
||||
RABCDAsm v1.4 (2011.02.xx)
|
||||
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,15 +48,13 @@ 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
|
||||
@@ -64,11 +62,9 @@ as straight-forward as:
|
||||
dmd swfdecompress swffile zlibx
|
||||
dmd 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
|
||||
@@ -992,8 +993,8 @@ 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): %s", pos, pos, e), e);
|
||||
}
|
||||
|
||||
ubyte readU8()
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
+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)
|
||||
|
||||
+15
-19
@@ -41,16 +41,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 +80,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 +235,7 @@ final class ASProgram
|
||||
|
||||
Instance instance;
|
||||
|
||||
string toString()
|
||||
override string toString()
|
||||
{
|
||||
return instance.name.toString();
|
||||
}
|
||||
@@ -735,6 +726,8 @@ private final class AStoABC
|
||||
/// 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 +736,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 +745,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 +768,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 +783,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-23
@@ -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];
|
||||
@@ -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;
|
||||
@@ -1075,10 +1076,10 @@ final class Assembler
|
||||
{
|
||||
try
|
||||
instructions[f.ii].arguments[f.ai].jumpTarget = parseLabel(f.name, labels);
|
||||
catch (Object o)
|
||||
catch (Exception e)
|
||||
{
|
||||
setFile(f.where.load);
|
||||
throw o;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1086,10 +1087,10 @@ final class Assembler
|
||||
{
|
||||
try
|
||||
instructions[f.ii].arguments[f.ai].switchTargets[f.si] = parseLabel(f.name, labels);
|
||||
catch (Object o)
|
||||
catch (Exception e)
|
||||
{
|
||||
setFile(f.where.load);
|
||||
throw o;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1109,10 +1110,10 @@ final class Assembler
|
||||
auto word = readWord();
|
||||
try
|
||||
return parseLabel(word, labels);
|
||||
catch (Object o)
|
||||
catch (Exception e)
|
||||
{
|
||||
backpedal(word.length);
|
||||
throw o;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1213,9 +1214,9 @@ final class Assembler
|
||||
*f.ptr = *mp;
|
||||
}
|
||||
}
|
||||
catch (Object o)
|
||||
catch (Exception e)
|
||||
{
|
||||
string s = files[0].positionStr ~ ": " ~ o.toString();
|
||||
string s = files[0].positionStr ~ ": " ~ e.msg;
|
||||
if (fileCount == -1)
|
||||
s ~= "\n\t(inclusion context unavailable)";
|
||||
else
|
||||
|
||||
+82
-77
@@ -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");
|
||||
enum getMixinRecursive = getRawMixin!("&" ~ 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 (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