Commit 2180fe02 authored by jan.koester's avatar jan.koester
Browse files

bugfix

parent 360b6b5c
Loading
Loading
Loading
Loading
+15 −3
Changes for parser.cpp: 15 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -852,6 +852,18 @@ std::string Parser::expand(const std::string& input, const Makefile& mf) const {
    return do_expand(input, mf, nullptr);
}

std::string Parser::expand_recursive_var(
        const std::string& name, const std::string& value, const Makefile& mf,
        const std::map<std::string, std::string>* auto_vars) const {
    // Break self-referential expansion cycles. GNU make aborts with
    // "Recursive variable references itself"; we instead treat the recursive
    // reference as empty so a single legitimate self-append still terminates.
    if (!expanding_.insert(name).second) return "";
    std::string out = do_expand(value, mf, auto_vars);
    expanding_.erase(name);
    return out;
}

std::string Parser::expand_with_automatic(const std::string& input, const Makefile& mf,
                                            const std::string& target,
                                            const std::string& first_prereq,
@@ -943,7 +955,7 @@ std::string Parser::do_expand(const std::string& input, const Makefile& mf,
            auto it = mf.variables.find(varname);
            if (it != mf.variables.end()) {
                if (it->second.flavor == VarFlavor::Recursive) {
                    result += do_expand(it->second.value, mf, auto_vars);
                    result += expand_recursive_var(varname, it->second.value, mf, auto_vars);
                } else {
                    result += it->second.value;
                }
@@ -997,7 +1009,7 @@ std::string Parser::expand_ref(const std::string& content, const Makefile& mf,
                auto vit = mf.variables.find(var);
                if (vit != mf.variables.end()) {
                    val = (vit->second.flavor == VarFlavor::Recursive)
                              ? do_expand(vit->second.value, mf, auto_vars)
                              ? expand_recursive_var(var, vit->second.value, mf, auto_vars)
                              : vit->second.value;
                }
            }
@@ -1019,7 +1031,7 @@ std::string Parser::expand_ref(const std::string& content, const Makefile& mf,
    auto it = mf.variables.find(expanded_name);
    if (it != mf.variables.end()) {
        if (it->second.flavor == VarFlavor::Recursive) {
            return do_expand(it->second.value, mf, auto_vars);
            return expand_recursive_var(expanded_name, it->second.value, mf, auto_vars);
        }
        return it->second.value;
    }
+10 −0
Changes for parser.h: 10 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -93,6 +93,16 @@ private:

    std::string do_expand(const std::string& input, const Makefile& mf,
                           const std::map<std::string, std::string>* auto_vars) const;
    // Names of recursively-expanded variables currently being expanded, used to
    // break self-referential cycles (e.g. "X = $(X) more") that would otherwise
    // recurse until the process exhausts memory. Matches GNU make, which refuses
    // to expand a variable that references itself.
    mutable std::set<std::string> expanding_;
    // Expand a recursively-flavored variable's value while guarding against
    // cycles; returns "" if 'name' is already on the expansion stack.
    std::string expand_recursive_var(const std::string& name, const std::string& value,
                                     const Makefile& mf,
                                     const std::map<std::string, std::string>* auto_vars) const;
    std::string expand_ref(const std::string& content, const Makefile& mf,
                            const std::map<std::string, std::string>* auto_vars) const;
    std::string expand_function(const std::string& name, const std::string& args,