]> granicus.if.org Git - re2c/commitdiff
Resolve names of included files relative to including file, not to the main file.
authorUlya Trofimovich <skvadrik@gmail.com>
Sat, 29 Dec 2018 00:16:53 +0000 (00:16 +0000)
committerUlya Trofimovich <skvadrik@gmail.com>
Sat, 29 Dec 2018 00:16:53 +0000 (00:16 +0000)
re2c/Makefile.am
re2c/bootstrap/src/conf/parse_opts.cc
re2c/src/ast/input.cc
re2c/src/ast/input.h
re2c/src/ast/scanner.cc
re2c/src/conf/opt.cc
re2c/src/conf/opt.h
re2c/src/conf/parse_opts.re

index de184738f2472adcfa7309c3efc39d8649f40011..f00cd9ab591578e5f8482851fab6d0ba6cdd6df7 100644 (file)
@@ -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 = \
index b5e31d69f22500f85ed9f2ae41d1f76b9c6827a8..324192d5aa20f26817df2800f19819722ad02cef 100644 (file)
@@ -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;
 
index 9323f7651af1d1084cb2adb191bcae0bd70129ab..6955413b202d41d0198ccf78b9c01eddf256a0ab 100644 (file)
@@ -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>" ? 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<std::string> &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>" ? 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;
 }
 
index 376588e00a3a94cfea08cb6bdf6aa9f28e890a6c..25df02f77250aeb396849f423b757906281fb384 100644 (file)
@@ -20,8 +20,8 @@ struct Input
 
     Input();
     ~Input();
-    bool open(const std::string &);
-    bool open_in_dirs(const std::string &, const std::vector<std::string> &);
+    bool open(const std::string &filename, const std::string *parent
+        , const std::vector<std::string> &incpaths);
 
     FORBID_COPY(Input);
 };
index f8afa6924927a8b549ebec3a4d97d2a71b3bce4c..28fc2742e27af9dcae424146fdb9ff513f2c3f41 100644 (file)
@@ -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;
index d99fb71973932ae85f741d9a8d8473dee7e212c3..2925ff4a1948bacea4cabf033d1cfde1f666f9ed 100644 (file)
@@ -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];
index 05ccbf343d0ea4c0c208d8f12dfb4f4f3c6cce81..af58d65d5186b6395f95f4e09440a77bb4289a7d 100644 (file)
@@ -171,7 +171,7 @@ struct conopt_t
 #        undef CONSTOPT1
 #        undef CONSTOPT
     {}
-    void fix(const char *filename);
+    void fix();
     FORBID_COPY(conopt_t);
 };
 
index 5446922e3e806dc1e253897e6fba01e7e49fa8d6..c8d1b31f790e33f678c564a55822e6f9271364e0 100644 (file)
@@ -280,7 +280,7 @@ end:
         error ("no source file");
         return EXIT_FAIL;
     }
-    globopts.fix(opts.source_file);
+    globopts.fix();
 
     return OK;