blob: a47d55f4377611ecc1c0e0ee20c15de939dacffc [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 Hamaji2e6cbfc2015-06-16 18:46:50 +0900355void ValueFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900356 printf("TODO(value)");
357}
358
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900359void EvalFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900360 // TODO: eval leaks everything... for now.
361 //shared_ptr<string> text = args[0]->Eval(ev);
362 string* text = new string;
363 args[0]->Eval(ev, text);
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900364 vector<AST*> asts;
365 Parse(*text, ev->loc(), &asts);
366 for (AST* ast : asts) {
367 LOG("%s", ast->DebugString().c_str());
368 ast->Eval(ev);
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900369 //delete ast;
Shinichiro Hamaji80456fb2015-06-18 14:56:10 +0900370 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900371}
372
Shinichiro Hamajifcf1b762015-06-18 03:43:54 +0900373void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
374 shared_ptr<string> cmd = args[0]->Eval(ev);
375 LOG("ShellFunc: %s", cmd->c_str());
376 string out;
377 // TODO: Handle $(SHELL).
378 FILE* fp = popen(cmd->c_str(), "r");
379 while (true) {
380 char buf[4096];
381 size_t r = fread(buf, 1, 4096, fp);
382 out.append(buf, buf+r);
383 if (r == 0) {
384 fclose(fp);
385 break;
386 }
387 }
388
389 while (out[out.size()-1] == '\n')
390 out.pop_back();
391 for (size_t i = 0; i < out.size(); i++) {
392 if (out[i] == '\n')
393 out[i] = ' ';
394 }
395 *s += out;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900396}
397
Shinichiro Hamaji3064f1f2015-06-18 16:32:09 +0900398void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
399 static const char* tmpvar_names[] = {
400 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
401 };
402
403 shared_ptr<string> func_name = args[0]->Eval(ev);
404 Var* func = ev->LookupVar(*func_name);
405 vector<unique_ptr<SimpleVar>> av;
406 vector<unique_ptr<ScopedVar>> sv;
407 for (size_t i = 1; i < args.size(); i++) {
408 unique_ptr<SimpleVar> s(new SimpleVar(args[i]->Eval(ev), "automatic"));
409 sv.push_back(move(unique_ptr<ScopedVar>(
410 new ScopedVar(ev->mutable_vars(), tmpvar_names[i], s.get()))));
411 av.push_back(move(s));
412 }
413 func->Eval(ev, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900414}
415
Shinichiro Hamajicf0cd682015-06-18 16:18:13 +0900416void ForeachFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
417 shared_ptr<string> varname = args[0]->Eval(ev);
418 shared_ptr<string> list = args[1]->Eval(ev);
419 WordWriter ww(s);
420 for (StringPiece tok : WordScanner(*list)) {
421 unique_ptr<SimpleVar> v(new SimpleVar(
422 make_shared<string>(tok.data(), tok.size()), "automatic"));
423 ScopedVar sv(ev->mutable_vars(), *varname, v.get());
424 ww.MaybeAddWhitespace();
425 args[2]->Eval(ev, s);
426 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900427}
428
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900429void OriginFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900430 printf("TODO(origin)");
431}
432
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900433void FlavorFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900434 printf("TODO(flavor)");
435}
436
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900437void InfoFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900438 shared_ptr<string> a = args[0]->Eval(ev);
439 printf("%s\n", a->c_str());
440 fflush(stdout);
441}
442
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900443void WarningFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900444 shared_ptr<string> a = args[0]->Eval(ev);
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900445 printf("%s:%d: %s\n", LOCF(ev->loc()), a->c_str());
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900446 fflush(stdout);
447}
448
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900449void ErrorFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900450 shared_ptr<string> a = args[0]->Eval(ev);
451 ev->Error(StringPrintf("*** %s.", a->c_str()));
452}
453
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900454FuncInfo g_func_infos[] = {
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900455 { "patsubst", &PatsubstFunc, 3, 3, false, false },
456 { "strip", &StripFunc, 1, 1, false, false },
457 { "subst", &SubstFunc, 3, 3, false, false },
458 { "findstring", &FindstringFunc, 2, 2, false, false },
459 { "filter", &FilterFunc, 2, 2, false, false },
460 { "filter-out", &FilterOutFunc, 2, 2, false, false },
461 { "sort", &SortFunc, 1, 1, false, false },
462 { "word", &WordFunc, 2, 2, false, false },
463 { "wordlist", &WordlistFunc, 3, 3, false, false },
464 { "words", &WordsFunc, 1, 1, false, false },
465 { "firstword", &FirstwordFunc, 1, 1, false, false },
466 { "lastword", &LastwordFunc, 1, 1, false, false },
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900467
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900468 { "join", &JoinFunc, 2, 2, false, false },
469 { "wildcard", &WildcardFunc, 1, 1, false, false },
470 { "dir", &DirFunc, 1, 1, false, false },
471 { "notdir", &NotdirFunc, 1, 1, false, false },
472 { "suffix", &SuffixFunc, 1, 1, false, false },
473 { "basename", &BasenameFunc, 1, 1, false, false },
474 { "addsuffix", &AddsuffixFunc, 2, 2, false, false },
475 { "addprefix", &AddprefixFunc, 2, 2, false, false },
476 { "realpath", &RealpathFunc, 1, 1, false, false },
477 { "abspath", &AbspathFunc, 1, 1, false, false },
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900478
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900479 { "if", &IfFunc, 3, 2, false, true },
480 { "and", &AndFunc, 0, 0, true, false },
481 { "or", &OrFunc, 0, 0, true, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900482
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900483 { "value", &ValueFunc, 1, 1, false, false },
484 { "eval", &EvalFunc, 1, 1, false, false },
485 { "shell", &ShellFunc, 1, 1, false, false },
486 { "call", &CallFunc, 0, 0, false, false },
487 { "foreach", &ForeachFunc, 3, 3, false, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900488
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900489 { "origin", &OriginFunc, 1, 1, false, false },
490 { "flavor", &FlavorFunc, 1, 1, false, false },
Shinichiro Hamajie22fe8e2015-06-18 07:11:54 +0900491
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900492 { "info", &InfoFunc, 1, 1, false, false },
493 { "warning", &WarningFunc, 1, 1, false, false },
494 { "error", &ErrorFunc, 1, 1, false, false },
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900495};
496
497unordered_map<StringPiece, FuncInfo*>* g_func_info_map;
498
499} // namespace
500
501void InitFuncTable() {
502 g_func_info_map = new unordered_map<StringPiece, FuncInfo*>;
503 for (size_t i = 0; i < sizeof(g_func_infos) / sizeof(g_func_infos[0]); i++) {
504 FuncInfo* fi = &g_func_infos[i];
505 bool ok = g_func_info_map->insert(make_pair(Intern(fi->name), fi)).second;
506 CHECK(ok);
507 }
508}
509
510void QuitFuncTable() {
511 delete g_func_info_map;
512}
513
514FuncInfo* GetFuncInfo(StringPiece name) {
515 auto found = g_func_info_map->find(name);
516 if (found == g_func_info_map->end())
517 return NULL;
518 return found->second;
519}