diff --git a/ResourceFiles/ResourceFork.cc b/ResourceFiles/ResourceFork.cc index fc2d70d0fe..7d9ab80f1f 100644 --- a/ResourceFiles/ResourceFork.cc +++ b/ResourceFiles/ResourceFork.cc @@ -27,7 +27,9 @@ void Resources::writeFork(std::ostream& out) const { const Resource& r = rr.second; const std::string& data = r.getData(); - resourceInfos[ r.getType() ][ r.getID() ] = out.tellp() - datastart; + unsigned offset = out.tellp() - datastart; + offset = (r.getAttr() << 24) | (offset & 0xFFFFFF); + resourceInfos[ r.getType() ][ r.getID() ] = (int)offset; longword(out, data.size()); out << data; } diff --git a/ResourceFiles/ResourceFork.h b/ResourceFiles/ResourceFork.h index 0c8bfaf165..0caebd1891 100644 --- a/ResourceFiles/ResourceFork.h +++ b/ResourceFiles/ResourceFork.h @@ -22,6 +22,7 @@ public: inline int getID() const { return id; } inline ResRef getTypeAndID() const { return ResRef(type, id); } std::string getName() const { return name; } + int getAttr() const { return attr; } }; class Fork diff --git a/Rez/ResSpec.h b/Rez/ResSpec.h index 2aa648a061..305817da0a 100644 --- a/Rez/ResSpec.h +++ b/Rez/ResSpec.h @@ -10,7 +10,7 @@ class ResSpec : public ResRef std::string name_; public: - ResSpec() {} + ResSpec() : attr_(0) {} ResSpec(ResType type, int id, int attr = 0, std::string name = "") : ResRef(type, id), attr_(attr), name_(name) {} diff --git a/Rez/RezParser.yy b/Rez/RezParser.yy index 4cd8432456..2ac08cd66d 100644 --- a/Rez/RezParser.yy +++ b/Rez/RezParser.yy @@ -125,6 +125,7 @@ #include "RezLexer.h" #include "RezWorld.h" #include "ResourceCompiler.h" + #include "Diagnostic.h" static yy::RezParser::symbol_type yylex(RezLexer& lexer, RezWorld&) { @@ -133,7 +134,7 @@ void yy::RezParser::error(const location_type& loc, std::string const& err) { - std::cerr << loc << ": " << err << std::endl; + world.problem(Diagnostic(Diagnostic::error, err, loc)); } static std::string fromHex(std::string hex) @@ -431,17 +432,56 @@ resource : "resource" res_spec "{" resource_body "}" ; %type res_spec; +%type resource_attributes; res_spec : res_type "(" expression resource_attributes ")" - { $$ = $resource_attributes( ResSpec($res_type, $expression->evaluateInt(nullptr)) ); } - -%type > resource_attributes ; -resource_attributes : %empty { $$ = [](ResSpec s){ return s; }; } - | resource_attributes "," IDENTIFIER { $$ = $1; } - | resource_attributes "," string_expression { $$ = $1; } + { + $$ = $resource_attributes; + $$.type() = $res_type; + $$.id() = $expression->evaluateInt(nullptr); + } + ; +resource_attributes : %empty { $$ = ResSpec(); } + | resource_attributes "," IDENTIFIER + { + $$ = $1; + if($IDENTIFIER == "changed") + $$.attr() |= 2; + else if($IDENTIFIER == "preload") + $$.attr() |= 4; + else if($IDENTIFIER == "protected") + $$.attr() |= 8; + else if($IDENTIFIER == "locked") + $$.attr() |= 16; + else if($IDENTIFIER == "purgeable") + $$.attr() |= 32; + else if($IDENTIFIER == "sysheap") + $$.attr() |= 64; + else if($IDENTIFIER == "unchanged") + $$.attr() &= ~2; + else if($IDENTIFIER == "nonpreload") + $$.attr() &= ~4; + else if($IDENTIFIER == "unprotected") + $$.attr() &= ~8; + else if($IDENTIFIER == "unlocked") + $$.attr() &= ~16; + else if($IDENTIFIER == "nonpurgeable") + $$.attr() &= ~32; + else if($IDENTIFIER == "appheap") + $$.attr() &= ~64; + else + world.problem(Diagnostic(Diagnostic::error, "illegal attribute " + $IDENTIFIER, @1)); + } + | resource_attributes "," string_expression + { + $$ = $1; + $$.name() = $3->evaluateString(nullptr); + } ; + + %type resource_body resource_body1; resource_body : %empty { $$ = std::make_shared(yy::location()); } | resource_body1 { $$ = $1; $$->location = @1; }