You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
17
external/llvm/tools/llvm-rc/CMakeLists.txt
vendored
17
external/llvm/tools/llvm-rc/CMakeLists.txt
vendored
@ -1,17 +0,0 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
Option
|
||||
Support
|
||||
)
|
||||
|
||||
set(LLVM_TARGET_DEFINITIONS Opts.td)
|
||||
|
||||
tablegen(LLVM Opts.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(RcTableGen)
|
||||
|
||||
add_llvm_tool(llvm-rc
|
||||
llvm-rc.cpp
|
||||
ResourceFileWriter.cpp
|
||||
ResourceScriptParser.cpp
|
||||
ResourceScriptStmt.cpp
|
||||
ResourceScriptToken.cpp
|
||||
)
|
22
external/llvm/tools/llvm-rc/LLVMBuild.txt
vendored
22
external/llvm/tools/llvm-rc/LLVMBuild.txt
vendored
@ -1,22 +0,0 @@
|
||||
;===- ./tools/llvm-rc/LLVMBuild.txt ----------------------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Tool
|
||||
name = llvm-rc
|
||||
parent = Tools
|
||||
required_libraries = Option
|
56
external/llvm/tools/llvm-rc/Opts.td
vendored
56
external/llvm/tools/llvm-rc/Opts.td
vendored
@ -1,56 +0,0 @@
|
||||
include "llvm/Option/OptParser.td"
|
||||
|
||||
// All the switches can be preceded by either '/' or '-'.
|
||||
// These options seem to be important for the tool
|
||||
// and should be implemented.
|
||||
|
||||
def FILEOUT : Separate<[ "/", "-" ], "FO">,
|
||||
HelpText<"Change the output file location.">;
|
||||
|
||||
def DEFINE : Separate<[ "/", "-" ], "D">,
|
||||
HelpText<"Define a symbol for the C preprocessor.">;
|
||||
def UNDEF : Separate<[ "/", "-" ], "U">,
|
||||
HelpText<"Undefine a symbol for the C preprocessor.">;
|
||||
|
||||
def LANG_ID : Separate<[ "/", "-" ], "L">,
|
||||
HelpText<"Set the default language identifier.">;
|
||||
def LANG_NAME : Separate<[ "/", "-" ], "LN">,
|
||||
HelpText<"Set the default language name.">;
|
||||
|
||||
def INCLUDE : Separate<[ "/", "-" ], "I">, HelpText<"Add an include path.">;
|
||||
def NOINCLUDE : Flag<[ "/", "-" ], "X">, HelpText<"Ignore 'include' variable.">;
|
||||
|
||||
def ADD_NULL : Flag<[ "/", "-" ], "N">,
|
||||
HelpText<"Null-terminate all strings in the string table.">;
|
||||
|
||||
def DUPID_NOWARN : Flag<[ "/", "-" ], "Y">,
|
||||
HelpText<"Suppress warnings on duplicate resource IDs.">;
|
||||
|
||||
def VERBOSE : Flag<[ "/", "-" ], "V">, HelpText<"Be verbose.">;
|
||||
def HELP : Flag<[ "/", "-" ], "?">, HelpText<"Display this help and exit.">;
|
||||
def H : Flag<[ "/", "-" ], "H">,
|
||||
Alias<HELP>,
|
||||
HelpText<"Display this help and exit.">;
|
||||
|
||||
def DRY_RUN : Flag<[ "/", "-" ], "dry-run">,
|
||||
HelpText<"Don't compile the input; only try to parse it.">;
|
||||
|
||||
// Unused switches (at least for now). These will stay unimplemented
|
||||
// in an early stage of development and can be ignored. However, we need to
|
||||
// parse them in order to preserve the compatibility with the original tool.
|
||||
|
||||
def NOLOGO : Flag<[ "/", "-" ], "NOLOGO">;
|
||||
def R : Flag<[ "/", "-" ], "R">;
|
||||
def SL : Flag<[ "/", "-" ], "SL">;
|
||||
|
||||
// (Codepages support.)
|
||||
def C : Flag<[ "/", "-" ], "C">;
|
||||
def W : Flag<[ "/", "-" ], "W">;
|
||||
|
||||
// (Support of MUI and similar.)
|
||||
def FM : Separate<[ "/", "-" ], "FM">;
|
||||
def Q : Separate<[ "/", "-" ], "Q">;
|
||||
def G : Flag<[ "/", "-" ], "G">;
|
||||
def GN : Flag<[ "/", "-" ], "GN">;
|
||||
def G1 : Flag<[ "/", "-" ], "G1">;
|
||||
def G2 : Flag<[ "/", "-" ], "G2">;
|
1449
external/llvm/tools/llvm-rc/ResourceFileWriter.cpp
vendored
1449
external/llvm/tools/llvm-rc/ResourceFileWriter.cpp
vendored
File diff suppressed because it is too large
Load Diff
195
external/llvm/tools/llvm-rc/ResourceFileWriter.h
vendored
195
external/llvm/tools/llvm-rc/ResourceFileWriter.h
vendored
@ -1,195 +0,0 @@
|
||||
//===-- ResourceSerializator.h ----------------------------------*- C++-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines a visitor serializing resources to a .res stream.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
|
||||
#define LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
|
||||
|
||||
#include "ResourceScriptStmt.h"
|
||||
#include "ResourceVisitor.h"
|
||||
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MemoryBuffer;
|
||||
|
||||
namespace rc {
|
||||
|
||||
struct SearchParams {
|
||||
std::vector<std::string> Include; // Additional folders to search for files.
|
||||
std::vector<std::string> NoInclude; // Folders to exclude from file search.
|
||||
StringRef InputFilePath; // The full path of the input file.
|
||||
};
|
||||
|
||||
class ResourceFileWriter : public Visitor {
|
||||
public:
|
||||
ResourceFileWriter(const SearchParams &Params,
|
||||
std::unique_ptr<raw_fd_ostream> Stream)
|
||||
: Params(Params), FS(std::move(Stream)), IconCursorID(1) {
|
||||
assert(FS && "Output stream needs to be provided to the serializator");
|
||||
}
|
||||
|
||||
Error visitNullResource(const RCResource *) override;
|
||||
Error visitAcceleratorsResource(const RCResource *) override;
|
||||
Error visitCursorResource(const RCResource *) override;
|
||||
Error visitDialogResource(const RCResource *) override;
|
||||
Error visitHTMLResource(const RCResource *) override;
|
||||
Error visitIconResource(const RCResource *) override;
|
||||
Error visitMenuResource(const RCResource *) override;
|
||||
Error visitVersionInfoResource(const RCResource *) override;
|
||||
Error visitStringTableResource(const RCResource *) override;
|
||||
Error visitUserDefinedResource(const RCResource *) override;
|
||||
|
||||
Error visitCaptionStmt(const CaptionStmt *) override;
|
||||
Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
|
||||
Error visitFontStmt(const FontStmt *) override;
|
||||
Error visitLanguageStmt(const LanguageResource *) override;
|
||||
Error visitStyleStmt(const StyleStmt *) override;
|
||||
Error visitVersionStmt(const VersionStmt *) override;
|
||||
|
||||
// Stringtables are output at the end of .res file. We need a separate
|
||||
// function to do it.
|
||||
Error dumpAllStringTables();
|
||||
|
||||
bool AppendNull; // Append '\0' to each existing STRINGTABLE element?
|
||||
|
||||
struct ObjectInfo {
|
||||
uint16_t LanguageInfo;
|
||||
uint32_t Characteristics;
|
||||
uint32_t VersionInfo;
|
||||
|
||||
Optional<uint32_t> Style;
|
||||
StringRef Caption;
|
||||
struct FontInfo {
|
||||
uint32_t Size;
|
||||
StringRef Typeface;
|
||||
uint32_t Weight;
|
||||
bool IsItalic;
|
||||
uint32_t Charset;
|
||||
};
|
||||
Optional<FontInfo> Font;
|
||||
|
||||
ObjectInfo() : LanguageInfo(0), Characteristics(0), VersionInfo(0) {}
|
||||
} ObjectData;
|
||||
|
||||
struct StringTableInfo {
|
||||
// Each STRINGTABLE bundle depends on ID of the bundle and language
|
||||
// description.
|
||||
using BundleKey = std::pair<uint16_t, uint16_t>;
|
||||
// Each bundle is in fact an array of 16 strings.
|
||||
struct Bundle {
|
||||
std::array<Optional<StringRef>, 16> Data;
|
||||
ObjectInfo DeclTimeInfo;
|
||||
Bundle(const ObjectInfo &Info) : DeclTimeInfo(Info) {}
|
||||
};
|
||||
std::map<BundleKey, Bundle> BundleData;
|
||||
// Bundles are listed in the order of their first occurence.
|
||||
std::vector<BundleKey> BundleList;
|
||||
} StringTableData;
|
||||
|
||||
private:
|
||||
Error handleError(Error Err, const RCResource *Res);
|
||||
|
||||
Error
|
||||
writeResource(const RCResource *Res,
|
||||
Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
|
||||
|
||||
// NullResource
|
||||
Error writeNullBody(const RCResource *);
|
||||
|
||||
// AcceleratorsResource
|
||||
Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
|
||||
bool IsLastItem);
|
||||
Error writeAcceleratorsBody(const RCResource *);
|
||||
|
||||
// CursorResource and IconResource
|
||||
Error visitIconOrCursorResource(const RCResource *);
|
||||
Error visitIconOrCursorGroup(const RCResource *);
|
||||
Error visitSingleIconOrCursor(const RCResource *);
|
||||
Error writeSingleIconOrCursorBody(const RCResource *);
|
||||
Error writeIconOrCursorGroupBody(const RCResource *);
|
||||
|
||||
// DialogResource
|
||||
Error writeSingleDialogControl(const Control &, bool IsExtended);
|
||||
Error writeDialogBody(const RCResource *);
|
||||
|
||||
// HTMLResource
|
||||
Error writeHTMLBody(const RCResource *);
|
||||
|
||||
// MenuResource
|
||||
Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
|
||||
uint16_t Flags);
|
||||
Error writeMenuDefinitionList(const MenuDefinitionList &List);
|
||||
Error writeMenuBody(const RCResource *);
|
||||
|
||||
// StringTableResource
|
||||
Error visitStringTableBundle(const RCResource *);
|
||||
Error writeStringTableBundleBody(const RCResource *);
|
||||
Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
|
||||
uint16_t StringID, StringRef String);
|
||||
|
||||
// User defined resource
|
||||
Error writeUserDefinedBody(const RCResource *);
|
||||
|
||||
// VersionInfoResource
|
||||
Error writeVersionInfoBody(const RCResource *);
|
||||
Error writeVersionInfoBlock(const VersionInfoBlock &);
|
||||
Error writeVersionInfoValue(const VersionInfoValue &);
|
||||
|
||||
const SearchParams &Params;
|
||||
|
||||
// Output stream handling.
|
||||
std::unique_ptr<raw_fd_ostream> FS;
|
||||
|
||||
uint64_t tell() const { return FS->tell(); }
|
||||
|
||||
uint64_t writeObject(const ArrayRef<uint8_t> Data);
|
||||
|
||||
template <typename T> uint64_t writeInt(const T &Value) {
|
||||
support::detail::packed_endian_specific_integral<T, support::little,
|
||||
support::unaligned>
|
||||
Object(Value);
|
||||
return writeObject(Object);
|
||||
}
|
||||
|
||||
template <typename T> uint64_t writeObject(const T &Value) {
|
||||
return writeObject(ArrayRef<uint8_t>(
|
||||
reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
|
||||
}
|
||||
|
||||
template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
|
||||
FS->pwrite((const char *)&Value, sizeof(T), Position);
|
||||
}
|
||||
|
||||
Error writeCString(StringRef Str, bool WriteTerminator = true);
|
||||
|
||||
Error writeIdentifier(const IntOrString &Ident);
|
||||
Error writeIntOrString(const IntOrString &Data);
|
||||
|
||||
void writeRCInt(RCInt);
|
||||
|
||||
Error appendFile(StringRef Filename);
|
||||
|
||||
void padStream(uint64_t Length);
|
||||
|
||||
Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;
|
||||
|
||||
// Icon and cursor IDs are allocated starting from 1 and increasing for
|
||||
// each icon/cursor dumped. This maintains the current ID to be allocated.
|
||||
uint16_t IconCursorID;
|
||||
};
|
||||
|
||||
} // namespace rc
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
714
external/llvm/tools/llvm-rc/ResourceScriptParser.cpp
vendored
714
external/llvm/tools/llvm-rc/ResourceScriptParser.cpp
vendored
File diff suppressed because it is too large
Load Diff
187
external/llvm/tools/llvm-rc/ResourceScriptParser.h
vendored
187
external/llvm/tools/llvm-rc/ResourceScriptParser.h
vendored
@ -1,187 +0,0 @@
|
||||
//===-- ResourceScriptParser.h ----------------------------------*- C++-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines the RC scripts parser. It takes a sequence of RC tokens
|
||||
// and then provides the method to parse the resources one by one.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMRC_RESOURCESCRIPTPARSER_H
|
||||
#define LLVM_TOOLS_LLVMRC_RESOURCESCRIPTPARSER_H
|
||||
|
||||
#include "ResourceScriptStmt.h"
|
||||
#include "ResourceScriptToken.h"
|
||||
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace opt {
|
||||
class InputArgList;
|
||||
}
|
||||
namespace rc {
|
||||
|
||||
class RCParser {
|
||||
public:
|
||||
using LocIter = std::vector<RCToken>::iterator;
|
||||
using ParseType = Expected<std::unique_ptr<RCResource>>;
|
||||
using ParseOptionType = Expected<std::unique_ptr<OptionalStmt>>;
|
||||
|
||||
// Class describing a single failure of parser.
|
||||
class ParserError : public ErrorInfo<ParserError> {
|
||||
public:
|
||||
ParserError(const Twine &Expected, const LocIter CurLoc, const LocIter End);
|
||||
|
||||
void log(raw_ostream &OS) const override { OS << CurMessage; }
|
||||
std::error_code convertToErrorCode() const override {
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
const std::string &getMessage() const { return CurMessage; }
|
||||
|
||||
static char ID; // Keep llvm::Error happy.
|
||||
|
||||
private:
|
||||
std::string CurMessage;
|
||||
LocIter ErrorLoc, FileEnd;
|
||||
};
|
||||
|
||||
explicit RCParser(std::vector<RCToken> TokenList);
|
||||
|
||||
// Reads and returns a single resource definition, or error message if any
|
||||
// occurred.
|
||||
ParseType parseSingleResource();
|
||||
|
||||
bool isEof() const;
|
||||
|
||||
private:
|
||||
using Kind = RCToken::Kind;
|
||||
|
||||
// Checks if the current parser state points to the token of type TokenKind.
|
||||
bool isNextTokenKind(Kind TokenKind) const;
|
||||
|
||||
// These methods assume that the parser is not in EOF state.
|
||||
|
||||
// Take a look at the current token. Do not fetch it.
|
||||
const RCToken &look() const;
|
||||
// Read the current token and advance the state by one token.
|
||||
const RCToken &read();
|
||||
// Advance the state by one token, discarding the current token.
|
||||
void consume();
|
||||
|
||||
// The following methods try to read a single token, check if it has the
|
||||
// correct type and then parse it.
|
||||
// Each integer can be written as an arithmetic expression producing an
|
||||
// unsigned 32-bit integer.
|
||||
Expected<RCInt> readInt(); // Parse an integer.
|
||||
Expected<StringRef> readString(); // Parse a string.
|
||||
Expected<StringRef> readIdentifier(); // Parse an identifier.
|
||||
Expected<IntOrString> readIntOrString(); // Parse an integer or a string.
|
||||
Expected<IntOrString> readTypeOrName(); // Parse an integer or an identifier.
|
||||
|
||||
// Helper integer expression parsing methods.
|
||||
Expected<RCInt> parseIntExpr1();
|
||||
Expected<RCInt> parseIntExpr2();
|
||||
|
||||
// Advance the state by one, discarding the current token.
|
||||
// If the discarded token had an incorrect type, fail.
|
||||
Error consumeType(Kind TokenKind);
|
||||
|
||||
// Check the current token type. If it's TokenKind, discard it.
|
||||
// Return true if the parser consumed this token successfully.
|
||||
bool consumeOptionalType(Kind TokenKind);
|
||||
|
||||
// Read at least MinCount, and at most MaxCount integers separated by
|
||||
// commas. The parser stops reading after fetching MaxCount integers
|
||||
// or after an error occurs. Whenever the parser reads a comma, it
|
||||
// expects an integer to follow.
|
||||
Expected<SmallVector<RCInt, 8>> readIntsWithCommas(size_t MinCount,
|
||||
size_t MaxCount);
|
||||
|
||||
// Read an unknown number of flags preceded by commas. Each correct flag
|
||||
// has an entry in FlagDesc array of length NumFlags. In case i-th
|
||||
// flag (0-based) has been read, the result is OR-ed with FlagValues[i].
|
||||
// As long as parser has a comma to read, it expects to be fed with
|
||||
// a correct flag afterwards.
|
||||
Expected<uint32_t> parseFlags(ArrayRef<StringRef> FlagDesc,
|
||||
ArrayRef<uint32_t> FlagValues);
|
||||
|
||||
// Reads a set of optional statements. These can change the behavior of
|
||||
// a number of resource types (e.g. STRINGTABLE, MENU or DIALOG) if provided
|
||||
// before the main block with the contents of the resource.
|
||||
// Usually, resources use a basic set of optional statements:
|
||||
// CHARACTERISTICS, LANGUAGE, VERSION
|
||||
// However, DIALOG and DIALOGEX extend this list by the following items:
|
||||
// CAPTION, CLASS, EXSTYLE, FONT, MENU, STYLE
|
||||
// UseExtendedStatements flag (off by default) allows the parser to read
|
||||
// the additional types of statements.
|
||||
//
|
||||
// Ref (to the list of all optional statements):
|
||||
// msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
|
||||
enum class OptStmtType { BasicStmt, DialogStmt, DialogExStmt };
|
||||
|
||||
Expected<OptionalStmtList>
|
||||
parseOptionalStatements(OptStmtType StmtsType = OptStmtType::BasicStmt);
|
||||
|
||||
// Read a single optional statement.
|
||||
Expected<std::unique_ptr<OptionalStmt>>
|
||||
parseSingleOptionalStatement(OptStmtType StmtsType = OptStmtType::BasicStmt);
|
||||
|
||||
// Top-level resource parsers.
|
||||
ParseType parseLanguageResource();
|
||||
ParseType parseAcceleratorsResource();
|
||||
ParseType parseCursorResource();
|
||||
ParseType parseDialogResource(bool IsExtended);
|
||||
ParseType parseIconResource();
|
||||
ParseType parseHTMLResource();
|
||||
ParseType parseMenuResource();
|
||||
ParseType parseStringTableResource();
|
||||
ParseType parseUserDefinedResource(IntOrString Type);
|
||||
ParseType parseVersionInfoResource();
|
||||
|
||||
// Helper DIALOG parser - a single control.
|
||||
Expected<Control> parseControl();
|
||||
|
||||
// Helper MENU parser.
|
||||
Expected<MenuDefinitionList> parseMenuItemsList();
|
||||
|
||||
// Helper VERSIONINFO parser - read the contents of a single BLOCK statement,
|
||||
// from BEGIN to END.
|
||||
Expected<std::unique_ptr<VersionInfoBlock>>
|
||||
parseVersionInfoBlockContents(StringRef BlockName);
|
||||
// Helper VERSIONINFO parser - read either VALUE or BLOCK statement.
|
||||
Expected<std::unique_ptr<VersionInfoStmt>> parseVersionInfoStmt();
|
||||
// Helper VERSIONINFO parser - read fixed VERSIONINFO statements.
|
||||
Expected<VersionInfoResource::VersionInfoFixed> parseVersionInfoFixed();
|
||||
|
||||
// Optional statement parsers.
|
||||
ParseOptionType parseLanguageStmt();
|
||||
ParseOptionType parseCharacteristicsStmt();
|
||||
ParseOptionType parseVersionStmt();
|
||||
ParseOptionType parseCaptionStmt();
|
||||
ParseOptionType parseFontStmt(OptStmtType DialogType);
|
||||
ParseOptionType parseStyleStmt();
|
||||
|
||||
// Raises an error. If IsAlreadyRead = false (default), this complains about
|
||||
// the token that couldn't be parsed. If the flag is on, this complains about
|
||||
// the correctly read token that makes no sense (that is, the current parser
|
||||
// state is beyond the erroneous token.)
|
||||
Error getExpectedError(const Twine &Message, bool IsAlreadyRead = false);
|
||||
|
||||
std::vector<RCToken> Tokens;
|
||||
LocIter CurLoc;
|
||||
const LocIter End;
|
||||
};
|
||||
|
||||
} // namespace rc
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
266
external/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
vendored
266
external/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
vendored
@ -1,266 +0,0 @@
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
//
|
||||
// This implements methods defined in ResourceScriptStmt.h.
|
||||
//
|
||||
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380599(v=vs.85).aspx
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#include "ResourceScriptStmt.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace rc {
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const IntOrString &Item) {
|
||||
if (Item.IsInt)
|
||||
return OS << Item.Data.Int;
|
||||
else
|
||||
return OS << Item.Data.String;
|
||||
}
|
||||
|
||||
raw_ostream &OptionalStmtList::log(raw_ostream &OS) const {
|
||||
for (const auto &Stmt : Statements) {
|
||||
OS << " Option: ";
|
||||
Stmt->log(OS);
|
||||
}
|
||||
return OS;
|
||||
}
|
||||
|
||||
raw_ostream &LanguageResource::log(raw_ostream &OS) const {
|
||||
return OS << "Language: " << Lang << ", Sublanguage: " << SubLang << "\n";
|
||||
}
|
||||
|
||||
StringRef AcceleratorsResource::Accelerator::OptionsStr
|
||||
[AcceleratorsResource::Accelerator::NumFlags] = {
|
||||
"ASCII", "VIRTKEY", "NOINVERT", "ALT", "SHIFT", "CONTROL"};
|
||||
|
||||
uint32_t AcceleratorsResource::Accelerator::OptionsFlags
|
||||
[AcceleratorsResource::Accelerator::NumFlags] = {ASCII, VIRTKEY, NOINVERT,
|
||||
ALT, SHIFT, CONTROL};
|
||||
|
||||
raw_ostream &AcceleratorsResource::log(raw_ostream &OS) const {
|
||||
OS << "Accelerators (" << ResName << "): \n";
|
||||
OptStatements->log(OS);
|
||||
for (const auto &Acc : Accelerators) {
|
||||
OS << " Accelerator: " << Acc.Event << " " << Acc.Id;
|
||||
for (size_t i = 0; i < Accelerator::NumFlags; ++i)
|
||||
if (Acc.Flags & Accelerator::OptionsFlags[i])
|
||||
OS << " " << Accelerator::OptionsStr[i];
|
||||
OS << "\n";
|
||||
}
|
||||
return OS;
|
||||
}
|
||||
|
||||
raw_ostream &CursorResource::log(raw_ostream &OS) const {
|
||||
return OS << "Cursor (" << ResName << "): " << CursorLoc << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &IconResource::log(raw_ostream &OS) const {
|
||||
return OS << "Icon (" << ResName << "): " << IconLoc << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &HTMLResource::log(raw_ostream &OS) const {
|
||||
return OS << "HTML (" << ResName << "): " << HTMLLoc << "\n";
|
||||
}
|
||||
|
||||
StringRef MenuDefinition::OptionsStr[MenuDefinition::NumFlags] = {
|
||||
"CHECKED", "GRAYED", "HELP", "INACTIVE", "MENUBARBREAK", "MENUBREAK"};
|
||||
|
||||
uint32_t MenuDefinition::OptionsFlags[MenuDefinition::NumFlags] = {
|
||||
CHECKED, GRAYED, HELP, INACTIVE, MENUBARBREAK, MENUBREAK};
|
||||
|
||||
raw_ostream &MenuDefinition::logFlags(raw_ostream &OS, uint16_t Flags) {
|
||||
for (size_t i = 0; i < NumFlags; ++i)
|
||||
if (Flags & OptionsFlags[i])
|
||||
OS << " " << OptionsStr[i];
|
||||
return OS;
|
||||
}
|
||||
|
||||
raw_ostream &MenuDefinitionList::log(raw_ostream &OS) const {
|
||||
OS << " Menu list starts\n";
|
||||
for (auto &Item : Definitions)
|
||||
Item->log(OS);
|
||||
return OS << " Menu list ends\n";
|
||||
}
|
||||
|
||||
raw_ostream &MenuItem::log(raw_ostream &OS) const {
|
||||
OS << " MenuItem (" << Name << "), ID = " << Id;
|
||||
logFlags(OS, Flags);
|
||||
return OS << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &MenuSeparator::log(raw_ostream &OS) const {
|
||||
return OS << " Menu separator\n";
|
||||
}
|
||||
|
||||
raw_ostream &PopupItem::log(raw_ostream &OS) const {
|
||||
OS << " Popup (" << Name << ")";
|
||||
logFlags(OS, Flags);
|
||||
OS << ":\n";
|
||||
return SubItems.log(OS);
|
||||
}
|
||||
|
||||
raw_ostream &MenuResource::log(raw_ostream &OS) const {
|
||||
OS << "Menu (" << ResName << "):\n";
|
||||
OptStatements->log(OS);
|
||||
return Elements.log(OS);
|
||||
}
|
||||
|
||||
raw_ostream &StringTableResource::log(raw_ostream &OS) const {
|
||||
OS << "StringTable:\n";
|
||||
OptStatements->log(OS);
|
||||
for (const auto &String : Table)
|
||||
OS << " " << String.first << " => " << String.second << "\n";
|
||||
return OS;
|
||||
}
|
||||
|
||||
const StringMap<Control::CtlInfo> Control::SupportedCtls = {
|
||||
{"LTEXT", CtlInfo{0x50020000, ClsStatic, true}},
|
||||
{"CTEXT", CtlInfo{0x50020001, ClsStatic, true}},
|
||||
{"RTEXT", CtlInfo{0x50020002, ClsStatic, true}},
|
||||
{"PUSHBUTTON", CtlInfo{0x50010000, ClsButton, true}},
|
||||
{"DEFPUSHBUTTON", CtlInfo{0x50010001, ClsButton, true}},
|
||||
{"EDITTEXT", CtlInfo{0x50810000, ClsEdit, false}},
|
||||
};
|
||||
|
||||
raw_ostream &Control::log(raw_ostream &OS) const {
|
||||
OS << " Control (" << ID << "): " << Type << ", title: " << Title
|
||||
<< ", loc: (" << X << ", " << Y << "), size: [" << Width << ", " << Height
|
||||
<< "]";
|
||||
if (Style)
|
||||
OS << ", style: " << *Style;
|
||||
if (ExtStyle)
|
||||
OS << ", ext. style: " << *ExtStyle;
|
||||
if (HelpID)
|
||||
OS << ", help ID: " << *HelpID;
|
||||
return OS << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &DialogResource::log(raw_ostream &OS) const {
|
||||
OS << "Dialog" << (IsExtended ? "Ex" : "") << " (" << ResName << "): loc: ("
|
||||
<< X << ", " << Y << "), size: [" << Width << ", " << Height
|
||||
<< "], help ID: " << HelpID << "\n";
|
||||
OptStatements->log(OS);
|
||||
for (auto &Ctl : Controls)
|
||||
Ctl.log(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
raw_ostream &VersionInfoBlock::log(raw_ostream &OS) const {
|
||||
OS << " Start of block (name: " << Name << ")\n";
|
||||
for (auto &Stmt : Stmts)
|
||||
Stmt->log(OS);
|
||||
return OS << " End of block\n";
|
||||
}
|
||||
|
||||
raw_ostream &VersionInfoValue::log(raw_ostream &OS) const {
|
||||
OS << " " << Key << " =>";
|
||||
size_t NumValues = Values.size();
|
||||
for (size_t Id = 0; Id < NumValues; ++Id) {
|
||||
if (Id > 0 && HasPrecedingComma[Id])
|
||||
OS << ",";
|
||||
OS << " " << Values[Id];
|
||||
}
|
||||
return OS << "\n";
|
||||
}
|
||||
|
||||
using VersionInfoFixed = VersionInfoResource::VersionInfoFixed;
|
||||
using VersionInfoFixedType = VersionInfoFixed::VersionInfoFixedType;
|
||||
|
||||
const StringRef
|
||||
VersionInfoFixed::FixedFieldsNames[VersionInfoFixed::FtNumTypes] = {
|
||||
"", "FILEVERSION", "PRODUCTVERSION", "FILEFLAGSMASK",
|
||||
"FILEFLAGS", "FILEOS", "FILETYPE", "FILESUBTYPE"};
|
||||
|
||||
const StringMap<VersionInfoFixedType> VersionInfoFixed::FixedFieldsInfoMap = {
|
||||
{FixedFieldsNames[FtFileVersion], FtFileVersion},
|
||||
{FixedFieldsNames[FtProductVersion], FtProductVersion},
|
||||
{FixedFieldsNames[FtFileFlagsMask], FtFileFlagsMask},
|
||||
{FixedFieldsNames[FtFileFlags], FtFileFlags},
|
||||
{FixedFieldsNames[FtFileOS], FtFileOS},
|
||||
{FixedFieldsNames[FtFileType], FtFileType},
|
||||
{FixedFieldsNames[FtFileSubtype], FtFileSubtype}};
|
||||
|
||||
VersionInfoFixedType VersionInfoFixed::getFixedType(StringRef Type) {
|
||||
auto UpperType = Type.upper();
|
||||
auto Iter = FixedFieldsInfoMap.find(UpperType);
|
||||
if (Iter != FixedFieldsInfoMap.end())
|
||||
return Iter->getValue();
|
||||
return FtUnknown;
|
||||
}
|
||||
|
||||
bool VersionInfoFixed::isTypeSupported(VersionInfoFixedType Type) {
|
||||
return FtUnknown < Type && Type < FtNumTypes;
|
||||
}
|
||||
|
||||
bool VersionInfoFixed::isVersionType(VersionInfoFixedType Type) {
|
||||
switch (Type) {
|
||||
case FtFileVersion:
|
||||
case FtProductVersion:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
raw_ostream &VersionInfoFixed::log(raw_ostream &OS) const {
|
||||
for (int Type = FtUnknown; Type < FtNumTypes; ++Type) {
|
||||
if (!isTypeSupported((VersionInfoFixedType)Type))
|
||||
continue;
|
||||
OS << " Fixed: " << FixedFieldsNames[Type] << ":";
|
||||
for (uint32_t Val : FixedInfo[Type])
|
||||
OS << " " << Val;
|
||||
OS << "\n";
|
||||
}
|
||||
return OS;
|
||||
}
|
||||
|
||||
raw_ostream &VersionInfoResource::log(raw_ostream &OS) const {
|
||||
OS << "VersionInfo (" << ResName << "):\n";
|
||||
FixedData.log(OS);
|
||||
return MainBlock.log(OS);
|
||||
}
|
||||
|
||||
raw_ostream &UserDefinedResource::log(raw_ostream &OS) const {
|
||||
OS << "User-defined (type: " << Type << ", name: " << ResName << "): ";
|
||||
if (IsFileResource)
|
||||
return OS << FileLoc << "\n";
|
||||
OS << "data = ";
|
||||
for (auto &Item : Contents)
|
||||
OS << Item << " ";
|
||||
return OS << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &CharacteristicsStmt::log(raw_ostream &OS) const {
|
||||
return OS << "Characteristics: " << Value << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &VersionStmt::log(raw_ostream &OS) const {
|
||||
return OS << "Version: " << Value << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &CaptionStmt::log(raw_ostream &OS) const {
|
||||
return OS << "Caption: " << Value << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &FontStmt::log(raw_ostream &OS) const {
|
||||
OS << "Font: size = " << Size << ", face = " << Name
|
||||
<< ", weight = " << Weight;
|
||||
if (Italic)
|
||||
OS << ", italic";
|
||||
return OS << ", charset = " << Charset << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &StyleStmt::log(raw_ostream &OS) const {
|
||||
return OS << "Style: " << Value << "\n";
|
||||
}
|
||||
|
||||
} // namespace rc
|
||||
} // namespace llvm
|
827
external/llvm/tools/llvm-rc/ResourceScriptStmt.h
vendored
827
external/llvm/tools/llvm-rc/ResourceScriptStmt.h
vendored
File diff suppressed because it is too large
Load Diff
366
external/llvm/tools/llvm-rc/ResourceScriptToken.cpp
vendored
366
external/llvm/tools/llvm-rc/ResourceScriptToken.cpp
vendored
@ -1,366 +0,0 @@
|
||||
//===-- ResourceScriptToken.cpp ---------------------------------*- C++-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements an interface defined in ResourceScriptToken.h.
|
||||
// In particular, it defines an .rc script tokenizer.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#include "ResourceScriptToken.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
using Kind = RCToken::Kind;
|
||||
|
||||
// Checks if Representation is a correct description of an RC integer.
|
||||
// It should be a 32-bit unsigned integer, either decimal, octal (0[0-7]+),
|
||||
// or hexadecimal (0x[0-9a-f]+). It might be followed by a single 'L'
|
||||
// character (that is the difference between our representation and
|
||||
// StringRef's one). If Representation is correct, 'true' is returned and
|
||||
// the return value is put back in Num.
|
||||
static bool rcGetAsInteger(StringRef Representation, uint32_t &Num) {
|
||||
size_t Length = Representation.size();
|
||||
if (Length == 0)
|
||||
return false;
|
||||
// Strip the last 'L' if unnecessary.
|
||||
if (std::toupper(Representation.back()) == 'L')
|
||||
Representation = Representation.drop_back(1);
|
||||
|
||||
return !Representation.getAsInteger<uint32_t>(0, Num);
|
||||
}
|
||||
|
||||
RCToken::RCToken(RCToken::Kind RCTokenKind, StringRef Value)
|
||||
: TokenKind(RCTokenKind), TokenValue(Value) {}
|
||||
|
||||
uint32_t RCToken::intValue() const {
|
||||
assert(TokenKind == Kind::Int);
|
||||
// We assume that the token already is a correct integer (checked by
|
||||
// rcGetAsInteger).
|
||||
uint32_t Result;
|
||||
bool IsSuccess = rcGetAsInteger(TokenValue, Result);
|
||||
assert(IsSuccess);
|
||||
(void)IsSuccess; // Silence the compiler warning when -DNDEBUG flag is on.
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool RCToken::isLongInt() const {
|
||||
return TokenKind == Kind::Int && std::toupper(TokenValue.back()) == 'L';
|
||||
}
|
||||
|
||||
StringRef RCToken::value() const { return TokenValue; }
|
||||
|
||||
Kind RCToken::kind() const { return TokenKind; }
|
||||
|
||||
bool RCToken::isBinaryOp() const {
|
||||
switch (TokenKind) {
|
||||
case Kind::Plus:
|
||||
case Kind::Minus:
|
||||
case Kind::Pipe:
|
||||
case Kind::Amp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Error getStringError(const Twine &message) {
|
||||
return make_error<StringError>("Error parsing file: " + message,
|
||||
inconvertibleErrorCode());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class Tokenizer {
|
||||
public:
|
||||
Tokenizer(StringRef Input) : Data(Input), DataLength(Input.size()) {}
|
||||
|
||||
Expected<std::vector<RCToken>> run();
|
||||
|
||||
private:
|
||||
// All 'advancing' methods return boolean values; if they're equal to false,
|
||||
// the stream has ended or failed.
|
||||
bool advance(size_t Amount = 1);
|
||||
bool skipWhitespaces();
|
||||
|
||||
// Consumes a token. If any problem occurred, a non-empty Error is returned.
|
||||
Error consumeToken(const Kind TokenKind);
|
||||
|
||||
// Check if tokenizer is about to read FollowingChars.
|
||||
bool willNowRead(StringRef FollowingChars) const;
|
||||
|
||||
// Check if tokenizer can start reading an identifier at current position.
|
||||
// The original tool did non specify the rules to determine what is a correct
|
||||
// identifier. We assume they should follow the C convention:
|
||||
// [a-zA-Z_][a-zA-Z0-9_]*.
|
||||
bool canStartIdentifier() const;
|
||||
// Check if tokenizer can continue reading an identifier.
|
||||
bool canContinueIdentifier() const;
|
||||
|
||||
// Check if tokenizer can start reading an integer.
|
||||
// A correct integer always starts with a 0-9 digit,
|
||||
// can contain characters 0-9A-Fa-f (digits),
|
||||
// Ll (marking the integer is 32-bit), Xx (marking the representation
|
||||
// is hexadecimal). As some kind of separator should come after the
|
||||
// integer, we can consume the integer until a non-alphanumeric
|
||||
// character.
|
||||
bool canStartInt() const;
|
||||
bool canContinueInt() const;
|
||||
|
||||
bool canStartString() const;
|
||||
|
||||
// Check if tokenizer can start reading a single line comment (e.g. a comment
|
||||
// that begins with '//')
|
||||
bool canStartLineComment() const;
|
||||
|
||||
// Check if tokenizer can start or finish reading a block comment (e.g. a
|
||||
// comment that begins with '/*' and ends with '*/')
|
||||
bool canStartBlockComment() const;
|
||||
|
||||
// Throw away all remaining characters on the current line.
|
||||
void skipCurrentLine();
|
||||
|
||||
bool streamEof() const;
|
||||
|
||||
// Classify the token that is about to be read from the current position.
|
||||
Kind classifyCurrentToken() const;
|
||||
|
||||
// Process the Kind::Identifier token - check if it is
|
||||
// an identifier describing a block start or end.
|
||||
void processIdentifier(RCToken &token) const;
|
||||
|
||||
StringRef Data;
|
||||
size_t DataLength, Pos;
|
||||
};
|
||||
|
||||
void Tokenizer::skipCurrentLine() {
|
||||
Pos = Data.find_first_of("\r\n", Pos);
|
||||
Pos = Data.find_first_not_of("\r\n", Pos);
|
||||
|
||||
if (Pos == StringRef::npos)
|
||||
Pos = DataLength;
|
||||
}
|
||||
|
||||
Expected<std::vector<RCToken>> Tokenizer::run() {
|
||||
Pos = 0;
|
||||
std::vector<RCToken> Result;
|
||||
|
||||
// Consume an optional UTF-8 Byte Order Mark.
|
||||
if (willNowRead("\xef\xbb\xbf"))
|
||||
advance(3);
|
||||
|
||||
while (!streamEof()) {
|
||||
if (!skipWhitespaces())
|
||||
break;
|
||||
|
||||
Kind TokenKind = classifyCurrentToken();
|
||||
if (TokenKind == Kind::Invalid)
|
||||
return getStringError("Invalid token found at position " + Twine(Pos));
|
||||
|
||||
const size_t TokenStart = Pos;
|
||||
if (Error TokenError = consumeToken(TokenKind))
|
||||
return std::move(TokenError);
|
||||
|
||||
// Comments are just deleted, don't bother saving them.
|
||||
if (TokenKind == Kind::LineComment || TokenKind == Kind::StartComment)
|
||||
continue;
|
||||
|
||||
RCToken Token(TokenKind, Data.take_front(Pos).drop_front(TokenStart));
|
||||
if (TokenKind == Kind::Identifier) {
|
||||
processIdentifier(Token);
|
||||
} else if (TokenKind == Kind::Int) {
|
||||
uint32_t TokenInt;
|
||||
if (!rcGetAsInteger(Token.value(), TokenInt)) {
|
||||
// The integer has incorrect format or cannot be represented in
|
||||
// a 32-bit integer.
|
||||
return getStringError("Integer invalid or too large: " +
|
||||
Token.value().str());
|
||||
}
|
||||
}
|
||||
|
||||
Result.push_back(Token);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Tokenizer::advance(size_t Amount) {
|
||||
Pos += Amount;
|
||||
return !streamEof();
|
||||
}
|
||||
|
||||
bool Tokenizer::skipWhitespaces() {
|
||||
while (!streamEof() && std::isspace(Data[Pos]))
|
||||
advance();
|
||||
return !streamEof();
|
||||
}
|
||||
|
||||
Error Tokenizer::consumeToken(const Kind TokenKind) {
|
||||
switch (TokenKind) {
|
||||
// One-character token consumption.
|
||||
#define TOKEN(Name)
|
||||
#define SHORT_TOKEN(Name, Ch) case Kind::Name:
|
||||
#include "ResourceScriptTokenList.def"
|
||||
advance();
|
||||
return Error::success();
|
||||
|
||||
case Kind::LineComment:
|
||||
advance(2);
|
||||
skipCurrentLine();
|
||||
return Error::success();
|
||||
|
||||
case Kind::StartComment: {
|
||||
advance(2);
|
||||
auto EndPos = Data.find("*/", Pos);
|
||||
if (EndPos == StringRef::npos)
|
||||
return getStringError(
|
||||
"Unclosed multi-line comment beginning at position " + Twine(Pos));
|
||||
advance(EndPos - Pos);
|
||||
advance(2);
|
||||
return Error::success();
|
||||
}
|
||||
case Kind::Identifier:
|
||||
while (!streamEof() && canContinueIdentifier())
|
||||
advance();
|
||||
return Error::success();
|
||||
|
||||
case Kind::Int:
|
||||
while (!streamEof() && canContinueInt())
|
||||
advance();
|
||||
return Error::success();
|
||||
|
||||
case Kind::String:
|
||||
// Consume the preceding 'L', if there is any.
|
||||
if (std::toupper(Data[Pos]) == 'L')
|
||||
advance();
|
||||
// Consume the double-quote.
|
||||
advance();
|
||||
|
||||
// Consume the characters until the end of the file, line or string.
|
||||
while (true) {
|
||||
if (streamEof()) {
|
||||
return getStringError("Unterminated string literal.");
|
||||
} else if (Data[Pos] == '"') {
|
||||
// Consume the ending double-quote.
|
||||
advance();
|
||||
// However, if another '"' follows this double-quote, the string didn't
|
||||
// end and we just included '"' into the string.
|
||||
if (!willNowRead("\""))
|
||||
return Error::success();
|
||||
} else if (Data[Pos] == '\n') {
|
||||
return getStringError("String literal not terminated in the line.");
|
||||
}
|
||||
|
||||
advance();
|
||||
}
|
||||
|
||||
case Kind::Invalid:
|
||||
assert(false && "Cannot consume an invalid token.");
|
||||
}
|
||||
|
||||
llvm_unreachable("Unknown RCToken::Kind");
|
||||
}
|
||||
|
||||
bool Tokenizer::willNowRead(StringRef FollowingChars) const {
|
||||
return Data.drop_front(Pos).startswith(FollowingChars);
|
||||
}
|
||||
|
||||
bool Tokenizer::canStartIdentifier() const {
|
||||
assert(!streamEof());
|
||||
|
||||
const char CurChar = Data[Pos];
|
||||
return std::isalpha(CurChar) || CurChar == '_';
|
||||
}
|
||||
|
||||
bool Tokenizer::canContinueIdentifier() const {
|
||||
assert(!streamEof());
|
||||
const char CurChar = Data[Pos];
|
||||
return std::isalnum(CurChar) || CurChar == '_';
|
||||
}
|
||||
|
||||
bool Tokenizer::canStartInt() const {
|
||||
assert(!streamEof());
|
||||
return std::isdigit(Data[Pos]);
|
||||
}
|
||||
|
||||
bool Tokenizer::canStartBlockComment() const {
|
||||
assert(!streamEof());
|
||||
return Data.drop_front(Pos).startswith("/*");
|
||||
}
|
||||
|
||||
bool Tokenizer::canStartLineComment() const {
|
||||
assert(!streamEof());
|
||||
return Data.drop_front(Pos).startswith("//");
|
||||
}
|
||||
|
||||
bool Tokenizer::canContinueInt() const {
|
||||
assert(!streamEof());
|
||||
return std::isalnum(Data[Pos]);
|
||||
}
|
||||
|
||||
bool Tokenizer::canStartString() const {
|
||||
return willNowRead("\"") || willNowRead("L\"") || willNowRead("l\"");
|
||||
}
|
||||
|
||||
bool Tokenizer::streamEof() const { return Pos == DataLength; }
|
||||
|
||||
Kind Tokenizer::classifyCurrentToken() const {
|
||||
if (canStartBlockComment())
|
||||
return Kind::StartComment;
|
||||
if (canStartLineComment())
|
||||
return Kind::LineComment;
|
||||
|
||||
if (canStartInt())
|
||||
return Kind::Int;
|
||||
if (canStartString())
|
||||
return Kind::String;
|
||||
// BEGIN and END are at this point of lexing recognized as identifiers.
|
||||
if (canStartIdentifier())
|
||||
return Kind::Identifier;
|
||||
|
||||
const char CurChar = Data[Pos];
|
||||
|
||||
switch (CurChar) {
|
||||
// One-character token classification.
|
||||
#define TOKEN(Name)
|
||||
#define SHORT_TOKEN(Name, Ch) \
|
||||
case Ch: \
|
||||
return Kind::Name;
|
||||
#include "ResourceScriptTokenList.def"
|
||||
|
||||
default:
|
||||
return Kind::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
void Tokenizer::processIdentifier(RCToken &Token) const {
|
||||
assert(Token.kind() == Kind::Identifier);
|
||||
StringRef Name = Token.value();
|
||||
|
||||
if (Name.equals_lower("begin"))
|
||||
Token = RCToken(Kind::BlockBegin, Name);
|
||||
else if (Name.equals_lower("end"))
|
||||
Token = RCToken(Kind::BlockEnd, Name);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
Expected<std::vector<RCToken>> tokenizeRC(StringRef Input) {
|
||||
return Tokenizer(Input).run();
|
||||
}
|
||||
|
||||
} // namespace llvm
|
@ -1,83 +0,0 @@
|
||||
//===-- ResourceScriptToken.h -----------------------------------*- C++-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
//
|
||||
// This declares the .rc script tokens and defines an interface for tokenizing
|
||||
// the input data. The list of available tokens is located at
|
||||
// ResourceScriptTokenList.def.
|
||||
//
|
||||
// Note that the tokenizer does not support comments or preprocessor
|
||||
// directives. The preprocessor should do its work on the .rc file before
|
||||
// running llvm-rc.
|
||||
//
|
||||
// As for now, it is possible to parse ASCII files only (the behavior on
|
||||
// UTF files might be undefined). However, it already consumes UTF-8 BOM, if
|
||||
// there is any. Thus, ASCII-compatible UTF-8 files are tokenized correctly.
|
||||
//
|
||||
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380599(v=vs.85).aspx
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMRC_RESOURCESCRIPTTOKEN_H
|
||||
#define LLVM_TOOLS_LLVMRC_RESOURCESCRIPTTOKEN_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// A definition of a single resource script token. Each token has its kind
|
||||
// (declared in ResourceScriptTokenList) and holds a value - a reference
|
||||
// representation of the token.
|
||||
// RCToken does not claim ownership on its value. A memory buffer containing
|
||||
// the token value should be stored in a safe place and cannot be freed
|
||||
// nor reallocated.
|
||||
class RCToken {
|
||||
public:
|
||||
enum class Kind {
|
||||
#define TOKEN(Name) Name,
|
||||
#define SHORT_TOKEN(Name, Ch) Name,
|
||||
#include "ResourceScriptTokenList.def"
|
||||
};
|
||||
|
||||
RCToken(RCToken::Kind RCTokenKind, StringRef Value);
|
||||
|
||||
// Get an integer value of the integer token.
|
||||
uint32_t intValue() const;
|
||||
bool isLongInt() const;
|
||||
|
||||
StringRef value() const;
|
||||
Kind kind() const;
|
||||
|
||||
// Check if a token describes a binary operator.
|
||||
bool isBinaryOp() const;
|
||||
|
||||
private:
|
||||
Kind TokenKind;
|
||||
StringRef TokenValue;
|
||||
};
|
||||
|
||||
// Tokenize Input.
|
||||
// In case no error occured, the return value contains
|
||||
// tokens in order they were in the input file.
|
||||
// In case of any error, the return value contains
|
||||
// a textual representation of error.
|
||||
//
|
||||
// Tokens returned by this function hold only references to the parts
|
||||
// of the Input. Memory buffer containing Input cannot be freed,
|
||||
// modified or reallocated.
|
||||
Expected<std::vector<RCToken>> tokenizeRC(StringRef Input);
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -1,40 +0,0 @@
|
||||
//===-- ResourceScriptTokenList.h -------------------------------*- C++-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a part of llvm-rc tokenizer. It lists all the possible tokens
|
||||
// that might occur in a correct .rc script.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
|
||||
// Long tokens. They might consist of more than one character.
|
||||
TOKEN(Invalid) // Invalid token. Should not occur in a valid script.
|
||||
TOKEN(Int) // Integer (decimal, octal or hexadecimal).
|
||||
TOKEN(String) // String value.
|
||||
TOKEN(Identifier) // Script identifier (resource name or type).
|
||||
TOKEN(LineComment) // Beginning of single-line comment.
|
||||
TOKEN(StartComment) // Beginning of multi-line comment.
|
||||
|
||||
// Short tokens. They usually consist of exactly one character.
|
||||
// The definitions are of the form SHORT_TOKEN(TokenName, TokenChar).
|
||||
// TokenChar is the one-character token representation occuring in the correct
|
||||
// .rc scripts.
|
||||
SHORT_TOKEN(BlockBegin, '{') // Start of the script block; can also be BEGIN.
|
||||
SHORT_TOKEN(BlockEnd, '}') // End of the block; can also be END.
|
||||
SHORT_TOKEN(Comma, ',') // Comma - resource arguments separator.
|
||||
SHORT_TOKEN(Plus, '+') // Addition operator.
|
||||
SHORT_TOKEN(Minus, '-') // Subtraction operator.
|
||||
SHORT_TOKEN(Pipe, '|') // Bitwise-OR operator.
|
||||
SHORT_TOKEN(Amp, '&') // Bitwise-AND operator.
|
||||
SHORT_TOKEN(Tilde, '~') // Bitwise-NOT operator.
|
||||
SHORT_TOKEN(LeftParen, '(') // Left parenthesis in the script expressions.
|
||||
SHORT_TOKEN(RightParen, ')') // Right parenthesis.
|
||||
|
||||
#undef TOKEN
|
||||
#undef SHORT_TOKEN
|
57
external/llvm/tools/llvm-rc/ResourceVisitor.h
vendored
57
external/llvm/tools/llvm-rc/ResourceVisitor.h
vendored
@ -1,57 +0,0 @@
|
||||
//===-- ResourceVisitor.h ---------------------------------------*- C++-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines a base class visiting resource script resources.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMRC_RESOURCEVISITOR_H
|
||||
#define LLVM_TOOLS_LLVMRC_RESOURCEVISITOR_H
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace rc {
|
||||
|
||||
class RCResource;
|
||||
|
||||
class CaptionStmt;
|
||||
class CharacteristicsStmt;
|
||||
class FontStmt;
|
||||
class LanguageResource;
|
||||
class StyleStmt;
|
||||
class VersionStmt;
|
||||
|
||||
class Visitor {
|
||||
public:
|
||||
virtual Error visitNullResource(const RCResource *) = 0;
|
||||
virtual Error visitAcceleratorsResource(const RCResource *) = 0;
|
||||
virtual Error visitCursorResource(const RCResource *) = 0;
|
||||
virtual Error visitDialogResource(const RCResource *) = 0;
|
||||
virtual Error visitHTMLResource(const RCResource *) = 0;
|
||||
virtual Error visitIconResource(const RCResource *) = 0;
|
||||
virtual Error visitMenuResource(const RCResource *) = 0;
|
||||
virtual Error visitStringTableResource(const RCResource *) = 0;
|
||||
virtual Error visitUserDefinedResource(const RCResource *) = 0;
|
||||
virtual Error visitVersionInfoResource(const RCResource *) = 0;
|
||||
|
||||
virtual Error visitCaptionStmt(const CaptionStmt *) = 0;
|
||||
virtual Error visitCharacteristicsStmt(const CharacteristicsStmt *) = 0;
|
||||
virtual Error visitFontStmt(const FontStmt *) = 0;
|
||||
virtual Error visitLanguageStmt(const LanguageResource *) = 0;
|
||||
virtual Error visitStyleStmt(const StyleStmt *) = 0;
|
||||
virtual Error visitVersionStmt(const VersionStmt *) = 0;
|
||||
|
||||
virtual ~Visitor() {}
|
||||
};
|
||||
|
||||
} // namespace rc
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
185
external/llvm/tools/llvm-rc/llvm-rc.cpp
vendored
185
external/llvm/tools/llvm-rc/llvm-rc.cpp
vendored
@ -1,185 +0,0 @@
|
||||
//===-- llvm-rc.cpp - Compile .rc scripts into .res -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Compile .rc scripts into .res files. This is intended to be a
|
||||
// platform-independent port of Microsoft's rc.exe tool.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ResourceFileWriter.h"
|
||||
#include "ResourceScriptParser.h"
|
||||
#include "ResourceScriptStmt.h"
|
||||
#include "ResourceScriptToken.h"
|
||||
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/PrettyStackTrace.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <system_error>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::rc;
|
||||
|
||||
namespace {
|
||||
|
||||
// Input options tables.
|
||||
|
||||
enum ID {
|
||||
OPT_INVALID = 0, // This is not a correct option ID.
|
||||
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES) \
|
||||
OPT_##ID,
|
||||
#include "Opts.inc"
|
||||
#undef OPTION
|
||||
};
|
||||
|
||||
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
|
||||
#include "Opts.inc"
|
||||
#undef PREFIX
|
||||
|
||||
static const opt::OptTable::Info InfoTable[] = {
|
||||
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES) \
|
||||
{ \
|
||||
PREFIX, NAME, HELPTEXT, \
|
||||
METAVAR, OPT_##ID, opt::Option::KIND##Class, \
|
||||
PARAM, FLAGS, OPT_##GROUP, \
|
||||
OPT_##ALIAS, ALIASARGS, VALUES},
|
||||
#include "Opts.inc"
|
||||
#undef OPTION
|
||||
};
|
||||
|
||||
class RcOptTable : public opt::OptTable {
|
||||
public:
|
||||
RcOptTable() : OptTable(InfoTable, /* IgnoreCase = */ true) {}
|
||||
};
|
||||
|
||||
static ExitOnError ExitOnErr;
|
||||
|
||||
LLVM_ATTRIBUTE_NORETURN static void fatalError(const Twine &Message) {
|
||||
errs() << Message << "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int main(int argc_, const char *argv_[]) {
|
||||
sys::PrintStackTraceOnErrorSignal(argv_[0]);
|
||||
PrettyStackTraceProgram X(argc_, argv_);
|
||||
|
||||
ExitOnErr.setBanner("llvm-rc: ");
|
||||
|
||||
SmallVector<const char *, 256> argv;
|
||||
SpecificBumpPtrAllocator<char> ArgAllocator;
|
||||
ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector(
|
||||
argv, makeArrayRef(argv_, argc_), ArgAllocator)));
|
||||
|
||||
llvm_shutdown_obj Y;
|
||||
|
||||
RcOptTable T;
|
||||
unsigned MAI, MAC;
|
||||
ArrayRef<const char *> ArgsArr = makeArrayRef(argv_ + 1, argc_);
|
||||
opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC);
|
||||
|
||||
// The tool prints nothing when invoked with no command-line arguments.
|
||||
if (InputArgs.hasArg(OPT_HELP)) {
|
||||
T.PrintHelp(outs(), "rc", "Resource Converter", false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const bool BeVerbose = InputArgs.hasArg(OPT_VERBOSE);
|
||||
|
||||
std::vector<std::string> InArgsInfo = InputArgs.getAllArgValues(OPT_INPUT);
|
||||
if (InArgsInfo.size() != 1) {
|
||||
fatalError("Exactly one input file should be provided.");
|
||||
}
|
||||
|
||||
// Read and tokenize the input file.
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> File =
|
||||
MemoryBuffer::getFile(InArgsInfo[0]);
|
||||
if (!File) {
|
||||
fatalError("Error opening file '" + Twine(InArgsInfo[0]) +
|
||||
"': " + File.getError().message());
|
||||
}
|
||||
|
||||
std::unique_ptr<MemoryBuffer> FileContents = std::move(*File);
|
||||
StringRef Contents = FileContents->getBuffer();
|
||||
|
||||
std::vector<RCToken> Tokens = ExitOnErr(tokenizeRC(Contents));
|
||||
|
||||
if (BeVerbose) {
|
||||
const Twine TokenNames[] = {
|
||||
#define TOKEN(Name) #Name,
|
||||
#define SHORT_TOKEN(Name, Ch) #Name,
|
||||
#include "ResourceScriptTokenList.def"
|
||||
};
|
||||
|
||||
for (const RCToken &Token : Tokens) {
|
||||
outs() << TokenNames[static_cast<int>(Token.kind())] << ": "
|
||||
<< Token.value();
|
||||
if (Token.kind() == RCToken::Kind::Int)
|
||||
outs() << "; int value = " << Token.intValue();
|
||||
|
||||
outs() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
SearchParams Params;
|
||||
SmallString<128> InputFile(InArgsInfo[0]);
|
||||
llvm::sys::fs::make_absolute(InputFile);
|
||||
Params.InputFilePath = InputFile;
|
||||
Params.Include = InputArgs.getAllArgValues(OPT_INCLUDE);
|
||||
Params.NoInclude = InputArgs.getAllArgValues(OPT_NOINCLUDE);
|
||||
|
||||
std::unique_ptr<ResourceFileWriter> Visitor;
|
||||
bool IsDryRun = InputArgs.hasArg(OPT_DRY_RUN);
|
||||
|
||||
if (!IsDryRun) {
|
||||
auto OutArgsInfo = InputArgs.getAllArgValues(OPT_FILEOUT);
|
||||
if (OutArgsInfo.size() != 1)
|
||||
fatalError(
|
||||
"Exactly one output file should be provided (using /FO flag).");
|
||||
|
||||
std::error_code EC;
|
||||
auto FOut =
|
||||
llvm::make_unique<raw_fd_ostream>(OutArgsInfo[0], EC, sys::fs::F_RW);
|
||||
if (EC)
|
||||
fatalError("Error opening output file '" + OutArgsInfo[0] +
|
||||
"': " + EC.message());
|
||||
Visitor = llvm::make_unique<ResourceFileWriter>(Params, std::move(FOut));
|
||||
Visitor->AppendNull = InputArgs.hasArg(OPT_ADD_NULL);
|
||||
|
||||
ExitOnErr(NullResource().visit(Visitor.get()));
|
||||
|
||||
// Set the default language; choose en-US arbitrarily.
|
||||
ExitOnErr(LanguageResource(0x09, 0x01).visit(Visitor.get()));
|
||||
}
|
||||
|
||||
rc::RCParser Parser{std::move(Tokens)};
|
||||
while (!Parser.isEof()) {
|
||||
auto Resource = ExitOnErr(Parser.parseSingleResource());
|
||||
if (BeVerbose)
|
||||
Resource->log(outs());
|
||||
if (!IsDryRun)
|
||||
ExitOnErr(Resource->visit(Visitor.get()));
|
||||
}
|
||||
|
||||
// STRINGTABLE resources come at the very end.
|
||||
if (!IsDryRun)
|
||||
ExitOnErr(Visitor->dumpAllStringTables());
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user