blob: 9e33f35f32888d5dbb31c0fc575f5bd93f10488c [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) {
23 shared_ptr<string> pat = args[0]->Eval(ev);
24 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 Hamaji2e6cbfc2015-06-16 18:46:50 +090027 for (StringPiece tok : WordScanner(*str)) {
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090028 ww.MaybeAddWhitespace();
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090029 AppendSubstPattern(tok, *pat, *repl, s);
30 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090031}
32
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090033void StripFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
34 shared_ptr<string> str = args[0]->Eval(ev);
35 WordWriter ww(s);
36 for (StringPiece tok : WordScanner(*str)) {
37 ww.Write(tok);
38 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090039}
40
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090041void SubstFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
42 shared_ptr<string> pat = args[0]->Eval(ev);
43 shared_ptr<string> repl = args[1]->Eval(ev);
44 shared_ptr<string> str = args[2]->Eval(ev);
45 size_t index = 0;
46 while (index < str->size()) {
47 size_t found = str->find(*pat, index);
48 if (found == string::npos)
49 break;
50 AppendString(StringPiece(*str).substr(index, found - index), s);
51 AppendString(*repl, s);
52 index = found + pat->size();
53 }
54 AppendString(StringPiece(*str).substr(index), s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090055}
56
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090057void FindstringFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
58 shared_ptr<string> find = args[0]->Eval(ev);
59 shared_ptr<string> in = args[1]->Eval(ev);
60 if (in->find(*find) != string::npos)
61 AppendString(*find, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090062}
63
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090064void FilterFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
65 shared_ptr<string> pat_buf = args[0]->Eval(ev);
66 shared_ptr<string> text = args[1]->Eval(ev);
67 vector<StringPiece> pats;
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +090068 WordScanner(*pat_buf).Split(&pats);
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090069 WordWriter ww(s);
70 for (StringPiece tok : WordScanner(*text)) {
71 for (StringPiece pat : pats) {
72 if (MatchPattern(tok, pat)) {
73 ww.Write(tok);
74 break;
75 }
76 }
77 }
78}
79
80void FilterOutFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
81 shared_ptr<string> pat_buf = args[0]->Eval(ev);
82 shared_ptr<string> text = args[1]->Eval(ev);
83 vector<StringPiece> pats;
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +090084 WordScanner(*pat_buf).Split(&pats);
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090085 WordWriter ww(s);
86 for (StringPiece tok : WordScanner(*text)) {
87 bool matched = false;
88 for (StringPiece pat : pats) {
89 if (MatchPattern(tok, pat)) {
90 matched = true;
91 break;
92 }
93 }
94 if (!matched)
95 ww.Write(tok);
96 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090097}
98
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +090099void SortFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
100 shared_ptr<string> list = args[0]->Eval(ev);
101 vector<StringPiece> toks;
102 WordScanner(*list).Split(&toks);
103 sort(toks.begin(), toks.end());
104 WordWriter ww(s);
105 StringPiece prev;
106 for (StringPiece tok : toks) {
107 if (prev != tok) {
108 ww.Write(tok);
109 prev = tok;
110 }
111 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900112}
113
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900114static int GetNumericValueForFunc(const string& buf) {
115 StringPiece s = TrimLeftSpace(buf);
116 char* end;
117 long n = strtol(s.data(), &end, 10);
118 if (n < 0 || n == LONG_MAX || s.data() + s.size() != end) {
119 return -1;
120 }
121 return n;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900122}
123
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900124void WordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
125 shared_ptr<string> n_str = args[0]->Eval(ev);
126 int n = GetNumericValueForFunc(*n_str);
127 if (n < 0) {
128 ev->Error(StringPrintf(
129 "*** non-numeric first argument to `word' function: '%s'.",
130 n_str->c_str()));
131 }
132 if (n == 0) {
133 ev->Error("*** first argument to `word' function must be greater than 0.");
134 }
135
136 shared_ptr<string> text = args[1]->Eval(ev);
137 for (StringPiece tok : WordScanner(*text)) {
138 n--;
139 if (n == 0) {
140 AppendString(tok, s);
141 break;
142 }
143 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900144}
145
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900146void WordlistFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
147 shared_ptr<string> s_str = args[0]->Eval(ev);
148 int si = GetNumericValueForFunc(*s_str);
149 if (si < 0) {
150 ev->Error(StringPrintf(
151 "*** non-numeric first argument to `wordlist' function: '%s'.",
152 s_str->c_str()));
153 }
154 if (si == 0) {
155 ev->Error(StringPrintf(
156 "*** invalid first argument to `wordlist' function: %s`",
157 s_str->c_str()));
158 }
159
160 shared_ptr<string> e_str = args[1]->Eval(ev);
161 int ei = GetNumericValueForFunc(*e_str);
162 if (ei < 0) {
163 ev->Error(StringPrintf(
164 "*** non-numeric second argument to `wordlist' function: '%s'.",
165 e_str->c_str()));
166 }
167
168 shared_ptr<string> text = args[2]->Eval(ev);
169 int i = 0;
170 WordWriter ww(s);
171 for (StringPiece tok : WordScanner(*text)) {
172 i++;
173 if (si <= i && i <= ei) {
174 ww.Write(tok);
175 }
176 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900177}
178
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900179void WordsFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
180 shared_ptr<string> text = args[0]->Eval(ev);
181 WordScanner ws(*text);
182 int n = 0;
183 for (auto iter = ws.begin(); iter != ws.end(); ++iter)
184 n++;
185 char buf[32];
186 sprintf(buf, "%d", n);
187 *s += buf;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900188}
189
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900190void FirstwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
191 shared_ptr<string> text = args[0]->Eval(ev);
192 for (StringPiece tok : WordScanner(*text)) {
193 AppendString(tok, s);
194 return;
195 }
196}
197
198void LastwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
199 shared_ptr<string> text = args[0]->Eval(ev);
200 StringPiece last;
201 for (StringPiece tok : WordScanner(*text)) {
202 last = tok;
203 }
204 AppendString(last, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900205}
206
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900207void JoinFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
208 shared_ptr<string> list1 = args[0]->Eval(ev);
209 shared_ptr<string> list2 = args[1]->Eval(ev);
210 WordScanner ws1(*list1);
211 WordScanner ws2(*list2);
212 WordWriter ww(s);
213 for (WordScanner::Iterator iter1 = ws1.begin(), iter2 = ws2.begin();
214 iter1 != ws1.end() && iter2 != ws2.end();
215 ++iter1, ++iter2) {
216 ww.Write(*iter1);
217 // Use |AppendString| not to append extra ' '.
218 AppendString(*iter2, s);
219 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900220}
221
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900222void WildcardFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
Shinichiro Hamaji284f3d12015-06-17 19:29:01 +0900223 shared_ptr<string> pat = args[0]->Eval(ev);
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900224 WordWriter ww(s);
Shinichiro Hamaji284f3d12015-06-17 19:29:01 +0900225 for (StringPiece tok : WordScanner(*pat)) {
Shinichiro Hamaji8f68bd32015-06-18 11:01:51 +0900226 ScopedTerminator st(tok);
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900227 // TODO: Make this faster by not always using glob.
228 glob_t gl;
229 glob(tok.data(), GLOB_NOSORT, NULL, &gl);
230 for (size_t i = 0; i < gl.gl_pathc; i++) {
231 ww.Write(gl.gl_pathv[i]);
232 }
233 globfree(&gl);
Shinichiro Hamaji284f3d12015-06-17 19:29:01 +0900234 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900235}
236
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900237void DirFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
238 shared_ptr<string> text = args[0]->Eval(ev);
239 WordWriter ww(s);
240 for (StringPiece tok : WordScanner(*text)) {
241 ww.Write(Dirname(tok));
242 if (tok != "/")
243 s->push_back('/');
244 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900245}
246
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900247void NotdirFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
248 shared_ptr<string> text = args[0]->Eval(ev);
249 WordWriter ww(s);
250 for (StringPiece tok : WordScanner(*text)) {
251 if (tok == "/") {
252 ww.Write(STRING_PIECE(""));
253 } else {
254 ww.Write(Basename(tok));
255 }
256 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900257}
258
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900259void SuffixFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
260 shared_ptr<string> text = args[0]->Eval(ev);
261 WordWriter ww(s);
262 for (StringPiece tok : WordScanner(*text)) {
263 StringPiece suf = GetExt(tok);
264 if (!suf.empty())
265 ww.Write(suf);
266 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900267}
268
Shinichiro Hamaji67f9a702015-06-18 06:00:57 +0900269void BasenameFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
270 shared_ptr<string> text = args[0]->Eval(ev);
271 WordWriter ww(s);
272 for (StringPiece tok : WordScanner(*text)) {
273 ww.Write(StripExt(tok));
274 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900275}
276
Shinichiro Hamaji5d694f02015-06-18 06:05:36 +0900277void AddsuffixFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
278 shared_ptr<string> suf = args[0]->Eval(ev);
279 shared_ptr<string> text = args[1]->Eval(ev);
280 WordWriter ww(s);
281 for (StringPiece tok : WordScanner(*text)) {
282 ww.Write(tok);
283 *s += *suf;
284 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900285}
286
Shinichiro Hamaji5d694f02015-06-18 06:05:36 +0900287void AddprefixFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
288 shared_ptr<string> pre = args[0]->Eval(ev);
289 shared_ptr<string> text = args[1]->Eval(ev);
290 WordWriter ww(s);
291 for (StringPiece tok : WordScanner(*text)) {
292 ww.Write(*pre);
293 AppendString(tok, s);
294 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900295}
296
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900297void RealpathFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
298 shared_ptr<string> text = args[0]->Eval(ev);
299 WordWriter ww(s);
300 for (StringPiece tok : WordScanner(*text)) {
Shinichiro Hamaji8f68bd32015-06-18 11:01:51 +0900301 ScopedTerminator st(tok);
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900302 char buf[PATH_MAX];
303 if (realpath(tok.data(), buf))
304 *s += buf;
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900305 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900306}
307
Shinichiro Hamaji8a963582015-06-18 07:05:58 +0900308void AbspathFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
309 shared_ptr<string> text = args[0]->Eval(ev);
310 WordWriter ww(s);
311 string buf;
312 for (StringPiece tok : WordScanner(*text)) {
313 AbsPath(tok, &buf);
314 ww.Write(buf);
315 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900316}
317
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900318void IfFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
319 shared_ptr<string> cond = args[0]->Eval(ev);
320 if (cond->empty()) {
321 if (args.size() > 2)
322 args[2]->Eval(ev, s);
323 } else {
324 args[1]->Eval(ev, s);
325 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900326}
327
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900328void AndFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
329 shared_ptr<string> cond;
330 for (Value* a : args) {
331 cond = a->Eval(ev);
332 if (cond->empty())
333 return;
334 }
335 if (cond.get()) {
336 *s += *cond;
337 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900338}
339
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900340void OrFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
341 for (Value* a : args) {
342 shared_ptr<string> cond = a->Eval(ev);
343 if (!cond->empty()) {
344 *s += *cond;
345 return;
346 }
347 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900348}
349
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900350void ValueFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900351 printf("TODO(value)");
352}
353
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900354void EvalFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900355 // TODO: eval leaks everything... for now.
356 //shared_ptr<string> text = args[0]->Eval(ev);
357 string* text = new string;
358 args[0]->Eval(ev, text);
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900359 vector<AST*> asts;
360 Parse(*text, ev->loc(), &asts);
361 for (AST* ast : asts) {
362 LOG("%s", ast->DebugString().c_str());
363 ast->Eval(ev);
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900364 //delete ast;
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900365 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900366}
367
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900368void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
369 shared_ptr<string> cmd = args[0]->Eval(ev);
370 LOG("ShellFunc: %s", cmd->c_str());
371 string out;
372 // TODO: Handle $(SHELL).
373 FILE* fp = popen(cmd->c_str(), "r");
374 while (true) {
375 char buf[4096];
376 size_t r = fread(buf, 1, 4096, fp);
377 out.append(buf, buf+r);
378 if (r == 0) {
379 fclose(fp);
380 break;
381 }
382 }
383
384 while (out[out.size()-1] == '\n')
385 out.pop_back();
386 for (size_t i = 0; i < out.size(); i++) {
387 if (out[i] == '\n')
388 out[i] = ' ';
389 }
390 *s += out;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900391}
392
Shinichiro Hamaji3064f1f2015-06-18 16:32:09 +0900393void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
394 static const char* tmpvar_names[] = {
395 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
396 };
397
398 shared_ptr<string> func_name = args[0]->Eval(ev);
399 Var* func = ev->LookupVar(*func_name);
400 vector<unique_ptr<SimpleVar>> av;
401 vector<unique_ptr<ScopedVar>> sv;
402 for (size_t i = 1; i < args.size(); i++) {
403 unique_ptr<SimpleVar> s(new SimpleVar(args[i]->Eval(ev), "automatic"));
404 sv.push_back(move(unique_ptr<ScopedVar>(
405 new ScopedVar(ev->mutable_vars(), tmpvar_names[i], s.get()))));
406 av.push_back(move(s));
407 }
408 func->Eval(ev, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900409}
410
Shinichiro Hamajicf0cd682015-06-18 16:18:13 +0900411void ForeachFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
412 shared_ptr<string> varname = args[0]->Eval(ev);
413 shared_ptr<string> list = args[1]->Eval(ev);
414 WordWriter ww(s);
415 for (StringPiece tok : WordScanner(*list)) {
416 unique_ptr<SimpleVar> v(new SimpleVar(
417 make_shared<string>(tok.data(), tok.size()), "automatic"));
418 ScopedVar sv(ev->mutable_vars(), *varname, v.get());
419 ww.MaybeAddWhitespace();
420 args[2]->Eval(ev, s);
421 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900422}
423
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900424void OriginFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900425 printf("TODO(origin)");
426}
427
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900428void FlavorFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900429 printf("TODO(flavor)");
430}
431
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900432void InfoFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900433 shared_ptr<string> a = args[0]->Eval(ev);
434 printf("%s\n", a->c_str());
435 fflush(stdout);
436}
437
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900438void WarningFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900439 shared_ptr<string> a = args[0]->Eval(ev);
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900440 printf("%s:%d: %s\n", LOCF(ev->loc()), a->c_str());
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900441 fflush(stdout);
442}
443
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900444void ErrorFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900445 shared_ptr<string> a = args[0]->Eval(ev);
446 ev->Error(StringPrintf("*** %s.", a->c_str()));
447}
448
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900449FuncInfo g_func_infos[] = {
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900450 { "patsubst", &PatsubstFunc, 3, 3, false, false },
451 { "strip", &StripFunc, 1, 1, false, false },
452 { "subst", &SubstFunc, 3, 3, false, false },
453 { "findstring", &FindstringFunc, 2, 2, false, false },
454 { "filter", &FilterFunc, 2, 2, false, false },
455 { "filter-out", &FilterOutFunc, 2, 2, false, false },
456 { "sort", &SortFunc, 1, 1, false, false },
457 { "word", &WordFunc, 2, 2, false, false },
458 { "wordlist", &WordlistFunc, 3, 3, false, false },
459 { "words", &WordsFunc, 1, 1, false, false },
460 { "firstword", &FirstwordFunc, 1, 1, false, false },
461 { "lastword", &LastwordFunc, 1, 1, false, false },
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900462
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900463 { "join", &JoinFunc, 2, 2, false, false },
464 { "wildcard", &WildcardFunc, 1, 1, false, false },
465 { "dir", &DirFunc, 1, 1, false, false },
466 { "notdir", &NotdirFunc, 1, 1, false, false },
467 { "suffix", &SuffixFunc, 1, 1, false, false },
468 { "basename", &BasenameFunc, 1, 1, false, false },
469 { "addsuffix", &AddsuffixFunc, 2, 2, false, false },
470 { "addprefix", &AddprefixFunc, 2, 2, false, false },
471 { "realpath", &RealpathFunc, 1, 1, false, false },
472 { "abspath", &AbspathFunc, 1, 1, false, false },
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900473
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900474 { "if", &IfFunc, 3, 2, false, true },
475 { "and", &AndFunc, 0, 0, true, false },
476 { "or", &OrFunc, 0, 0, true, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900477
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900478 { "value", &ValueFunc, 1, 1, false, false },
479 { "eval", &EvalFunc, 1, 1, false, false },
480 { "shell", &ShellFunc, 1, 1, false, false },
481 { "call", &CallFunc, 0, 0, false, false },
482 { "foreach", &ForeachFunc, 3, 3, false, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900483
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900484 { "origin", &OriginFunc, 1, 1, false, false },
485 { "flavor", &FlavorFunc, 1, 1, false, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900486
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900487 { "info", &InfoFunc, 1, 1, false, false },
488 { "warning", &WarningFunc, 1, 1, false, false },
489 { "error", &ErrorFunc, 1, 1, false, false },
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900490};
491
492unordered_map<StringPiece, FuncInfo*>* g_func_info_map;
493
494} // namespace
495
496void InitFuncTable() {
497 g_func_info_map = new unordered_map<StringPiece, FuncInfo*>;
498 for (size_t i = 0; i < sizeof(g_func_infos) / sizeof(g_func_infos[0]); i++) {
499 FuncInfo* fi = &g_func_infos[i];
500 bool ok = g_func_info_map->insert(make_pair(Intern(fi->name), fi)).second;
501 CHECK(ok);
502 }
503}
504
505void QuitFuncTable() {
506 delete g_func_info_map;
507}
508
509FuncInfo* GetFuncInfo(StringPiece name) {
510 auto found = g_func_info_map->find(name);
511 if (found == g_func_info_map->end())
512 return NULL;
513 return found->second;
514}