Loading parser.cpp +64 −52 Changes for parser.cpp: 64 added lines, 52 removed lines. Original line number Diff line number Diff line Loading @@ -215,22 +215,63 @@ bool Parser::handle_conditional(const std::string& line_in, Makefile& mf) { } } if (line.substr(0, 5) == "ifeq " || line.substr(0, 5) == "ifeq\t" || line == "ifeq") { auto is_if_directive = [](const std::string& l) { return l.substr(0, 5) == "ifeq " || l.substr(0, 5) == "ifeq\t" || l == "ifeq" || l.substr(0, 6) == "ifneq " || l.substr(0, 6) == "ifneq\t" || l == "ifneq" || l.substr(0, 6) == "ifdef " || l.substr(0, 6) == "ifdef\t" || l.substr(0, 7) == "ifndef " || l.substr(0, 7) == "ifndef\t"; }; if (is_if_directive(line)) { // A nested conditional inside an inactive branch is always inactive. if (!cond_stack_.empty() && !cond_stack_.back().active) { cond_stack_.push_back({false, false}); return true; } bool cond = eval_if_directive(line, mf); cond_stack_.push_back({cond, cond}); return true; } if (line == "else" || line.substr(0, 5) == "else ") { if (cond_stack_.empty()) return true; std::string rest = line.size() > 5 ? trim(line.substr(5)) : ""; bool parent_active = cond_stack_.size() < 2 || cond_stack_[cond_stack_.size() - 2].active; if (!parent_active || cond_stack_.back().seen_true) { // Either the enclosing branch is dead, or an earlier branch of this // if-chain already matched: this clause is inactive regardless. cond_stack_.back().active = false; return true; } if (!rest.empty() && is_if_directive(rest)) { // 'else ifeq/ifneq/ifdef/ifndef ...': evaluate the new condition. bool cond = eval_if_directive(rest, mf); cond_stack_.back().active = cond; if (cond) cond_stack_.back().seen_true = true; } else { // Plain 'else'. cond_stack_.back().active = true; cond_stack_.back().seen_true = true; } return true; } if (line == "endif") { if (!cond_stack_.empty()) cond_stack_.pop_back(); return true; } return false; } bool Parser::eval_if_directive(const std::string& line, Makefile& mf) { if (line.substr(0, 5) == "ifeq " || line.substr(0, 5) == "ifeq\t" || line == "ifeq") { std::string args = trim(line.substr(4)); std::string a, b; if (!args.empty() && args[0] == '(') { int depth = 0; size_t comma_pos = std::string::npos; for (size_t i = 1; i < args.size(); i++) { // Count plain parens only. '$(' contains a '(' that is matched // by its corresponding ')', so no special-casing is needed; a // separate '$' increment would double-count and hide the // top-level comma (e.g. ifeq ($(filter a,$(X)),)). if (args[i] == '(') { depth++; continue; } if (args[i] == ')') { if (depth > 0) { depth--; continue; } Loading Loading @@ -258,25 +299,16 @@ bool Parser::handle_conditional(const std::string& line_in, Makefile& mf) { } } } a = expand(a, mf); b = expand(b, mf); cond_stack_.push_back({a == b, a == b}); return true; return expand(a, mf) == expand(b, mf); } if (line.substr(0, 6) == "ifneq " || line.substr(0, 6) == "ifneq\t" || line == "ifneq") { if (!cond_stack_.empty() && !cond_stack_.back().active) { cond_stack_.push_back({false, false}); return true; } if (line.substr(0, 6) == "ifneq " || line.substr(0, 6) == "ifneq\t" || line == "ifneq") { std::string args = trim(line.substr(5)); std::string a, b; if (!args.empty() && args[0] == '(') { int depth = 0; size_t comma_pos = std::string::npos; for (size_t i = 1; i < args.size(); i++) { // Plain paren counting (see ifeq above for rationale). if (args[i] == '(') { depth++; continue; } if (args[i] == ')') { if (depth > 0) { depth--; continue; } Loading @@ -291,50 +323,30 @@ bool Parser::handle_conditional(const std::string& line_in, Makefile& mf) { size_t end = args.rfind(')'); b = trim(args.substr(comma_pos + 1, end - comma_pos - 1)); } } else if (args.size() >= 4 && (args[0] == '"' || args[0] == '\'')) { char q1 = args[0]; size_t end1 = args.find(q1, 1); if (end1 != std::string::npos) { a = args.substr(1, end1 - 1); std::string rest = trim(args.substr(end1 + 1)); if (!rest.empty()) { char q2 = rest[0]; size_t end2 = rest.find(q2, 1); if (end2 != std::string::npos) b = rest.substr(1, end2 - 1); } } a = expand(a, mf); b = expand(b, mf); cond_stack_.push_back({a != b, a != b}); return true; } return expand(a, mf) != expand(b, mf); } if (line.substr(0, 6) == "ifdef " || line.substr(0, 6) == "ifdef\t") { if (!cond_stack_.empty() && !cond_stack_.back().active) { cond_stack_.push_back({false, false}); return true; } std::string var = trim(line.substr(5)); bool defined = mf.variables.count(var) && !mf.variables.at(var).value.empty(); cond_stack_.push_back({defined, defined}); return true; return mf.variables.count(var) && !mf.variables.at(var).value.empty(); } if (line.substr(0, 7) == "ifndef " || line.substr(0, 7) == "ifndef\t") { if (!cond_stack_.empty() && !cond_stack_.back().active) { cond_stack_.push_back({false, false}); return true; } std::string var = trim(line.substr(6)); bool defined = mf.variables.count(var) && !mf.variables.at(var).value.empty(); cond_stack_.push_back({!defined, !defined}); return true; } if (line == "else" || line.substr(0, 5) == "else ") { if (cond_stack_.empty()) return true; bool parent_active = cond_stack_.size() < 2 || cond_stack_[cond_stack_.size() - 2].active; if (parent_active && !cond_stack_.back().seen_true) { cond_stack_.back().active = true; cond_stack_.back().seen_true = true; } else { cond_stack_.back().active = false; } return true; } if (line == "endif") { if (!cond_stack_.empty()) cond_stack_.pop_back(); return true; return !(mf.variables.count(var) && !mf.variables.at(var).value.empty()); } return false; Loading Loading
parser.cpp +64 −52 Changes for parser.cpp: 64 added lines, 52 removed lines. Original line number Diff line number Diff line Loading @@ -215,22 +215,63 @@ bool Parser::handle_conditional(const std::string& line_in, Makefile& mf) { } } if (line.substr(0, 5) == "ifeq " || line.substr(0, 5) == "ifeq\t" || line == "ifeq") { auto is_if_directive = [](const std::string& l) { return l.substr(0, 5) == "ifeq " || l.substr(0, 5) == "ifeq\t" || l == "ifeq" || l.substr(0, 6) == "ifneq " || l.substr(0, 6) == "ifneq\t" || l == "ifneq" || l.substr(0, 6) == "ifdef " || l.substr(0, 6) == "ifdef\t" || l.substr(0, 7) == "ifndef " || l.substr(0, 7) == "ifndef\t"; }; if (is_if_directive(line)) { // A nested conditional inside an inactive branch is always inactive. if (!cond_stack_.empty() && !cond_stack_.back().active) { cond_stack_.push_back({false, false}); return true; } bool cond = eval_if_directive(line, mf); cond_stack_.push_back({cond, cond}); return true; } if (line == "else" || line.substr(0, 5) == "else ") { if (cond_stack_.empty()) return true; std::string rest = line.size() > 5 ? trim(line.substr(5)) : ""; bool parent_active = cond_stack_.size() < 2 || cond_stack_[cond_stack_.size() - 2].active; if (!parent_active || cond_stack_.back().seen_true) { // Either the enclosing branch is dead, or an earlier branch of this // if-chain already matched: this clause is inactive regardless. cond_stack_.back().active = false; return true; } if (!rest.empty() && is_if_directive(rest)) { // 'else ifeq/ifneq/ifdef/ifndef ...': evaluate the new condition. bool cond = eval_if_directive(rest, mf); cond_stack_.back().active = cond; if (cond) cond_stack_.back().seen_true = true; } else { // Plain 'else'. cond_stack_.back().active = true; cond_stack_.back().seen_true = true; } return true; } if (line == "endif") { if (!cond_stack_.empty()) cond_stack_.pop_back(); return true; } return false; } bool Parser::eval_if_directive(const std::string& line, Makefile& mf) { if (line.substr(0, 5) == "ifeq " || line.substr(0, 5) == "ifeq\t" || line == "ifeq") { std::string args = trim(line.substr(4)); std::string a, b; if (!args.empty() && args[0] == '(') { int depth = 0; size_t comma_pos = std::string::npos; for (size_t i = 1; i < args.size(); i++) { // Count plain parens only. '$(' contains a '(' that is matched // by its corresponding ')', so no special-casing is needed; a // separate '$' increment would double-count and hide the // top-level comma (e.g. ifeq ($(filter a,$(X)),)). if (args[i] == '(') { depth++; continue; } if (args[i] == ')') { if (depth > 0) { depth--; continue; } Loading Loading @@ -258,25 +299,16 @@ bool Parser::handle_conditional(const std::string& line_in, Makefile& mf) { } } } a = expand(a, mf); b = expand(b, mf); cond_stack_.push_back({a == b, a == b}); return true; return expand(a, mf) == expand(b, mf); } if (line.substr(0, 6) == "ifneq " || line.substr(0, 6) == "ifneq\t" || line == "ifneq") { if (!cond_stack_.empty() && !cond_stack_.back().active) { cond_stack_.push_back({false, false}); return true; } if (line.substr(0, 6) == "ifneq " || line.substr(0, 6) == "ifneq\t" || line == "ifneq") { std::string args = trim(line.substr(5)); std::string a, b; if (!args.empty() && args[0] == '(') { int depth = 0; size_t comma_pos = std::string::npos; for (size_t i = 1; i < args.size(); i++) { // Plain paren counting (see ifeq above for rationale). if (args[i] == '(') { depth++; continue; } if (args[i] == ')') { if (depth > 0) { depth--; continue; } Loading @@ -291,50 +323,30 @@ bool Parser::handle_conditional(const std::string& line_in, Makefile& mf) { size_t end = args.rfind(')'); b = trim(args.substr(comma_pos + 1, end - comma_pos - 1)); } } else if (args.size() >= 4 && (args[0] == '"' || args[0] == '\'')) { char q1 = args[0]; size_t end1 = args.find(q1, 1); if (end1 != std::string::npos) { a = args.substr(1, end1 - 1); std::string rest = trim(args.substr(end1 + 1)); if (!rest.empty()) { char q2 = rest[0]; size_t end2 = rest.find(q2, 1); if (end2 != std::string::npos) b = rest.substr(1, end2 - 1); } } a = expand(a, mf); b = expand(b, mf); cond_stack_.push_back({a != b, a != b}); return true; } return expand(a, mf) != expand(b, mf); } if (line.substr(0, 6) == "ifdef " || line.substr(0, 6) == "ifdef\t") { if (!cond_stack_.empty() && !cond_stack_.back().active) { cond_stack_.push_back({false, false}); return true; } std::string var = trim(line.substr(5)); bool defined = mf.variables.count(var) && !mf.variables.at(var).value.empty(); cond_stack_.push_back({defined, defined}); return true; return mf.variables.count(var) && !mf.variables.at(var).value.empty(); } if (line.substr(0, 7) == "ifndef " || line.substr(0, 7) == "ifndef\t") { if (!cond_stack_.empty() && !cond_stack_.back().active) { cond_stack_.push_back({false, false}); return true; } std::string var = trim(line.substr(6)); bool defined = mf.variables.count(var) && !mf.variables.at(var).value.empty(); cond_stack_.push_back({!defined, !defined}); return true; } if (line == "else" || line.substr(0, 5) == "else ") { if (cond_stack_.empty()) return true; bool parent_active = cond_stack_.size() < 2 || cond_stack_[cond_stack_.size() - 2].active; if (parent_active && !cond_stack_.back().seen_true) { cond_stack_.back().active = true; cond_stack_.back().seen_true = true; } else { cond_stack_.back().active = false; } return true; } if (line == "endif") { if (!cond_stack_.empty()) cond_stack_.pop_back(); return true; return !(mf.variables.count(var) && !mf.variables.at(var).value.empty()); } return false; Loading