//===-- ResourceFileWriter.cpp --------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===---------------------------------------------------------------------===//
//
// This implements the visitor serializing resources to a .res stream.
//
//===---------------------------------------------------------------------===//

#include "ResourceFileWriter.h"
#include "llvm/Object/WindowsResource.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"

using namespace llvm::support;

// Take an expression returning llvm::Error and forward the error if it exists.
#define RETURN_IF_ERROR(Expr)                                                  \
  if (auto Err = (Expr))                                                       \
    return Err;

namespace llvm {
namespace rc {

// Class that employs RAII to save the current FileWriter object state
// and revert to it as soon as we leave the scope. This is useful if resources
// declare their own resource-local statements.
class ContextKeeper {
  ResourceFileWriter *FileWriter;
  ResourceFileWriter::ObjectInfo SavedInfo;

public:
  ContextKeeper(ResourceFileWriter *V)
      : FileWriter(V), SavedInfo(V->ObjectData) {}
  ~ContextKeeper() { FileWriter->ObjectData = SavedInfo; }
};

static Error createError(const Twine &Message,
                         std::errc Type = std::errc::invalid_argument) {
  return make_error<StringError>(Message, std::make_error_code(Type));
}

static Error checkNumberFits(uint32_t Number, size_t MaxBits,
                             const Twine &FieldName) {
  assert(1 <= MaxBits && MaxBits <= 32);
  if (!(Number >> MaxBits))
    return Error::success();
  return createError(FieldName + " (" + Twine(Number) + ") does not fit in " +
                         Twine(MaxBits) + " bits.",
                     std::errc::value_too_large);
}

template <typename FitType>
static Error checkNumberFits(uint32_t Number, const Twine &FieldName) {
  return checkNumberFits(Number, sizeof(FitType) * 8, FieldName);
}

// A similar function for signed integers.
template <typename FitType>
static Error checkSignedNumberFits(uint32_t Number, const Twine &FieldName,
                                   bool CanBeNegative) {
  int32_t SignedNum = Number;
  if (SignedNum < std::numeric_limits<FitType>::min() ||
      SignedNum > std::numeric_limits<FitType>::max())
    return createError(FieldName + " (" + Twine(SignedNum) +
                           ") does not fit in " + Twine(sizeof(FitType) * 8) +
                           "-bit signed integer type.",
                       std::errc::value_too_large);

  if (!CanBeNegative && SignedNum < 0)
    return createError(FieldName + " (" + Twine(SignedNum) +
                       ") cannot be negative.");

  return Error::success();
}

static Error checkRCInt(RCInt Number, const Twine &FieldName) {
  if (Number.isLong())
    return Error::success();
  return checkNumberFits<uint16_t>(Number, FieldName);
}

static Error checkIntOrString(IntOrString Value, const Twine &FieldName) {
  if (!Value.isInt())
    return Error::success();
  return checkNumberFits<uint16_t>(Value.getInt(), FieldName);
}

static bool stripQuotes(StringRef &Str, bool &IsLongString) {
  if (!Str.contains('"'))
    return false;

  // Just take the contents of the string, checking if it's been marked long.
  IsLongString = Str.startswith_insensitive("L");
  if (IsLongString)
    Str = Str.drop_front();

  bool StripSuccess = Str.consume_front("\"") && Str.consume_back("\"");
  (void)StripSuccess;
  assert(StripSuccess && "Strings should be enclosed in quotes.");
  return true;
}

static UTF16 cp1252ToUnicode(unsigned char C) {
  static const UTF16 Map80[] = {
      0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
      0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
      0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
      0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178,
  };
  if (C >= 0x80 && C <= 0x9F)
    return Map80[C - 0x80];
  return C;
}

// Describes a way to handle '\0' characters when processing the string.
// rc.exe tool sometimes behaves in a weird way in postprocessing.
// If the string to be output is equivalent to a C-string (e.g. in MENU
// titles), string is (predictably) truncated after first 0-byte.
// When outputting a string table, the behavior is equivalent to appending
// '\0\0' at the end of the string, and then stripping the string
// before the first '\0\0' occurrence.
// Finally, when handling strings in user-defined resources, 0-bytes
// aren't stripped, nor do they terminate the string.

enum class NullHandlingMethod {
  UserResource,   // Don't terminate string on '\0'.
  CutAtNull,      // Terminate string on '\0'.
  CutAtDoubleNull // Terminate string on '\0\0'; strip final '\0'.
};

// Parses an identifier or string and returns a processed version of it:
//   * Strip the string boundary quotes.
//   * Convert the input code page characters to UTF16.
//   * Squash "" to a single ".
//   * Replace the escape sequences with their processed version.
// For identifiers, this is no-op.
static Error processString(StringRef Str, NullHandlingMethod NullHandler,
                           bool &IsLongString, SmallVectorImpl<UTF16> &Result,
                           int CodePage) {
  bool IsString = stripQuotes(Str, IsLongString);
  SmallVector<UTF16, 128> Chars;

  // Convert the input bytes according to the chosen codepage.
  if (CodePage == CpUtf8) {
    convertUTF8ToUTF16String(Str, Chars);
  } else if (CodePage == CpWin1252) {
    for (char C : Str)
      Chars.push_back(cp1252ToUnicode((unsigned char)C));
  } else {
    // For other, unknown codepages, only allow plain ASCII input.
    for (char C : Str) {
      if ((unsigned char)C > 0x7F)
        return createError("Non-ASCII 8-bit codepoint (" + Twine(C) +
                           ") can't be interpreted in the current codepage");
      Chars.push_back((unsigned char)C);
    }
  }

  if (!IsString) {
    // It's an identifier if it's not a string. Make all characters uppercase.
    for (UTF16 &Ch : Chars) {
      assert(Ch <= 0x7F && "We didn't allow identifiers to be non-ASCII");
      Ch = toupper(Ch);
    }
    Result.swap(Chars);
    return Error::success();
  }
  Result.reserve(Chars.size());
  size_t Pos = 0;

  auto AddRes = [&Result, NullHandler, IsLongString](UTF16 Char) -> Error {
    if (!IsLongString) {
      if (NullHandler == NullHandlingMethod::UserResource) {
        // Narrow strings in user-defined resources are *not* output in
        // UTF-16 format.
        if (Char > 0xFF)
          return createError("Non-8-bit codepoint (" + Twine(Char) +
                             ") can't occur in a user-defined narrow string");
      }
    }

    Result.push_back(Char);
    return Error::success();
  };
  auto AddEscapedChar = [AddRes, IsLongString, CodePage](UTF16 Char) -> Error {
    if (!IsLongString) {
      // Escaped chars in narrow strings have to be interpreted according to
      // the chosen code page.
      if (Char > 0xFF)
        return createError("Non-8-bit escaped char (" + Twine(Char) +
                           ") can't occur in narrow string");
      if (CodePage == CpUtf8) {
        if (Char >= 0x80)
          return createError("Unable to interpret single byte (" + Twine(Char) +
                             ") as UTF-8");
      } else if (CodePage == CpWin1252) {
        Char = cp1252ToUnicode(Char);
      } else {
        // Unknown/unsupported codepage, only allow ASCII input.
        if (Char > 0x7F)
          return createError("Non-ASCII 8-bit codepoint (" + Twine(Char) +
                             ") can't "
                             "occur in a non-Unicode string");
      }
    }

    return AddRes(Char);
  };

  while (Pos < Chars.size()) {
    UTF16 CurChar = Chars[Pos];
    ++Pos;

    // Strip double "".
    if (CurChar == '"') {
      if (Pos == Chars.size() || Chars[Pos] != '"')
        return createError("Expected \"\"");
      ++Pos;
      RETURN_IF_ERROR(AddRes('"'));
      continue;
    }

    if (CurChar == '\\') {
      UTF16 TypeChar = Chars[Pos];
      ++Pos;

      if (TypeChar == 'x' || TypeChar == 'X') {
        // Read a hex number. Max number of characters to read differs between
        // narrow and wide strings.
        UTF16 ReadInt = 0;
        size_t RemainingChars = IsLongString ? 4 : 2;
        // We don't want to read non-ASCII hex digits. std:: functions past
        // 0xFF invoke UB.
        //
        // FIXME: actually, Microsoft version probably doesn't check this
        // condition and uses their Unicode version of 'isxdigit'. However,
        // there are some hex-digit Unicode character outside of ASCII, and
        // some of these are actually accepted by rc.exe, the notable example
        // being fullwidth forms (U+FF10..U+FF19 etc.) These can be written
        // instead of ASCII digits in \x... escape sequence and get accepted.
        // However, the resulting hexcodes seem totally unpredictable.
        // We think it's infeasible to try to reproduce this behavior, nor to
        // put effort in order to detect it.
        while (RemainingChars && Pos < Chars.size() && Chars[Pos] < 0x80) {
          if (!isxdigit(Chars[Pos]))
            break;
          char Digit = tolower(Chars[Pos]);
          ++Pos;

          ReadInt <<= 4;
          if (isdigit(Digit))
            ReadInt |= Digit - '0';
          else
            ReadInt |= Digit - 'a' + 10;

          --RemainingChars;
        }

        RETURN_IF_ERROR(AddEscapedChar(ReadInt));
        continue;
      }

      if (TypeChar >= '0' && TypeChar < '8') {
        // Read an octal number. Note that we've already read the first digit.
        UTF16 ReadInt = TypeChar - '0';
        size_t RemainingChars = IsLongString ? 6 : 2;

        while (RemainingChars && Pos < Chars.size() && Chars[Pos] >= '0' &&
               Chars[Pos] < '8') {
          ReadInt <<= 3;
          ReadInt |= Chars[Pos] - '0';
          --RemainingChars;
          ++Pos;
        }

        RETURN_IF_ERROR(AddEscapedChar(ReadInt));

        continue;
      }

      switch (TypeChar) {
      case 'A':
      case 'a':
        // Windows '\a' translates into '\b' (Backspace).
        RETURN_IF_ERROR(AddRes('\b'));
        break;

      case 'n': // Somehow, RC doesn't recognize '\N' and '\R'.
        RETURN_IF_ERROR(AddRes('\n'));
        break;

      case 'r':
        RETURN_IF_ERROR(AddRes('\r'));
        break;

      case 'T':
      case 't':
        RETURN_IF_ERROR(AddRes('\t'));
        break;

      case '\\':
        RETURN_IF_ERROR(AddRes('\\'));
        break;

      case '"':
        // RC accepts \" only if another " comes afterwards; then, \"" means
        // a single ".
        if (Pos == Chars.size() || Chars[Pos] != '"')
          return createError("Expected \\\"\"");
        ++Pos;
        RETURN_IF_ERROR(AddRes('"'));
        break;

      default:
        // If TypeChar means nothing, \ is should be output to stdout with
        // following char. However, rc.exe consumes these characters when
        // dealing with wide strings.
        if (!IsLongString) {
          RETURN_IF_ERROR(AddRes('\\'));
          RETURN_IF_ERROR(AddRes(TypeChar));
        }
        break;
      }

      continue;
    }

    // If nothing interesting happens, just output the character.
    RETURN_IF_ERROR(AddRes(CurChar));
  }

  switch (NullHandler) {
  case NullHandlingMethod::CutAtNull:
    for (size_t Pos = 0; Pos < Result.size(); ++Pos)
      if (Result[Pos] == '\0')
        Result.resize(Pos);
    break;

  case NullHandlingMethod::CutAtDoubleNull:
    for (size_t Pos = 0; Pos + 1 < Result.size(); ++Pos)
      if (Result[Pos] == '\0' && Result[Pos + 1] == '\0')
        Result.resize(Pos);
    if (Result.size() > 0 && Result.back() == '\0')
      Result.pop_back();
    break;

  case NullHandlingMethod::UserResource:
    break;
  }

  return Error::success();
}

uint64_t ResourceFileWriter::writeObject(const ArrayRef<uint8_t> Data) {
  uint64_t Result = tell();
  FS->write((const char *)Data.begin(), Data.size());
  return Result;
}

Error ResourceFileWriter::writeCString(StringRef Str, bool WriteTerminator) {
  SmallVector<UTF16, 128> ProcessedString;
  bool IsLongString;
  RETURN_IF_ERROR(processString(Str, NullHandlingMethod::CutAtNull,
                                IsLongString, ProcessedString,
                                Params.CodePage));
  for (auto Ch : ProcessedString)
    writeInt<uint16_t>(Ch);
  if (WriteTerminator)
    writeInt<uint16_t>(0);
  return Error::success();
}

Error ResourceFileWriter::writeIdentifier(const IntOrString &Ident) {
  return writeIntOrString(Ident);
}

Error ResourceFileWriter::writeIntOrString(const IntOrString &Value) {
  if (!Value.isInt())
    return writeCString(Value.getString());

  writeInt<uint16_t>(0xFFFF);
  writeInt<uint16_t>(Value.getInt());
  return Error::success();
}

void ResourceFileWriter::writeRCInt(RCInt Value) {
  if (Value.isLong())
    writeInt<uint32_t>(Value);
  else
    writeInt<uint16_t>(Value);
}

Error ResourceFileWriter::appendFile(StringRef Filename) {
  bool IsLong;
  stripQuotes(Filename, IsLong);

  auto File = loadFile(Filename);
  if (!File)
    return File.takeError();

  *FS << (*File)->getBuffer();
  return Error::success();
}

void ResourceFileWriter::padStream(uint64_t Length) {
  assert(Length > 0);
  uint64_t Location = tell();
  Location %= Length;
  uint64_t Pad = (Length - Location) % Length;
  for (uint64_t i = 0; i < Pad; ++i)
    writeInt<uint8_t>(0);
}

Error ResourceFileWriter::handleError(Error Err, const RCResource *Res) {
  if (Err)
    return joinErrors(createError("Error in " + Res->getResourceTypeName() +
                                  " statement (ID " + Twine(Res->ResName) +
                                  "): "),
                      std::move(Err));
  return Error::success();
}

Error ResourceFileWriter::visitNullResource(const RCResource *Res) {
  return writeResource(Res, &ResourceFileWriter::writeNullBody);
}

Error ResourceFileWriter::visitAcceleratorsResource(const RCResource *Res) {
  return writeResource(Res, &ResourceFileWriter::writeAcceleratorsBody);
}

Error ResourceFileWriter::visitBitmapResource(const RCResource *Res) {
  return writeResource(Res, &ResourceFileWriter::writeBitmapBody);
}

Error ResourceFileWriter::visitCursorResource(const RCResource *Res) {
  return handleError(visitIconOrCursorResource(Res), Res);
}

Error ResourceFileWriter::visitDialogResource(const RCResource *Res) {
  return writeResource(Res, &ResourceFileWriter::writeDialogBody);
}

Error ResourceFileWriter::visitIconResource(const RCResource *Res) {
  return handleError(visitIconOrCursorResource(Res), Res);
}

Error ResourceFileWriter::visitCaptionStmt(const CaptionStmt *Stmt) {
  ObjectData.Caption = Stmt->Value;
  return Error::success();
}

Error ResourceFileWriter::visitClassStmt(const ClassStmt *Stmt) {
  ObjectData.Class = Stmt->Value;
  return Error::success();
}

Error ResourceFileWriter::visitHTMLResource(const RCResource *Res) {
  return writeResource(Res, &ResourceFileWriter::writeHTMLBody);
}

Error ResourceFileWriter::visitMenuResource(const RCResource *Res) {
  return writeResource(Res, &ResourceFileWriter::writeMenuBody);
}

Error ResourceFileWriter::visitStringTableResource(const RCResource *Base) {
  const auto *Res = cast<StringTableResource>(Base);

  ContextKeeper RAII(this);
  RETURN_IF_ERROR(Res->applyStmts(this));

  for (auto &String : Res->Table) {
    RETURN_IF_ERROR(checkNumberFits<uint16_t>(String.first, "String ID"));
    uint16_t BundleID = String.first >> 4;
    StringTableInfo::BundleKey Key(BundleID, ObjectData.LanguageInfo);
    auto &BundleData = StringTableData.BundleData;
    auto Iter = BundleData.find(Key);

    if (Iter == BundleData.end()) {
      // Need to create a bundle.
      StringTableData.BundleList.push_back(Key);
      auto EmplaceResult = BundleData.emplace(
          Key, StringTableInfo::Bundle(ObjectData, Res->MemoryFlags));
      assert(EmplaceResult.second && "Could not create a bundle");
      Iter = EmplaceResult.first;
    }

    RETURN_IF_ERROR(
        insertStringIntoBundle(Iter->second, String.first, String.second));
  }

  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);
}

Error ResourceFileWriter::visitCharacteristicsStmt(
    const CharacteristicsStmt *Stmt) {
  ObjectData.Characteristics = Stmt->Value;
  return Error::success();
}

Error ResourceFileWriter::visitExStyleStmt(const ExStyleStmt *Stmt) {
  ObjectData.ExStyle = Stmt->Value;
  return Error::success();
}

Error ResourceFileWriter::visitFontStmt(const FontStmt *Stmt) {
  RETURN_IF_ERROR(checkNumberFits<uint16_t>(Stmt->Size, "Font size"));
  RETURN_IF_ERROR(checkNumberFits<uint16_t>(Stmt->Weight, "Font weight"));
  RETURN_IF_ERROR(checkNumberFits<uint8_t>(Stmt->Charset, "Font charset"));
  ObjectInfo::FontInfo Font{Stmt->Size, Stmt->Name, Stmt->Weight, Stmt->Italic,
                            Stmt->Charset};
  ObjectData.Font.emplace(Font);
  return Error::success();
}

Error ResourceFileWriter::visitLanguageStmt(const LanguageResource *Stmt) {
  RETURN_IF_ERROR(checkNumberFits(Stmt->Lang, 10, "Primary language ID"));
  RETURN_IF_ERROR(checkNumberFits(Stmt->SubLang, 6, "Sublanguage ID"));
  ObjectData.LanguageInfo = Stmt->Lang | (Stmt->SubLang << 10);
  return Error::success();
}

Error ResourceFileWriter::visitStyleStmt(const StyleStmt *Stmt) {
  ObjectData.Style = Stmt->Value;
  return Error::success();
}

Error ResourceFileWriter::visitVersionStmt(const VersionStmt *Stmt) {
  ObjectData.VersionInfo = Stmt->Value;
  return Error::success();
}

Error ResourceFileWriter::writeResource(
    const RCResource *Res,
    Error (ResourceFileWriter::*BodyWriter)(const RCResource *)) {
  // We don't know the sizes yet.
  object::WinResHeaderPrefix HeaderPrefix{ulittle32_t(0U), ulittle32_t(0U)};
  uint64_t HeaderLoc = writeObject(HeaderPrefix);

  auto ResType = Res->getResourceType();
  RETURN_IF_ERROR(checkIntOrString(ResType, "Resource type"));
  RETURN_IF_ERROR(checkIntOrString(Res->ResName, "Resource ID"));
  RETURN_IF_ERROR(handleError(writeIdentifier(ResType), Res));
  RETURN_IF_ERROR(handleError(writeIdentifier(Res->ResName), Res));

  // Apply the resource-local optional statements.
  ContextKeeper RAII(this);
  RETURN_IF_ERROR(handleError(Res->applyStmts(this), Res));

  padStream(sizeof(uint32_t));
  object::WinResHeaderSuffix HeaderSuffix{
      ulittle32_t(0), // DataVersion; seems to always be 0
      ulittle16_t(Res->MemoryFlags), ulittle16_t(ObjectData.LanguageInfo),
      ulittle32_t(ObjectData.VersionInfo),
      ulittle32_t(ObjectData.Characteristics)};
  writeObject(HeaderSuffix);

  uint64_t DataLoc = tell();
  RETURN_IF_ERROR(handleError((this->*BodyWriter)(Res), Res));
  // RETURN_IF_ERROR(handleError(dumpResource(Ctx)));

  // Update the sizes.
  HeaderPrefix.DataSize = tell() - DataLoc;
  HeaderPrefix.HeaderSize = DataLoc - HeaderLoc;
  writeObjectAt(HeaderPrefix, HeaderLoc);
  padStream(sizeof(uint32_t));

  return Error::success();
}

// --- NullResource helpers. --- //

Error ResourceFileWriter::writeNullBody(const RCResource *) {
  return Error::success();
}

// --- AcceleratorsResource helpers. --- //

Error ResourceFileWriter::writeSingleAccelerator(
    const AcceleratorsResource::Accelerator &Obj, bool IsLastItem) {
  using Accelerator = AcceleratorsResource::Accelerator;
  using Opt = Accelerator::Options;

  struct AccelTableEntry {
    ulittle16_t Flags;
    ulittle16_t ANSICode;
    ulittle16_t Id;
    uint16_t Padding;
  } Entry{ulittle16_t(0), ulittle16_t(0), ulittle16_t(0), 0};

  bool IsASCII = Obj.Flags & Opt::ASCII, IsVirtKey = Obj.Flags & Opt::VIRTKEY;

  // Remove ASCII flags (which doesn't occur in .res files).
  Entry.Flags = Obj.Flags & ~Opt::ASCII;

  if (IsLastItem)
    Entry.Flags |= 0x80;

  RETURN_IF_ERROR(checkNumberFits<uint16_t>(Obj.Id, "ACCELERATORS entry ID"));
  Entry.Id = ulittle16_t(Obj.Id);

  auto createAccError = [&Obj](const char *Msg) {
    return createError("Accelerator ID " + Twine(Obj.Id) + ": " + Msg);
  };

  if (IsASCII && IsVirtKey)
    return createAccError("Accelerator can't be both ASCII and VIRTKEY");

  if (!IsVirtKey && (Obj.Flags & (Opt::ALT | Opt::SHIFT | Opt::CONTROL)))
    return createAccError("Can only apply ALT, SHIFT or CONTROL to VIRTKEY"
                          " accelerators");

  if (Obj.Event.isInt()) {
    if (!IsASCII && !IsVirtKey)
      return createAccError(
          "Accelerator with a numeric event must be either ASCII"
          " or VIRTKEY");

    uint32_t EventVal = Obj.Event.getInt();
    RETURN_IF_ERROR(
        checkNumberFits<uint16_t>(EventVal, "Numeric event key ID"));
    Entry.ANSICode = ulittle16_t(EventVal);
    writeObject(Entry);
    return Error::success();
  }

  StringRef Str = Obj.Event.getString();
  bool IsWide;
  stripQuotes(Str, IsWide);

  if (Str.size() == 0 || Str.size() > 2)
    return createAccError(
        "Accelerator string events should have length 1 or 2");

  if (Str[0] == '^') {
    if (Str.size() == 1)
      return createAccError("No character following '^' in accelerator event");
    if (IsVirtKey)
      return createAccError(
          "VIRTKEY accelerator events can't be preceded by '^'");

    char Ch = Str[1];
    if (Ch >= 'a' && Ch <= 'z')
      Entry.ANSICode = ulittle16_t(Ch - 'a' + 1);
    else if (Ch >= 'A' && Ch <= 'Z')
      Entry.ANSICode = ulittle16_t(Ch - 'A' + 1);
    else
      return createAccError("Control character accelerator event should be"
                            " alphabetic");

    writeObject(Entry);
    return Error::success();
  }

  if (Str.size() == 2)
    return createAccError("Event string should be one-character, possibly"
                          " preceded by '^'");

  uint8_t EventCh = Str[0];
  // The original tool just warns in this situation. We chose to fail.
  if (IsVirtKey && !isalnum(EventCh))
    return createAccError("Non-alphanumeric characters cannot describe virtual"
                          " keys");
  if (EventCh > 0x7F)
    return createAccError("Non-ASCII description of accelerator");

  if (IsVirtKey)
    EventCh = toupper(EventCh);
  Entry.ANSICode = ulittle16_t(EventCh);
  writeObject(Entry);
  return Error::success();
}

Error ResourceFileWriter::writeAcceleratorsBody(const RCResource *Base) {
  auto *Res = cast<AcceleratorsResource>(Base);
  size_t AcceleratorId = 0;
  for (auto &Acc : Res->Accelerators) {
    ++AcceleratorId;
    RETURN_IF_ERROR(
        writeSingleAccelerator(Acc, AcceleratorId == Res->Accelerators.size()));
  }
  return Error::success();
}

// --- BitmapResource helpers. --- //

Error ResourceFileWriter::writeBitmapBody(const RCResource *Base) {
  StringRef Filename = cast<BitmapResource>(Base)->BitmapLoc;
  bool IsLong;
  stripQuotes(Filename, IsLong);

  auto File = loadFile(Filename);
  if (!File)
    return File.takeError();

  StringRef Buffer = (*File)->getBuffer();

  // Skip the 14 byte BITMAPFILEHEADER.
  constexpr size_t BITMAPFILEHEADER_size = 14;
  if (Buffer.size() < BITMAPFILEHEADER_size || Buffer[0] != 'B' ||
      Buffer[1] != 'M')
    return createError("Incorrect bitmap file.");

  *FS << Buffer.substr(BITMAPFILEHEADER_size);
  return Error::success();
}

// --- CursorResource and IconResource helpers. --- //

// ICONRESDIR structure. Describes a single icon in resource group.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648016.aspx
struct IconResDir {
  uint8_t Width;
  uint8_t Height;
  uint8_t ColorCount;
  uint8_t Reserved;
};

// CURSORDIR structure. Describes a single cursor in resource group.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648011(v=vs.85).aspx
struct CursorDir {
  ulittle16_t Width;
  ulittle16_t Height;
};

// RESDIRENTRY structure, stripped from the last item. Stripping made
// for compatibility with RESDIR.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648026(v=vs.85).aspx
struct ResourceDirEntryStart {
  union {
    CursorDir Cursor; // Used in CURSOR resources.
    IconResDir Icon;  // Used in .ico and .cur files, and ICON resources.
  };
  ulittle16_t Planes;   // HotspotX (.cur files but not CURSOR resource).
  ulittle16_t BitCount; // HotspotY (.cur files but not CURSOR resource).
  ulittle32_t Size;
  // ulittle32_t ImageOffset;  // Offset to image data (ICONDIRENTRY only).
  // ulittle16_t IconID;       // Resource icon ID (RESDIR only).
};

// BITMAPINFOHEADER structure. Describes basic information about the bitmap
// being read.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx
struct BitmapInfoHeader {
  ulittle32_t Size;
  ulittle32_t Width;
  ulittle32_t Height;
  ulittle16_t Planes;
  ulittle16_t BitCount;
  ulittle32_t Compression;
  ulittle32_t SizeImage;
  ulittle32_t XPelsPerMeter;
  ulittle32_t YPelsPerMeter;
  ulittle32_t ClrUsed;
  ulittle32_t ClrImportant;
};

// Group icon directory header. Called ICONDIR in .ico/.cur files and
// NEWHEADER in .res files.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648023(v=vs.85).aspx
struct GroupIconDir {
  ulittle16_t Reserved; // Always 0.
  ulittle16_t ResType;  // 1 for icons, 2 for cursors.
  ulittle16_t ResCount; // Number of items.
};

enum class IconCursorGroupType { Icon, Cursor };

class SingleIconCursorResource : public RCResource {
public:
  IconCursorGroupType Type;
  const ResourceDirEntryStart &Header;
  ArrayRef<uint8_t> Image;

