[C++] Introduce Symbol
diff --git a/Makefile b/Makefile
index bb91bf2..6e4b9fb 100644
--- a/Makefile
+++ b/Makefile
@@ -32,6 +32,7 @@
string_pool.cc \
stringprintf.cc \
strutil.cc \
+ symtab.cc \
time.cc \
value.cc \
var.cc
diff --git a/command.cc b/command.cc
index 39aa9fc..f696cd5 100644
--- a/command.cc
+++ b/command.cc
@@ -94,33 +94,33 @@
};
void AutoAtVar::Eval(Evaluator*, string* s) const {
- AppendString(ce_->current_dep_node()->output, s);
+ *s += ce_->current_dep_node()->output.str();
}
void AutoLessVar::Eval(Evaluator*, string* s) const {
auto& ai = ce_->current_dep_node()->actual_inputs;
if (!ai.empty())
- AppendString(ai[0], s);
+ *s += ai[0].str();
}
void AutoHatVar::Eval(Evaluator*, string* s) const {
unordered_set<StringPiece> seen;
WordWriter ww(s);
- for (StringPiece ai : ce_->current_dep_node()->actual_inputs) {
- if (seen.insert(ai).second)
- ww.Write(ai);
+ for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
+ if (seen.insert(ai.str()).second)
+ ww.Write(ai.str());
}
}
void AutoPlusVar::Eval(Evaluator*, string* s) const {
WordWriter ww(s);
- for (StringPiece ai : ce_->current_dep_node()->actual_inputs) {
- ww.Write(ai);
+ for (Symbol ai : ce_->current_dep_node()->actual_inputs) {
+ ww.Write(ai.str());
}
}
void AutoStarVar::Eval(Evaluator*, string* s) const {
- AppendString(StripExt(ce_->current_dep_node()->output), s);
+ AppendString(StripExt(ce_->current_dep_node()->output.str()), s);
}
void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
@@ -163,9 +163,9 @@
Vars* vars = ev_->mutable_vars();
#define INSERT_AUTO_VAR(name, sym) do { \
Var* v = new name(this, sym); \
- (*vars)[STRING_PIECE(sym)] = v; \
- (*vars)[STRING_PIECE(sym"D")] = new AutoSuffixDVar(this, sym"D", v); \
- (*vars)[STRING_PIECE(sym"F")] = new AutoSuffixFVar(this, sym"F", v); \
+ (*vars)[Intern(sym)] = v; \
+ (*vars)[Intern(sym"D")] = new AutoSuffixDVar(this, sym"D", v); \
+ (*vars)[Intern(sym"F")] = new AutoSuffixFVar(this, sym"F", v); \
} while (0)
INSERT_AUTO_VAR(AutoAtVar, "@");
INSERT_AUTO_VAR(AutoLessVar, "<");
@@ -198,8 +198,7 @@
ParseCommandPrefixes(&cmd, &echo, &ignore_error);
if (!cmd.empty()) {
- Command* command = new Command;
- command->output = n->output;
+ Command* command = new Command(n->output);
command->cmd = make_shared<string>(cmd.as_string());
command->echo = echo;
command->ignore_error = ignore_error;
diff --git a/command.h b/command.h
index f06533f..e93de34 100644
--- a/command.h
+++ b/command.h
@@ -18,7 +18,7 @@
#include <memory>
#include <vector>
-#include "string_piece.h"
+#include "symtab.h"
using namespace std;
@@ -26,10 +26,10 @@
class Evaluator;
struct Command {
- Command()
- : echo(true), ignore_error(false) {
+ explicit Command(Symbol o)
+ : output(o), echo(true), ignore_error(false) {
}
- StringPiece output;
+ Symbol output;
shared_ptr<string> cmd;
bool echo;
bool ignore_error;
diff --git a/dep.cc b/dep.cc
index d8980b7..7416774 100644
--- a/dep.cc
+++ b/dep.cc
@@ -27,17 +27,18 @@
#include "log.h"
#include "rule.h"
#include "strutil.h"
+#include "symtab.h"
#include "var.h"
namespace {
static vector<DepNode*>* g_dep_node_pool;
-static StringPiece ReplaceSuffix(StringPiece s, StringPiece newsuf) {
+static Symbol ReplaceSuffix(Symbol s, Symbol newsuf) {
string r;
- AppendString(StripExt(s), &r);
+ AppendString(StripExt(s.str()), &r);
r += '.';
- AppendString(newsuf, &r);
+ AppendString(newsuf.str(), &r);
return Intern(r);
}
@@ -99,7 +100,7 @@
} // namespace
-DepNode::DepNode(StringPiece o, bool p)
+DepNode::DepNode(Symbol o, bool p)
: output(o),
has_rule(false),
is_order_only(false),
@@ -112,7 +113,7 @@
public:
DepBuilder(Evaluator* ev,
const vector<shared_ptr<Rule>>& rules,
- const unordered_map<StringPiece, Vars*>& rule_vars)
+ const unordered_map<Symbol, Vars*>& rule_vars)
: ev_(ev),
rule_vars_(rule_vars),
implicit_rules_(new RuleTrie()),
@@ -123,9 +124,9 @@
LOG_STAT("%zu implicit rules", implicit_rules_->size());
LOG_STAT("%zu suffix rules", suffix_rules_.size());
- auto found = rules_.find(".PHONY");
+ auto found = rules_.find(Intern(".PHONY"));
if (found != rules_.end()) {
- for (StringPiece input : found->second->inputs) {
+ for (Symbol input : found->second->inputs) {
phony_.insert(input);
}
}
@@ -134,7 +135,7 @@
~DepBuilder() {
}
- void Build(vector<StringPiece> targets,
+ void Build(vector<Symbol> targets,
vector<DepNode*>* nodes) {
if (targets.empty()) {
if (!first_rule_) {
@@ -146,10 +147,10 @@
// TODO: LogStats?
- for (StringPiece target : targets) {
+ for (Symbol target : targets) {
cur_rule_vars_.reset(new Vars);
ev_->set_current_scope(cur_rule_vars_.get());
- DepNode* n = BuildPlan(target, "");
+ DepNode* n = BuildPlan(target, Intern(""));
nodes->push_back(n);
ev_->set_current_scope(NULL);
cur_rule_vars_.reset(NULL);
@@ -157,13 +158,13 @@
}
private:
- bool Exists(StringPiece target) {
+ bool Exists(Symbol target) {
auto found = rules_.find(target);
if (found != rules_.end())
return true;
if (phony_.count(target))
return true;
- return ::Exists(target);
+ return ::Exists(target.str());
}
void PopulateRules(const vector<shared_ptr<Rule>>& rules) {
@@ -179,11 +180,11 @@
}
}
- bool PopulateSuffixRule(shared_ptr<Rule> rule, StringPiece output) {
- if (output.empty() || output[0] != '.')
+ bool PopulateSuffixRule(shared_ptr<Rule> rule, Symbol output) {
+ if (output.empty() || output.str()[0] != '.')
return false;
- StringPiece rest = output.substr(1);
+ const StringPiece rest = StringPiece(output.str()).substr(1);
size_t dot_index = rest.find('.');
// If there is only a single dot or the third dot, this is not a
// suffix rule.
@@ -196,7 +197,7 @@
StringPiece output_suffix = rest.substr(dot_index+1);
shared_ptr<Rule> r = make_shared<Rule>(*rule);
r->inputs.clear();
- r->inputs.push_back(input_suffix);
+ r->inputs.push_back(Intern(input_suffix));
r->is_suffix_rule = true;
suffix_rules_[output_suffix].push_back(r);
return true;
@@ -204,18 +205,18 @@
shared_ptr<Rule> MergeRules(const Rule& old_rule,
const Rule& rule,
- StringPiece output,
+ Symbol output,
bool is_suffix_rule) {
if (old_rule.is_double_colon != rule.is_double_colon) {
ERROR("%s:%d: *** target file `%s' has both : and :: entries.",
- LOCF(rule.loc), output.as_string().c_str());
+ LOCF(rule.loc), output.str().c_str());
}
if (!old_rule.cmds.empty() && !rule.cmds.empty() &&
!is_suffix_rule && !rule.is_double_colon) {
WARN("%s:%d: warning: overriding commands for target `%s'",
- LOCF(rule.cmd_loc()), output.as_string().c_str());
+ LOCF(rule.cmd_loc()), output.str().c_str());
WARN("%s:%d: warning: ignoring old commands for target `%s'",
- LOCF(old_rule.cmd_loc()), output.as_string().c_str());
+ LOCF(old_rule.cmd_loc()), output.str().c_str());
}
shared_ptr<Rule> r = make_shared<Rule>(rule);
@@ -245,14 +246,14 @@
old_rule.order_only_inputs.end(),
back_inserter(r->inputs));
}
- for (StringPiece p : old_rule.output_patterns) {
+ for (Symbol p : old_rule.output_patterns) {
r->output_patterns.push_back(p);
}
return r;
}
void PopulateExplicitRule(shared_ptr<Rule> rule) {
- for (StringPiece output : rule->outputs) {
+ for (Symbol output : rule->outputs) {
const bool is_suffix_rule = PopulateSuffixRule(rule, output);
rule = make_shared<Rule>(*rule);
@@ -271,44 +272,44 @@
}
void PopulateImplicitRule(shared_ptr<Rule> rule) {
- for (StringPiece output_pattern : rule->output_patterns) {
+ for (Symbol output_pattern : rule->output_patterns) {
shared_ptr<Rule> r = make_shared<Rule>(*rule);
r->output_patterns.clear();
r->output_patterns.push_back(output_pattern);
- implicit_rules_->Add(output_pattern, r);
+ implicit_rules_->Add(output_pattern.str(), r);
}
}
- shared_ptr<Rule> LookupRule(StringPiece o) {
+ shared_ptr<Rule> LookupRule(Symbol o) {
auto found = rules_.find(o);
if (found != rules_.end())
return found->second;
return NULL;
}
- Vars* LookupRuleVars(StringPiece o) {
+ Vars* LookupRuleVars(Symbol o) {
auto found = rule_vars_.find(o);
if (found != rule_vars_.end())
return found->second;
return NULL;
}
- bool CanPickImplicitRule(shared_ptr<Rule> rule, StringPiece output) {
+ bool CanPickImplicitRule(shared_ptr<Rule> rule, Symbol output) {
CHECK(rule->output_patterns.size() == 1);
- Pattern pat(rule->output_patterns[0]);
- if (!pat.Match(output)) {
+ Pattern pat(rule->output_patterns[0].str());
+ if (!pat.Match(output.str())) {
return false;
}
- for (StringPiece input : rule->inputs) {
+ for (Symbol input : rule->inputs) {
string buf;
- pat.AppendSubst(output, input, &buf);
- if (!Exists(buf))
+ pat.AppendSubst(output.str(), input.str(), &buf);
+ if (!Exists(Intern(buf)))
return false;
}
return true;
}
- Vars* MergeImplicitRuleVars(StringPiece output, Vars* vars) {
+ Vars* MergeImplicitRuleVars(Symbol output, Vars* vars) {
auto found = rule_vars_.find(output);
if (found == rule_vars_.end())
return vars;
@@ -322,7 +323,7 @@
return r;
}
- bool PickRule(StringPiece output,
+ bool PickRule(Symbol output,
shared_ptr<Rule>* out_rule, Vars** out_var) {
shared_ptr<Rule> rule = LookupRule(output);
Vars* vars = LookupRuleVars(output);
@@ -335,7 +336,7 @@
}
vector<shared_ptr<Rule>> irules;
- implicit_rules_->Get(output, &irules);
+ implicit_rules_->Get(output.str(), &irules);
for (auto iter = irules.rbegin(); iter != irules.rend(); ++iter) {
shared_ptr<Rule> irule = *iter;
if (!CanPickImplicitRule(irule, output))
@@ -362,7 +363,7 @@
return true;
}
- StringPiece output_suffix = GetExt(output);
+ StringPiece output_suffix = GetExt(output.str());
if (output_suffix.get(0) != '.')
return rule.get();
output_suffix = output_suffix.substr(1);
@@ -373,7 +374,7 @@
for (shared_ptr<Rule> irule : found->second) {
CHECK(irule->inputs.size() == 1);
- StringPiece input = ReplaceSuffix(output, irule->inputs[0]);
+ Symbol input = ReplaceSuffix(output, irule->inputs[0]);
if (!Exists(input))
continue;
@@ -398,10 +399,10 @@
return rule.get();
}
- DepNode* BuildPlan(StringPiece output, StringPiece needed_by) {
+ DepNode* BuildPlan(Symbol output, Symbol needed_by) {
LOG("BuildPlan: %s for %s",
- output.as_string().c_str(),
- needed_by.as_string().c_str());
+ output.c_str(),
+ needed_by.c_str());
auto found = done_.find(output);
if (found != done_.end()) {
@@ -420,7 +421,7 @@
vector<unique_ptr<ScopedVar>> sv;
if (vars) {
for (const auto& p : *vars) {
- StringPiece name = p.first;
+ Symbol name = p.first;
RuleVar* var = reinterpret_cast<RuleVar*>(p.second);
CHECK(var);
Var* new_var = var->v();
@@ -446,16 +447,17 @@
}
}
- for (StringPiece input : rule->inputs) {
+ for (Symbol input : rule->inputs) {
if (rule->output_patterns.size() > 0) {
if (rule->output_patterns.size() > 1) {
ERROR("TODO: multiple output pattern is not supported yet");
}
string o;
- Pattern(rule->output_patterns[0]).AppendSubst(output, input, &o);
+ Pattern(rule->output_patterns[0].str()).AppendSubst(
+ output.str(), input.str(), &o);
input = Intern(o);
} else if (rule->is_suffix_rule) {
- input = Intern(ReplaceSuffix(output, input));
+ input = ReplaceSuffix(output, input);
}
n->actual_inputs.push_back(input);
@@ -463,7 +465,7 @@
n->deps.push_back(c);
}
- for (StringPiece input : rule->order_only_inputs) {
+ for (Symbol input : rule->order_only_inputs) {
DepNode* c = BuildPlan(input, output);
c->is_order_only = true;
n->deps.push_back(c);
@@ -487,8 +489,8 @@
}
Evaluator* ev_;
- unordered_map<StringPiece, shared_ptr<Rule>> rules_;
- const unordered_map<StringPiece, Vars*>& rule_vars_;
+ unordered_map<Symbol, shared_ptr<Rule>> rules_;
+ const unordered_map<Symbol, Vars*>& rule_vars_;
unique_ptr<Vars> cur_rule_vars_;
unique_ptr<RuleTrie> implicit_rules_;
@@ -496,14 +498,14 @@
SuffixRuleMap suffix_rules_;
shared_ptr<Rule> first_rule_;
- unordered_map<StringPiece, DepNode*> done_;
- unordered_set<StringPiece> phony_;
+ unordered_map<Symbol, DepNode*> done_;
+ unordered_set<Symbol> phony_;
};
void MakeDep(Evaluator* ev,
const vector<shared_ptr<Rule>>& rules,
- const unordered_map<StringPiece, Vars*>& rule_vars,
- const vector<StringPiece>& targets,
+ const unordered_map<Symbol, Vars*>& rule_vars,
+ const vector<Symbol>& targets,
vector<DepNode*>* nodes) {
DepBuilder db(ev, rules, rule_vars);
db.Build(targets, nodes);
diff --git a/dep.h b/dep.h
index 934d4fe..22434a3 100644
--- a/dep.h
+++ b/dep.h
@@ -22,6 +22,7 @@
#include "loc.h"
#include "string_piece.h"
+#include "symtab.h"
class Evaluator;
class Rule;
@@ -29,16 +30,16 @@
class Vars;
struct DepNode {
- DepNode(StringPiece output, bool is_phony);
+ DepNode(Symbol output, bool is_phony);
- StringPiece output;
+ Symbol output;
vector<Value*> cmds;
vector<DepNode*> deps;
vector<DepNode*> parents;
bool has_rule;
bool is_order_only;
bool is_phony;
- vector<StringPiece> actual_inputs;
+ vector<Symbol> actual_inputs;
Vars* rule_vars;
Loc loc;
};
@@ -48,8 +49,8 @@
void MakeDep(Evaluator* ev,
const vector<shared_ptr<Rule>>& rules,
- const unordered_map<StringPiece, Vars*>& rule_vars,
- const vector<StringPiece>& targets,
+ const unordered_map<Symbol, Vars*>& rule_vars,
+ const vector<Symbol>& targets,
vector<DepNode*>* nodes);
#endif // DEP_H_
diff --git a/eval.cc b/eval.cc
index 0710082..489d342 100644
--- a/eval.cc
+++ b/eval.cc
@@ -26,6 +26,7 @@
#include "parser.h"
#include "rule.h"
#include "strutil.h"
+#include "symtab.h"
#include "value.h"
#include "var.h"
@@ -49,7 +50,7 @@
// }
}
-Var* Evaluator::EvalRHS(StringPiece lhs, Value* rhs_v, StringPiece orig_rhs,
+Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs,
AssignOp op, bool is_override) {
VarOrigin origin = (
(is_bootstrap_ ? VarOrigin::DEFAULT :
@@ -87,7 +88,7 @@
}
}
- LOG("Assign: %.*s=%s", SPF(lhs), rhs->DebugString().c_str());
+ LOG("Assign: %s=%s", lhs.c_str(), rhs->DebugString().c_str());
if (needs_assign) {
return rhs;
}
@@ -97,7 +98,7 @@
void Evaluator::EvalAssign(const AssignAST* ast) {
loc_ = ast->loc();
last_rule_ = NULL;
- StringPiece lhs = Intern(*ast->lhs->Eval(this));
+ Symbol lhs = Intern(*ast->lhs->Eval(this));
if (lhs.empty())
Error("*** empty variable name.");
Var* rhs = EvalRHS(lhs, ast->rhs, ast->orig_rhs, ast->op,
@@ -130,7 +131,7 @@
return;
}
- for (StringPiece output : rule_var.outputs) {
+ for (Symbol output : rule_var.outputs) {
auto p = rule_vars_.emplace(output, nullptr);
if (p.second) {
p.first->second = new Vars;
@@ -153,7 +154,7 @@
}
current_scope_ = p.first->second;
- StringPiece lhs = Intern(rule_var.lhs);
+ Symbol lhs = Intern(rule_var.lhs);
Var* rhs_var = EvalRHS(lhs, rhs, STRING_PIECE("*TODO*"), rule_var.op);
if (rhs_var)
current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op));
@@ -182,7 +183,7 @@
switch (ast->op) {
case CondOp::IFDEF:
case CondOp::IFNDEF: {
- StringPiece lhs = Intern(*ast->lhs->Eval(this));
+ Symbol lhs = Intern(*ast->lhs->Eval(this));
Var* v = LookupVarInCurrentScope(lhs);
shared_ptr<string> s = v->Eval(this);
is_true = (s->empty() == (ast->op == CondOp::IFNDEF));
@@ -228,8 +229,8 @@
return;
}
- Var* var_list = LookupVar("MAKEFILE_LIST");
- var_list->AppendVar(this, NewLiteral(Intern(TrimLeadingCurdir(fname))));
+ Var* var_list = LookupVar(Intern("MAKEFILE_LIST"));
+ var_list->AppendVar(this, NewLiteral(Intern(TrimLeadingCurdir(fname)).str()));
for (AST* ast : mk->asts()) {
LOG("%s", ast->DebugString().c_str());
ast->Eval(this);
@@ -279,7 +280,7 @@
}
}
-Var* Evaluator::LookupVar(StringPiece name) {
+Var* Evaluator::LookupVar(Symbol name) {
if (current_scope_) {
Var* v = current_scope_->Lookup(name);
if (v->IsDefined())
@@ -291,7 +292,7 @@
return in_vars_->Lookup(name);
}
-Var* Evaluator::LookupVarInCurrentScope(StringPiece name) {
+Var* Evaluator::LookupVarInCurrentScope(Symbol name) {
if (current_scope_) {
return current_scope_->Lookup(name);
}
diff --git a/eval.h b/eval.h
index 179b825..dcdb87f 100644
--- a/eval.h
+++ b/eval.h
@@ -22,6 +22,7 @@
#include "ast.h"
#include "loc.h"
#include "string_piece.h"
+#include "symtab.h"
using namespace std;
@@ -51,18 +52,18 @@
void EvalInclude(const IncludeAST* ast);
void EvalExport(const ExportAST* ast);
- Var* LookupVar(StringPiece name);
+ Var* LookupVar(Symbol name);
// For target specific variables.
- Var* LookupVarInCurrentScope(StringPiece name);
+ Var* LookupVarInCurrentScope(Symbol name);
const Loc& loc() const { return loc_; }
const vector<shared_ptr<Rule>>& rules() const { return rules_; }
- const unordered_map<StringPiece, Vars*>& rule_vars() const {
+ const unordered_map<Symbol, Vars*>& rule_vars() const {
return rule_vars_;
}
Vars* mutable_vars() { return vars_; }
- const unordered_map<StringPiece, bool>& exports() const { return exports_; }
+ const unordered_map<Symbol, bool>& exports() const { return exports_; }
void Error(const string& msg);
@@ -74,15 +75,15 @@
void set_avoid_io(bool a) { avoid_io_ = a; }
private:
- Var* EvalRHS(StringPiece lhs, Value* rhs, StringPiece orig_rhs, AssignOp op,
+ Var* EvalRHS(Symbol lhs, Value* rhs, StringPiece orig_rhs, AssignOp op,
bool is_override = false);
void DoInclude(const char* fname, bool should_exist);
const Vars* in_vars_;
Vars* vars_;
- unordered_map<StringPiece, Vars*> rule_vars_;
+ unordered_map<Symbol, Vars*> rule_vars_;
vector<shared_ptr<Rule>> rules_;
- unordered_map<StringPiece, bool> exports_;
+ unordered_map<Symbol, bool> exports_;
Rule* last_rule_;
Vars* current_scope_;
diff --git a/exec.cc b/exec.cc
index 69cf4ea..056318e 100644
--- a/exec.cc
+++ b/exec.cc
@@ -32,6 +32,7 @@
#include "log.h"
#include "string_piece.h"
#include "strutil.h"
+#include "symtab.h"
#include "value.h"
#include "var.h"
@@ -49,15 +50,15 @@
done_[n->output] = true;
LOG("ExecNode: %s for %s",
- n->output.as_string().c_str(),
- needed_by ? needed_by->output.as_string().c_str() : "(null)");
+ n->output.c_str(),
+ needed_by ? needed_by->output.c_str() : "(null)");
for (DepNode* d : n->deps) {
- if (d->is_order_only && Exists(d->output)) {
+ if (d->is_order_only && Exists(d->output.str())) {
continue;
}
// TODO: Check the timestamp.
- if (Exists(d->output)) {
+ if (Exists(d->output.str())) {
continue;
}
ExecNode(d, n);
@@ -74,11 +75,11 @@
int result = system(command->cmd->c_str());
if (result != 0) {
if (command->ignore_error) {
- fprintf(stderr, "[%.*s] Error %d (ignored)\n",
- SPF(command->output), WEXITSTATUS(result));
+ fprintf(stderr, "[%s] Error %d (ignored)\n",
+ command->output.c_str(), WEXITSTATUS(result));
} else {
- fprintf(stderr, "*** [%.*s] Error %d\n",
- SPF(command->output), WEXITSTATUS(result));
+ fprintf(stderr, "*** [%s] Error %d\n",
+ command->output.c_str(), WEXITSTATUS(result));
exit(1);
}
}
@@ -89,7 +90,7 @@
private:
CommandEvaluator ce_;
- unordered_map<StringPiece, bool> done_;
+ unordered_map<Symbol, bool> done_;
};
} // namespace
diff --git a/func.cc b/func.cc
index dfafe30..306de80 100644
--- a/func.cc
+++ b/func.cc
@@ -31,6 +31,7 @@
#include "log.h"
#include "parser.h"
#include "strutil.h"
+#include "symtab.h"
#include "var.h"
namespace {
@@ -391,7 +392,7 @@
void ValueFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
shared_ptr<string> var_name = args[0]->Eval(ev);
- Var* var = ev->LookupVar(*var_name);
+ Var* var = ev->LookupVar(Intern(*var_name));
AppendString(var->String().as_string(), s);
}
@@ -447,7 +448,7 @@
};
shared_ptr<string> func_name = args[0]->Eval(ev);
- Var* func = ev->LookupVar(*func_name);
+ Var* func = ev->LookupVar(Intern(*func_name));
vector<unique_ptr<SimpleVar>> av;
for (size_t i = 1; i < args.size(); i++) {
unique_ptr<SimpleVar> s(
@@ -457,7 +458,8 @@
vector<unique_ptr<ScopedVar>> sv;
for (size_t i = 1; i < args.size(); i++) {
sv.push_back(move(unique_ptr<ScopedVar>(
- new ScopedVar(ev->mutable_vars(), tmpvar_names[i], av[i-1].get()))));
+ new ScopedVar(ev->mutable_vars(),
+ Intern(tmpvar_names[i]), av[i-1].get()))));
}
func->Eval(ev, s);
}
@@ -469,7 +471,7 @@
for (StringPiece tok : WordScanner(*list)) {
unique_ptr<SimpleVar> v(new SimpleVar(
make_shared<string>(tok.data(), tok.size()), VarOrigin::AUTOMATIC));
- ScopedVar sv(ev->mutable_vars(), *varname, v.get());
+ ScopedVar sv(ev->mutable_vars(), Intern(*varname), v.get());
ww.MaybeAddWhitespace();
args[2]->Eval(ev, s);
}
@@ -477,13 +479,13 @@
void OriginFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
shared_ptr<string> var_name = args[0]->Eval(ev);
- Var* var = ev->LookupVar(*var_name);
+ Var* var = ev->LookupVar(Intern(*var_name));
*s += GetOriginStr(var->Origin());
}
void FlavorFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
shared_ptr<string> var_name = args[0]->Eval(ev);
- Var* var = ev->LookupVar(*var_name);
+ Var* var = ev->LookupVar(Intern(*var_name));
*s += var->Flavor();
}
@@ -567,7 +569,7 @@
g_func_info_map = new unordered_map<StringPiece, FuncInfo*>;
for (size_t i = 0; i < sizeof(g_func_infos) / sizeof(g_func_infos[0]); i++) {
FuncInfo* fi = &g_func_infos[i];
- bool ok = g_func_info_map->insert(make_pair(Intern(fi->name), fi)).second;
+ bool ok = g_func_info_map->emplace(fi->name, fi).second;
CHECK(ok);
}
}
diff --git a/main.cc b/main.cc
index b99a035..aa09bed 100644
--- a/main.cc
+++ b/main.cc
@@ -34,6 +34,7 @@
#include "string_piece.h"
#include "stringprintf.h"
#include "strutil.h"
+#include "symtab.h"
#include "time.h"
#include "var.h"
@@ -61,7 +62,7 @@
}
static void ParseCommandLine(int argc, char* argv[],
- vector<StringPiece>* targets,
+ vector<Symbol>* targets,
vector<StringPiece>* cl_vars) {
for (int i = 1; i < argc; i++) {
const char* arg = argv[i];
@@ -116,7 +117,7 @@
QuitSymtab();
}
-static void ReadBootstrapMakefile(const vector<StringPiece>& targets,
+static void ReadBootstrapMakefile(const vector<Symbol>& targets,
vector<AST*>* asts) {
string bootstrap = (
"CC:=cc\n"
@@ -138,7 +139,7 @@
// TODO: Add more builtin rules.
);
bootstrap += StringPrintf("MAKECMDGOALS:=%s\n",
- JoinStrings(targets, " ").c_str());
+ JoinSymbols(targets, " ").c_str());
char cwd[PATH_MAX];
if (!getcwd(cwd, PATH_MAX)) {
@@ -146,13 +147,13 @@
CHECK(false);
}
bootstrap += StringPrintf("CURDIR:=%s\n", cwd);
- Parse(Intern(bootstrap), Loc("*bootstrap*", 0), asts);
+ Parse(Intern(bootstrap).str(), Loc("*bootstrap*", 0), asts);
}
static void SetVar(StringPiece l, VarOrigin origin, Vars* vars) {
size_t found = l.find('=');
CHECK(found != string::npos);
- StringPiece lhs = Intern(l.substr(0, found));
+ Symbol lhs = Intern(l.substr(0, found));
StringPiece rhs = l.substr(found + 1);
vars->Assign(lhs,
new RecursiveVar(NewLiteral(rhs.data()), origin, rhs.data()));
@@ -168,7 +169,7 @@
}
}
-static int Run(const vector<StringPiece>& targets,
+static int Run(const vector<Symbol>& targets,
const vector<StringPiece>& cl_vars) {
MakefileCacheManager* cache_mgr = NewMakefileCacheManager();
@@ -185,7 +186,7 @@
}
ev->set_is_bootstrap(false);
- vars->Assign("MAKEFILE_LIST",
+ vars->Assign(Intern("MAKEFILE_LIST"),
new SimpleVar(make_shared<string>(
StringPrintf(" %s", g_makefile)), VarOrigin::FILE));
@@ -205,7 +206,7 @@
}
for (const auto& p : ev->exports()) {
- const string& name = p.first.as_string();
+ const Symbol name = p.first;
if (p.second) {
Var* v = ev->LookupVar(name);
shared_ptr<string> value = v->Eval(ev);
@@ -242,7 +243,7 @@
int main(int argc, char* argv[]) {
Init();
- vector<StringPiece> targets;
+ vector<Symbol> targets;
vector<StringPiece> cl_vars;
ParseCommandLine(argc, argv, &targets, &cl_vars);
int r = Run(targets, cl_vars);
diff --git a/ninja.cc b/ninja.cc
index 27eccfb..418c36a 100644
--- a/ninja.cc
+++ b/ninja.cc
@@ -197,19 +197,19 @@
}
void EmitBuild(DepNode* node, const string& rule_name) {
- fprintf(fp_, "build %.*s: %s", SPF(node->output), rule_name.c_str());
- vector<StringPiece> order_onlys;
+ fprintf(fp_, "build %s: %s", node->output.c_str(), rule_name.c_str());
+ vector<Symbol> order_onlys;
for (DepNode* d : node->deps) {
if (d->is_order_only) {
order_onlys.push_back(d->output);
} else {
- fprintf(fp_, " %.*s", SPF(d->output));
+ fprintf(fp_, " %s", d->output.c_str());
}
}
if (!order_onlys.empty()) {
fprintf(fp_, " ||");
- for (StringPiece oo : order_onlys) {
- fprintf(fp_, " %.*s", SPF(oo));
+ for (Symbol oo : order_onlys) {
+ fprintf(fp_, " %s", oo.c_str());
}
}
fprintf(fp_, "\n");
@@ -242,7 +242,7 @@
CommandEvaluator ce_;
Evaluator* ev_;
FILE* fp_;
- unordered_set<StringPiece> done_;
+ unordered_set<Symbol> done_;
int rule_id_;
string cmd_buf_;
};
diff --git a/rule.cc b/rule.cc
index 7c882a3..0a81c69 100644
--- a/rule.cc
+++ b/rule.cc
@@ -20,6 +20,7 @@
#include "parser.h"
#include "stringprintf.h"
#include "strutil.h"
+#include "symtab.h"
#include "value.h"
namespace {
@@ -31,11 +32,11 @@
is_order_only = true;
continue;
}
- input = Intern(TrimLeadingCurdir(input));
+ Symbol input_sym = Intern(TrimLeadingCurdir(input));
if (is_order_only) {
- r->order_only_inputs.push_back(input);
+ r->order_only_inputs.push_back(input_sym);
} else {
- r->inputs.push_back(input);
+ r->inputs.push_back(input_sym);
}
}
}
@@ -60,12 +61,13 @@
}
StringPiece first = line.substr(0, index);
- vector<StringPiece> outputs;
+ vector<Symbol> outputs;
for (StringPiece tok : WordScanner(first)) {
outputs.push_back(Intern(TrimLeadingCurdir(tok)));
}
- const bool is_first_pattern = !outputs.empty() && IsPatternRule(outputs[0]);
+ const bool is_first_pattern = (
+ !outputs.empty() && IsPatternRule(outputs[0].str()));
if (is_first_pattern) {
if (outputs.size() > 1) {
// TODO: Multiple output patterns are not supported yet.
@@ -107,7 +109,7 @@
CHECK(rest[term_index] == ';');
// TODO: Maybe better to avoid Intern here?
rule->cmds.push_back(
- NewLiteral(Intern(TrimLeftSpace(rest.substr(term_index + 1)))));
+ NewLiteral(Intern(TrimLeftSpace(rest.substr(term_index + 1))).str()));
rest = rest.substr(0, term_index);
}
@@ -135,7 +137,7 @@
if (rule->output_patterns.size() > 1) {
ERROR("%s:%d: *** multiple target patterns.", LOCF(loc));
}
- if (!IsPatternRule(rule->output_patterns[0])) {
+ if (!IsPatternRule(rule->output_patterns[0].str())) {
ERROR("%s:%d: *** target pattern contains no '%%'.", LOCF(loc));
}
ParseInputs(rule, third);
@@ -143,15 +145,15 @@
string Rule::DebugString() const {
vector<string> v;
- v.push_back(StringPrintf("outputs=[%s]", JoinStrings(outputs, ",").c_str()));
- v.push_back(StringPrintf("inputs=[%s]", JoinStrings(inputs, ",").c_str()));
+ v.push_back(StringPrintf("outputs=[%s]", JoinSymbols(outputs, ",").c_str()));
+ v.push_back(StringPrintf("inputs=[%s]", JoinSymbols(inputs, ",").c_str()));
if (!order_only_inputs.empty()) {
v.push_back(StringPrintf("order_only_inputs=[%s]",
- JoinStrings(order_only_inputs, ",").c_str()));
+ JoinSymbols(order_only_inputs, ",").c_str()));
}
if (!output_patterns.empty()) {
v.push_back(StringPrintf("output_patterns=[%s]",
- JoinStrings(output_patterns, ",").c_str()));
+ JoinSymbols(output_patterns, ",").c_str()));
}
if (is_double_colon)
v.push_back("is_double_colon");
diff --git a/rule.h b/rule.h
index d839685..c6fd72c 100644
--- a/rule.h
+++ b/rule.h
@@ -21,6 +21,7 @@
#include "loc.h"
#include "log.h"
#include "string_piece.h"
+#include "symtab.h"
using namespace std;
@@ -34,10 +35,10 @@
string DebugString() const;
- vector<StringPiece> outputs;
- vector<StringPiece> inputs;
- vector<StringPiece> order_only_inputs;
- vector<StringPiece> output_patterns;
+ vector<Symbol> outputs;
+ vector<Symbol> inputs;
+ vector<Symbol> order_only_inputs;
+ vector<Symbol> output_patterns;
bool is_double_colon;
bool is_suffix_rule;
vector<Value*> cmds;
@@ -51,7 +52,7 @@
};
struct RuleVarAssignment {
- vector<StringPiece> outputs;
+ vector<Symbol> outputs;
StringPiece lhs;
StringPiece rhs;
AssignOp op;
diff --git a/strutil.cc b/strutil.cc
index 99eb163..7042b3a 100644
--- a/strutil.cc
+++ b/strutil.cc
@@ -18,11 +18,9 @@
#include <ctype.h>
#include <limits.h>
-#include <string.h>
#include <unistd.h>
#include <stack>
-#include <unordered_map>
#include <utility>
#include "log.h"
@@ -103,31 +101,6 @@
const_cast<char*>(s_.data())[s_.size()] = c_;
}
-static unordered_map<StringPiece, char*>* g_symtab;
-
-void InitSymtab() {
- g_symtab = new unordered_map<StringPiece, char*>;
-}
-
-void QuitSymtab() {
- for (auto p : *g_symtab) {
- free(p.second);
- }
- delete g_symtab;
-}
-
-StringPiece Intern(StringPiece s) {
- auto found = g_symtab->find(s);
- if (found != g_symtab->end())
- return found->first;
-
- char* b = static_cast<char*>(malloc(s.size()+1));
- memcpy(b, s.data(), s.size());
- s = StringPiece(b, s.size());
- (*g_symtab)[s] = b;
- return s;
-}
-
void AppendString(StringPiece str, string* out) {
out->append(str.begin(), str.end());
}
diff --git a/strutil.h b/strutil.h
index 368ee23..6a51ee7 100644
--- a/strutil.h
+++ b/strutil.h
@@ -69,10 +69,6 @@
char c_;
};
-void InitSymtab();
-void QuitSymtab();
-StringPiece Intern(StringPiece s);
-
template <class String>
inline string JoinStrings(vector<String> v, const char* sep) {
string r;
diff --git a/symtab.cc b/symtab.cc
new file mode 100644
index 0000000..342d222
--- /dev/null
+++ b/symtab.cc
@@ -0,0 +1,79 @@
+// Copyright 2015 Google Inc. All rights reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build ignore
+
+#include "symtab.h"
+
+#include <string.h>
+
+#include <unordered_map>
+
+#include "log.h"
+#include "strutil.h"
+
+vector<string>* g_symbols;
+
+Symbol::Symbol(int v)
+ : v_(v) {
+}
+
+class Symtab {
+ public:
+ Symtab() {
+ CHECK(g_symbols == NULL);
+ g_symbols = &symbols_;
+ Symbol s = Intern("");
+ CHECK(s.v_ == 0);
+ CHECK(Intern("") == s);
+ }
+
+ Symbol Intern(StringPiece s) {
+ auto found = symtab_.find(s);
+ if (found != symtab_.end()) {
+ return found->second;
+ }
+ symbols_.push_back(s.as_string());
+ Symbol sym = Symbol(symtab_.size());
+ bool ok = symtab_.emplace(symbols_.back(), sym).second;
+ CHECK(ok);
+ return sym;
+ }
+
+ private:
+ unordered_map<StringPiece, Symbol> symtab_;
+ vector<string> symbols_;
+};
+
+static Symtab* g_symtab;
+
+void InitSymtab() {
+ g_symtab = new Symtab;
+}
+
+void QuitSymtab() {
+ delete g_symtab;
+}
+
+Symbol Intern(StringPiece s) {
+ return g_symtab->Intern(s);
+}
+
+string JoinSymbols(const vector<Symbol>& syms, const char* sep) {
+ vector<string> strs;
+ for (Symbol s : syms) {
+ strs.push_back(s.str());
+ }
+ return JoinStrings(strs, sep);
+}
diff --git a/symtab.h b/symtab.h
new file mode 100644
index 0000000..55e1ce3
--- /dev/null
+++ b/symtab.h
@@ -0,0 +1,76 @@
+// Copyright 2015 Google Inc. All rights reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SYMTAB_H_
+#define SYMTAB_H_
+
+#include <string>
+#include <vector>
+
+#include "string_piece.h"
+
+using namespace std;
+
+extern vector<string>* g_symbols;
+
+class Symtab;
+
+class Symbol {
+ public:
+ const string& str() const {
+ return (*g_symbols)[v_];
+ }
+
+ const char* c_str() const {
+ return str().c_str();
+ }
+
+ bool empty() const { return !v_; }
+
+ int val() const { return v_; }
+
+ char get(size_t i) const {
+ const string& s = str();
+ if (i >= s.size())
+ return 0;
+ return s[i];
+ }
+
+ private:
+ explicit Symbol(int v);
+
+ int v_;
+
+ friend class Symtab;
+};
+
+inline bool operator==(const Symbol& x, const Symbol& y) {
+ return x.val() == y.val();
+}
+
+namespace std {
+template<> struct hash<Symbol> {
+ size_t operator()(const Symbol& s) const {
+ return s.val();
+ }
+};
+}
+
+void InitSymtab();
+void QuitSymtab();
+Symbol Intern(StringPiece s);
+
+string JoinSymbols(const vector<Symbol>& syms, const char* sep);
+
+#endif // SYMTAB_H_
diff --git a/value.cc b/value.cc
index 5337e4f..873111e 100644
--- a/value.cc
+++ b/value.cc
@@ -131,13 +131,13 @@
virtual shared_ptr<string> Eval(Evaluator* ev) const override {
shared_ptr<string> name = name_->Eval(ev);
- Var* v = ev->LookupVar(*name);
+ Var* v = ev->LookupVar(Intern(*name));
return v->Eval(ev);
}
virtual void Eval(Evaluator* ev, string* s) const override {
shared_ptr<string> name = name_->Eval(ev);
- Var* v = ev->LookupVar(*name);
+ Var* v = ev->LookupVar(Intern(*name));
v->Eval(ev, s);
}
@@ -162,7 +162,7 @@
virtual void Eval(Evaluator* ev, string* s) const override {
shared_ptr<string> name = name_->Eval(ev);
- Var* v = ev->LookupVar(*name);
+ Var* v = ev->LookupVar(Intern(*name));
shared_ptr<string> value = v->Eval(ev);
shared_ptr<string> pat_str = pat_->Eval(ev);
shared_ptr<string> subst = subst_->Eval(ev);
diff --git a/var.cc b/var.cc
index 64385c0..c0926c6 100644
--- a/var.cc
+++ b/var.cc
@@ -110,14 +110,14 @@
}
}
-Var* Vars::Lookup(StringPiece name) const {
+Var* Vars::Lookup(Symbol name) const {
auto found = find(name);
if (found == end())
return kUndefined;
return found->second;
}
-void Vars::Assign(StringPiece name, Var* v) {
+void Vars::Assign(Symbol name, Var* v) {
auto p = insert(make_pair(name, v));
if (!p.second) {
Var* orig = p.first->second;
@@ -134,7 +134,7 @@
}
}
-ScopedVar::ScopedVar(Vars* vars, StringPiece name, Var* var)
+ScopedVar::ScopedVar(Vars* vars, Symbol name, Var* var)
: vars_(vars), orig_(NULL) {
auto p = vars->insert(make_pair(name, var));
iter_ = p.first;
diff --git a/var.h b/var.h
index 85f3490..eac1f45 100644
--- a/var.h
+++ b/var.h
@@ -21,6 +21,7 @@
#include "ast.h"
#include "string_piece.h"
+#include "symtab.h"
#include "value.h"
using namespace std;
@@ -170,19 +171,19 @@
AssignOp op_;
};
-class Vars : public unordered_map<StringPiece, Var*> {
+class Vars : public unordered_map<Symbol, Var*> {
public:
~Vars();
- Var* Lookup(StringPiece name) const;
+ Var* Lookup(Symbol name) const;
- void Assign(StringPiece name, Var* v);
+ void Assign(Symbol name, Var* v);
};
class ScopedVar {
public:
// Does not take ownerships of arguments.
- ScopedVar(Vars* vars, StringPiece name, Var* var);
+ ScopedVar(Vars* vars, Symbol name, Var* var);
~ScopedVar();
private: