//===-- 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/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::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 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);
  IntWithNotMask CtlStyle(TypeInfo.Style);
  CtlStyle |= Ctl.Style.getValueOr(RCInt(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.getValue()), 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.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.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;
  uint32_t ExStyle = ObjectData.ExStyle.getValueOr(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);
    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;

  // 0. The file path is absolute and the file exists.
  if (sys::path::is_absolute(File))
    return errorOrToExpected(MemoryBuffer::getFile(File, -1, 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, -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
