Commit 51ab8ecb authored by jan.koester's avatar jan.koester
Browse files

bugfix

parent c8a276ef
Loading
Loading
Loading
Loading
+34 −1
Changes for parser.cpp: 34 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -696,6 +696,30 @@ bool Parser::try_parse_rule(const std::string& line, Makefile& mf, Rule*& curren
    size_t prereq_start = colon_pos + 1 + (double_colon ? 1 : 0);
    std::string rhs_raw = prereq_start < line.size() ? trim(line.substr(prereq_start)) : "";

    // Inline recipe form: "targets: prereqs ; recipe". A depth-0 ';' separates
    // the prerequisites from a single inline recipe line, which may be empty
    // (e.g. Kbuild's "$(sort ...): . ;" no-op rule that suppresses implicit
    // rules and asserts the target is produced by descending). Without this the
    // ';' was treated as a prerequisite ("No rule to make target ';'").
    bool has_inline_recipe = false;
    std::string inline_recipe;
    {
        int d = 0;
        for (size_t i = 0; i < rhs_raw.size(); ++i) {
            char c = rhs_raw[i];
            if (c == '$' && i + 1 < rhs_raw.size() && (rhs_raw[i+1] == '(' || rhs_raw[i+1] == '{')) {
                d++; i++;
            } else if ((c == ')' || c == '}') && d > 0) {
                d--;
            } else if (c == ';' && d == 0) {
                has_inline_recipe = true;
                inline_recipe = trim(rhs_raw.substr(i + 1));
                rhs_raw = trim(rhs_raw.substr(0, i));
                break;
            }
        }
    }

    targets_str = expand(targets_str, mf);

    auto targets = split_words(targets_str);
@@ -730,8 +754,9 @@ bool Parser::try_parse_rule(const std::string& line, Makefile& mf, Rule*& curren
                rule.prerequisites = pprereqs;
                rule.is_pattern = false;
                rule.target_pattern = tpat;
                if (has_inline_recipe) rule.recipes.push_back(inline_recipe);
                mf.rules.push_back(std::move(rule));
                current_rule = &mf.rules.back();
                current_rule = has_inline_recipe ? nullptr : &mf.rules.back();
                return true;
            }
        }
@@ -805,6 +830,14 @@ bool Parser::try_parse_rule(const std::string& line, Makefile& mf, Rule*& curren
    mf.rules.push_back({targets, prereqs, order_only, {}, is_pattern, ""});
    current_rule = &mf.rules.back();

    if (has_inline_recipe) {
        // GNU make: an inline recipe completes the rule; subsequent tab-indented
        // lines do not belong to it. Record it (an empty recipe still counts,
        // preventing implicit rules) and stop appending to this rule.
        current_rule->recipes.push_back(inline_recipe);
        current_rule = nullptr;
    }

    if (mf.default_target.empty() && !is_pattern && !targets.empty() && targets[0][0] != '.') {
        mf.default_target = targets[0];
    }