  SingleIconCursorResource(IconCursorGroupType ResourceType,
                           const ResourceDirEntryStart &HeaderEntry,
                           ArrayRef<uint8_t> ImageData, uint16_t Flags)
      : RCResource(Flags), Type(ResourceType), Header(HeaderEntry),
        Image(ImageData) {}

  Twine getResourceTypeName() const override { return "Icon/cursor image"; }
  IntOrString getResourceType() const override {
    return Type == IconCursorGroupType::Icon ? RkSingleIcon : RkSingleCursor;
  }
  ResourceKind getKind() const override { return RkSingleCursorOrIconRes; }
  static bool classof(const RCResource *Res) {
    return Res->getKind() == RkSingleCursorOrIconRes;
  }
};

class IconCursorGroupResource : public RCResource {
public:
  IconCursorGroupType Type;
  GroupIconDir Header;
  std::vector<ResourceDirEntryStart> ItemEntries;

  IconCursorGroupResource(IconCursorGroupType ResourceType,
                          const GroupIconDir &HeaderData,
                          std::vector<ResourceDirEntryStart> &&Entries)
      : Type(ResourceType), Header(HeaderData),
        ItemEntries(std::move(Entries)) {}

  Twine getResourceTypeName() const override { return "Icon/cursor group"; }
  IntOrString getResourceType() const override {
    return Type == IconCursorGroupType::Icon ? RkIconGroup : RkCursorGroup;
  }
  ResourceKind getKind() const override { return RkCursorOrIconGroupRes; }
  static bool classof(const RCResource *Res) {
    return Res->getKind() == RkCursorOrIconGroupRes;
  }
};

Error ResourceFileWriter::writeSingleIconOrCursorBody(const RCResource *Base) {
  auto *Res = cast<SingleIconCursorResource>(Base);
  if (Res->Type == IconCursorGroupType::Cursor) {
    // In case of cursors, two WORDS are appended to the beginning
    // of the resource: HotspotX (Planes in RESDIRENTRY),
    // and HotspotY (BitCount).
    //
    // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648026.aspx
    //  (Remarks section).
    writeObject(Res->Header.Planes);
    writeObject(Res->Header.BitCount);
  }

  writeObject(Res->Image);
  return Error::success();
}

Error ResourceFileWriter::writeIconOrCursorGroupBody(const RCResource *Base) {
  auto *Res = cast<IconCursorGroupResource>(Base);
  writeObject(Res->Header);
  for (auto Item : Res->ItemEntries) {
    writeObject(Item);
    writeInt(IconCursorID++);
  }
  return Error::success();
}

Error ResourceFileWriter::visitSingleIconOrCursor(const RCResource *Res) {
  return writeResource(Res, &ResourceFileWriter::writeSingleIconOrCursorBody);
}

Error ResourceFileWriter::visitIconOrCursorGroup(const RCResource *Res) {
  return writeResource(Res, &ResourceFileWriter::writeIconOrCursorGroupBody);
}

Error ResourceFileWriter::visitIconOrCursorResource(const RCResource *Base) {
  IconCursorGroupType Type;
  StringRef FileStr;
  IntOrString ResName = Base->ResName;

  if (auto *IconRes = dyn_cast<IconResource>(Base)) {
    FileStr = IconRes->IconLoc;
    Type = IconCursorGroupType::Icon;
  } else {
    auto *CursorRes = cast<CursorResource>(Base);
    FileStr = CursorRes->CursorLoc;
    Type = IconCursorGroupType::Cursor;
  }

  bool IsLong;
  stripQuotes(FileStr, IsLong);
  auto File = loadFile(FileStr);

  if (!File)
    return File.takeError();

  BinaryStreamReader Reader((*File)->getBuffer(), support::little);

  // Read the file headers.
  //   - At the beginning, ICONDIR/NEWHEADER header.
  //   - Then, a number of RESDIR headers follow. These contain offsets
  //       to data.
  const GroupIconDir *Header;

  RETURN_IF_ERROR(Reader.readObject(Header));
  if (Header->Reserved != 0)
    return createError("Incorrect icon/cursor Reserved field; should be 0.");
  uint16_t NeededType = Type == IconCursorGroupType::Icon ? 1 : 2;
  if (Header->ResType != NeededType)
    return createError("Incorrect icon/cursor ResType field; should be " +
                       Twine(NeededType) + ".");

  uint16_t NumItems = Header->ResCount;

  // Read single ico/cur headers.
  std::vector<ResourceDirEntryStart> ItemEntries;
  ItemEntries.reserve(NumItems);
  std::vector<uint32_t> ItemOffsets(NumItems);
  for (size_t ID = 0; ID < NumItems; ++ID) {
    const ResourceDirEntryStart *Object;
    RETURN_IF_ERROR(Reader.readObject(Object));
    ItemEntries.push_back(*Object);
    RETURN_IF_ERROR(Reader.readInteger(ItemOffsets[ID]));
  }

  // Now write each icon/cursors one by one. At first, all the contents
  // without ICO/CUR header. This is described by SingleIconCursorResource.
  for (size_t ID = 0; ID < NumItems; ++ID) {
    // Load the fragment of file.
    Reader.setOffset(ItemOffsets[ID]);
    ArrayRef<uint8_t> Image;
    RETURN_IF_ERROR(Reader.readArray(Image, ItemEntries[ID].Size));
    SingleIconCursorResource SingleRes(Type, ItemEntries[ID], Image,
                                       Base->MemoryFlags);
    SingleRes.setName(IconCursorID + ID);
    RETURN_IF_ERROR(visitSingleIconOrCursor(&SingleRes));
  }

  // Now, write all the headers concatenated into a separate resource.
  for (size_t ID = 0; ID < NumItems; ++ID) {
    // We need to rewrite the cursor headers, and fetch actual values
    // for Planes/BitCount.
    const auto &OldHeader = ItemEntries[ID];
    ResourceDirEntryStart NewHeader = OldHeader;

    if (Type == IconCursorGroupType::Cursor) {
      NewHeader.Cursor.Width = OldHeader.Icon.Width;
      // Each cursor in fact stores two bitmaps, one under another.
      // Height provided in cursor definition describes the height of the
      // cursor, whereas the value existing in resource definition describes
      // the height of the bitmap. Therefore, we need to double this height.
      NewHeader.Cursor.Height = OldHeader.Icon.Height * 2;

      // Two WORDs were written at the beginning of the resource (hotspot
      // location). This is reflected in Size field.
      NewHeader.Size += 2 * sizeof(uint16_t);
    }

    // Now, we actually need to read the bitmap header to find
    // the number of planes and the number of bits per pixel.
    Reader.setOffset(ItemOffsets[ID]);
    const BitmapInfoHeader *BMPHeader;
    RETURN_IF_ERROR(Reader.readObject(BMPHeader));
    if (BMPHeader->Size == sizeof(BitmapInfoHeader)) {
      NewHeader.Planes = BMPHeader->Planes;
      NewHeader.BitCount = BMPHeader->BitCount;
    } else {
      // A PNG .ico file.
      // https://blogs.msdn.microsoft.com/oldnewthing/20101022-00/?p=12473
      // "The image must be in 32bpp"
      NewHeader.Planes = 1;
      NewHeader.BitCount = 32;
    }

    ItemEntries[ID] = NewHeader;
  }

  IconCursorGroupResource HeaderRes(Type, *Header, std::move(ItemEntries));
  HeaderRes.setName(ResName);
  if (Base->MemoryFlags & MfPreload) {
    HeaderRes.MemoryFlags |= MfPreload;
    HeaderRes.MemoryFlags &= ~MfPure;
  }
  RETURN_IF_ERROR(visitIconOrCursorGroup(&HeaderRes));

  return Error::success();
}

// --- DialogResource helpers. --- //

Error ResourceFileWriter::writeSingleDialogControl(const Control &Ctl,
                                                   bool IsExtended) {
  // Each control should be aligned to DWORD.
  padStream(sizeof(uint32_t));

  auto TypeInfo = Control::SupportedCtls.lookup(Ctl.Type);
  IntWithNotMask CtlStyle(TypeInfo.Style);
  CtlStyle |= Ctl.Style.value_or(RCInt(0));
  uint32_t CtlExtStyle = Ctl.ExtStyle.value_or(0);

  // DIALOG(EX) item header prefix.
  if (!IsExtended) {
    struct {
      ulittle32_t Style;
      ulittle32_t ExtStyle;
    } Prefix{ulittle32_t(CtlStyle.getValue()), ulittle32_t(CtlExtStyle)};
    writeObject(Prefix);
  } else {
    struct {
      ulittle32_t HelpID;
      ulittle32_t ExtStyle;
      ulittle32_t Style;
    } Prefix{ulittle32_t(Ctl.HelpID.value_or(0)), ulittle32_t(CtlExtStyle),
             ulittle32_t(CtlStyle.getValue())};
    writeObject(Prefix);
  }

  // Common fixed-length part.
  RETURN_IF_ERROR(checkSignedNumberFits<int16_t>(
      Ctl.X, "Dialog control x-coordinate", true));
  RETURN_IF_ERROR(checkSignedNumberFits<int16_t>(
      Ctl.Y, "Dialog control y-coordinate", true));
  RETURN_IF_ERROR(
      checkSignedNumberFits<int16_t>(Ctl.Width, "Dialog control width", false));
  RETURN_IF_ERROR(checkSignedNumberFits<int16_t>(
      Ctl.Height, "Dialog control height", false));
  struct {
    ulittle16_t X;
    ulittle16_t Y;
    ulittle16_t Width;
    ulittle16_t Height;
  } Middle{ulittle16_t(Ctl.X), ulittle16_t(Ctl.Y), ulittle16_t(Ctl.Width),
           ulittle16_t(Ctl.Height)};
  writeObject(Middle);

  // ID; it's 16-bit in DIALOG and 32-bit in DIALOGEX.
  if (!IsExtended) {
    // It's common to use -1, i.e. UINT32_MAX, for controls one doesn't
    // want to refer to later.
    if (Ctl.ID != static_cast<uint32_t>(-1))
      RETURN_IF_ERROR(checkNumberFits<uint16_t>(
          Ctl.ID, "Control ID in simple DIALOG resource"));
    writeInt<uint16_t>(Ctl.ID);
  } else {
    writeInt<uint32_t>(Ctl.ID);
  }

  // Window class - either 0xFFFF + 16-bit integer or a string.
  RETURN_IF_ERROR(writeIntOrString(Ctl.Class));

  // Element caption/reference ID. ID is preceded by 0xFFFF.
  RETURN_IF_ERROR(checkIntOrString(Ctl.Title, "Control reference ID"));
  RETURN_IF_ERROR(writeIntOrString(Ctl.Title));

  // # bytes of extra creation data count. Don't pass any.
  writeInt<uint16_t>(0);

  return Error::success();
}

Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
  auto *Res = cast<DialogResource>(Base);

