[C++] Implement define
diff --git a/parser.cc b/parser.cc
index eaec6fb..97fe353 100644
--- a/parser.cc
+++ b/parser.cc
@@ -7,6 +7,7 @@
#include "loc.h"
#include "log.h"
#include "string_piece.h"
+#include "strutil.h"
#include "value.h"
enum struct ParserState {
@@ -50,6 +51,7 @@
(*make_directives_)["include"] = &Parser::ParseInclude;
(*make_directives_)["-include"] = &Parser::ParseInclude;
(*make_directives_)["sinclude"] = &Parser::ParseInclude;
+ (*make_directives_)["define"] = &Parser::ParseDefine;
shortest_directive_len_ = 9999;
longest_directive_len_ = 0;
@@ -92,6 +94,11 @@
if (line.empty() || (line.size() == 1 && line[0] == '\r'))
return;
+ if (!define_name_.empty()) {
+ ParseInsideDefine(line);
+ return;
+ }
+
if (line[0] == '\t' && state_ != ParserState::NOT_AFTER_RULE) {
CommandAST* ast = new CommandAST();
ast->expr = ParseExpr(line.substr(1), true);
@@ -124,7 +131,7 @@
void ParseRule(StringPiece line, size_t sep) {
const bool is_rule = line.find(':') != string::npos;
- RuleAST* ast = new RuleAST;
+ RuleAST* ast = new RuleAST();
ast->set_loc(loc_);
size_t found = line.substr(sep + 1).find_first_of("=;");
@@ -163,7 +170,7 @@
break;
}
- AssignAST* ast = new AssignAST;
+ AssignAST* ast = new AssignAST();
ast->set_loc(loc_);
ast->lhs = ParseExpr(line.substr(0, lhs_end).StripSpaces(), false);
ast->rhs = ParseExpr(line.substr(sep + 1).StripLeftSpaces(), false);
@@ -180,6 +187,35 @@
out_asts_->push_back(ast);
}
+ void ParseDefine(StringPiece line, StringPiece) {
+ if (line.empty()) {
+ Error("*** empty variable name.");
+ }
+ define_name_ = line;
+ define_start_ = 0;
+ define_start_line_ = loc_.lineno;
+ }
+
+ void ParseInsideDefine(StringPiece line) {
+ if (line.StripLeftSpaces() != "endef") {
+ if (define_start_ == 0)
+ define_start_ = l_;
+ return;
+ }
+
+ AssignAST* ast = new AssignAST();
+ ast->set_loc(Loc(loc_.filename, define_start_line_));
+ ast->lhs = ParseExpr(define_name_, false);
+ StringPiece rhs;
+ if (define_start_)
+ rhs = buf_.substr(define_start_, l_ - define_start_).StripRightSpaces();
+ ast->rhs = ParseExpr(rhs, false);
+ ast->op = AssignOp::EQ;
+ ast->directive = AssignDirective::NONE;
+ out_asts_->push_back(ast);
+ define_name_.clear();
+ }
+
bool HandleDirective(StringPiece line) {
if (line.size() < shortest_directive_len_)
return false;
@@ -192,7 +228,8 @@
if (found == make_directives_->end())
return false;
- (this->*found->second)(line.substr(directive.size() + 1), directive);
+ StringPiece rest = line.substr(directive.size() + 1).StripLeftSpaces();
+ (this->*found->second)(rest, directive);
return true;
}
@@ -201,6 +238,9 @@
ParserState state_;
vector<AST*>* out_asts_;
+ StringPiece define_name_;
+ size_t define_start_;
+ int define_start_line_;
Loc loc_;
bool fixed_lineno_;