From 3bb5b23c4a51c58c1d7700b09e76bc717fef7364 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Mon, 7 May 2018 20:27:37 +0000 Subject: [PATCH] [llvm-rc] Implement the BITMAP resource type Differential Revision: https://reviews.llvm.org/D46509 llvm-svn: 331670 --- test/tools/llvm-rc/include-paths.test | 17 ++++++++-------- tools/llvm-rc/ResourceFileWriter.cpp | 27 ++++++++++++++++++++++++++ tools/llvm-rc/ResourceFileWriter.h | 4 ++++ tools/llvm-rc/ResourceScriptParser.cpp | 7 +++++++ tools/llvm-rc/ResourceScriptParser.h | 1 + tools/llvm-rc/ResourceScriptStmt.cpp | 4 ++++ tools/llvm-rc/ResourceScriptStmt.h | 24 +++++++++++++++++++++++ tools/llvm-rc/ResourceVisitor.h | 1 + 8 files changed, 76 insertions(+), 9 deletions(-) diff --git a/test/tools/llvm-rc/include-paths.test b/test/tools/llvm-rc/include-paths.test index 7313ffac295..f24cc449504 100644 --- a/test/tools/llvm-rc/include-paths.test +++ b/test/tools/llvm-rc/include-paths.test @@ -22,7 +22,7 @@ ; RUN: llvm-rc /FO %t.nested-include.res %p/Inputs/include.rc ; RUN: llvm-readobj %t.nested-include.res | FileCheck --check-prefix=FOUND %s -FOUND: Resource type (string): BITMAP +FOUND: Resource type (int): 2 FOUND-NEXT: Resource name (string): FOO FOUND-NEXT: Data version: 0 FOUND-NEXT: Memory flags: 0x30 @@ -30,15 +30,14 @@ FOUND-NEXT: Language ID: 1033 FOUND-NEXT: Version (major): 0 FOUND-NEXT: Version (minor): 0 FOUND-NEXT: Characteristics: 0 -FOUND-NEXT: Data size: 110 +FOUND-NEXT: Data size: 96 FOUND-NEXT: Data: ( -FOUND-NEXT: 0000: 424D6E00 00000000 00003600 00002800 |BMn.......6...(.| -FOUND-NEXT: 0010: 00000200 00000700 00000100 18000000 |................| -FOUND-NEXT: 0020: 00003800 00000000 00000000 00000000 |..8.............| -FOUND-NEXT: 0030: 00000000 00005BB3 855BB385 0000FFFF |......[..[......| -FOUND-NEXT: 0040: FFFFFFFF 0000FFFF FFFFFFFF 0000FFFF |................| -FOUND-NEXT: 0050: FFFFFFFF 00005BB3 85FFFFFF 0000FFFF |......[.........| -FOUND-NEXT: 0060: FF0EC9FF 0000241C EDFFFFFF 0000 |......$.......| +FOUND-NEXT: 0000: 28000000 02000000 07000000 01001800 |(...............| +FOUND-NEXT: 0010: 00000000 38000000 00000000 00000000 |....8...........| +FOUND-NEXT: 0020: 00000000 00000000 5BB3855B B3850000 |........[..[....| +FOUND-NEXT: 0030: FFFFFFFF FFFF0000 FFFFFFFF FFFF0000 |................| +FOUND-NEXT: 0040: FFFFFFFF FFFF0000 5BB385FF FFFF0000 |........[.......| +FOUND-NEXT: 0050: FFFFFF0E C9FF0000 241CEDFF FFFF0000 |........$.......| FOUND-NEXT: ) MISSING: llvm-rc: Error in BITMAP statement (ID foo): diff --git a/tools/llvm-rc/ResourceFileWriter.cpp b/tools/llvm-rc/ResourceFileWriter.cpp index 93471db200e..54f6c0ede73 100644 --- a/tools/llvm-rc/ResourceFileWriter.cpp +++ b/tools/llvm-rc/ResourceFileWriter.cpp @@ -437,6 +437,10 @@ Error ResourceFileWriter::visitAcceleratorsResource(const RCResource *Res) { return writeResource(Res, &ResourceFileWriter::writeAcceleratorsBody); } +Error ResourceFileWriter::visitBitmapResource(const RCResource *Res) { + return writeResource(Res, &ResourceFileWriter::writeBitmapBody); +} + Error ResourceFileWriter::visitCursorResource(const RCResource *Res) { return handleError(visitIconOrCursorResource(Res), Res); } @@ -684,6 +688,29 @@ Error ResourceFileWriter::writeAcceleratorsBody(const RCResource *Base) { return Error::success(); } +// --- BitmapResource helpers. --- // + +Error ResourceFileWriter::writeBitmapBody(const RCResource *Base) { + StringRef Filename = cast(Base)->BitmapLoc; + bool IsLong; + stripQuotes(Filename, IsLong); + + auto File = loadFile(Filename); + if (!File) + return File.takeError(); + + StringRef Buffer = (*File)->getBuffer(); + + // Skip the 14 byte BITMAPFILEHEADER. + constexpr size_t BITMAPFILEHEADER_size = 14; + if (Buffer.size() < BITMAPFILEHEADER_size || Buffer[0] != 'B' || + Buffer[1] != 'M') + return createError("Incorrect bitmap file."); + + *FS << Buffer.substr(BITMAPFILEHEADER_size); + return Error::success(); +} + // --- CursorResource and IconResource helpers. --- // // ICONRESDIR structure. Describes a single icon in resouce group. diff --git a/tools/llvm-rc/ResourceFileWriter.h b/tools/llvm-rc/ResourceFileWriter.h index aef3bfa3c71..6048bf47600 100644 --- a/tools/llvm-rc/ResourceFileWriter.h +++ b/tools/llvm-rc/ResourceFileWriter.h @@ -122,6 +122,10 @@ private: bool IsLastItem); Error writeAcceleratorsBody(const RCResource *); + // BitmapResource + Error visitBitmapResource(const RCResource *); + Error writeBitmapBody(const RCResource *); + // CursorResource and IconResource Error visitIconOrCursorResource(const RCResource *); Error visitIconOrCursorGroup(const RCResource *); diff --git a/tools/llvm-rc/ResourceScriptParser.cpp b/tools/llvm-rc/ResourceScriptParser.cpp index d8398b78514..ffa18bdf198 100644 --- a/tools/llvm-rc/ResourceScriptParser.cpp +++ b/tools/llvm-rc/ResourceScriptParser.cpp @@ -66,6 +66,8 @@ RCParser::ParseType RCParser::parseSingleResource() { if (TypeToken->equalsLower("ACCELERATORS")) Result = parseAcceleratorsResource(); + else if (TypeToken->equalsLower("BITMAP")) + Result = parseBitmapResource(); else if (TypeToken->equalsLower("CURSOR")) Result = parseCursorResource(); else if (TypeToken->equalsLower("DIALOG")) @@ -484,6 +486,11 @@ Expected RCParser::parseControl() { TakeOptArg(7)); } +RCParser::ParseType RCParser::parseBitmapResource() { + ASSIGN_OR_RETURN(Arg, readString()); + return llvm::make_unique(*Arg); +} + RCParser::ParseType RCParser::parseIconResource() { ASSIGN_OR_RETURN(Arg, readString()); return llvm::make_unique(*Arg); diff --git a/tools/llvm-rc/ResourceScriptParser.h b/tools/llvm-rc/ResourceScriptParser.h index 84fdfd5a586..e22619a5834 100644 --- a/tools/llvm-rc/ResourceScriptParser.h +++ b/tools/llvm-rc/ResourceScriptParser.h @@ -138,6 +138,7 @@ private: // Top-level resource parsers. ParseType parseLanguageResource(); ParseType parseAcceleratorsResource(); + ParseType parseBitmapResource(); ParseType parseCursorResource(); ParseType parseDialogResource(bool IsExtended); ParseType parseIconResource(); diff --git a/tools/llvm-rc/ResourceScriptStmt.cpp b/tools/llvm-rc/ResourceScriptStmt.cpp index 42505cc76d0..03742b5b350 100644 --- a/tools/llvm-rc/ResourceScriptStmt.cpp +++ b/tools/llvm-rc/ResourceScriptStmt.cpp @@ -57,6 +57,10 @@ raw_ostream &AcceleratorsResource::log(raw_ostream &OS) const { return OS; } +raw_ostream &BitmapResource::log(raw_ostream &OS) const { + return OS << "Bitmap (" << ResName << "): " << BitmapLoc << "\n"; +} + raw_ostream &CursorResource::log(raw_ostream &OS) const { return OS << "Cursor (" << ResName << "): " << CursorLoc << "\n"; } diff --git a/tools/llvm-rc/ResourceScriptStmt.h b/tools/llvm-rc/ResourceScriptStmt.h index e44120b770f..485b7cab1d2 100644 --- a/tools/llvm-rc/ResourceScriptStmt.h +++ b/tools/llvm-rc/ResourceScriptStmt.h @@ -121,6 +121,7 @@ enum ResourceKind { // kind is equal to this type ID. RkNull = 0, RkSingleCursor = 1, + RkBitmap = 2, RkSingleIcon = 3, RkMenu = 4, RkDialog = 5, @@ -305,6 +306,29 @@ public: } }; +// BITMAP resource. Represents a bitmap (".bmp") file. +// +// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380680(v=vs.85).aspx +class BitmapResource : public RCResource { +public: + StringRef BitmapLoc; + + BitmapResource(StringRef Location) : BitmapLoc(Location) {} + raw_ostream &log(raw_ostream &) const override; + + IntOrString getResourceType() const override { return RkBitmap; } + uint16_t getMemoryFlags() const override { return MfPure | MfMoveable; } + + Twine getResourceTypeName() const override { return "BITMAP"; } + Error visit(Visitor *V) const override { + return V->visitBitmapResource(this); + } + ResourceKind getKind() const override { return RkBitmap; } + static bool classof(const RCResource *Res) { + return Res->getKind() == RkBitmap; + } +}; + // CURSOR resource. Represents a single cursor (".cur") file. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx diff --git a/tools/llvm-rc/ResourceVisitor.h b/tools/llvm-rc/ResourceVisitor.h index 530b4a8add2..373b3cb7e6f 100644 --- a/tools/llvm-rc/ResourceVisitor.h +++ b/tools/llvm-rc/ResourceVisitor.h @@ -32,6 +32,7 @@ class Visitor { public: virtual Error visitNullResource(const RCResource *) = 0; virtual Error visitAcceleratorsResource(const RCResource *) = 0; + virtual Error visitBitmapResource(const RCResource *) = 0; virtual Error visitCursorResource(const RCResource *) = 0; virtual Error visitDialogResource(const RCResource *) = 0; virtual Error visitHTMLResource(const RCResource *) = 0;