ResourceFileWriter.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. //===-- ResourceSerializator.h ----------------------------------*- C++-*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===---------------------------------------------------------------------===//
  8. //
  9. // This defines a visitor serializing resources to a .res stream.
  10. //
  11. //===---------------------------------------------------------------------===//
  12. #ifndef LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
  13. #define LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
  14. #include "ResourceScriptStmt.h"
  15. #include "ResourceVisitor.h"
  16. #include "llvm/Support/Endian.h"
  17. namespace llvm {
  18. class MemoryBuffer;
  19. namespace rc {
  20. enum CodePage {
  21. CpAcp = 0, // The current used codepage. Since there's no such
  22. // notion in LLVM what codepage it actually means,
  23. // this only allows ASCII.
  24. CpWin1252 = 1252, // A codepage where most 8 bit values correspond to
  25. // unicode code points with the same value.
  26. CpUtf8 = 65001, // UTF-8.
  27. };
  28. struct WriterParams {
  29. std::vector<std::string> Include; // Additional folders to search for files.
  30. bool NoInclude; // Ignore the INCLUDE variable.
  31. StringRef InputFilePath; // The full path of the input file.
  32. int CodePage = CpAcp; // The codepage for interpreting characters.
  33. };
  34. class ResourceFileWriter : public Visitor {
  35. public:
  36. ResourceFileWriter(const WriterParams &Params,
  37. std::unique_ptr<raw_fd_ostream> Stream)
  38. : Params(Params), FS(std::move(Stream)), IconCursorID(1) {
  39. assert(FS && "Output stream needs to be provided to the serializator");
  40. }
  41. Error visitNullResource(const RCResource *) override;
  42. Error visitAcceleratorsResource(const RCResource *) override;
  43. Error visitCursorResource(const RCResource *) override;
  44. Error visitDialogResource(const RCResource *) override;
  45. Error visitHTMLResource(const RCResource *) override;
  46. Error visitIconResource(const RCResource *) override;
  47. Error visitMenuResource(const RCResource *) override;
  48. Error visitVersionInfoResource(const RCResource *) override;
  49. Error visitStringTableResource(const RCResource *) override;
  50. Error visitUserDefinedResource(const RCResource *) override;
  51. Error visitCaptionStmt(const CaptionStmt *) override;
  52. Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
  53. Error visitClassStmt(const ClassStmt *) override;
  54. Error visitExStyleStmt(const ExStyleStmt *) override;
  55. Error visitFontStmt(const FontStmt *) override;
  56. Error visitLanguageStmt(const LanguageResource *) override;
  57. Error visitStyleStmt(const StyleStmt *) override;
  58. Error visitVersionStmt(const VersionStmt *) override;
  59. // Stringtables are output at the end of .res file. We need a separate
  60. // function to do it.
  61. Error dumpAllStringTables();
  62. bool AppendNull = false; // Append '\0' to each existing STRINGTABLE element?
  63. struct ObjectInfo {
  64. uint16_t LanguageInfo;
  65. uint32_t Characteristics;
  66. uint32_t VersionInfo;
  67. Optional<uint32_t> Style;
  68. Optional<uint32_t> ExStyle;
  69. StringRef Caption;
  70. struct FontInfo {
  71. uint32_t Size;
  72. StringRef Typeface;
  73. uint32_t Weight;
  74. bool IsItalic;
  75. uint32_t Charset;
  76. };
  77. Optional<FontInfo> Font;
  78. IntOrString Class;
  79. ObjectInfo()
  80. : LanguageInfo(0), Characteristics(0), VersionInfo(0),
  81. Class(StringRef()) {}
  82. } ObjectData;
  83. struct StringTableInfo {
  84. // Each STRINGTABLE bundle depends on ID of the bundle and language
  85. // description.
  86. using BundleKey = std::pair<uint16_t, uint16_t>;
  87. // Each bundle is in fact an array of 16 strings.
  88. struct Bundle {
  89. std::array<Optional<std::vector<StringRef>>, 16> Data;
  90. ObjectInfo DeclTimeInfo;
  91. uint16_t MemoryFlags;
  92. Bundle(const ObjectInfo &Info, uint16_t Flags)
  93. : DeclTimeInfo(Info), MemoryFlags(Flags) {}
  94. };
  95. std::map<BundleKey, Bundle> BundleData;
  96. // Bundles are listed in the order of their first occurrence.
  97. std::vector<BundleKey> BundleList;
  98. } StringTableData;
  99. private:
  100. Error handleError(Error Err, const RCResource *Res);
  101. Error
  102. writeResource(const RCResource *Res,
  103. Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
  104. // NullResource
  105. Error writeNullBody(const RCResource *);
  106. // AcceleratorsResource
  107. Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
  108. bool IsLastItem);
  109. Error writeAcceleratorsBody(const RCResource *);
  110. // BitmapResource
  111. Error visitBitmapResource(const RCResource *) override;
  112. Error writeBitmapBody(const RCResource *);
  113. // CursorResource and IconResource
  114. Error visitIconOrCursorResource(const RCResource *);
  115. Error visitIconOrCursorGroup(const RCResource *);
  116. Error visitSingleIconOrCursor(const RCResource *);
  117. Error writeSingleIconOrCursorBody(const RCResource *);
  118. Error writeIconOrCursorGroupBody(const RCResource *);
  119. // DialogResource
  120. Error writeSingleDialogControl(const Control &, bool IsExtended);
  121. Error writeDialogBody(const RCResource *);
  122. // HTMLResource
  123. Error writeHTMLBody(const RCResource *);
  124. // MenuResource
  125. Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
  126. uint16_t Flags);
  127. Error writeMenuDefinitionList(const MenuDefinitionList &List);
  128. Error writeMenuBody(const RCResource *);
  129. // StringTableResource
  130. Error visitStringTableBundle(const RCResource *);
  131. Error writeStringTableBundleBody(const RCResource *);
  132. Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
  133. uint16_t StringID,
  134. const std::vector<StringRef> &String);
  135. // User defined resource
  136. Error writeUserDefinedBody(const RCResource *);
  137. // VersionInfoResource
  138. Error writeVersionInfoBody(const RCResource *);
  139. Error writeVersionInfoBlock(const VersionInfoBlock &);
  140. Error writeVersionInfoValue(const VersionInfoValue &);
  141. const WriterParams &Params;
  142. // Output stream handling.
  143. std::unique_ptr<raw_fd_ostream> FS;
  144. uint64_t tell() const { return FS->tell(); }
  145. uint64_t writeObject(const ArrayRef<uint8_t> Data);
  146. template <typename T> uint64_t writeInt(const T &Value) {
  147. support::detail::packed_endian_specific_integral<T, support::little,
  148. support::unaligned>
  149. Object(Value);
  150. return writeObject(Object);
  151. }
  152. template <typename T> uint64_t writeObject(const T &Value) {
  153. return writeObject(ArrayRef<uint8_t>(
  154. reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
  155. }
  156. template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
  157. FS->pwrite((const char *)&Value, sizeof(T), Position);
  158. }
  159. Error writeCString(StringRef Str, bool WriteTerminator = true);
  160. Error writeIdentifier(const IntOrString &Ident);
  161. Error writeIntOrString(const IntOrString &Data);
  162. void writeRCInt(RCInt);
  163. Error appendFile(StringRef Filename);
  164. void padStream(uint64_t Length);
  165. Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;
  166. // Icon and cursor IDs are allocated starting from 1 and increasing for
  167. // each icon/cursor dumped. This maintains the current ID to be allocated.
  168. uint16_t IconCursorID;
  169. };
  170. } // namespace rc
  171. } // namespace llvm
  172. #endif