[llvm-rc] Add VERSIONINFO parsing ability. [6/8]

This extends the set of llvm-rc parser's available resources by
another one, VERSIONINFO.

Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058.aspx

Thanks to Nico Weber for his original work in this area.

Differential Revision: https://reviews.llvm.org/D37021

llvm-svn: 314468
diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
index cfbd2f8..eb123e5 100644
--- a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
+++ b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
@@ -142,6 +142,78 @@
   return OS;
 }
 
+raw_ostream &VersionInfoBlock::log(raw_ostream &OS) const {
+  OS << "  Start of block (name: " << Name << ")\n";
+  for (auto &Stmt : Stmts)
+    Stmt->log(OS);
+  return OS << "  End of block\n";
+}
+
+raw_ostream &VersionInfoValue::log(raw_ostream &OS) const {
+  OS << "  " << Key << " =>";
+  for (auto &Value : Values)
+    OS << " " << Value;
+  return OS << "\n";
+}
+
+using VersionInfoFixed = VersionInfoResource::VersionInfoFixed;
+using VersionInfoFixedType = VersionInfoFixed::VersionInfoFixedType;
+
+const StringRef
+    VersionInfoFixed::FixedFieldsNames[VersionInfoFixed::FtNumTypes] = {
+        "",          "FILEVERSION", "PRODUCTVERSION", "FILEFLAGSMASK",
+        "FILEFLAGS", "FILEOS",      "FILETYPE",       "FILESUBTYPE"};
+
+const StringMap<VersionInfoFixedType> VersionInfoFixed::FixedFieldsInfoMap = {
+    {FixedFieldsNames[FtFileVersion], FtFileVersion},
+    {FixedFieldsNames[FtProductVersion], FtProductVersion},
+    {FixedFieldsNames[FtFileFlagsMask], FtFileFlagsMask},
+    {FixedFieldsNames[FtFileFlags], FtFileFlags},
+    {FixedFieldsNames[FtFileOS], FtFileOS},
+    {FixedFieldsNames[FtFileType], FtFileType},
+    {FixedFieldsNames[FtFileSubtype], FtFileSubtype}};
+
+VersionInfoFixedType VersionInfoFixed::getFixedType(StringRef Type) {
+  auto UpperType = Type.upper();
+  auto Iter = FixedFieldsInfoMap.find(UpperType);
+  if (Iter != FixedFieldsInfoMap.end())
+    return Iter->getValue();
+  return FtUnknown;
+}
+
+bool VersionInfoFixed::isTypeSupported(VersionInfoFixedType Type) {
+  return FtUnknown < Type && Type < FtNumTypes;
+}
+
+bool VersionInfoFixed::isVersionType(VersionInfoFixedType Type) {
+  switch (Type) {
+  case FtFileVersion:
+  case FtProductVersion:
+    return true;
+
+  default:
+    return false;
+  }
+}
+
+raw_ostream &VersionInfoFixed::log(raw_ostream &OS) const {
+  for (int Type = FtUnknown; Type < FtNumTypes; ++Type) {
+    if (!isTypeSupported((VersionInfoFixedType)Type))
+      continue;
+    OS << "  Fixed: " << FixedFieldsNames[Type] << ":";
+    for (uint32_t Val : FixedInfo[Type])
+      OS << " " << Val;
+    OS << "\n";
+  }
+  return OS;
+}
+
+raw_ostream &VersionInfoResource::log(raw_ostream &OS) const {
+  OS << "VersionInfo (" << ResName << "):\n";
+  FixedData.log(OS);
+  return MainBlock.log(OS);
+}
+
 raw_ostream &CharacteristicsStmt::log(raw_ostream &OS) const {
   return OS << "Characteristics: " << Value << "\n";
 }