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