diff options
author | LaMont Jones <lamontjones@google.com> | 2023-06-02 21:34:19 +0000 |
---|---|---|
committer | Cole Faust <colecfaust@gmail.com> | 2023-06-21 12:30:10 -0700 |
commit | e361127627b94b6eeaf8522941bb1220342a5554 (patch) | |
tree | c7e7b0b8f89d8b1035091d8fa1c77cc92fd7957b | |
parent | a420c70e1a2fac2b5597b6a9a8f522e0448a38ce (diff) | |
download | kati-e361127627b94b6eeaf8522941bb1220342a5554.tar.gz |
Add KATI_foreach_sep function
syntax: $(KATI_foreach_sep var,separator,list,text)
Rather than using a space to separate items in the expanded result,
`separator` is used.
comma := ,
v := $(KATI_foreach_sep w,$(comma) ,a b c,"$(w)")
v will be set to: `"a", "b", "c"`
Change-Id: I426d7b24846dc495b9134319dd452809837fe5f9
-rw-r--r-- | src/expr.cc | 2 | ||||
-rw-r--r-- | src/func.cc | 23 | ||||
-rw-r--r-- | src/strutil.cc | 6 | ||||
-rw-r--r-- | src/strutil.h | 2 | ||||
-rw-r--r-- | testcase/foreach.mk | 8 |
5 files changed, 34 insertions, 7 deletions
diff --git a/src/expr.cc b/src/expr.cc index 41b60bb..e3a8629 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -215,7 +215,7 @@ class VarSubst : public Value { WordWriter ww(s); Pattern pat(pat_str); for (std::string_view tok : WordScanner(value)) { - ww.MaybeAddWhitespace(); + ww.MaybeAddSeparator(); pat.AppendSubstRef(tok, subst, s); } } diff --git a/src/func.cc b/src/func.cc index 316e423..d5bca3a 100644 --- a/src/func.cc +++ b/src/func.cc @@ -108,7 +108,7 @@ void PatsubstFunc(const std::vector<Value*>& args, WordWriter ww(s); Pattern pat(pat_str); for (std::string_view tok : WordScanner(str)) { - ww.MaybeAddWhitespace(); + ww.MaybeAddSeparator(); pat.AppendSubst(tok, repl, s); } } @@ -721,12 +721,30 @@ void ForeachFunc(const std::vector<Value*>& args, std::unique_ptr<SimpleVar> v( new SimpleVar(std::string(tok), VarOrigin::AUTOMATIC, nullptr, Loc())); ScopedGlobalVar sv(Intern(varname), v.get()); - ww.MaybeAddWhitespace(); + ww.MaybeAddSeparator(); args[2]->Eval(ev, s); } ev->IncrementEvalDepth(); } +void ForeachWithSepFunc(const std::vector<Value*>& args, + Evaluator* ev, + std::string* s) { + const std::string&& varname = args[0]->Eval(ev); + const std::string&& separator = args[1]->Eval(ev); + const std::string&& list = args[2]->Eval(ev); + ev->DecrementEvalDepth(); + WordWriter ww(s); + for (std::string_view tok : WordScanner(list)) { + std::unique_ptr<SimpleVar> v( + new SimpleVar(std::string(tok), VarOrigin::AUTOMATIC, nullptr, Loc())); + ScopedGlobalVar sv(Intern(varname), v.get()); + ww.MaybeAddSeparator(separator); + args[3]->Eval(ev, s); + } + ev->IncrementEvalDepth(); +} + void OriginFunc(const std::vector<Value*>& args, Evaluator* ev, std::string* s) { @@ -1112,6 +1130,7 @@ static const std::unordered_map<std::string_view, FuncInfo> g_func_info_map = { ENTRY("KATI_extra_file_deps", &ExtraFileDepsFunc, 0, 0, false, false), ENTRY("KATI_shell_no_rerun", &ShellFuncNoRerun, 1, 1, false, false), + ENTRY("KATI_foreach_sep", &ForeachWithSepFunc, 4, 4, false, false), }; } // namespace diff --git a/src/strutil.cc b/src/strutil.cc index 0a222ad..149c729 100644 --- a/src/strutil.cc +++ b/src/strutil.cc @@ -83,16 +83,16 @@ void WordScanner::Split(std::vector<std::string_view>* o) { WordWriter::WordWriter(std::string* o) : out_(o), needs_space_(false) {} -void WordWriter::MaybeAddWhitespace() { +void WordWriter::MaybeAddSeparator(std::string_view sep) { if (needs_space_) { - out_->push_back(' '); + out_->append(sep); } else { needs_space_ = true; } } void WordWriter::Write(std::string_view s) { - MaybeAddWhitespace(); + MaybeAddSeparator(); out_->append(s); } diff --git a/src/strutil.h b/src/strutil.h index e199e14..bd71c1b 100644 --- a/src/strutil.h +++ b/src/strutil.h @@ -47,7 +47,7 @@ class WordScanner { class WordWriter { public: explicit WordWriter(std::string* o); - void MaybeAddWhitespace(); + void MaybeAddSeparator(std::string_view sep = " "); void Write(std::string_view s); private: diff --git a/testcase/foreach.mk b/testcase/foreach.mk index 3dde97a..e1b8a00 100644 --- a/testcase/foreach.mk +++ b/testcase/foreach.mk @@ -1,7 +1,15 @@ base := base dirs := a b c d dir := FAIL +comma := , files := $(foreach dir,$(dirs),$(foreach subdir,$(dirs),$(dir)/$(subdir)/$(base))) +ifdef KATI +files2 := $(KATI_foreach_sep dir,$(comma) ,$(dirs),"$(dir)") +else +# Since make doesn't have the function, manually set the result. +files2 := "a", "b", "c", "d" +endif test: echo $(files) + echo $(files2) |