Skip to content

Commit b989fcb

Browse files
committed
[llvm-rc] Allow string table values split into multiple string literals
This can practically easily be a product of combining strings with macros in resource files. This fixes mstorsjo/llvm-mingw#140. As string literals within llvm-rc are handled as StringRefs, each referencing an uninterpreted slice of the input file, with actual interpretation of the input string (codepage handling, unescaping etc) done only right before writing them out to disk, it's hard to concatenate them other than just bundling them up in a vector, without rearchitecting a large part of llvm-rc. This matches how the same already is supported in VersionInfoValue, with a std::vector<IntOrString> Values. MS rc.exe only supports concatenated string literals in version info values (already supported), string tables (implemented in this patch) and user data resources (easily implemented in a separate patch, but hasn't been requested by any end user yet), while GNU windres supports string immediates split into multiple strings anywhere (e.g. like (100 ICON "myicon" ".ico"). Not sure if concatenation in other statements actually is used in the wild though, in resource files normally built by GNU windres. Differential Revision: https://reviews.llvm.org/D85183
1 parent e0d99e9 commit b989fcb

File tree

6 files changed

+31
-17
lines changed

6 files changed

+31
-17
lines changed

llvm/test/tools/llvm-rc/Inputs/tag-stringtable-basic.rc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ STRINGTABLE {
1313
STRINGTABLE
1414
VERSION 100
1515
LANGUAGE 4, 7 {
16-
16 "hello"
17-
17 "world"
16+
16 "hel" "lo"
17+
17 "wor" L"ld"
1818
}
1919

2020
STRINGTABLE

llvm/tools/llvm-rc/ResourceFileWriter.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,8 @@ Error ResourceFileWriter::visitStringTableBundle(const RCResource *Res) {
12461246
}
12471247

12481248
Error ResourceFileWriter::insertStringIntoBundle(
1249-
StringTableInfo::Bundle &Bundle, uint16_t StringID, StringRef String) {
1249+
StringTableInfo::Bundle &Bundle, uint16_t StringID,
1250+
const std::vector<StringRef> &String) {
12501251
uint16_t StringLoc = StringID & 15;
12511252
if (Bundle.Data[StringLoc])
12521253
return createError("Multiple STRINGTABLE strings located under ID " +
@@ -1261,13 +1262,15 @@ Error ResourceFileWriter::writeStringTableBundleBody(const RCResource *Base) {
12611262
// The string format is a tiny bit different here. We
12621263
// first output the size of the string, and then the string itself
12631264
// (which is not null-terminated).
1264-
bool IsLongString;
12651265
SmallVector<UTF16, 128> Data;
1266-
RETURN_IF_ERROR(processString(Res->Bundle.Data[ID].getValueOr(StringRef()),
1267-
NullHandlingMethod::CutAtDoubleNull,
1268-
IsLongString, Data, Params.CodePage));
1269-
if (AppendNull && Res->Bundle.Data[ID])
1270-
Data.push_back('\0');
1266+
if (Res->Bundle.Data[ID]) {
1267+
bool IsLongString;
1268+
for (StringRef S : *Res->Bundle.Data[ID])
1269+
RETURN_IF_ERROR(processString(S, NullHandlingMethod::CutAtDoubleNull,
1270+
IsLongString, Data, Params.CodePage));
1271+
if (AppendNull)
1272+
Data.push_back('\0');
1273+
}
12711274
RETURN_IF_ERROR(
12721275
checkNumberFits<uint16_t>(Data.size(), "STRINGTABLE string size"));
12731276
writeInt<uint16_t>(Data.size());

llvm/tools/llvm-rc/ResourceFileWriter.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class ResourceFileWriter : public Visitor {
103103
using BundleKey = std::pair<uint16_t, uint16_t>;
104104
// Each bundle is in fact an array of 16 strings.
105105
struct Bundle {
106-
std::array<Optional<StringRef>, 16> Data;
106+
std::array<Optional<std::vector<StringRef>>, 16> Data;
107107
ObjectInfo DeclTimeInfo;
108108
uint16_t MemoryFlags;
109109
Bundle(const ObjectInfo &Info, uint16_t Flags)
@@ -157,7 +157,8 @@ class ResourceFileWriter : public Visitor {
157157
Error visitStringTableBundle(const RCResource *);
158158
Error writeStringTableBundleBody(const RCResource *);
159159
Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
160-
uint16_t StringID, StringRef String);
160+
uint16_t StringID,
161+
const std::vector<StringRef> &String);
161162

162163
// User defined resource
163164
Error writeUserDefinedBody(const RCResource *);

llvm/tools/llvm-rc/ResourceScriptParser.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,8 +698,14 @@ RCParser::ParseType RCParser::parseStringTableResource() {
698698
// between, however we strictly adhere to the single statement definition.
699699
ASSIGN_OR_RETURN(IDResult, readInt());
700700
consumeOptionalType(Kind::Comma);
701+
702+
std::vector<StringRef> Strings;
701703
ASSIGN_OR_RETURN(StrResult, readString());
702-
Table->addString(*IDResult, *StrResult);
704+
Strings.push_back(*StrResult);
705+
while (isNextTokenKind(Kind::String))
706+
Strings.push_back(read().value());
707+
708+
Table->addStrings(*IDResult, std::move(Strings));
703709
}
704710

705711
return std::move(Table);

llvm/tools/llvm-rc/ResourceScriptStmt.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,12 @@ raw_ostream &MenuResource::log(raw_ostream &OS) const {
118118
raw_ostream &StringTableResource::log(raw_ostream &OS) const {
119119
OS << "StringTable:\n";
120120
OptStatements->log(OS);
121-
for (const auto &String : Table)
122-
OS << " " << String.first << " => " << String.second << "\n";
121+
for (const auto &String : Table) {
122+
OS << " " << String.first << " =>";
123+
for (const auto &S : String.second)
124+
OS << " " << S;
125+
OS << "\n";
126+
}
123127
return OS;
124128
}
125129

llvm/tools/llvm-rc/ResourceScriptStmt.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,12 +583,12 @@ class MenuResource : public OptStatementsRCResource {
583583
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
584584
class StringTableResource : public OptStatementsRCResource {
585585
public:
586-
std::vector<std::pair<uint32_t, StringRef>> Table;
586+
std::vector<std::pair<uint32_t, std::vector<StringRef>>> Table;
587587

588588
StringTableResource(OptionalStmtList &&List, uint16_t Flags)
589589
: OptStatementsRCResource(std::move(List), Flags) {}
590-
void addString(uint32_t ID, StringRef String) {
591-
Table.emplace_back(ID, String);
590+
void addStrings(uint32_t ID, std::vector<StringRef> &&Strings) {
591+
Table.emplace_back(ID, Strings);
592592
}
593593
raw_ostream &log(raw_ostream &) const override;
594594
Twine getResourceTypeName() const override { return "STRINGTABLE"; }

0 commit comments

Comments
 (0)