#104, handle iasm

This commit is contained in:
Basile Burg 2017-01-23 02:20:43 +01:00
parent 76df25458c
commit 7e5de81f80
No known key found for this signature in database
GPG Key ID: 1868039F415CB8CF
1 changed files with 103 additions and 27 deletions

View File

@ -1,9 +1,9 @@
module halstead;
import
std.algorithm.iteration, std.conv, std.json, std.meta;
std.algorithm, std.conv, std.json, std.meta;
import
std.stdio, std.range: iota;
std.stdio, std.ascii, std.digest.crc, std.range: iota;
import
dparse.ast, dparse.lexer, dparse.parser, dparse.rollback_allocator;
import
@ -82,6 +82,16 @@ private final class HalsteadMetric: ASTVisitor
}
}
void addOperandFromToken(const ref Token tk)
{
if (isLiteral(tk.type))
{
alias immutHexStr = toHexString!(Order.increasing, LetterCase.upper);
++operands["literal" ~ immutHexStr(tk.text.crc32Of)];
}
else ++operands[tk.text];
}
void pushExprFlags(bool leftFlag = false, bool rightFlag = false)
{
binExprFlag.length += 1;
@ -107,7 +117,6 @@ private final class HalsteadMetric: ASTVisitor
void serialize()
{
import std.stdio: write;
JSONValue js;
js["functions"] = fs;
js.toString.write;
@ -151,7 +160,6 @@ private final class HalsteadMetric: ASTVisitor
version(unittest)
{
import std.stdio: writeln;
writeln(functions[$-1]);
writeln("\toperators: ",operators);
writeln("\toperands : ",operands);
@ -164,15 +172,7 @@ private final class HalsteadMetric: ASTVisitor
{
ta.accept(this);
if (ta.templateSingleArgument)
{
if (!isLiteral(ta.templateSingleArgument.token.type))
++operands[ta.templateSingleArgument.token.text];
else
{
import std.digest.crc: crc32Of, toHexString;
++operands["literal" ~ ta.templateSingleArgument.token.text.crc32Of.toHexString.idup];
}
}
addOperandFromToken(ta.templateSingleArgument.token);
}
override void visit(const(FunctionCallExpression) expr)
@ -184,7 +184,7 @@ private final class HalsteadMetric: ASTVisitor
if (expr.templateArguments)
{
if (expr.templateArguments.templateSingleArgument)
++operands[expr.templateArguments.templateSingleArgument.token.text];
addOperandFromToken(expr.templateArguments.templateSingleArgument.token);
}
expr.accept(this);
@ -256,11 +256,7 @@ private final class HalsteadMetric: ASTVisitor
++operands[primary.identifierOrTemplateInstance.identifier.text];
}
}
else if (primary.primary.type.isLiteral)
{
import std.digest.crc: crc32Of, toHexString;
++operands["literal" ~ primary.primary.text.crc32Of.toHexString.idup];
}
else addOperandFromToken(primary.primary);
primary.accept(this);
}
@ -296,6 +292,39 @@ private final class HalsteadMetric: ASTVisitor
if (expr.suffix.type)
++operators[str(expr.suffix.type)];
}
override void visit(const(AsmInstruction) ai)
{
if (ai.identifierOrIntegerOrOpcode != tok!"")
{
++operators[ai.identifierOrIntegerOrOpcode.text];
}
ai.accept(this);
}
override void visit(const(Register) reg)
{
if (reg.identifier != tok!"")
{
++operands[reg.identifier.text];
}
if (reg.hasIntegerLiteral)
{
addOperandFromToken(reg.intLiteral);
}
reg.accept(this);
}
override void visit(const(AsmPrimaryExp) ape)
{
if (ape.token != tok!"")
addOperandFromToken(ape.token);
if (ape.identifierChain)
ape.identifierChain.identifiers
.filter!(a => !a.text.among("dword","ptr"))
.each!(a => addOperandFromToken(a));
ape.accept(this);
}
override void visit(const(IndexExpression) expr)
{
@ -358,11 +387,6 @@ private final class HalsteadMetric: ASTVisitor
++operators["else"];
}
override void visit(const(DeclarationOrStatement) st)
{
st.accept(this);
}
override void visit(const(WhileStatement) st)
{
++operators["while"];
@ -1211,7 +1235,6 @@ unittest
unittest
{
//TODO: handle iasm
Function r =
q{
void foo()
@ -1219,7 +1242,60 @@ unittest
asm{xor EAX,ECX;}
}
}.test;
//assert(r.operandsKinds == 2);
//assert(r.operatorsKinds == 1);
assert(r.operandsKinds == 2);
assert(r.operatorsKinds == 1);
}
unittest
{
// needs https://github.com/Hackerpilot/libdparse/pull/124
Function r =
q{
void foo()
{
asm{mov EAX, SS:CL;}
}
}.test;
//assert(r.operandsKinds == 3);
assert(r.operatorsKinds == 1);
}
unittest
{
Function r =
q{
void foo()
{
asm{mov EAX, a.b.c;}
}
}.test;
assert(r.operandsKinds == 4);
assert(r.operatorsKinds == 1);
}
unittest
{
Function r =
q{
void foo()
{
asm{imul EAX, dword [EBP + EBX * 4 + 0x0FFFFFFD4];}
}
}.test;
assert(r.operandsKinds == 5);
assert(r.operatorsKinds == 3);
}
unittest
{
Function r =
q{
void foo()
{
asm{imul EAX, ECX, dword[ESP + 8];}
}
}.test;
assert(r.operandsKinds == 4);
assert(r.operatorsKinds == 2);
}