From d1d1c926b4c0b68be085c7268a8d5ab8225b8fba Mon Sep 17 00:00:00 2001 From: Ulya Trofimovich Date: Sat, 29 Dec 2018 00:16:53 +0000 Subject: [PATCH] Resolve names of included files relative to including file, not to the main file. --- re2c/Makefile.am | 2 ++ re2c/bootstrap/src/conf/parse_opts.cc | 4 +-- re2c/src/ast/input.cc | 45 +++++++++++++++------------ re2c/src/ast/input.h | 4 +-- re2c/src/ast/scanner.cc | 13 ++++++-- re2c/src/conf/opt.cc | 18 +---------- re2c/src/conf/opt.h | 2 +- re2c/src/conf/parse_opts.re | 2 +- 8 files changed, 44 insertions(+), 46 deletions(-) diff --git a/re2c/Makefile.am b/re2c/Makefile.am index de184738..f00cd9ab 100644 --- a/re2c/Makefile.am +++ b/re2c/Makefile.am @@ -58,6 +58,7 @@ SRC_HDR = \ src/util/counter.h \ src/util/forbid_copy.h \ src/util/free_list.h \ + src/util/get_dir.h \ src/util/hash32.h \ src/util/local_increment.h \ src/util/lookup.h \ @@ -144,6 +145,7 @@ SRC = \ src/ast/scanner.cc \ src/ast/unescape.cc \ src/ast/validate.cc \ + src/util/get_dir.cc \ src/util/s_to_n32_unsafe.cc \ src/util/range.cc re2c_SOURCES = \ diff --git a/re2c/bootstrap/src/conf/parse_opts.cc b/re2c/bootstrap/src/conf/parse_opts.cc index b5e31d69..324192d5 100644 --- a/re2c/bootstrap/src/conf/parse_opts.cc +++ b/re2c/bootstrap/src/conf/parse_opts.cc @@ -1,4 +1,4 @@ -/* Generated by re2c 1.1.1 on Tue Dec 25 23:07:11 2018 */ +/* Generated by re2c 1.1.1 on Thu Dec 27 23:18:50 2018 */ #line 1 "../src/conf/parse_opts.re" #include "src/code/input_api.h" #include "src/conf/msg.h" @@ -3391,7 +3391,7 @@ end: error ("no source file"); return EXIT_FAIL; } - globopts.fix(opts.source_file); + globopts.fix(); return OK; diff --git a/re2c/src/ast/input.cc b/re2c/src/ast/input.cc index 9323f765..6955413b 100644 --- a/re2c/src/ast/input.cc +++ b/re2c/src/ast/input.cc @@ -1,6 +1,7 @@ #include "src/ast/input.h" #include "src/ast/scanner.h" #include "src/conf/msg.h" +#include "src/util/get_dir.h" #include "src/util/string_utils.h" namespace re2c { @@ -14,35 +15,39 @@ Input::Input() , line(1) {} -bool Input::open(const std::string &filename) -{ - name = escaped_name = filename; - strrreplace(escaped_name, "\\", "\\\\"); - - file = name == "" ? stdin : fopen(name.c_str(), "rb"); - if (!file) { - error("cannot open file: %s", name.c_str()); - return false; - } - - return true; -} - -bool Input::open_in_dirs(const std::string &filename +bool Input::open(const std::string &filename, const std::string *parent , const std::vector &incpaths) { - name = escaped_name = filename; - strrreplace(escaped_name, "\\", "\\\\"); + std::string path; + name = filename; - for (size_t i = 0; !file && i < incpaths.size(); ++i) { - const std::string path = incpaths[i] + name; + if (!parent) { + path = name; + file = name == "" ? stdin : fopen(name.c_str(), "rb"); + } + else { + // first, search relative to the directory of including file + path = *parent; + get_dir(path); + path += name; file = fopen(path.c_str(), "rb"); + + // otherwise search in all include paths + for (size_t i = 0; !file && i < incpaths.size(); ++i) { + path = incpaths[i] + name; + file = fopen(path.c_str(), "rb"); + } } + if (!file) { - error("cannot open file: %s", name.c_str()); + fatal("cannot open file: %s", name.c_str()); return false; } + // name displayed in #line directives is the resolved name + escaped_name = path; + strrreplace(escaped_name, "\\", "\\\\"); + return true; } diff --git a/re2c/src/ast/input.h b/re2c/src/ast/input.h index 376588e0..25df02f7 100644 --- a/re2c/src/ast/input.h +++ b/re2c/src/ast/input.h @@ -20,8 +20,8 @@ struct Input Input(); ~Input(); - bool open(const std::string &); - bool open_in_dirs(const std::string &, const std::vector &); + bool open(const std::string &filename, const std::string *parent + , const std::vector &incpaths); FORBID_COPY(Input); }; diff --git a/re2c/src/ast/scanner.cc b/re2c/src/ast/scanner.cc index f8afa692..28fc2742 100644 --- a/re2c/src/ast/scanner.cc +++ b/re2c/src/ast/scanner.cc @@ -36,13 +36,20 @@ bool Scanner::init(const std::string &filename) { Input *in = new Input; files.push_back(in); - return in->open(filename); + return in->open(filename, NULL, globopts->incpaths); } bool Scanner::include(const std::string &filename) { + // get name of the current file (before unreading) + const std::string &parent = get_fname(); + // unread buffer tail: we'll return to it later - // file fragments are laid out left-to-right from nested to outer + // In the buffer nested files go before outer files. In the file stack, + // however, outer files go before nested files (nested are at the top). + // We want to break from the unreading cycle early, therefore we go in + // reverse order of file offsets in buffer and break as soon as the end + // offset is less than cursor (current position). for (size_t i = 0; i < files.size(); ++i) { Input *in = files[i]; if (in->so >= cur) { @@ -64,7 +71,7 @@ bool Scanner::include(const std::string &filename) // open new file and place place at the top of stack Input *in = new Input; files.push_back(in); - if (!in->open_in_dirs(filename, globopts->incpaths)) return false; + if (!in->open(filename, &parent, globopts->incpaths)) return false; // refill buffer (discard everything up to cursor, clear EOF) lim = cur = mar = ctx = tok = ptr = pos = bot + BSIZE; diff --git a/re2c/src/conf/opt.cc b/re2c/src/conf/opt.cc index d99fb719..2925ff4a 100644 --- a/re2c/src/conf/opt.cc +++ b/re2c/src/conf/opt.cc @@ -4,28 +4,12 @@ namespace re2c { -static void get_dir(std::string &path) -{ - // scan the path backwards until the first slash (if any) and clip - size_t i = path.length(); - for (; i > 0; --i) { - const char c = path[i - 1]; - if (c == '/' || c == '\\') break; - } - path.resize(i); - if (i == 0) path.push_back('.'); -} - -void conopt_t::fix(const char *filename) +void conopt_t::fix() { if (target == TARGET_SKELETON) { fFlag = false; } - // first include path must be the directory of the source file - std::string path(filename); - get_dir(path); - incpaths.insert(incpaths.begin(), path); // append directory separator '/' to all paths that do not have it for (size_t i = 0; i < incpaths.size(); ++i) { std::string &p = incpaths[i]; diff --git a/re2c/src/conf/opt.h b/re2c/src/conf/opt.h index 05ccbf34..af58d65d 100644 --- a/re2c/src/conf/opt.h +++ b/re2c/src/conf/opt.h @@ -171,7 +171,7 @@ struct conopt_t # undef CONSTOPT1 # undef CONSTOPT {} - void fix(const char *filename); + void fix(); FORBID_COPY(conopt_t); }; diff --git a/re2c/src/conf/parse_opts.re b/re2c/src/conf/parse_opts.re index 5446922e..c8d1b31f 100644 --- a/re2c/src/conf/parse_opts.re +++ b/re2c/src/conf/parse_opts.re @@ -280,7 +280,7 @@ end: error ("no source file"); return EXIT_FAIL; } - globopts.fix(opts.source_file); + globopts.fix(); return OK; -- 2.40.0