mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-04 12:43:24 +00:00
The parser and flatc now allow include directories to be specified.
Bug: 17139854 Change-Id: I0eac65d054951e00a8811ad1d80ba8c37012dbf0 Tested: on Linux.
This commit is contained in:
@@ -91,6 +91,7 @@ static void Error(const char *err, const char *obj, bool usage) {
|
||||
for (size_t i = 0; i < sizeof(generators) / sizeof(generators[0]); ++i)
|
||||
printf(" -%s %s.\n", generators[i].extension, generators[i].help);
|
||||
printf(" -o PATH Prefix PATH to all generated files.\n"
|
||||
" -I PATH Search for includes in the specified path.\n"
|
||||
" -S Strict JSON: add quotes to field names.\n"
|
||||
" -P Don\'t prefix enum values with the enum name in C++.\n"
|
||||
"FILEs may depend on declarations in earlier files.\n"
|
||||
@@ -112,6 +113,7 @@ int main(int argc, const char *argv[]) {
|
||||
bool generator_enabled[num_generators] = { false };
|
||||
bool any_generator = false;
|
||||
std::vector<std::string> filenames;
|
||||
std::vector<const char *> include_directories;
|
||||
size_t binary_files_from = std::numeric_limits<size_t>::max();
|
||||
for (int i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
@@ -123,11 +125,11 @@ int main(int argc, const char *argv[]) {
|
||||
switch (arg[1]) {
|
||||
case 'o':
|
||||
if (++i >= argc) Error("missing path following", arg, true);
|
||||
output_path = argv[i];
|
||||
if (!(output_path.back() == flatbuffers::kPathSeparator ||
|
||||
output_path.back() == flatbuffers::kPosixPathSeparator)) {
|
||||
output_path += flatbuffers::kPathSeparator;
|
||||
}
|
||||
output_path = flatbuffers::ConCatPathFileName(argv[i], "");
|
||||
break;
|
||||
case 'I':
|
||||
if (++i >= argc) Error("missing path following", arg, true);
|
||||
include_directories.push_back(argv[i]);
|
||||
break;
|
||||
case 'S':
|
||||
opts.strict_json = true;
|
||||
@@ -177,8 +179,13 @@ int main(int argc, const char *argv[]) {
|
||||
reinterpret_cast<const uint8_t *>(contents.c_str()),
|
||||
contents.length());
|
||||
} else {
|
||||
if (!parser.Parse(contents.c_str(), file_it->c_str()))
|
||||
auto local_include_directory = flatbuffers::StripFileName(*file_it);
|
||||
include_directories.push_back(local_include_directory.c_str());
|
||||
include_directories.push_back(nullptr);
|
||||
if (!parser.Parse(contents.c_str(), &include_directories[0]))
|
||||
Error((*file_it + ": " + parser.error_).c_str());
|
||||
include_directories.pop_back();
|
||||
include_directories.pop_back();
|
||||
}
|
||||
|
||||
std::string filebase = flatbuffers::StripPath(
|
||||
|
||||
@@ -860,11 +860,7 @@ void Parser::MarkGenerated() {
|
||||
}
|
||||
}
|
||||
|
||||
bool Parser::Parse(const char *source, const char *filepath) {
|
||||
included_files_[filepath] = true;
|
||||
// This is the starting point to reset to if we interrupted our parsing
|
||||
// to deal with an include:
|
||||
restart_parse_after_include:
|
||||
bool Parser::Parse(const char *source, const char **include_paths) {
|
||||
source_ = cursor_ = source;
|
||||
line_ = 1;
|
||||
error_.clear();
|
||||
@@ -875,17 +871,25 @@ bool Parser::Parse(const char *source, const char *filepath) {
|
||||
while (IsNext(kTokenInclude)) {
|
||||
auto name = attribute_;
|
||||
Expect(kTokenStringConstant);
|
||||
auto path = StripFileName(filepath);
|
||||
if (path.length()) name = path + kPathSeparator + name;
|
||||
if (included_files_.find(name) == included_files_.end()) {
|
||||
// We found an include file that we have not parsed yet.
|
||||
// Load it and parse it.
|
||||
std::string contents;
|
||||
if (!LoadFile(name.c_str(), true, &contents))
|
||||
if (!include_paths) {
|
||||
const char *current_directory[] = { "", nullptr };
|
||||
include_paths = current_directory;
|
||||
}
|
||||
for (auto paths = include_paths; paths && *paths; paths++) {
|
||||
auto filepath = flatbuffers::ConCatPathFileName(*paths, name);
|
||||
if(LoadFile(filepath.c_str(), true, &contents)) break;
|
||||
}
|
||||
if (contents.empty())
|
||||
Error("unable to load include file: " + name);
|
||||
Parse(contents.c_str(), name.c_str());
|
||||
// Any errors, we're done.
|
||||
if (error_.length()) return false;
|
||||
included_files_[name] = true;
|
||||
if (!Parse(contents.c_str(), include_paths)) {
|
||||
// Any errors, we're done.
|
||||
return false;
|
||||
}
|
||||
// We do not want to output code for any included files:
|
||||
MarkGenerated();
|
||||
// This is the easiest way to continue this file after an include:
|
||||
@@ -893,7 +897,9 @@ bool Parser::Parse(const char *source, const char *filepath) {
|
||||
// file anew. This will cause it to encounter the same include statement
|
||||
// again, but this time it will skip it, because it was entered into
|
||||
// included_files_.
|
||||
goto restart_parse_after_include;
|
||||
// This is recursive, but only go as deep as the number of include
|
||||
// statements.
|
||||
return Parse(source, include_paths);
|
||||
}
|
||||
Expect(';');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user