  // Default style: WS_POPUP | WS_BORDER | WS_SYSMENU.
  const uint32_t DefaultStyle = 0x80880000;
  const uint32_t StyleFontFlag = 0x40;
  const uint32_t StyleCaptionFlag = 0x00C00000;

  uint32_t UsedStyle = ObjectData.Style.value_or(DefaultStyle);
  if (ObjectData.Font)
    UsedStyle |= StyleFontFlag;
  else
    UsedStyle &= ~StyleFontFlag;

  // Actually, in case of empty (but existent) caption, the examined field
  // is equal to "\"\"". That's why empty captions are still noticed.
  if (ObjectData.Caption != "")
    UsedStyle |= StyleCaptionFlag;

  const uint16_t DialogExMagic = 0xFFFF;
  uint32_t ExStyle = ObjectData.ExStyle.value_or(0);

  // Write DIALOG(EX) header prefix. These are pretty different.
  if (!Res->IsExtended) {
    // We cannot let the higher word of DefaultStyle be equal to 0xFFFF.
    // In such a case, whole object (in .res file) is equivalent to a
    // DIALOGEX. It might lead to access violation/segmentation fault in
    // resource readers. For example,
    //   1 DIALOG 0, 0, 0, 65432
    //   STYLE 0xFFFF0001 {}
    // would be compiled to a DIALOGEX with 65432 controls.
    if ((UsedStyle >> 16) == DialogExMagic)
      return createError("16 higher bits of DIALOG resource style cannot be"
                         " equal to 0xFFFF");

    struct {
      ulittle32_t Style;
      ulittle32_t ExtStyle;
    } Prefix{ulittle32_t(UsedStyle),
             ulittle32_t(ExStyle)};

    writeObject(Prefix);
  } else {
    struct {
      ulittle16_t Version;
      ulittle16_t Magic;
      ulittle32_t HelpID;
      ulittle32_t ExtStyle;
      ulittle32_t Style;
    } Prefix{ulittle16_t(1), ulittle16_t(DialogExMagic),
             ulittle32_t(Res->HelpID), ulittle32_t(ExStyle), ulittle32_t(UsedStyle)};

    writeObject(Prefix);
  }

