[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_;
diff --git a/strutil.cc b/strutil.cc
index 400565a..85bfa9f 100644
--- a/strutil.cc
+++ b/strutil.cc
@@ -154,3 +154,15 @@
out->append(s.begin(), s.end());
out->append(subst.begin(), subst.end());
}
+
+string NoLineBreak(const string& s) {
+ size_t index = s.find('\n');
+ if (index == string::npos)
+ return s;
+ string r = s;
+ while (index != string::npos) {
+ r = s.substr(0, index) + "\\n" + s.substr(index + 1);
+ index = s.find('\n', index + 2);
+ }
+ return r;
+}
diff --git a/strutil.h b/strutil.h
index 0b84f1e..600463c 100644
--- a/strutil.h
+++ b/strutil.h
@@ -72,4 +72,6 @@
void AppendSubstRef(StringPiece str, StringPiece pat, StringPiece subst,
string* out);
+string NoLineBreak(const string& s);
+
#endif // STRUTIL_H_
diff --git a/value.cc b/value.cc
index 4143f46..d762bcf 100644
--- a/value.cc
+++ b/value.cc
@@ -29,7 +29,7 @@
string Value::DebugString() const {
if (this) {
- return DebugString_();
+ return NoLineBreak(DebugString_());
}
return "(null)";
}