//===-- ResourceFileWriter.cpp --------------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
//
// 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/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_lower("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:
//   * String the string boundary quotes.
//   * 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::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 resouce 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 = dyn_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);
  uint32_t CtlStyle = TypeInfo.Style | Ctl.Style.getValueOr(0);
  uint32_t CtlExtStyle = Ctl.ExtStyle.getValueOr(0);

  // DIALOG(EX) item header prefix.
  if (!IsExtended) {
    struct {
      ulittle32_t Style;
      ulittle32_t ExtStyle;
    } Prefix{ulittle32_t(CtlStyle), ulittle32_t(CtlExtStyle)};
    writeObject(Prefix);
  } else {
    struct {
      ulittle32_t HelpID;
      ulittle32_t ExtStyle;
      ulittle32_t Style;
    } Prefix{ulittle32_t(Ctl.HelpID.getValueOr(0)), ulittle32_t(CtlExtStyle),
             ulittle32_t(CtlStyle)};
    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.getValueOr(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;

  // 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(0)}; // As of now, we don't keep 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(0), 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);
    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, 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).
    bool IsLongString;
    SmallVector<UTF16, 128> Data;
    RETURN_IF_ERROR(processString(Res->Bundle.Data[ID].getValueOr(StringRef()),
                                  NullHandlingMethod::CutAtDoubleNull,
                                  IsLongString, Data, Params.CodePage));
    if (AppendNull && Res->Bundle.Data[ID])
      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;

  // 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, -1, 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, -1, 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, -1, false));
  }

  if (auto Result =
          llvm::sys::Process::FindInEnvPath("INCLUDE", File, Params.NoInclude))
    return errorOrToExpected(MemoryBuffer::getFile(*Result, -1, false));

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

} // namespace rc
} // namespace llvm