  // Now, a common part. First, fixed-length fields.
  RETURN_IF_ERROR(checkNumberFits<uint16_t>(Res->Controls.size(),
                                            "Number of dialog controls"));
  RETURN_IF_ERROR(
      checkSignedNumberFits<int16_t>(Res->X, "Dialog x-coordinate", true));
  RETURN_IF_ERROR(
      checkSignedNumberFits<int16_t>(Res->Y, "Dialog y-coordinate", true));
  RETURN_IF_ERROR(
      checkSignedNumberFits<int16_t>(Res->Width, "Dialog width", false));
  RETURN_IF_ERROR(
      checkSignedNumberFits<int16_t>(Res->Height, "Dialog height", false));
  struct {
    ulittle16_t Count;
    ulittle16_t PosX;
    ulittle16_t PosY;
    ulittle16_t DialogWidth;
    ulittle16_t DialogHeight;
  } Middle{ulittle16_t(Res->Controls.size()), ulittle16_t(Res->X),
           ulittle16_t(Res->Y), ulittle16_t(Res->Width),
           ulittle16_t(Res->Height)};
  writeObject(Middle);

  // MENU field. As of now, we don't keep them in the state and can peacefully
  // think there is no menu attached to the dialog.
  writeInt<uint16_t>(0);

  // Window CLASS field.
  RETURN_IF_ERROR(writeIntOrString(ObjectData.Class));

