From c93cb8feaecb274aab9a4e176aa108f20bc8b1a5 Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Tue, 14 Oct 2014 00:11:21 +0200 Subject: [PATCH] implement $$byte, $$word, $$long, $$bitfield --- Rez/Expression.cc | 23 +++++++++++++++++++++++ Rez/Expression.h | 10 ++++++++++ Rez/ResourceCompiler.cc | 36 +++++++++++++++++++++++++++++++++++- Rez/ResourceCompiler.h | 8 +++++++- Rez/ResourceDefinitions.cc | 7 ++----- Rez/RezParser.yy | 8 ++++---- 6 files changed, 81 insertions(+), 11 deletions(-) diff --git a/Rez/Expression.cc b/Rez/Expression.cc index 02aa7a4f21..6994541c39 100644 --- a/Rez/Expression.cc +++ b/Rez/Expression.cc @@ -136,6 +136,8 @@ ExprPtr IdentifierExpr::lookup(ResourceCompiler *ctx) int IdentifierExpr::evaluateInt(ResourceCompiler *ctx) { + if(ctx->isPrePass()) + return 0; return lookup(ctx)->evaluateInt(ctx); } @@ -186,3 +188,24 @@ std::string UnimplementedExpr::evaluateString(ResourceCompiler *ctx) std::cerr << msg << std::endl; return ""; } + + +PeekExpr::PeekExpr(ExprPtr addr, ExprPtr offset, ExprPtr size) + : addr(addr), offset(offset), size(size) +{ +} + +PeekExpr::PeekExpr(ExprPtr addr, int size) + : addr(addr), + offset(std::make_shared(0)), + size(std::make_shared(size)) +{ +} + +int PeekExpr::evaluateInt(ResourceCompiler *ctx) +{ + int p = addr->evaluateInt(ctx) + offset->evaluateInt(ctx); + int s = size->evaluateInt(ctx); + + return ctx->peek(p, s); +} diff --git a/Rez/Expression.h b/Rez/Expression.h index 2e950c26b9..0300ec6aec 100644 --- a/Rez/Expression.h +++ b/Rez/Expression.h @@ -148,5 +148,15 @@ public: virtual std::string evaluateString(ResourceCompiler *ctx); }; +class PeekExpr : public Expression +{ + ExprPtr addr; + ExprPtr offset; + ExprPtr size; +public: + PeekExpr(ExprPtr addr, ExprPtr offset, ExprPtr size); + PeekExpr(ExprPtr addr, int size); + virtual int evaluateInt(ResourceCompiler *ctx); +}; #endif // EXPRESSION_H diff --git a/Rez/ResourceCompiler.cc b/Rez/ResourceCompiler.cc index b22419b727..ebc86a8e92 100644 --- a/Rez/ResourceCompiler.cc +++ b/Rez/ResourceCompiler.cc @@ -41,6 +41,37 @@ void ResourceCompiler::write(int nBits, int value) //currentOffset += nBits; } +int ResourceCompiler::peek(int bitPos, int size) +{ + int bytePos = bitPos / 8; + int endBytePos = (bitPos + size - 1) / 8 + 1; + + unsigned bitPosInByte = bitPos % 8; + unsigned outPos = 32 - size; + + unsigned val = 0; + + for(int i = bytePos; i != endBytePos; ++i) + { + unsigned byte; + if(i < data.size()) + byte = data[i]; + else if(i < prePassData.size()) + byte = prePassData[i]; + else + byte = 0; + + unsigned read = byte << (bitPosInByte + 24); + val |= (read >> outPos); + + outPos += 8 - bitPosInByte; + + bitPosInByte = 0; + } + + return val; +} + ExprPtr ResourceCompiler::lookupIdentifier(std::string name, const Subscripts &sub) { if(currentField) @@ -70,10 +101,13 @@ void ResourceCompiler::compile() if(verboseFlag) std::cout << "(first pass)\n"; currentOffset = 0; data.clear(); + prePass = true; typeDefinition->compile(body, this, true); if(verboseFlag) std::cout << "(second pass)\n"; currentOffset = 0; - data.clear(); + prePassData = std::move(data); + data.clear(); // ### + prePass = false; typeDefinition->compile(body, this, false); if(verboseFlag) std::cout << "(done)\n"; diff --git a/Rez/ResourceCompiler.h b/Rez/ResourceCompiler.h index 2ae56d4c58..056f55da91 100644 --- a/Rez/ResourceCompiler.h +++ b/Rez/ResourceCompiler.h @@ -31,10 +31,12 @@ class ResourceCompiler Field* currentField; Subscripts currentSubscripts; - std::vector data; + std::vector data, prePassData; bool verboseFlag; void beginArrayScope(std::string& arrayName, int index); + + bool prePass; public: ResourceCompiler(TypeDefinitionPtr type, CompoundExprPtr body, bool verboseFlag); @@ -44,6 +46,8 @@ public: void write(int nBits, int value); int tell() { return currentOffset; } + int peek(int bitPos, int size); + ExprPtr lookupIdentifier(std::string name, const Subscripts& sub = Subscripts()); void defineLabel(const std::string& name); @@ -52,6 +56,8 @@ public: int getArrayCount(const std::string& arrayName); int getArrayIndex(const std::string& arrayName); + bool isPrePass() { return prePass; } + class FieldScope { ResourceCompiler *compiler; diff --git a/Rez/ResourceDefinitions.cc b/Rez/ResourceDefinitions.cc index 08c8ce44d8..6d55f9ad0b 100644 --- a/Rez/ResourceDefinitions.cc +++ b/Rez/ResourceDefinitions.cc @@ -169,11 +169,8 @@ void SimpleField::compileInt(ExprPtr expr, ResourceCompiler *compiler, bool preP } int actualValue = 0; - if(!prePass) - { - ResourceCompiler::FieldScope scope(compiler, this); - actualValue = (value ? value : expr)->evaluateInt(compiler); - } + ResourceCompiler::FieldScope scope(compiler, this); + actualValue = (value ? value : expr)->evaluateInt(compiler); compiler->write(bitSize, actualValue); } diff --git a/Rez/RezParser.yy b/Rez/RezParser.yy index 2384fa6ef6..ff4d421476 100644 --- a/Rez/RezParser.yy +++ b/Rez/RezParser.yy @@ -371,13 +371,13 @@ expression8 : INTLIT { $$ = std::make_shared($1); } | "$$arrayindex" "(" identifier_expression ")" { $$ = std::make_shared($identifier_expression); } | "$$bitfield" "(" expression "," expression "," expression ")" - { $$ = std::make_shared("$$bitfield"); } + { $$ = std::make_shared($3, $5, $7); } | "$$word" "(" expression ")" - { $$ = std::make_shared("$$word"); } + { $$ = std::make_shared($3, 16); } | "$$byte" "(" expression ")" - { $$ = std::make_shared("$$byte"); } + { $$ = std::make_shared($3, 8); } | "$$long" "(" expression ")" - { $$ = std::make_shared("$$long"); } + { $$ = std::make_shared($3, 32); } ; %type identifier_expression;