blob: de8b9a15a284549b2b3bd9edb60c12b87929353d [file] [log] [blame]
Shinichiro Hamaji1d545aa2015-06-23 15:29:13 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015// +build ignore
16
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090017#include "func.h"
18
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +090019#include <glob.h>
Shinichiro Hamajid5271452015-06-17 18:50:03 +090020#include <limits.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090021#include <stdio.h>
Shinichiro Hamajid5271452015-06-17 18:50:03 +090022#include <stdlib.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090023
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +090024#include <algorithm>
Shinichiro Hamajid5271452015-06-17 18:50:03 +090025#include <iterator>
Shinichiro Hamajicf0cd682015-06-18 16:18:13 +090026#include <memory>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090027#include <unordered_map>
28
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +090029#include "ast.h"
Shinichiro Hamaji9619b362015-06-16 16:13:25 +090030#include "eval.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090031#include "log.h"
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +090032#include "parser.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090033#include "strutil.h"
Shinichiro Hamajicf0cd682015-06-18 16:18:13 +090034#include "var.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090035
36namespace {
37
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090038void PatsubstFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090039 shared_ptr<string> pat_str = args[0]->Eval(ev);
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090040 shared_ptr<string> repl = args[1]->Eval(ev);
41 shared_ptr<string> str = args[2]->Eval(ev);
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090042 WordWriter ww(s);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090043 Pattern pat(*pat_str);
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090044 for (StringPiece tok : WordScanner(*str)) {
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090045 ww.MaybeAddWhitespace();
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090046 pat.AppendSubst(tok, *repl, s);
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090047 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090048}
49
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090050void StripFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
51 shared_ptr<string> str = args[0]->Eval(ev);
52 WordWriter ww(s);
53 for (StringPiece tok : WordScanner(*str)) {
54 ww.Write(tok);
55 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090056}
57
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090058void SubstFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
59 shared_ptr<string> pat = args[0]->Eval(ev);
60 shared_ptr<string> repl = args[1]->Eval(ev);
61 shared_ptr<string> str = args[2]->Eval(ev);
62 size_t index = 0;
63 while (index < str->size()) {
64 size_t found = str->find(*pat, index);
65 if (found == string::npos)
66 break;
67 AppendString(StringPiece(*str).substr(index, found - index), s);
68 AppendString(*repl, s);
69 index = found + pat->size();
70 }
71 AppendString(StringPiece(*str).substr(index), s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090072}
73
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090074void FindstringFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
75 shared_ptr<string> find = args[0]->Eval(ev);
76 shared_ptr<string> in = args[1]->Eval(ev);
77 if (in->find(*find) != string::npos)
78 AppendString(*find, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090079}
80
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090081void FilterFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
82 shared_ptr<string> pat_buf = args[0]->Eval(ev);
83 shared_ptr<string> text = args[1]->Eval(ev);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090084 vector<Pattern> pats;
85 for (StringPiece pat : WordScanner(*pat_buf)) {
86 pats.push_back(Pattern(pat));
87 }
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090088 WordWriter ww(s);
89 for (StringPiece tok : WordScanner(*text)) {
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090090 for (const Pattern& pat : pats) {
91 if (pat.Match(tok)) {
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090092 ww.Write(tok);
93 break;
94 }
95 }
96 }
97}
98
99void FilterOutFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
100 shared_ptr<string> pat_buf = args[0]->Eval(ev);
101 shared_ptr<string> text = args[1]->Eval(ev);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +0900102 vector<Pattern> pats;
103 for (StringPiece pat : WordScanner(*pat_buf)) {
104 pats.push_back(Pattern(pat));
105 }
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +0900106 WordWriter ww(s);
107 for (StringPiece tok : WordScanner(*text)) {
108 bool matched = false;
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +0900109 for (const Pattern& pat : pats) {
110 if (pat.Match(tok)) {
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +0900111 matched = true;
112 break;
113 }
114 }
115 if (!matched)
116 ww.Write(tok);
117 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900118}
119
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +0900120void SortFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
121 shared_ptr<string> list = args[0]->Eval(ev);
122 vector<StringPiece> toks;
123 WordScanner(*list).Split(&toks);
124 sort(toks.begin(), toks.end());
125 WordWriter ww(s);
126 StringPiece prev;
127 for (StringPiece tok : toks) {
128 if (prev != tok) {
129 ww.Write(tok);
130 prev = tok;
131 }
132 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900133}
134
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900135static int GetNumericValueForFunc(const string& buf) {
136 StringPiece s = TrimLeftSpace(buf);
137 char* end;
138 long n = strtol(s.data(), &end, 10);
139 if (n < 0 || n == LONG_MAX || s.data() + s.size() != end) {
140 return -1;
141 }
142 return n;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900143}
144
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900145void WordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
146 shared_ptr<string> n_str = args[0]->Eval(ev);
147 int n = GetNumericValueForFunc(*n_str);
148 if (n < 0) {
149 ev->Error(StringPrintf(
150 "*** non-numeric first argument to `word' function: '%s'.",
151 n_str->c_str()));
152 }
153 if (n == 0) {
154 ev->Error("*** first argument to `word' function must be greater than 0.");
155 }
156
157 shared_ptr<string> text = args[1]->Eval(ev);
158 for (StringPiece tok : WordScanner(*text)) {
159 n--;
160 if (n == 0) {
161 AppendString(tok, s);
162 break;
163 }
164 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900165}
166
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900167void WordlistFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
168 shared_ptr<string> s_str = args[0]->Eval(ev);
169 int si = GetNumericValueForFunc(*s_str);
170 if (si < 0) {
171 ev->Error(StringPrintf(
172 "*** non-numeric first argument to `wordlist' function: '%s'.",
173 s_str->c_str()));
174 }
175 if (si == 0) {
176 ev->Error(StringPrintf(
177 "*** invalid first argument to `wordlist' function: %s`",
178 s_str->c_str()));
179 }
180
181 shared_ptr<string> e_str = args[1]->Eval(ev);
182 int ei = GetNumericValueForFunc(*e_str);
183 if (ei < 0) {
184 ev->Error(StringPrintf(
185 "*** non-numeric second argument to `wordlist' function: '%s'.",
186 e_str->c_str()));
187 }
188
189 shared_ptr<string> text = args[2]->Eval(ev);
190 int i = 0;
191 WordWriter ww(s);
192 for (StringPiece tok : WordScanner(*text)) {
193 i++;
194 if (si <= i && i <= ei) {
195 ww.Write(tok);
196 }
197 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900198}
199
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900200void WordsFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
201 shared_ptr<string> text = args[0]->Eval(ev);
202 WordScanner ws(*text);
203 int n = 0;
204 for (auto iter = ws.begin(); iter != ws.end(); ++iter)
205 n++;
206 char buf[32];
207 sprintf(buf, "%d", n);
208 *s += buf;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900209}
210
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900211void FirstwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
212 shared_ptr<string> text = args[0]->Eval(ev);
213 for (StringPiece tok : WordScanner(*text)) {
214 AppendString(tok, s);
215 return;
216 }
217}
218
219void LastwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
220 shared_ptr<string> text = args[0]->Eval(ev);
221 StringPiece last;
222 for (StringPiece tok : WordScanner(*text)) {
223 last = tok;
224 }
225 AppendString(last, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900226}
227
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900228void JoinFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
229 shared_ptr<string> list1 = args[0]->Eval(ev);
230 shared_ptr<string> list2 = args[1]->Eval(ev);
231 WordScanner ws1(*list1);
232 WordScanner ws2(*list2);
233 WordWriter ww(s);
234 for (WordScanner::Iterator iter1 = ws1.begin(), iter2 = ws2.begin();
235 iter1 != ws1.end() && iter2 != ws2.end();
236 ++iter1, ++iter2) {
237 ww.Write(*iter1);
238 // Use |AppendString| not to append extra ' '.
239 AppendString(*iter2, s);
240 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900241}
242
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900243void WildcardFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
Shinichiro Hamaji284f3d12015-06-17 19:29:01 +0900244 shared_ptr<string> pat = args[0]->Eval(ev);
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900245 WordWriter ww(s);
Shinichiro Hamaji284f3d12015-06-17 19:29:01 +0900246 for (StringPiece tok : WordScanner(*pat)) {
Shinichiro Hamaji8f68bd32015-06-18 11:01:51 +0900247 ScopedTerminator st(tok);
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900248 // TODO: Make this faster by not always using glob.
249 glob_t gl;
250 glob(tok.data(), GLOB_NOSORT, NULL, &gl);
251 for (size_t i = 0; i < gl.gl_pathc; i++) {
252 ww.Write(gl.gl_pathv[i]);
253 }
254 globfree(&gl);
Shinichiro Hamaji284f3d12015-06-17 19:29:01 +0900255 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900256}
257
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900258void DirFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
259 shared_ptr<string> text = args[0]->Eval(ev);
260 WordWriter ww(s);
261 for (StringPiece tok : WordScanner(*text)) {
262 ww.Write(Dirname(tok));
263 if (tok != "/")
264 s->push_back('/');
265 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900266}
267
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900268void NotdirFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
269 shared_ptr<string> text = args[0]->Eval(ev);
270 WordWriter ww(s);
271 for (StringPiece tok : WordScanner(*text)) {
272 if (tok == "/") {
273 ww.Write(STRING_PIECE(""));
274 } else {
275 ww.Write(Basename(tok));
276 }
277 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900278}
279
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900280void SuffixFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
281 shared_ptr<string> text = args[0]->Eval(ev);
282 WordWriter ww(s);
283 for (StringPiece tok : WordScanner(*text)) {
284 StringPiece suf = GetExt(tok);
285 if (!suf.empty())
286 ww.Write(suf);
287 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900288}
289
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900290void BasenameFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
291 shared_ptr<string> text = args[0]->Eval(ev);
292 WordWriter ww(s);
293 for (StringPiece tok : WordScanner(*text)) {
294 ww.Write(StripExt(tok));
295 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900296}
297
Shinichiro Hamaji5d694f02015-06-18 06:05:36 +0900298void AddsuffixFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
299 shared_ptr<string> suf = args[0]->Eval(ev);
300 shared_ptr<string> text = args[1]->Eval(ev);
301 WordWriter ww(s);
302 for (StringPiece tok : WordScanner(*text)) {
303 ww.Write(tok);
304 *s += *suf;
305 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900306}
307
Shinichiro Hamaji5d694f02015-06-18 06:05:36 +0900308void AddprefixFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
309 shared_ptr<string> pre = args[0]->Eval(ev);
310 shared_ptr<string> text = args[1]->Eval(ev);
311 WordWriter ww(s);
312 for (StringPiece tok : WordScanner(*text)) {
313 ww.Write(*pre);
314 AppendString(tok, s);
315 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900316}
317
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900318void RealpathFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
319 shared_ptr<string> text = args[0]->Eval(ev);
320 WordWriter ww(s);
321 for (StringPiece tok : WordScanner(*text)) {
Shinichiro Hamaji8f68bd32015-06-18 11:01:51 +0900322 ScopedTerminator st(tok);
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900323 char buf[PATH_MAX];
324 if (realpath(tok.data(), buf))
325 *s += buf;
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900326 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900327}
328
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900329void AbspathFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
330 shared_ptr<string> text = args[0]->Eval(ev);
331 WordWriter ww(s);
332 string buf;
333 for (StringPiece tok : WordScanner(*text)) {
334 AbsPath(tok, &buf);
335 ww.Write(buf);
336 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900337}
338
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900339void IfFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
340 shared_ptr<string> cond = args[0]->Eval(ev);
341 if (cond->empty()) {
342 if (args.size() > 2)
343 args[2]->Eval(ev, s);
344 } else {
345 args[1]->Eval(ev, s);
346 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900347}
348
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900349void AndFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
350 shared_ptr<string> cond;
351 for (Value* a : args) {
352 cond = a->Eval(ev);
353 if (cond->empty())
354 return;
355 }
356 if (cond.get()) {
357 *s += *cond;
358 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900359}
360
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900361void OrFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
362 for (Value* a : args) {
363 shared_ptr<string> cond = a->Eval(ev);
364 if (!cond->empty()) {
365 *s += *cond;
366 return;
367 }
368 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900369}
370
Shinichiro Hamaji81699be2015-06-22 18:07:38 +0900371void ValueFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
372 shared_ptr<string> var_name = args[0]->Eval(ev);
373 Var* var = ev->LookupVar(*var_name);
374 AppendString(var->String().as_string(), s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900375}
376
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900377void EvalFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900378 // TODO: eval leaks everything... for now.
379 //shared_ptr<string> text = args[0]->Eval(ev);
380 string* text = new string;
381 args[0]->Eval(ev, text);
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900382 vector<AST*> asts;
383 Parse(*text, ev->loc(), &asts);
384 for (AST* ast : asts) {
385 LOG("%s", ast->DebugString().c_str());
386 ast->Eval(ev);
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900387 //delete ast;
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900388 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900389}
390
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900391void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
392 shared_ptr<string> cmd = args[0]->Eval(ev);
393 LOG("ShellFunc: %s", cmd->c_str());
394 string out;
395 // TODO: Handle $(SHELL).
396 FILE* fp = popen(cmd->c_str(), "r");
397 while (true) {
398 char buf[4096];
399 size_t r = fread(buf, 1, 4096, fp);
400 out.append(buf, buf+r);
401 if (r == 0) {
402 fclose(fp);
403 break;
404 }
405 }
406
407 while (out[out.size()-1] == '\n')
408 out.pop_back();
409 for (size_t i = 0; i < out.size(); i++) {
410 if (out[i] == '\n')
411 out[i] = ' ';
412 }
413 *s += out;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900414}
415
Shinichiro Hamaji3064f1f2015-06-18 16:32:09 +0900416void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
417 static const char* tmpvar_names[] = {
418 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
419 };
420
421 shared_ptr<string> func_name = args[0]->Eval(ev);
422 Var* func = ev->LookupVar(*func_name);
423 vector<unique_ptr<SimpleVar>> av;
Shinichiro Hamaji3064f1f2015-06-18 16:32:09 +0900424 for (size_t i = 1; i < args.size(); i++) {
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +0900425 unique_ptr<SimpleVar> s(
426 new SimpleVar(args[i]->Eval(ev), VarOrigin::AUTOMATIC));
Shinichiro Hamaji3064f1f2015-06-18 16:32:09 +0900427 av.push_back(move(s));
428 }
Shinichiro Hamaji5d53bc72015-06-26 08:31:54 +0900429 vector<unique_ptr<ScopedVar>> sv;
430 for (size_t i = 1; i < args.size(); i++) {
431 sv.push_back(move(unique_ptr<ScopedVar>(
432 new ScopedVar(ev->mutable_vars(), tmpvar_names[i], av[i-1].get()))));
433 }
Shinichiro Hamaji3064f1f2015-06-18 16:32:09 +0900434 func->Eval(ev, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900435}
436
Shinichiro Hamajicf0cd682015-06-18 16:18:13 +0900437void ForeachFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
438 shared_ptr<string> varname = args[0]->Eval(ev);
439 shared_ptr<string> list = args[1]->Eval(ev);
440 WordWriter ww(s);
441 for (StringPiece tok : WordScanner(*list)) {
442 unique_ptr<SimpleVar> v(new SimpleVar(
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +0900443 make_shared<string>(tok.data(), tok.size()), VarOrigin::AUTOMATIC));
Shinichiro Hamajicf0cd682015-06-18 16:18:13 +0900444 ScopedVar sv(ev->mutable_vars(), *varname, v.get());
445 ww.MaybeAddWhitespace();
446 args[2]->Eval(ev, s);
447 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900448}
449
Shinichiro Hamajic22fdb42015-06-22 18:10:40 +0900450void OriginFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
451 shared_ptr<string> var_name = args[0]->Eval(ev);
452 Var* var = ev->LookupVar(*var_name);
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +0900453 *s += GetOriginStr(var->Origin());
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900454}
455
Shinichiro Hamajic22fdb42015-06-22 18:10:40 +0900456void FlavorFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
457 shared_ptr<string> var_name = args[0]->Eval(ev);
458 Var* var = ev->LookupVar(*var_name);
459 *s += var->Flavor();
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900460}
461
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900462void InfoFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900463 shared_ptr<string> a = args[0]->Eval(ev);
464 printf("%s\n", a->c_str());
465 fflush(stdout);
466}
467
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900468void WarningFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900469 shared_ptr<string> a = args[0]->Eval(ev);
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900470 printf("%s:%d: %s\n", LOCF(ev->loc()), a->c_str());
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900471 fflush(stdout);
472}
473
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900474void ErrorFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900475 shared_ptr<string> a = args[0]->Eval(ev);
476 ev->Error(StringPrintf("*** %s.", a->c_str()));
477}
478
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900479FuncInfo g_func_infos[] = {
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900480 { "patsubst", &PatsubstFunc, 3, 3, false, false },
481 { "strip", &StripFunc, 1, 1, false, false },
482 { "subst", &SubstFunc, 3, 3, false, false },
483 { "findstring", &FindstringFunc, 2, 2, false, false },
484 { "filter", &FilterFunc, 2, 2, false, false },
485 { "filter-out", &FilterOutFunc, 2, 2, false, false },
486 { "sort", &SortFunc, 1, 1, false, false },
487 { "word", &WordFunc, 2, 2, false, false },
488 { "wordlist", &WordlistFunc, 3, 3, false, false },
489 { "words", &WordsFunc, 1, 1, false, false },
490 { "firstword", &FirstwordFunc, 1, 1, false, false },
491 { "lastword", &LastwordFunc, 1, 1, false, false },
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900492
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900493 { "join", &JoinFunc, 2, 2, false, false },
494 { "wildcard", &WildcardFunc, 1, 1, false, false },
495 { "dir", &DirFunc, 1, 1, false, false },
496 { "notdir", &NotdirFunc, 1, 1, false, false },
497 { "suffix", &SuffixFunc, 1, 1, false, false },
498 { "basename", &BasenameFunc, 1, 1, false, false },
499 { "addsuffix", &AddsuffixFunc, 2, 2, false, false },
500 { "addprefix", &AddprefixFunc, 2, 2, false, false },
501 { "realpath", &RealpathFunc, 1, 1, false, false },
502 { "abspath", &AbspathFunc, 1, 1, false, false },
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900503
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900504 { "if", &IfFunc, 3, 2, false, true },
505 { "and", &AndFunc, 0, 0, true, false },
506 { "or", &OrFunc, 0, 0, true, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900507
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900508 { "value", &ValueFunc, 1, 1, false, false },
509 { "eval", &EvalFunc, 1, 1, false, false },
510 { "shell", &ShellFunc, 1, 1, false, false },
511 { "call", &CallFunc, 0, 0, false, false },
512 { "foreach", &ForeachFunc, 3, 3, false, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900513
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900514 { "origin", &OriginFunc, 1, 1, false, false },
515 { "flavor", &FlavorFunc, 1, 1, false, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900516
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900517 { "info", &InfoFunc, 1, 1, false, false },
518 { "warning", &WarningFunc, 1, 1, false, false },
519 { "error", &ErrorFunc, 1, 1, false, false },
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900520};
521
522unordered_map<StringPiece, FuncInfo*>* g_func_info_map;
523
524} // namespace
525
526void InitFuncTable() {
527 g_func_info_map = new unordered_map<StringPiece, FuncInfo*>;
528 for (size_t i = 0; i < sizeof(g_func_infos) / sizeof(g_func_infos[0]); i++) {
529 FuncInfo* fi = &g_func_infos[i];
530 bool ok = g_func_info_map->insert(make_pair(Intern(fi->name), fi)).second;
531 CHECK(ok);
532 }
533}
534
535void QuitFuncTable() {
536 delete g_func_info_map;
537}
538
539FuncInfo* GetFuncInfo(StringPiece name) {
540 auto found = g_func_info_map->find(name);
541 if (found == g_func_info_map->end())
542 return NULL;
543 return found->second;
544}