  // Window title or a single word equal to 0.
  RETURN_IF_ERROR(writeCString(ObjectData.Caption));

  // If there *is* a window font declared, output its data.
  auto &Font = ObjectData.Font;
  if (Font) {
    writeInt<uint16_t>(Font->Size);
    // Additional description occurs only in DIALOGEX.
    if (Res->IsExtended) {
      writeInt<uint16_t>(Font->Weight);
      writeInt<uint8_t>(Font->IsItalic);
      writeInt<uint8_t>(Font->Charset);
    }
    RETURN_IF_ERROR(writeCString(Font->Typeface));
  }

  auto handleCtlError = [&](Error &&Err, const Control &Ctl) -> Error {
    if (!Err)
      return Error::success();
    return joinErrors(createError("Error in " + Twine(Ctl.Type) +
                                  " control  (ID " + Twine(Ctl.ID) + "):"),
                      std::move(Err));
  };

  for (auto &Ctl : Res->Controls)
    RETURN_IF_ERROR(
        handleCtlError(writeSingleDialogControl(Ctl, Res->IsExtended), Ctl));

  return Error::success();
}

// --- HTMLResource helpers. --- //

Error ResourceFileWriter::writeHTMLBody(const RCResource *Base) {
  return appendFile(cast<HTMLResource>(Base)->HTMLLoc);
}

