blob: cfe7ff3387f24571c9545f63bedc4371701cac5c [file] [log] [blame]
Shinichiro Hamaji776ca302015-06-06 03:52:48 +09001#include "func.h"
2
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +09003#include <glob.h>
Shinichiro Hamajid5271452015-06-17 18:50:03 +09004#include <limits.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +09005#include <stdio.h>
Shinichiro Hamajid5271452015-06-17 18:50:03 +09006#include <stdlib.h>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +09007
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +09008#include <algorithm>
Shinichiro Hamajid5271452015-06-17 18:50:03 +09009#include <iterator>
Shinichiro Hamajicf0cd682015-06-18 16:18:13 +090010#include <memory>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090011#include <unordered_map>
12
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +090013#include "ast.h"
Shinichiro Hamaji9619b362015-06-16 16:13:25 +090014#include "eval.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090015#include "log.h"
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +090016#include "parser.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090017#include "strutil.h"
Shinichiro Hamajicf0cd682015-06-18 16:18:13 +090018#include "var.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090019
20namespace {
21
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090022void PatsubstFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090023 shared_ptr<string> pat_str = args[0]->Eval(ev);
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090024 shared_ptr<string> repl = args[1]->Eval(ev);
25 shared_ptr<string> str = args[2]->Eval(ev);
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090026 WordWriter ww(s);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090027 Pattern pat(*pat_str);
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090028 for (StringPiece tok : WordScanner(*str)) {
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090029 ww.MaybeAddWhitespace();
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090030 pat.AppendSubst(tok, *repl, s);
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090031 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090032}
33
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090034void StripFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
35 shared_ptr<string> str = args[0]->Eval(ev);
36 WordWriter ww(s);
37 for (StringPiece tok : WordScanner(*str)) {
38 ww.Write(tok);
39 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090040}
41
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090042void SubstFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
43 shared_ptr<string> pat = args[0]->Eval(ev);
44 shared_ptr<string> repl = args[1]->Eval(ev);
45 shared_ptr<string> str = args[2]->Eval(ev);
46 size_t index = 0;
47 while (index < str->size()) {
48 size_t found = str->find(*pat, index);
49 if (found == string::npos)
50 break;
51 AppendString(StringPiece(*str).substr(index, found - index), s);
52 AppendString(*repl, s);
53 index = found + pat->size();
54 }
55 AppendString(StringPiece(*str).substr(index), s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090056}
57
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090058void FindstringFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
59 shared_ptr<string> find = args[0]->Eval(ev);
60 shared_ptr<string> in = args[1]->Eval(ev);
61 if (in->find(*find) != string::npos)
62 AppendString(*find, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090063}
64
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090065void FilterFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
66 shared_ptr<string> pat_buf = args[0]->Eval(ev);
67 shared_ptr<string> text = args[1]->Eval(ev);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090068 vector<Pattern> pats;
69 for (StringPiece pat : WordScanner(*pat_buf)) {
70 pats.push_back(Pattern(pat));
71 }
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090072 WordWriter ww(s);
73 for (StringPiece tok : WordScanner(*text)) {
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090074 for (const Pattern& pat : pats) {
75 if (pat.Match(tok)) {
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090076 ww.Write(tok);
77 break;
78 }
79 }
80 }
81}
82
83void FilterOutFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
84 shared_ptr<string> pat_buf = args[0]->Eval(ev);
85 shared_ptr<string> text = args[1]->Eval(ev);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090086 vector<Pattern> pats;
87 for (StringPiece pat : WordScanner(*pat_buf)) {
88 pats.push_back(Pattern(pat));
89 }
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090090 WordWriter ww(s);
91 for (StringPiece tok : WordScanner(*text)) {
92 bool matched = false;
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +090093 for (const Pattern& pat : pats) {
94 if (pat.Match(tok)) {
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090095 matched = true;
96 break;
97 }
98 }
99 if (!matched)
100 ww.Write(tok);
101 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900102}
103
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +0900104void SortFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
105 shared_ptr<string> list = args[0]->Eval(ev);
106 vector<StringPiece> toks;
107 WordScanner(*list).Split(&toks);
108 sort(toks.begin(), toks.end());
109 WordWriter ww(s);
110 StringPiece prev;
111 for (StringPiece tok : toks) {
112 if (prev != tok) {
113 ww.Write(tok);
114 prev = tok;
115 }
116 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900117}
118
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900119static int GetNumericValueForFunc(const string& buf) {
120 StringPiece s = TrimLeftSpace(buf);
121 char* end;
122 long n = strtol(s.data(), &end, 10);
123 if (n < 0 || n == LONG_MAX || s.data() + s.size() != end) {
124 return -1;
125 }
126 return n;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900127}
128
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900129void WordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
130 shared_ptr<string> n_str = args[0]->Eval(ev);
131 int n = GetNumericValueForFunc(*n_str);
132 if (n < 0) {
133 ev->Error(StringPrintf(
134 "*** non-numeric first argument to `word' function: '%s'.",
135 n_str->c_str()));
136 }
137 if (n == 0) {
138 ev->Error("*** first argument to `word' function must be greater than 0.");
139 }
140
141 shared_ptr<string> text = args[1]->Eval(ev);
142 for (StringPiece tok : WordScanner(*text)) {
143 n--;
144 if (n == 0) {
145 AppendString(tok, s);
146 break;
147 }
148 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900149}
150
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900151void WordlistFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
152 shared_ptr<string> s_str = args[0]->Eval(ev);
153 int si = GetNumericValueForFunc(*s_str);
154 if (si < 0) {
155 ev->Error(StringPrintf(
156 "*** non-numeric first argument to `wordlist' function: '%s'.",
157 s_str->c_str()));
158 }
159 if (si == 0) {
160 ev->Error(StringPrintf(
161 "*** invalid first argument to `wordlist' function: %s`",
162 s_str->c_str()));
163 }
164
165 shared_ptr<string> e_str = args[1]->Eval(ev);
166 int ei = GetNumericValueForFunc(*e_str);
167 if (ei < 0) {
168 ev->Error(StringPrintf(
169 "*** non-numeric second argument to `wordlist' function: '%s'.",
170 e_str->c_str()));
171 }
172
173 shared_ptr<string> text = args[2]->Eval(ev);
174 int i = 0;
175 WordWriter ww(s);
176 for (StringPiece tok : WordScanner(*text)) {
177 i++;
178 if (si <= i && i <= ei) {
179 ww.Write(tok);
180 }
181 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900182}
183
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900184void WordsFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
185 shared_ptr<string> text = args[0]->Eval(ev);
186 WordScanner ws(*text);
187 int n = 0;
188 for (auto iter = ws.begin(); iter != ws.end(); ++iter)
189 n++;
190 char buf[32];
191 sprintf(buf, "%d", n);
192 *s += buf;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900193}
194
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900195void FirstwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
196 shared_ptr<string> text = args[0]->Eval(ev);
197 for (StringPiece tok : WordScanner(*text)) {
198 AppendString(tok, s);
199 return;
200 }
201}
202
203void LastwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
204 shared_ptr<string> text = args[0]->Eval(ev);
205 StringPiece last;
206 for (StringPiece tok : WordScanner(*text)) {
207 last = tok;
208 }
209 AppendString(last, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900210}
211
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900212void JoinFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
213 shared_ptr<string> list1 = args[0]->Eval(ev);
214 shared_ptr<string> list2 = args[1]->Eval(ev);
215 WordScanner ws1(*list1);
216 WordScanner ws2(*list2);
217 WordWriter ww(s);
218 for (WordScanner::Iterator iter1 = ws1.begin(), iter2 = ws2.begin();
219 iter1 != ws1.end() && iter2 != ws2.end();
220 ++iter1, ++iter2) {
221 ww.Write(*iter1);
222 // Use |AppendString| not to append extra ' '.
223 AppendString(*iter2, s);
224 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900225}
226
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900227void WildcardFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
Shinichiro Hamaji284f3d12015-06-17 19:29:01 +0900228 shared_ptr<string> pat = args[0]->Eval(ev);
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900229 WordWriter ww(s);
Shinichiro Hamaji284f3d12015-06-17 19:29:01 +0900230 for (StringPiece tok : WordScanner(*pat)) {
Shinichiro Hamaji8f68bd32015-06-18 11:01:51 +0900231 ScopedTerminator st(tok);
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900232 // TODO: Make this faster by not always using glob.
233 glob_t gl;
234 glob(tok.data(), GLOB_NOSORT, NULL, &gl);
235 for (size_t i = 0; i < gl.gl_pathc; i++) {
236 ww.Write(gl.gl_pathv[i]);
237 }
238 globfree(&gl);
Shinichiro Hamaji284f3d12015-06-17 19:29:01 +0900239 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900240}
241
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900242void DirFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
243 shared_ptr<string> text = args[0]->Eval(ev);
244 WordWriter ww(s);
245 for (StringPiece tok : WordScanner(*text)) {
246 ww.Write(Dirname(tok));
247 if (tok != "/")
248 s->push_back('/');
249 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900250}
251
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900252void NotdirFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
253 shared_ptr<string> text = args[0]->Eval(ev);
254 WordWriter ww(s);
255 for (StringPiece tok : WordScanner(*text)) {
256 if (tok == "/") {
257 ww.Write(STRING_PIECE(""));
258 } else {
259 ww.Write(Basename(tok));
260 }
261 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900262}
263
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900264void SuffixFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
265 shared_ptr<string> text = args[0]->Eval(ev);
266 WordWriter ww(s);
267 for (StringPiece tok : WordScanner(*text)) {
268 StringPiece suf = GetExt(tok);
269 if (!suf.empty())
270 ww.Write(suf);
271 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900272}
273
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900274void BasenameFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
275 shared_ptr<string> text = args[0]->Eval(ev);
276 WordWriter ww(s);
277 for (StringPiece tok : WordScanner(*text)) {
278 ww.Write(StripExt(tok));
279 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900280}
281
Shinichiro Hamaji5d694f02015-06-18 06:05:36 +0900282void AddsuffixFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
283 shared_ptr<string> suf = args[0]->Eval(ev);
284 shared_ptr<string> text = args[1]->Eval(ev);
285 WordWriter ww(s);
286 for (StringPiece tok : WordScanner(*text)) {
287 ww.Write(tok);
288 *s += *suf;
289 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900290}
291
Shinichiro Hamaji5d694f02015-06-18 06:05:36 +0900292void AddprefixFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
293 shared_ptr<string> pre = args[0]->Eval(ev);
294 shared_ptr<string> text = args[1]->Eval(ev);
295 WordWriter ww(s);
296 for (StringPiece tok : WordScanner(*text)) {
297 ww.Write(*pre);
298 AppendString(tok, s);
299 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900300}
301
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900302void RealpathFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
303 shared_ptr<string> text = args[0]->Eval(ev);
304 WordWriter ww(s);
305 for (StringPiece tok : WordScanner(*text)) {
Shinichiro Hamaji8f68bd32015-06-18 11:01:51 +0900306 ScopedTerminator st(tok);
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900307 char buf[PATH_MAX];
308 if (realpath(tok.data(), buf))
309 *s += buf;
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900310 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900311}
312
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900313void AbspathFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
314 shared_ptr<string> text = args[0]->Eval(ev);
315 WordWriter ww(s);
316 string buf;
317 for (StringPiece tok : WordScanner(*text)) {
318 AbsPath(tok, &buf);
319 ww.Write(buf);
320 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900321}
322
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900323void IfFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
324 shared_ptr<string> cond = args[0]->Eval(ev);
325 if (cond->empty()) {
326 if (args.size() > 2)
327 args[2]->Eval(ev, s);
328 } else {
329 args[1]->Eval(ev, s);
330 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900331}
332
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900333void AndFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
334 shared_ptr<string> cond;
335 for (Value* a : args) {
336 cond = a->Eval(ev);
337 if (cond->empty())
338 return;
339 }
340 if (cond.get()) {
341 *s += *cond;
342 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900343}
344
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900345void OrFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
346 for (Value* a : args) {
347 shared_ptr<string> cond = a->Eval(ev);
348 if (!cond->empty()) {
349 *s += *cond;
350 return;
351 }
352 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900353}
354
Shinichiro Hamaji81699be2015-06-22 18:07:38 +0900355void ValueFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
356 shared_ptr<string> var_name = args[0]->Eval(ev);
357 Var* var = ev->LookupVar(*var_name);
358 AppendString(var->String().as_string(), s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900359}
360
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900361void EvalFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900362 // TODO: eval leaks everything... for now.
363 //shared_ptr<string> text = args[0]->Eval(ev);
364 string* text = new string;
365 args[0]->Eval(ev, text);
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900366 vector<AST*> asts;
367 Parse(*text, ev->loc(), &asts);
368 for (AST* ast : asts) {
369 LOG("%s", ast->DebugString().c_str());
370 ast->Eval(ev);
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900371 //delete ast;
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900372 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900373}
374
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900375void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
376 shared_ptr<string> cmd = args[0]->Eval(ev);
377 LOG("ShellFunc: %s", cmd->c_str());
378 string out;
379 // TODO: Handle $(SHELL).
380 FILE* fp = popen(cmd->c_str(), "r");
381 while (true) {
382 char buf[4096];
383 size_t r = fread(buf, 1, 4096, fp);
384 out.append(buf, buf+r);
385 if (r == 0) {
386 fclose(fp);
387 break;
388 }
389 }
390
391 while (out[out.size()-1] == '\n')
392 out.pop_back();
393 for (size_t i = 0; i < out.size(); i++) {
394 if (out[i] == '\n')
395 out[i] = ' ';
396 }
397 *s += out;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900398}
399
Shinichiro Hamaji3064f1f2015-06-18 16:32:09 +0900400void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
401 static const char* tmpvar_names[] = {
402 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
403 };
404
405 shared_ptr<string> func_name = args[0]->Eval(ev);
406 Var* func = ev->LookupVar(*func_name);
407 vector<unique_ptr<SimpleVar>> av;
408 vector<unique_ptr<ScopedVar>> sv;
409 for (size_t i = 1; i < args.size(); i++) {
410 unique_ptr<SimpleVar> s(new SimpleVar(args[i]->Eval(ev), "automatic"));
411 sv.push_back(move(unique_ptr<ScopedVar>(
412 new ScopedVar(ev->mutable_vars(), tmpvar_names[i], s.get()))));
413 av.push_back(move(s));
414 }
415 func->Eval(ev, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900416}
417
Shinichiro Hamajicf0cd682015-06-18 16:18:13 +0900418void ForeachFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
419 shared_ptr<string> varname = args[0]->Eval(ev);
420 shared_ptr<string> list = args[1]->Eval(ev);
421 WordWriter ww(s);
422 for (StringPiece tok : WordScanner(*list)) {
423 unique_ptr<SimpleVar> v(new SimpleVar(
424 make_shared<string>(tok.data(), tok.size()), "automatic"));
425 ScopedVar sv(ev->mutable_vars(), *varname, v.get());
426 ww.MaybeAddWhitespace();
427 args[2]->Eval(ev, s);
428 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900429}
430
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900431void OriginFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900432 printf("TODO(origin)");
433}
434
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900435void FlavorFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900436 printf("TODO(flavor)");
437}
438
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900439void InfoFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900440 shared_ptr<string> a = args[0]->Eval(ev);
441 printf("%s\n", a->c_str());
442 fflush(stdout);
443}
444
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900445void WarningFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900446 shared_ptr<string> a = args[0]->Eval(ev);
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900447 printf("%s:%d: %s\n", LOCF(ev->loc()), a->c_str());
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900448 fflush(stdout);
449}
450
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900451void ErrorFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900452 shared_ptr<string> a = args[0]->Eval(ev);
453 ev->Error(StringPrintf("*** %s.", a->c_str()));
454}
455
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900456FuncInfo g_func_infos[] = {
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900457 { "patsubst", &PatsubstFunc, 3, 3, false, false },
458 { "strip", &StripFunc, 1, 1, false, false },
459 { "subst", &SubstFunc, 3, 3, false, false },
460 { "findstring", &FindstringFunc, 2, 2, false, false },
461 { "filter", &FilterFunc, 2, 2, false, false },
462 { "filter-out", &FilterOutFunc, 2, 2, false, false },
463 { "sort", &SortFunc, 1, 1, false, false },
464 { "word", &WordFunc, 2, 2, false, false },
465 { "wordlist", &WordlistFunc, 3, 3, false, false },
466 { "words", &WordsFunc, 1, 1, false, false },
467 { "firstword", &FirstwordFunc, 1, 1, false, false },
468 { "lastword", &LastwordFunc, 1, 1, false, false },
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900469
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900470 { "join", &JoinFunc, 2, 2, false, false },
471 { "wildcard", &WildcardFunc, 1, 1, false, false },
472 { "dir", &DirFunc, 1, 1, false, false },
473 { "notdir", &NotdirFunc, 1, 1, false, false },
474 { "suffix", &SuffixFunc, 1, 1, false, false },
475 { "basename", &BasenameFunc, 1, 1, false, false },
476 { "addsuffix", &AddsuffixFunc, 2, 2, false, false },
477 { "addprefix", &AddprefixFunc, 2, 2, false, false },
478 { "realpath", &RealpathFunc, 1, 1, false, false },
479 { "abspath", &AbspathFunc, 1, 1, false, false },
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900480
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900481 { "if", &IfFunc, 3, 2, false, true },
482 { "and", &AndFunc, 0, 0, true, false },
483 { "or", &OrFunc, 0, 0, true, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900484
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900485 { "value", &ValueFunc, 1, 1, false, false },
486 { "eval", &EvalFunc, 1, 1, false, false },
487 { "shell", &ShellFunc, 1, 1, false, false },
488 { "call", &CallFunc, 0, 0, false, false },
489 { "foreach", &ForeachFunc, 3, 3, false, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900490
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900491 { "origin", &OriginFunc, 1, 1, false, false },
492 { "flavor", &FlavorFunc, 1, 1, false, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900493
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900494 { "info", &InfoFunc, 1, 1, false, false },
495 { "warning", &WarningFunc, 1, 1, false, false },
496 { "error", &ErrorFunc, 1, 1, false, false },
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900497};
498
499unordered_map<StringPiece, FuncInfo*>* g_func_info_map;
500
501} // namespace
502
503void InitFuncTable() {
504 g_func_info_map = new unordered_map<StringPiece, FuncInfo*>;
505 for (size_t i = 0; i < sizeof(g_func_infos) / sizeof(g_func_infos[0]); i++) {
506 FuncInfo* fi = &g_func_infos[i];
507 bool ok = g_func_info_map->insert(make_pair(Intern(fi->name), fi)).second;
508 CHECK(ok);
509 }
510}
511
512void QuitFuncTable() {
513 delete g_func_info_map;
514}
515
516FuncInfo* GetFuncInfo(StringPiece name) {
517 auto found = g_func_info_map->find(name);
518 if (found == g_func_info_map->end())
519 return NULL;
520 return found->second;
521}