[llvm-rc] Implement the BITMAP resource type
authorMartin Storsjo <martin@martin.st>
Mon, 7 May 2018 20:27:37 +0000 (20:27 +0000)
committerMartin Storsjo <martin@martin.st>
Mon, 7 May 2018 20:27:37 +0000 (20:27 +0000)
Differential Revision: https://reviews.llvm.org/D46509

llvm-svn: 331670

llvm/test/tools/llvm-rc/include-paths.test
llvm/tools/llvm-rc/ResourceFileWriter.cpp
llvm/tools/llvm-rc/ResourceFileWriter.h
llvm/tools/llvm-rc/ResourceScriptParser.cpp
llvm/tools/llvm-rc/ResourceScriptParser.h
llvm/tools/llvm-rc/ResourceScriptStmt.cpp
llvm/tools/llvm-rc/ResourceScriptStmt.h
llvm/tools/llvm-rc/ResourceVisitor.h

index 7313ffa..f24cc44 100644 (file)
@@ -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):
index 93471db..54f6c0e 100644 (file)
@@ -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<BitmapResource>(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.
index aef3bfa..6048bf4 100644 (file)
@@ -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 *);
index d8398b7..ffa18bd 100644 (file)
@@ -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<Control> RCParser::parseControl() {
                  TakeOptArg(7));
 }
 
+RCParser::ParseType RCParser::parseBitmapResource() {
+  ASSIGN_OR_RETURN(Arg, readString());
+  return llvm::make_unique<BitmapResource>(*Arg);
+}
+
 RCParser::ParseType RCParser::parseIconResource() {
   ASSIGN_OR_RETURN(Arg, readString());
   return llvm::make_unique<IconResource>(*Arg);
index 84fdfd5..e22619a 100644 (file)
@@ -138,6 +138,7 @@ private:
   // Top-level resource parsers.
   ParseType parseLanguageResource();
   ParseType parseAcceleratorsResource();
+  ParseType parseBitmapResource();
   ParseType parseCursorResource();
   ParseType parseDialogResource(bool IsExtended);
   ParseType parseIconResource();
index 42505cc..03742b5 100644 (file)
@@ -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";
 }
index e44120b..485b7ca 100644 (file)
@@ -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
index 530b4a8..373b3cb 100644 (file)
@@ -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;