// --- MenuResource helpers. --- //

Error ResourceFileWriter::writeMenuDefinition(
    const std::unique_ptr<MenuDefinition> &Def, uint16_t Flags) {
  assert(Def);
  const MenuDefinition *DefPtr = Def.get();

  if (auto *MenuItemPtr = dyn_cast<MenuItem>(DefPtr)) {
    writeInt<uint16_t>(Flags);
    // Some resource files use -1, i.e. UINT32_MAX, for empty menu items.
    if (MenuItemPtr->Id != static_cast<uint32_t>(-1))
      RETURN_IF_ERROR(
          checkNumberFits<uint16_t>(MenuItemPtr->Id, "MENUITEM action ID"));
    writeInt<uint16_t>(MenuItemPtr->Id);
    RETURN_IF_ERROR(writeCString(MenuItemPtr->Name));
    return Error::success();
  }

  if (isa<MenuSeparator>(DefPtr)) {
    writeInt<uint16_t>(Flags);
    writeInt<uint32_t>(0);
    return Error::success();
  }

  auto *PopupPtr = cast<PopupItem>(DefPtr);
  writeInt<uint16_t>(Flags);
  RETURN_IF_ERROR(writeCString(PopupPtr->Name));
  return writeMenuDefinitionList(PopupPtr->SubItems);
}

