forked from OSchip/llvm-project
[llvm-rc] Serialize user-defined resources to .res files.
This allows rc to serialize user-defined resources, as documented at: msdn.microsoft.com/en-us/library/windows/desktop/aa381054.aspx Escape sequences are yet unavailable, and are to be added in one of child patches. Patch by: Marek Sokolowski Differential Revision: https://reviews.llvm.org/D38423 llvm-svn: 315117
This commit is contained in:
parent
accab5908d
commit
9d8b358a49
Binary file not shown.
After Width: | Height: | Size: 110 B |
|
@ -0,0 +1,8 @@
|
|||
500 500 {
|
||||
1, 2, 3, 4, 5, "data", L"wide data", 0xABCD, 0xABCDEF01L
|
||||
}
|
||||
|
||||
NAME1 NAME2 {}
|
||||
|
||||
600 600 "bitmap.bmp"
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
; RUN: rm -rf %t
|
||||
; RUN: mkdir %t
|
||||
; RUN: cd %t
|
||||
; RUN: cp %p/Inputs/bitmap.bmp .
|
||||
; RUN: llvm-rc /FO %t/tag-user.res %p/Inputs/tag-user.rc
|
||||
; RUN: llvm-readobj %t/tag-user.res | FileCheck %s
|
||||
|
||||
; CHECK: Resource type (int): 500
|
||||
; CHECK-NEXT: Resource name (int): 500
|
||||
; CHECK-NEXT: Data version: 0
|
||||
; CHECK-NEXT: Memory flags: 0x30
|
||||
; CHECK-NEXT: Language ID: 1033
|
||||
; CHECK-NEXT: Version (major): 0
|
||||
; CHECK-NEXT: Version (minor): 0
|
||||
; CHECK-NEXT: Characteristics: 0
|
||||
; CHECK-NEXT: Data size: 38
|
||||
; CHECK-NEXT: Data: (
|
||||
; CHECK-NEXT: 0000: 01000200 03000400 05006461 74617700 |..........dataw.|
|
||||
; CHECK-NEXT: 0010: 69006400 65002000 64006100 74006100 |i.d.e. .d.a.t.a.|
|
||||
; CHECK-NEXT: 0020: CDAB01EF CDAB |......|
|
||||
; CHECK-NEXT: )
|
||||
|
||||
; CHECK-DAG: Resource type (string): NAME2
|
||||
; CHECK-NEXT: Resource name (string): NAME1
|
||||
; CHECK-NEXT: Data version: 0
|
||||
; CHECK-NEXT: Memory flags: 0x30
|
||||
; CHECK-NEXT: Language ID: 1033
|
||||
; CHECK-NEXT: Version (major): 0
|
||||
; CHECK-NEXT: Version (minor): 0
|
||||
; CHECK-NEXT: Characteristics: 0
|
||||
; CHECK-NEXT: Data size: 0
|
||||
; CHECK-NEXT: Data:: ()
|
||||
|
||||
; CHECK-DAG: Resource type (int): 600
|
||||
; CHECK-NEXT: Resource name (int): 600
|
||||
; CHECK-NEXT: Data version: 0
|
||||
; CHECK-NEXT: Memory flags: 0x30
|
||||
; CHECK-NEXT: Language ID: 1033
|
||||
; CHECK-NEXT: Version (major): 0
|
||||
; CHECK-NEXT: Version (minor): 0
|
||||
; CHECK-NEXT: Characteristics: 0
|
||||
; CHECK-NEXT: Data size: 110
|
||||
; CHECK-NEXT: Data: (
|
||||
; CHECK-NEXT: 0000: 424D6E00 00000000 00003600 00002800 |BMn.......6...(.|
|
||||
; CHECK-NEXT: 0010: 00000200 00000700 00000100 18000000 |................|
|
||||
; CHECK-NEXT: 0020: 00003800 00000000 00000000 00000000 |..8.............|
|
||||
; CHECK-NEXT: 0030: 00000000 00005BB3 855BB385 0000FFFF |......[..[......|
|
||||
; CHECK-NEXT: 0040: FFFFFFFF 0000FFFF FFFFFFFF 0000FFFF |................|
|
||||
; CHECK-NEXT: 0050: FFFFFFFF 00005BB3 85FFFFFF 0000FFFF |......[.........|
|
||||
; CHECK-NEXT: 0060: FF0EC9FF 0000241C EDFFFFFF 0000 |......$.......|
|
||||
; CHECK-NEXT: )
|
||||
|
||||
|
|
@ -298,6 +298,10 @@ Error ResourceFileWriter::visitStringTableResource(const RCResource *Base) {
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
Error ResourceFileWriter::visitUserDefinedResource(const RCResource *Res) {
|
||||
return writeResource(Res, &ResourceFileWriter::writeUserDefinedBody);
|
||||
}
|
||||
|
||||
Error ResourceFileWriter::visitVersionInfoResource(const RCResource *Res) {
|
||||
return writeResource(Res, &ResourceFileWriter::writeVersionInfoBody);
|
||||
}
|
||||
|
@ -1048,6 +1052,43 @@ Error ResourceFileWriter::dumpAllStringTables() {
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
// --- UserDefinedResource helpers. --- //
|
||||
|
||||
Error ResourceFileWriter::writeUserDefinedBody(const RCResource *Base) {
|
||||
auto *Res = cast<UserDefinedResource>(Base);
|
||||
|
||||
if (Res->IsFileResource)
|
||||
return appendFile(Res->FileLoc);
|
||||
|
||||
for (auto &Elem : Res->Contents) {
|
||||
if (Elem.isInt()) {
|
||||
RETURN_IF_ERROR(
|
||||
checkRCInt(Elem.getInt(), "Number in user-defined resource"));
|
||||
writeRCInt(Elem.getInt());
|
||||
continue;
|
||||
}
|
||||
|
||||
SmallVector<UTF16, 128> ProcessedString;
|
||||
bool IsLongString;
|
||||
RETURN_IF_ERROR(processString(Elem.getString(),
|
||||
NullHandlingMethod::UserResource,
|
||||
IsLongString, ProcessedString));
|
||||
|
||||
for (auto Ch : ProcessedString) {
|
||||
if (IsLongString) {
|
||||
writeObject(ulittle16_t(Ch));
|
||||
continue;
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(checkNumberFits<uint8_t>(
|
||||
Ch, "Character in narrow string in user-defined resoutce"));
|
||||
writeObject(uint8_t(Ch));
|
||||
}
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// --- VersionInfoResourceResource helpers. --- //
|
||||
|
||||
Error ResourceFileWriter::writeVersionInfoBlock(const VersionInfoBlock &Blk) {
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
Error visitMenuResource(const RCResource *) override;
|
||||
Error visitVersionInfoResource(const RCResource *) override;
|
||||
Error visitStringTableResource(const RCResource *) override;
|
||||
Error visitUserDefinedResource(const RCResource *) override;
|
||||
|
||||
Error visitCaptionStmt(const CaptionStmt *) override;
|
||||
Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
|
||||
|
@ -127,6 +128,9 @@ private:
|
|||
Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
|
||||
uint16_t StringID, StringRef String);
|
||||
|
||||
// User defined resource
|
||||
Error writeUserDefinedBody(const RCResource *);
|
||||
|
||||
// VersionInfoResource
|
||||
Error writeVersionInfoBody(const RCResource *);
|
||||
Error writeVersionInfoBlock(const VersionInfoBlock &);
|
||||
|
|
|
@ -591,18 +591,29 @@ public:
|
|||
// * a link to the file, e.g. NAME TYPE "filename",
|
||||
// * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}.
|
||||
class UserDefinedResource : public RCResource {
|
||||
public:
|
||||
IntOrString Type;
|
||||
StringRef FileLoc;
|
||||
std::vector<IntOrString> Contents;
|
||||
bool IsFileResource;
|
||||
|
||||
public:
|
||||
UserDefinedResource(IntOrString ResourceType, StringRef FileLocation)
|
||||
: Type(ResourceType), FileLoc(FileLocation), IsFileResource(true) {}
|
||||
UserDefinedResource(IntOrString ResourceType, std::vector<IntOrString> &&Data)
|
||||
: Type(ResourceType), Contents(std::move(Data)), IsFileResource(false) {}
|
||||
|
||||
raw_ostream &log(raw_ostream &) const override;
|
||||
IntOrString getResourceType() const override { return Type; }
|
||||
Twine getResourceTypeName() const override { return Type; }
|
||||
uint16_t getMemoryFlags() const override { return MfPure | MfMoveable; }
|
||||
|
||||
Error visit(Visitor *V) const override {
|
||||
return V->visitUserDefinedResource(this);
|
||||
}
|
||||
ResourceKind getKind() const override { return RkUser; }
|
||||
static bool classof(const RCResource *Res) {
|
||||
return Res->getKind() == RkUser;
|
||||
}
|
||||
};
|
||||
|
||||
// -- VERSIONINFO resource and its helper classes --
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
virtual Error visitIconResource(const RCResource *) = 0;
|
||||
virtual Error visitMenuResource(const RCResource *) = 0;
|
||||
virtual Error visitStringTableResource(const RCResource *) = 0;
|
||||
virtual Error visitUserDefinedResource(const RCResource *) = 0;
|
||||
virtual Error visitVersionInfoResource(const RCResource *) = 0;
|
||||
|
||||
virtual Error visitCaptionStmt(const CaptionStmt *) = 0;
|
||||
|
|
Loading…
Reference in New Issue