blob: 2fd95ae556a34dfa2d55012ceb400041e7fff476 [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 Hamaji776ca302015-06-06 03:52:48 +090010#include <unordered_map>
11
Shinichiro Hamaji9619b362015-06-16 16:13:25 +090012#include "eval.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090013#include "log.h"
14#include "strutil.h"
15
16namespace {
17
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090018void PatsubstFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
19 shared_ptr<string> pat = args[0]->Eval(ev);
20 shared_ptr<string> repl = args[1]->Eval(ev);
21 shared_ptr<string> str = args[2]->Eval(ev);
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090022 WordWriter ww(s);
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090023 for (StringPiece tok : WordScanner(*str)) {
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090024 ww.MaybeAddWhitespace();
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +090025 AppendSubstPattern(tok, *pat, *repl, s);
26 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090027}
28
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090029void StripFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
30 shared_ptr<string> str = args[0]->Eval(ev);
31 WordWriter ww(s);
32 for (StringPiece tok : WordScanner(*str)) {
33 ww.Write(tok);
34 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090035}
36
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +090037void SubstFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
38 shared_ptr<string> pat = args[0]->Eval(ev);
39 shared_ptr<string> repl = args[1]->Eval(ev);
40 shared_ptr<string> str = args[2]->Eval(ev);
41 size_t index = 0;
42 while (index < str->size()) {
43 size_t found = str->find(*pat, index);
44 if (found == string::npos)
45 break;
46 AppendString(StringPiece(*str).substr(index, found - index), s);
47 AppendString(*repl, s);
48 index = found + pat->size();
49 }
50 AppendString(StringPiece(*str).substr(index), s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090051}
52
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090053void FindstringFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
54 shared_ptr<string> find = args[0]->Eval(ev);
55 shared_ptr<string> in = args[1]->Eval(ev);
56 if (in->find(*find) != string::npos)
57 AppendString(*find, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090058}
59
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090060void FilterFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
61 shared_ptr<string> pat_buf = args[0]->Eval(ev);
62 shared_ptr<string> text = args[1]->Eval(ev);
63 vector<StringPiece> pats;
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +090064 WordScanner(*pat_buf).Split(&pats);
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090065 WordWriter ww(s);
66 for (StringPiece tok : WordScanner(*text)) {
67 for (StringPiece pat : pats) {
68 if (MatchPattern(tok, pat)) {
69 ww.Write(tok);
70 break;
71 }
72 }
73 }
74}
75
76void FilterOutFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
77 shared_ptr<string> pat_buf = args[0]->Eval(ev);
78 shared_ptr<string> text = args[1]->Eval(ev);
79 vector<StringPiece> pats;
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +090080 WordScanner(*pat_buf).Split(&pats);
Shinichiro Hamaji00cc6582015-06-17 18:12:46 +090081 WordWriter ww(s);
82 for (StringPiece tok : WordScanner(*text)) {
83 bool matched = false;
84 for (StringPiece pat : pats) {
85 if (MatchPattern(tok, pat)) {
86 matched = true;
87 break;
88 }
89 }
90 if (!matched)
91 ww.Write(tok);
92 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +090093}
94
Shinichiro Hamajid87e59e2015-06-17 18:18:34 +090095void SortFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
96 shared_ptr<string> list = args[0]->Eval(ev);
97 vector<StringPiece> toks;
98 WordScanner(*list).Split(&toks);
99 sort(toks.begin(), toks.end());
100 WordWriter ww(s);
101 StringPiece prev;
102 for (StringPiece tok : toks) {
103 if (prev != tok) {
104 ww.Write(tok);
105 prev = tok;
106 }
107 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900108}
109
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900110static int GetNumericValueForFunc(const string& buf) {
111 StringPiece s = TrimLeftSpace(buf);
112 char* end;
113 long n = strtol(s.data(), &end, 10);
114 if (n < 0 || n == LONG_MAX || s.data() + s.size() != end) {
115 return -1;
116 }
117 return n;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900118}
119
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900120void WordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
121 shared_ptr<string> n_str = args[0]->Eval(ev);
122 int n = GetNumericValueForFunc(*n_str);
123 if (n < 0) {
124 ev->Error(StringPrintf(
125 "*** non-numeric first argument to `word' function: '%s'.",
126 n_str->c_str()));
127 }
128 if (n == 0) {
129 ev->Error("*** first argument to `word' function must be greater than 0.");
130 }
131
132 shared_ptr<string> text = args[1]->Eval(ev);
133 for (StringPiece tok : WordScanner(*text)) {
134 n--;
135 if (n == 0) {
136 AppendString(tok, s);
137 break;
138 }
139 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900140}
141
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900142void WordlistFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
143 shared_ptr<string> s_str = args[0]->Eval(ev);
144 int si = GetNumericValueForFunc(*s_str);
145 if (si < 0) {
146 ev->Error(StringPrintf(
147 "*** non-numeric first argument to `wordlist' function: '%s'.",
148 s_str->c_str()));
149 }
150 if (si == 0) {
151 ev->Error(StringPrintf(
152 "*** invalid first argument to `wordlist' function: %s`",
153 s_str->c_str()));
154 }
155
156 shared_ptr<string> e_str = args[1]->Eval(ev);
157 int ei = GetNumericValueForFunc(*e_str);
158 if (ei < 0) {
159 ev->Error(StringPrintf(
160 "*** non-numeric second argument to `wordlist' function: '%s'.",
161 e_str->c_str()));
162 }
163
164 shared_ptr<string> text = args[2]->Eval(ev);
165 int i = 0;
166 WordWriter ww(s);
167 for (StringPiece tok : WordScanner(*text)) {
168 i++;
169 if (si <= i && i <= ei) {
170 ww.Write(tok);
171 }
172 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900173}
174
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900175void WordsFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
176 shared_ptr<string> text = args[0]->Eval(ev);
177 WordScanner ws(*text);
178 int n = 0;
179 for (auto iter = ws.begin(); iter != ws.end(); ++iter)
180 n++;
181 char buf[32];
182 sprintf(buf, "%d", n);
183 *s += buf;
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900184}
185
Shinichiro Hamajid5271452015-06-17 18:50:03 +0900186void FirstwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
187 shared_ptr<string> text = args[0]->Eval(ev);
188 for (StringPiece tok : WordScanner(*text)) {
189 AppendString(tok, s);
190 return;
191 }
192}
193
194void LastwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
195 shared_ptr<string> text = args[0]->Eval(ev);
196 StringPiece last;
197 for (StringPiece tok : WordScanner(*text)) {
198 last = tok;
199 }
200 AppendString(last, s);
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900201}
202
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900203void JoinFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
204 shared_ptr<string> list1 = args[0]->Eval(ev);
205 shared_ptr<string> list2 = args[1]->Eval(ev);
206 WordScanner ws1(*list1);
207 WordScanner ws2(*list2);
208 WordWriter ww(s);
209 for (WordScanner::Iterator iter1 = ws1.begin(), iter2 = ws2.begin();
210 iter1 != ws1.end() && iter2 != ws2.end();
211 ++iter1, ++iter2) {
212 ww.Write(*iter1);
213 // Use |AppendString| not to append extra ' '.
214 AppendString(*iter2, s);
215 }
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900216}
217
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900218void WildcardFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900219 printf("TODO(wildcard)");
220}
221
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900222void DirFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900223 printf("TODO(dir)");
224}
225
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900226void NotdirFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900227 printf("TODO(notdir)");
228}
229
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900230void SuffixFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900231 printf("TODO(suffix)");
232}
233
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900234void BasenameFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900235 printf("TODO(basename)");
236}
237
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900238void AddsuffixFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900239 printf("TODO(addsuffix)");
240}
241
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900242void AddprefixFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900243 printf("TODO(addprefix)");
244}
245
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900246void RealpathFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900247 printf("TODO(realpath)");
248}
249
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900250void AbspathFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900251 printf("TODO(abspath)");
252}
253
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900254void IfFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900255 printf("TODO(if)");
256}
257
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900258void AndFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900259 printf("TODO(and)");
260}
261
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900262void OrFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900263 printf("TODO(or)");
264}
265
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900266void ValueFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900267 printf("TODO(value)");
268}
269
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900270void EvalFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900271 printf("TODO(eval)");
272}
273
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900274void ShellFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900275 printf("TODO(shell)");
276}
277
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900278void CallFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900279 printf("TODO(call)");
280}
281
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900282void ForeachFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900283 printf("TODO(foreach)");
284}
285
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900286void OriginFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900287 printf("TODO(origin)");
288}
289
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900290void FlavorFunc(const vector<Value*>&, Evaluator*, string*) {
Shinichiro Hamaji4f22f5c2015-06-16 16:28:25 +0900291 printf("TODO(flavor)");
292}
293
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900294void InfoFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900295 shared_ptr<string> a = args[0]->Eval(ev);
296 printf("%s\n", a->c_str());
297 fflush(stdout);
298}
299
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900300void WarningFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900301 shared_ptr<string> a = args[0]->Eval(ev);
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900302 printf("%s:%d: %s\n", LOCF(ev->loc()), a->c_str());
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900303 fflush(stdout);
304}
305
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900306void ErrorFunc(const vector<Value*>& args, Evaluator* ev, string*) {
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900307 shared_ptr<string> a = args[0]->Eval(ev);
308 ev->Error(StringPrintf("*** %s.", a->c_str()));
309}
310
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900311FuncInfo g_func_infos[] = {
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900312 { "patsubst", &PatsubstFunc, 3 },
313 { "strip", &StripFunc, 1 },
314 { "subst", &SubstFunc, 3 },
315 { "findstring", &FindstringFunc, 2 },
316 { "filter", &FilterFunc, 2 },
317 { "filter-out", &FilterOutFunc, 2 },
318 { "sort", &SortFunc, 1 },
319 { "word", &WordFunc, 2 },
320 { "wordlist", &WordlistFunc, 3 },
321 { "words", &WordsFunc, 1 },
322 { "firstword", &FirstwordFunc, 1 },
323 { "lastword", &LastwordFunc, 1 },
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900324
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900325 { "join", &JoinFunc, 2 },
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900326 { "wildcard", &WildcardFunc, 1 },
327 { "dir", &DirFunc, 1 },
328 { "notdir", &NotdirFunc, 1 },
329 { "suffix", &SuffixFunc, 1 },
330 { "basename", &BasenameFunc, 1 },
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900331 { "addsuffix", &AddsuffixFunc, 2 },
332 { "addprefix", &AddprefixFunc, 2 },
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900333 { "realpath", &RealpathFunc, 1 },
334 { "abspath", &AbspathFunc, 1 },
Shinichiro Hamaji30b8e602015-06-17 19:28:54 +0900335
Shinichiro Hamaji2e6cbfc2015-06-16 18:46:50 +0900336 { "if", &IfFunc, 1 },
337 { "and", &AndFunc, 1 },
338 { "or", &OrFunc, 1 },
339 { "value", &ValueFunc, 1 },
340 { "eval", &EvalFunc, 1 },
341 { "shell", &ShellFunc, 1 },
342 { "call", &CallFunc, 1 },
343 { "foreach", &ForeachFunc, 1 },
344 { "origin", &OriginFunc, 1 },
345 { "flavor", &FlavorFunc, 1 },
346 { "info", &InfoFunc, 1 },
347 { "warning", &WarningFunc, 1 },
348 { "error", &ErrorFunc, 1 },
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900349};
350
351unordered_map<StringPiece, FuncInfo*>* g_func_info_map;
352
353} // namespace
354
355void InitFuncTable() {
356 g_func_info_map = new unordered_map<StringPiece, FuncInfo*>;
357 for (size_t i = 0; i < sizeof(g_func_infos) / sizeof(g_func_infos[0]); i++) {
358 FuncInfo* fi = &g_func_infos[i];
359 bool ok = g_func_info_map->insert(make_pair(Intern(fi->name), fi)).second;
360 CHECK(ok);
361 }
362}
363
364void QuitFuncTable() {
365 delete g_func_info_map;
366}
367
368FuncInfo* GetFuncInfo(StringPiece name) {
369 auto found = g_func_info_map->find(name);
370 if (found == g_func_info_map->end())
371 return NULL;
372 return found->second;
373}