Error ResourceFileWriter::writeMenuDefinitionList(
    const MenuDefinitionList &List) {
  for (auto &Def : List.Definitions) {
    uint16_t Flags = Def->getResFlags();
    // Last element receives an additional 0x80 flag.
    const uint16_t LastElementFlag = 0x0080;
    if (&Def == &List.Definitions.back())
      Flags |= LastElementFlag;

    RETURN_IF_ERROR(writeMenuDefinition(Def, Flags));
  }
  return Error::success();
}

Error ResourceFileWriter::writeMenuBody(const RCResource *Base) {
  // At first, MENUHEADER structure. In fact, these are two WORDs equal to 0.
  // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648018.aspx
  writeInt<uint32_t>(0);

  return writeMenuDefinitionList(cast<MenuResource>(Base)->Elements);
}

// --- StringTableResource helpers. --- //

class BundleResource : public RCResource {
public:
  using BundleType = ResourceFileWriter::StringTableInfo::Bundle;
  BundleType Bundle;

  BundleResource(const BundleType &StrBundle)
      : RCResource(StrBundle.MemoryFlags), Bundle(StrBundle) {}
  IntOrString getResourceType() const override { return 6; }

  ResourceKind getKind() const override { return RkStringTableBundle; }
  static bool classof(const RCResource *Res) {
    return Res->getKind() == RkStringTableBundle;
  }
  Twine getResourceTypeName() const override { return "STRINGTABLE"; }
};

Error ResourceFileWriter::visitStringTableBundle(const RCResource *Res) {
  return writeResource(Res, &ResourceFileWriter::writeStringTableBundleBody);
}

Error ResourceFileWriter::insertStringIntoBundle(
    StringTableInfo::Bundle &Bundle, uint16_t StringID,
    const std::vector<StringRef> &String) {
  uint16_t StringLoc = StringID & 15;
  if (Bundle.Data[StringLoc])
    return createError("Multiple STRINGTABLE strings located under ID " +
                       Twine(StringID));
  Bundle.Data[StringLoc] = String;
  return Error::success();
}

Error ResourceFileWriter::writeStringTableBundleBody(const RCResource *Base) {
  auto *Res = cast<BundleResource>(Base);
  for (size_t ID = 0; ID < Res->Bundle.Data.size(); ++ID) {
    // The string format is a tiny bit different here. We
    // first output the size of the string, and then the string itself
    // (which is not null-terminated).
    SmallVector<UTF16, 128> Data;
    if (Res->Bundle.Data[ID]) {
      bool IsLongString;
      for (StringRef S : *Res->Bundle.Data[ID])
        RETURN_IF_ERROR(processString(S, NullHandlingMethod::CutAtDoubleNull,
                                      IsLongString, Data, Params.CodePage));
      if (AppendNull)
        Data.push_back('\0');
    }
    RETURN_IF_ERROR(
        checkNumberFits<uint16_t>(Data.size(), "STRINGTABLE string size"));
    writeInt<uint16_t>(Data.size());
    for (auto Char : Data)
      writeInt(Char);
  }
  return Error::success();
}

Error ResourceFileWriter::dumpAllStringTables() {
  for (auto Key : StringTableData.BundleList) {
    auto Iter = StringTableData.BundleData.find(Key);
    assert(Iter != StringTableData.BundleData.end());

    // For a moment, revert the context info to moment of bundle declaration.
    ContextKeeper RAII(this);
    ObjectData = Iter->second.DeclTimeInfo;

    BundleResource Res(Iter->second);
    // Bundle #(k+1) contains keys [16k, 16k + 15].
    Res.setName(Key.first + 1);
    RETURN_IF_ERROR(visitStringTableBundle(&Res));
  }
  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, Params.CodePage));

    for (auto Ch : ProcessedString) {
      if (IsLongString) {
        writeInt(Ch);
        continue;
      }

      RETURN_IF_ERROR(checkNumberFits<uint8_t>(
          Ch, "Character in narrow string in user-defined resource"));
      writeInt<uint8_t>(Ch);
    }
  }

  return Error::success();
}

// --- VersionInfoResourceResource helpers. --- //

Error ResourceFileWriter::writeVersionInfoBlock(const VersionInfoBlock &Blk) {
  // Output the header if the block has name.
  bool OutputHeader = Blk.Name != "";
  uint64_t LengthLoc;

  padStream(sizeof(uint32_t));
  if (OutputHeader) {
    LengthLoc = writeInt<uint16_t>(0);
    writeInt<uint16_t>(0);
    writeInt<uint16_t>(1); // true
    RETURN_IF_ERROR(writeCString(Blk.Name));
    padStream(sizeof(uint32_t));
  }

  for (const std::unique_ptr<VersionInfoStmt> &Item : Blk.Stmts) {
    VersionInfoStmt *ItemPtr = Item.get();

    if (auto *BlockPtr = dyn_cast<VersionInfoBlock>(ItemPtr)) {
      RETURN_IF_ERROR(writeVersionInfoBlock(*BlockPtr));
      continue;
    }

    auto *ValuePtr = cast<VersionInfoValue>(ItemPtr);
    RETURN_IF_ERROR(writeVersionInfoValue(*ValuePtr));
  }

  if (OutputHeader) {
    uint64_t CurLoc = tell();
    writeObjectAt(ulittle16_t(CurLoc - LengthLoc), LengthLoc);
  }

  return Error::success();
}

Error ResourceFileWriter::writeVersionInfoValue(const VersionInfoValue &Val) {
  // rc has a peculiar algorithm to output VERSIONINFO VALUEs. Each VALUE
  // is a mapping from the key (string) to the value (a sequence of ints or
  // a sequence of strings).
  //
  // If integers are to be written: width of each integer written depends on
  // whether it's been declared 'long' (it's DWORD then) or not (it's WORD).
  // ValueLength defined in structure referenced below is then the total
  // number of bytes taken by these integers.
  //
  // If strings are to be written: characters are always WORDs.
  // Moreover, '\0' character is written after the last string, and between
  // every two strings separated by comma (if strings are not comma-separated,
  // they're simply concatenated). ValueLength is equal to the number of WORDs
  // written (that is, half of the bytes written).
  //
  // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms646994.aspx
  bool HasStrings = false, HasInts = false;
  for (auto &Item : Val.Values)
    (Item.isInt() ? HasInts : HasStrings) = true;

  assert((HasStrings || HasInts) && "VALUE must have at least one argument");
  if (HasStrings && HasInts)
    return createError(Twine("VALUE ") + Val.Key +
                       " cannot contain both strings and integers");

  padStream(sizeof(uint32_t));
  auto LengthLoc = writeInt<uint16_t>(0);
  auto ValLengthLoc = writeInt<uint16_t>(0);
  writeInt<uint16_t>(HasStrings);
  RETURN_IF_ERROR(writeCString(Val.Key));
  padStream(sizeof(uint32_t));

  auto DataLoc = tell();
  for (size_t Id = 0; Id < Val.Values.size(); ++Id) {
    auto &Item = Val.Values[Id];
    if (Item.isInt()) {
      auto Value = Item.getInt();
      RETURN_IF_ERROR(checkRCInt(Value, "VERSIONINFO integer value"));
      writeRCInt(Value);
      continue;
    }

    bool WriteTerminator =
        Id == Val.Values.size() - 1 || Val.HasPrecedingComma[Id + 1];
    RETURN_IF_ERROR(writeCString(Item.getString(), WriteTerminator));
  }

  auto CurLoc = tell();
  auto ValueLength = CurLoc - DataLoc;
  if (HasStrings) {
    assert(ValueLength % 2 == 0);
    ValueLength /= 2;
  }
  writeObjectAt(ulittle16_t(CurLoc - LengthLoc), LengthLoc);
  writeObjectAt(ulittle16_t(ValueLength), ValLengthLoc);
  return Error::success();
}

template <typename Ty>
static Ty getWithDefault(const StringMap<Ty> &Map, StringRef Key,
                         const Ty &Default) {
  auto Iter = Map.find(Key);
  if (Iter != Map.end())
    return Iter->getValue();
  return Default;
}

Error ResourceFileWriter::writeVersionInfoBody(const RCResource *Base) {
  auto *Res = cast<VersionInfoResource>(Base);

  const auto &FixedData = Res->FixedData;

  struct /* VS_FIXEDFILEINFO */ {
    ulittle32_t Signature = ulittle32_t(0xFEEF04BD);
    ulittle32_t StructVersion = ulittle32_t(0x10000);
    // It's weird to have most-significant DWORD first on the little-endian
    // machines, but let it be this way.
    ulittle32_t FileVersionMS;
    ulittle32_t FileVersionLS;
    ulittle32_t ProductVersionMS;
    ulittle32_t ProductVersionLS;
    ulittle32_t FileFlagsMask;
    ulittle32_t FileFlags;
    ulittle32_t FileOS;
    ulittle32_t FileType;
    ulittle32_t FileSubtype;
    // MS implementation seems to always set these fields to 0.
    ulittle32_t FileDateMS = ulittle32_t(0);
    ulittle32_t FileDateLS = ulittle32_t(0);
  } FixedInfo;

  // First, VS_VERSIONINFO.
  auto LengthLoc = writeInt<uint16_t>(0);
  writeInt<uint16_t>(sizeof(FixedInfo));
  writeInt<uint16_t>(0);
  cantFail(writeCString("VS_VERSION_INFO"));
  padStream(sizeof(uint32_t));

  using VersionInfoFixed = VersionInfoResource::VersionInfoFixed;
  auto GetField = [&](VersionInfoFixed::VersionInfoFixedType Type) {
    static const SmallVector<uint32_t, 4> DefaultOut{0, 0, 0, 0};
    if (!FixedData.IsTypePresent[(int)Type])
      return DefaultOut;
    return FixedData.FixedInfo[(int)Type];
  };

  auto FileVer = GetField(VersionInfoFixed::FtFileVersion);
  RETURN_IF_ERROR(checkNumberFits<uint16_t>(
      *std::max_element(FileVer.begin(), FileVer.end()), "FILEVERSION fields"));
  FixedInfo.FileVersionMS = (FileVer[0] << 16) | FileVer[1];
  FixedInfo.FileVersionLS = (FileVer[2] << 16) | FileVer[3];

  auto ProdVer = GetField(VersionInfoFixed::FtProductVersion);
  RETURN_IF_ERROR(checkNumberFits<uint16_t>(
      *std::max_element(ProdVer.begin(), ProdVer.end()),
      "PRODUCTVERSION fields"));
  FixedInfo.ProductVersionMS = (ProdVer[0] << 16) | ProdVer[1];
  FixedInfo.ProductVersionLS = (ProdVer[2] << 16) | ProdVer[3];

  FixedInfo.FileFlagsMask = GetField(VersionInfoFixed::FtFileFlagsMask)[0];
  FixedInfo.FileFlags = GetField(VersionInfoFixed::FtFileFlags)[0];
  FixedInfo.FileOS = GetField(VersionInfoFixed::FtFileOS)[0];
  FixedInfo.FileType = GetField(VersionInfoFixed::FtFileType)[0];
  FixedInfo.FileSubtype = GetField(VersionInfoFixed::FtFileSubtype)[0];

  writeObject(FixedInfo);
  padStream(sizeof(uint32_t));

  RETURN_IF_ERROR(writeVersionInfoBlock(Res->MainBlock));

  // FIXME: check overflow?
  writeObjectAt(ulittle16_t(tell() - LengthLoc), LengthLoc);

  return Error::success();
}

Expected<std::unique_ptr<MemoryBuffer>>
ResourceFileWriter::loadFile(StringRef File) const {
  SmallString<128> Path;
  SmallString<128> Cwd;
  std::unique_ptr<MemoryBuffer> Result;

  // 0. The file path is absolute or has a root directory, so we shouldn't
  // try to append it on top of other base directories. (An absolute path
  // must have a root directory, but e.g. the path "\dir\file" on windows
  // isn't considered absolute, but it does have a root directory. As long as
  // sys::path::append doesn't handle appending an absolute path or a path
  // starting with a root directory on top of a base, we must handle this
  // case separately at the top. C++17's path::append handles that case
  // properly though, so if using that to append paths below, this early
  // exception case could be removed.)
  if (sys::path::has_root_directory(File))
    return errorOrToExpected(MemoryBuffer::getFile(
        File, /*IsText=*/false, /*RequiresNullTerminator=*/false));

  // 1. The current working directory.
  sys::fs::current_path(Cwd);
  Path.assign(Cwd.begin(), Cwd.end());
  sys::path::append(Path, File);
  if (sys::fs::exists(Path))
    return errorOrToExpected(MemoryBuffer::getFile(
        Path, /*IsText=*/false, /*RequiresNullTerminator=*/false));

  // 2. The directory of the input resource file, if it is different from the
  // current working directory.
  StringRef InputFileDir = sys::path::parent_path(Params.InputFilePath);
  Path.assign(InputFileDir.begin(), InputFileDir.end());
  sys::path::append(Path, File);
  if (sys::fs::exists(Path))
    return errorOrToExpected(MemoryBuffer::getFile(
        Path, /*IsText=*/false, /*RequiresNullTerminator=*/false));

  // 3. All of the include directories specified on the command line.
  for (StringRef ForceInclude : Params.Include) {
    Path.assign(ForceInclude.begin(), ForceInclude.end());
    sys::path::append(Path, File);
    if (sys::fs::exists(Path))
      return errorOrToExpected(MemoryBuffer::getFile(
          Path, /*IsText=*/false, /*RequiresNullTerminator=*/false));
  }

  if (!Params.NoInclude) {
    if (auto Result = llvm::sys::Process::FindInEnvPath("INCLUDE", File))
      return errorOrToExpected(MemoryBuffer::getFile(
          *Result, /*IsText=*/false, /*RequiresNullTerminator=*/false));
  }

  return make_error<StringError>("error : file not found : " + Twine(File),
                                 inconvertibleErrorCode());
}

} // namespace rc
} // namespace llvm
