1*acea8879SAndroid Build Coastguard Worker /*
2*acea8879SAndroid Build Coastguard Worker * Copyright (C) 2009 The Android Open Source Project
3*acea8879SAndroid Build Coastguard Worker *
4*acea8879SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*acea8879SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*acea8879SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*acea8879SAndroid Build Coastguard Worker *
8*acea8879SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*acea8879SAndroid Build Coastguard Worker *
10*acea8879SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*acea8879SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*acea8879SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*acea8879SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*acea8879SAndroid Build Coastguard Worker * limitations under the License.
15*acea8879SAndroid Build Coastguard Worker */
16*acea8879SAndroid Build Coastguard Worker
17*acea8879SAndroid Build Coastguard Worker #include "edify/expr.h"
18*acea8879SAndroid Build Coastguard Worker
19*acea8879SAndroid Build Coastguard Worker #include <stdarg.h>
20*acea8879SAndroid Build Coastguard Worker #include <stdio.h>
21*acea8879SAndroid Build Coastguard Worker #include <stdlib.h>
22*acea8879SAndroid Build Coastguard Worker #include <string.h>
23*acea8879SAndroid Build Coastguard Worker #include <unistd.h>
24*acea8879SAndroid Build Coastguard Worker
25*acea8879SAndroid Build Coastguard Worker #include <memory>
26*acea8879SAndroid Build Coastguard Worker #include <string>
27*acea8879SAndroid Build Coastguard Worker #include <unordered_map>
28*acea8879SAndroid Build Coastguard Worker #include <vector>
29*acea8879SAndroid Build Coastguard Worker
30*acea8879SAndroid Build Coastguard Worker #include <android-base/parseint.h>
31*acea8879SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
32*acea8879SAndroid Build Coastguard Worker #include <android-base/strings.h>
33*acea8879SAndroid Build Coastguard Worker
34*acea8879SAndroid Build Coastguard Worker #include "otautil/error_code.h"
35*acea8879SAndroid Build Coastguard Worker
36*acea8879SAndroid Build Coastguard Worker // Functions should:
37*acea8879SAndroid Build Coastguard Worker //
38*acea8879SAndroid Build Coastguard Worker // - return a malloc()'d string
39*acea8879SAndroid Build Coastguard Worker // - if Evaluate() on any argument returns nullptr, return nullptr.
40*acea8879SAndroid Build Coastguard Worker
BooleanString(const std::string & s)41*acea8879SAndroid Build Coastguard Worker static bool BooleanString(const std::string& s) {
42*acea8879SAndroid Build Coastguard Worker return !s.empty();
43*acea8879SAndroid Build Coastguard Worker }
44*acea8879SAndroid Build Coastguard Worker
Evaluate(State * state,const std::unique_ptr<Expr> & expr,std::string * result)45*acea8879SAndroid Build Coastguard Worker bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) {
46*acea8879SAndroid Build Coastguard Worker if (result == nullptr) {
47*acea8879SAndroid Build Coastguard Worker return false;
48*acea8879SAndroid Build Coastguard Worker }
49*acea8879SAndroid Build Coastguard Worker
50*acea8879SAndroid Build Coastguard Worker std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv));
51*acea8879SAndroid Build Coastguard Worker if (!v) {
52*acea8879SAndroid Build Coastguard Worker return false;
53*acea8879SAndroid Build Coastguard Worker }
54*acea8879SAndroid Build Coastguard Worker if (v->type != Value::Type::STRING) {
55*acea8879SAndroid Build Coastguard Worker ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
56*acea8879SAndroid Build Coastguard Worker return false;
57*acea8879SAndroid Build Coastguard Worker }
58*acea8879SAndroid Build Coastguard Worker
59*acea8879SAndroid Build Coastguard Worker *result = v->data;
60*acea8879SAndroid Build Coastguard Worker return true;
61*acea8879SAndroid Build Coastguard Worker }
62*acea8879SAndroid Build Coastguard Worker
EvaluateValue(State * state,const std::unique_ptr<Expr> & expr)63*acea8879SAndroid Build Coastguard Worker Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) {
64*acea8879SAndroid Build Coastguard Worker return expr->fn(expr->name.c_str(), state, expr->argv);
65*acea8879SAndroid Build Coastguard Worker }
66*acea8879SAndroid Build Coastguard Worker
StringValue(const char * str)67*acea8879SAndroid Build Coastguard Worker Value* StringValue(const char* str) {
68*acea8879SAndroid Build Coastguard Worker if (str == nullptr) {
69*acea8879SAndroid Build Coastguard Worker return nullptr;
70*acea8879SAndroid Build Coastguard Worker }
71*acea8879SAndroid Build Coastguard Worker return new Value(Value::Type::STRING, str);
72*acea8879SAndroid Build Coastguard Worker }
73*acea8879SAndroid Build Coastguard Worker
StringValue(const std::string & str)74*acea8879SAndroid Build Coastguard Worker Value* StringValue(const std::string& str) {
75*acea8879SAndroid Build Coastguard Worker return StringValue(str.c_str());
76*acea8879SAndroid Build Coastguard Worker }
77*acea8879SAndroid Build Coastguard Worker
ConcatFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)78*acea8879SAndroid Build Coastguard Worker Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
79*acea8879SAndroid Build Coastguard Worker if (argv.empty()) {
80*acea8879SAndroid Build Coastguard Worker return StringValue("");
81*acea8879SAndroid Build Coastguard Worker }
82*acea8879SAndroid Build Coastguard Worker std::string result;
83*acea8879SAndroid Build Coastguard Worker for (size_t i = 0; i < argv.size(); ++i) {
84*acea8879SAndroid Build Coastguard Worker std::string str;
85*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[i], &str)) {
86*acea8879SAndroid Build Coastguard Worker return nullptr;
87*acea8879SAndroid Build Coastguard Worker }
88*acea8879SAndroid Build Coastguard Worker result += str;
89*acea8879SAndroid Build Coastguard Worker }
90*acea8879SAndroid Build Coastguard Worker
91*acea8879SAndroid Build Coastguard Worker return StringValue(result);
92*acea8879SAndroid Build Coastguard Worker }
93*acea8879SAndroid Build Coastguard Worker
IfElseFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)94*acea8879SAndroid Build Coastguard Worker Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
95*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2 && argv.size() != 3) {
96*acea8879SAndroid Build Coastguard Worker state->errmsg = "ifelse expects 2 or 3 arguments";
97*acea8879SAndroid Build Coastguard Worker return nullptr;
98*acea8879SAndroid Build Coastguard Worker }
99*acea8879SAndroid Build Coastguard Worker
100*acea8879SAndroid Build Coastguard Worker std::string cond;
101*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[0], &cond)) {
102*acea8879SAndroid Build Coastguard Worker return nullptr;
103*acea8879SAndroid Build Coastguard Worker }
104*acea8879SAndroid Build Coastguard Worker
105*acea8879SAndroid Build Coastguard Worker if (!cond.empty()) {
106*acea8879SAndroid Build Coastguard Worker return EvaluateValue(state, argv[1]);
107*acea8879SAndroid Build Coastguard Worker } else if (argv.size() == 3) {
108*acea8879SAndroid Build Coastguard Worker return EvaluateValue(state, argv[2]);
109*acea8879SAndroid Build Coastguard Worker }
110*acea8879SAndroid Build Coastguard Worker
111*acea8879SAndroid Build Coastguard Worker return StringValue("");
112*acea8879SAndroid Build Coastguard Worker }
113*acea8879SAndroid Build Coastguard Worker
AbortFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)114*acea8879SAndroid Build Coastguard Worker Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
115*acea8879SAndroid Build Coastguard Worker std::string msg;
116*acea8879SAndroid Build Coastguard Worker if (!argv.empty() && Evaluate(state, argv[0], &msg)) {
117*acea8879SAndroid Build Coastguard Worker state->errmsg += msg;
118*acea8879SAndroid Build Coastguard Worker } else {
119*acea8879SAndroid Build Coastguard Worker state->errmsg += "called abort()";
120*acea8879SAndroid Build Coastguard Worker }
121*acea8879SAndroid Build Coastguard Worker return nullptr;
122*acea8879SAndroid Build Coastguard Worker }
123*acea8879SAndroid Build Coastguard Worker
AssertFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)124*acea8879SAndroid Build Coastguard Worker Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
125*acea8879SAndroid Build Coastguard Worker for (size_t i = 0; i < argv.size(); ++i) {
126*acea8879SAndroid Build Coastguard Worker std::string result;
127*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[i], &result)) {
128*acea8879SAndroid Build Coastguard Worker return nullptr;
129*acea8879SAndroid Build Coastguard Worker }
130*acea8879SAndroid Build Coastguard Worker if (result.empty()) {
131*acea8879SAndroid Build Coastguard Worker int len = argv[i]->end - argv[i]->start;
132*acea8879SAndroid Build Coastguard Worker state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
133*acea8879SAndroid Build Coastguard Worker return nullptr;
134*acea8879SAndroid Build Coastguard Worker }
135*acea8879SAndroid Build Coastguard Worker }
136*acea8879SAndroid Build Coastguard Worker return StringValue("");
137*acea8879SAndroid Build Coastguard Worker }
138*acea8879SAndroid Build Coastguard Worker
SleepFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)139*acea8879SAndroid Build Coastguard Worker Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
140*acea8879SAndroid Build Coastguard Worker std::string val;
141*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[0], &val)) {
142*acea8879SAndroid Build Coastguard Worker return nullptr;
143*acea8879SAndroid Build Coastguard Worker }
144*acea8879SAndroid Build Coastguard Worker
145*acea8879SAndroid Build Coastguard Worker int v;
146*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseInt(val.c_str(), &v, 0)) {
147*acea8879SAndroid Build Coastguard Worker return nullptr;
148*acea8879SAndroid Build Coastguard Worker }
149*acea8879SAndroid Build Coastguard Worker sleep(v);
150*acea8879SAndroid Build Coastguard Worker
151*acea8879SAndroid Build Coastguard Worker return StringValue(val);
152*acea8879SAndroid Build Coastguard Worker }
153*acea8879SAndroid Build Coastguard Worker
StdoutFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)154*acea8879SAndroid Build Coastguard Worker Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
155*acea8879SAndroid Build Coastguard Worker for (size_t i = 0; i < argv.size(); ++i) {
156*acea8879SAndroid Build Coastguard Worker std::string v;
157*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[i], &v)) {
158*acea8879SAndroid Build Coastguard Worker return nullptr;
159*acea8879SAndroid Build Coastguard Worker }
160*acea8879SAndroid Build Coastguard Worker fputs(v.c_str(), stdout);
161*acea8879SAndroid Build Coastguard Worker }
162*acea8879SAndroid Build Coastguard Worker return StringValue("");
163*acea8879SAndroid Build Coastguard Worker }
164*acea8879SAndroid Build Coastguard Worker
LogicalAndFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)165*acea8879SAndroid Build Coastguard Worker Value* LogicalAndFn(const char* name, State* state,
166*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
167*acea8879SAndroid Build Coastguard Worker std::string left;
168*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[0], &left)) {
169*acea8879SAndroid Build Coastguard Worker return nullptr;
170*acea8879SAndroid Build Coastguard Worker }
171*acea8879SAndroid Build Coastguard Worker if (BooleanString(left)) {
172*acea8879SAndroid Build Coastguard Worker return EvaluateValue(state, argv[1]);
173*acea8879SAndroid Build Coastguard Worker } else {
174*acea8879SAndroid Build Coastguard Worker return StringValue("");
175*acea8879SAndroid Build Coastguard Worker }
176*acea8879SAndroid Build Coastguard Worker }
177*acea8879SAndroid Build Coastguard Worker
LogicalOrFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)178*acea8879SAndroid Build Coastguard Worker Value* LogicalOrFn(const char* name, State* state,
179*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
180*acea8879SAndroid Build Coastguard Worker std::string left;
181*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[0], &left)) {
182*acea8879SAndroid Build Coastguard Worker return nullptr;
183*acea8879SAndroid Build Coastguard Worker }
184*acea8879SAndroid Build Coastguard Worker if (!BooleanString(left)) {
185*acea8879SAndroid Build Coastguard Worker return EvaluateValue(state, argv[1]);
186*acea8879SAndroid Build Coastguard Worker } else {
187*acea8879SAndroid Build Coastguard Worker return StringValue(left);
188*acea8879SAndroid Build Coastguard Worker }
189*acea8879SAndroid Build Coastguard Worker }
190*acea8879SAndroid Build Coastguard Worker
LogicalNotFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)191*acea8879SAndroid Build Coastguard Worker Value* LogicalNotFn(const char* name, State* state,
192*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
193*acea8879SAndroid Build Coastguard Worker std::string val;
194*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[0], &val)) {
195*acea8879SAndroid Build Coastguard Worker return nullptr;
196*acea8879SAndroid Build Coastguard Worker }
197*acea8879SAndroid Build Coastguard Worker
198*acea8879SAndroid Build Coastguard Worker return StringValue(BooleanString(val) ? "" : "t");
199*acea8879SAndroid Build Coastguard Worker }
200*acea8879SAndroid Build Coastguard Worker
SubstringFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)201*acea8879SAndroid Build Coastguard Worker Value* SubstringFn(const char* name, State* state,
202*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
203*acea8879SAndroid Build Coastguard Worker std::string needle;
204*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[0], &needle)) {
205*acea8879SAndroid Build Coastguard Worker return nullptr;
206*acea8879SAndroid Build Coastguard Worker }
207*acea8879SAndroid Build Coastguard Worker
208*acea8879SAndroid Build Coastguard Worker std::string haystack;
209*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[1], &haystack)) {
210*acea8879SAndroid Build Coastguard Worker return nullptr;
211*acea8879SAndroid Build Coastguard Worker }
212*acea8879SAndroid Build Coastguard Worker
213*acea8879SAndroid Build Coastguard Worker std::string result = (haystack.find(needle) != std::string::npos) ? "t" : "";
214*acea8879SAndroid Build Coastguard Worker return StringValue(result);
215*acea8879SAndroid Build Coastguard Worker }
216*acea8879SAndroid Build Coastguard Worker
EqualityFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)217*acea8879SAndroid Build Coastguard Worker Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
218*acea8879SAndroid Build Coastguard Worker std::string left;
219*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[0], &left)) {
220*acea8879SAndroid Build Coastguard Worker return nullptr;
221*acea8879SAndroid Build Coastguard Worker }
222*acea8879SAndroid Build Coastguard Worker std::string right;
223*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[1], &right)) {
224*acea8879SAndroid Build Coastguard Worker return nullptr;
225*acea8879SAndroid Build Coastguard Worker }
226*acea8879SAndroid Build Coastguard Worker
227*acea8879SAndroid Build Coastguard Worker const char* result = (left == right) ? "t" : "";
228*acea8879SAndroid Build Coastguard Worker return StringValue(result);
229*acea8879SAndroid Build Coastguard Worker }
230*acea8879SAndroid Build Coastguard Worker
InequalityFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)231*acea8879SAndroid Build Coastguard Worker Value* InequalityFn(const char* name, State* state,
232*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
233*acea8879SAndroid Build Coastguard Worker std::string left;
234*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[0], &left)) {
235*acea8879SAndroid Build Coastguard Worker return nullptr;
236*acea8879SAndroid Build Coastguard Worker }
237*acea8879SAndroid Build Coastguard Worker std::string right;
238*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[1], &right)) {
239*acea8879SAndroid Build Coastguard Worker return nullptr;
240*acea8879SAndroid Build Coastguard Worker }
241*acea8879SAndroid Build Coastguard Worker
242*acea8879SAndroid Build Coastguard Worker const char* result = (left != right) ? "t" : "";
243*acea8879SAndroid Build Coastguard Worker return StringValue(result);
244*acea8879SAndroid Build Coastguard Worker }
245*acea8879SAndroid Build Coastguard Worker
SequenceFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)246*acea8879SAndroid Build Coastguard Worker Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
247*acea8879SAndroid Build Coastguard Worker std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
248*acea8879SAndroid Build Coastguard Worker if (!left) {
249*acea8879SAndroid Build Coastguard Worker return nullptr;
250*acea8879SAndroid Build Coastguard Worker }
251*acea8879SAndroid Build Coastguard Worker return EvaluateValue(state, argv[1]);
252*acea8879SAndroid Build Coastguard Worker }
253*acea8879SAndroid Build Coastguard Worker
LessThanIntFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)254*acea8879SAndroid Build Coastguard Worker Value* LessThanIntFn(const char* name, State* state,
255*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
256*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2) {
257*acea8879SAndroid Build Coastguard Worker state->errmsg = "less_than_int expects 2 arguments";
258*acea8879SAndroid Build Coastguard Worker return nullptr;
259*acea8879SAndroid Build Coastguard Worker }
260*acea8879SAndroid Build Coastguard Worker
261*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
262*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
263*acea8879SAndroid Build Coastguard Worker return nullptr;
264*acea8879SAndroid Build Coastguard Worker }
265*acea8879SAndroid Build Coastguard Worker
266*acea8879SAndroid Build Coastguard Worker // Parse up to at least long long or 64-bit integers.
267*acea8879SAndroid Build Coastguard Worker int64_t l_int;
268*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
269*acea8879SAndroid Build Coastguard Worker state->errmsg = "failed to parse int in " + args[0];
270*acea8879SAndroid Build Coastguard Worker return nullptr;
271*acea8879SAndroid Build Coastguard Worker }
272*acea8879SAndroid Build Coastguard Worker
273*acea8879SAndroid Build Coastguard Worker int64_t r_int;
274*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
275*acea8879SAndroid Build Coastguard Worker state->errmsg = "failed to parse int in " + args[1];
276*acea8879SAndroid Build Coastguard Worker return nullptr;
277*acea8879SAndroid Build Coastguard Worker }
278*acea8879SAndroid Build Coastguard Worker
279*acea8879SAndroid Build Coastguard Worker return StringValue(l_int < r_int ? "t" : "");
280*acea8879SAndroid Build Coastguard Worker }
281*acea8879SAndroid Build Coastguard Worker
GreaterThanIntFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)282*acea8879SAndroid Build Coastguard Worker Value* GreaterThanIntFn(const char* name, State* state,
283*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
284*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2) {
285*acea8879SAndroid Build Coastguard Worker state->errmsg = "greater_than_int expects 2 arguments";
286*acea8879SAndroid Build Coastguard Worker return nullptr;
287*acea8879SAndroid Build Coastguard Worker }
288*acea8879SAndroid Build Coastguard Worker
289*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
290*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
291*acea8879SAndroid Build Coastguard Worker return nullptr;
292*acea8879SAndroid Build Coastguard Worker }
293*acea8879SAndroid Build Coastguard Worker
294*acea8879SAndroid Build Coastguard Worker // Parse up to at least long long or 64-bit integers.
295*acea8879SAndroid Build Coastguard Worker int64_t l_int;
296*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
297*acea8879SAndroid Build Coastguard Worker state->errmsg = "failed to parse int in " + args[0];
298*acea8879SAndroid Build Coastguard Worker return nullptr;
299*acea8879SAndroid Build Coastguard Worker }
300*acea8879SAndroid Build Coastguard Worker
301*acea8879SAndroid Build Coastguard Worker int64_t r_int;
302*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
303*acea8879SAndroid Build Coastguard Worker state->errmsg = "failed to parse int in " + args[1];
304*acea8879SAndroid Build Coastguard Worker return nullptr;
305*acea8879SAndroid Build Coastguard Worker }
306*acea8879SAndroid Build Coastguard Worker
307*acea8879SAndroid Build Coastguard Worker return StringValue(l_int > r_int ? "t" : "");
308*acea8879SAndroid Build Coastguard Worker }
309*acea8879SAndroid Build Coastguard Worker
Literal(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)310*acea8879SAndroid Build Coastguard Worker Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
311*acea8879SAndroid Build Coastguard Worker return StringValue(name);
312*acea8879SAndroid Build Coastguard Worker }
313*acea8879SAndroid Build Coastguard Worker
314*acea8879SAndroid Build Coastguard Worker // -----------------------------------------------------------------
315*acea8879SAndroid Build Coastguard Worker // the function table
316*acea8879SAndroid Build Coastguard Worker // -----------------------------------------------------------------
317*acea8879SAndroid Build Coastguard Worker
318*acea8879SAndroid Build Coastguard Worker static std::unordered_map<std::string, Function> fn_table;
319*acea8879SAndroid Build Coastguard Worker
RegisterFunction(const std::string & name,Function fn)320*acea8879SAndroid Build Coastguard Worker void RegisterFunction(const std::string& name, Function fn) {
321*acea8879SAndroid Build Coastguard Worker fn_table[name] = fn;
322*acea8879SAndroid Build Coastguard Worker }
323*acea8879SAndroid Build Coastguard Worker
FindFunction(const std::string & name)324*acea8879SAndroid Build Coastguard Worker Function FindFunction(const std::string& name) {
325*acea8879SAndroid Build Coastguard Worker if (fn_table.find(name) == fn_table.end()) {
326*acea8879SAndroid Build Coastguard Worker return nullptr;
327*acea8879SAndroid Build Coastguard Worker } else {
328*acea8879SAndroid Build Coastguard Worker return fn_table[name];
329*acea8879SAndroid Build Coastguard Worker }
330*acea8879SAndroid Build Coastguard Worker }
331*acea8879SAndroid Build Coastguard Worker
RegisterBuiltins()332*acea8879SAndroid Build Coastguard Worker void RegisterBuiltins() {
333*acea8879SAndroid Build Coastguard Worker RegisterFunction("ifelse", IfElseFn);
334*acea8879SAndroid Build Coastguard Worker RegisterFunction("abort", AbortFn);
335*acea8879SAndroid Build Coastguard Worker RegisterFunction("assert", AssertFn);
336*acea8879SAndroid Build Coastguard Worker RegisterFunction("concat", ConcatFn);
337*acea8879SAndroid Build Coastguard Worker RegisterFunction("is_substring", SubstringFn);
338*acea8879SAndroid Build Coastguard Worker RegisterFunction("stdout", StdoutFn);
339*acea8879SAndroid Build Coastguard Worker RegisterFunction("sleep", SleepFn);
340*acea8879SAndroid Build Coastguard Worker
341*acea8879SAndroid Build Coastguard Worker RegisterFunction("less_than_int", LessThanIntFn);
342*acea8879SAndroid Build Coastguard Worker RegisterFunction("greater_than_int", GreaterThanIntFn);
343*acea8879SAndroid Build Coastguard Worker }
344*acea8879SAndroid Build Coastguard Worker
345*acea8879SAndroid Build Coastguard Worker
346*acea8879SAndroid Build Coastguard Worker // -----------------------------------------------------------------
347*acea8879SAndroid Build Coastguard Worker // convenience methods for functions
348*acea8879SAndroid Build Coastguard Worker // -----------------------------------------------------------------
349*acea8879SAndroid Build Coastguard Worker
350*acea8879SAndroid Build Coastguard Worker // Evaluate the expressions in argv, and put the results of strings in args. If any expression
351*acea8879SAndroid Build Coastguard Worker // evaluates to nullptr, return false. Return true on success.
ReadArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::string> * args)352*acea8879SAndroid Build Coastguard Worker bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
353*acea8879SAndroid Build Coastguard Worker std::vector<std::string>* args) {
354*acea8879SAndroid Build Coastguard Worker return ReadArgs(state, argv, args, 0, argv.size());
355*acea8879SAndroid Build Coastguard Worker }
356*acea8879SAndroid Build Coastguard Worker
ReadArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::string> * args,size_t start,size_t len)357*acea8879SAndroid Build Coastguard Worker bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
358*acea8879SAndroid Build Coastguard Worker std::vector<std::string>* args, size_t start, size_t len) {
359*acea8879SAndroid Build Coastguard Worker if (args == nullptr) {
360*acea8879SAndroid Build Coastguard Worker return false;
361*acea8879SAndroid Build Coastguard Worker }
362*acea8879SAndroid Build Coastguard Worker if (start + len > argv.size()) {
363*acea8879SAndroid Build Coastguard Worker return false;
364*acea8879SAndroid Build Coastguard Worker }
365*acea8879SAndroid Build Coastguard Worker for (size_t i = start; i < start + len; ++i) {
366*acea8879SAndroid Build Coastguard Worker std::string var;
367*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[i], &var)) {
368*acea8879SAndroid Build Coastguard Worker args->clear();
369*acea8879SAndroid Build Coastguard Worker return false;
370*acea8879SAndroid Build Coastguard Worker }
371*acea8879SAndroid Build Coastguard Worker args->push_back(var);
372*acea8879SAndroid Build Coastguard Worker }
373*acea8879SAndroid Build Coastguard Worker return true;
374*acea8879SAndroid Build Coastguard Worker }
375*acea8879SAndroid Build Coastguard Worker
376*acea8879SAndroid Build Coastguard Worker // Evaluate the expressions in argv, and put the results of Value* in args. If any expression
377*acea8879SAndroid Build Coastguard Worker // evaluate to nullptr, return false. Return true on success.
ReadValueArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::unique_ptr<Value>> * args)378*acea8879SAndroid Build Coastguard Worker bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
379*acea8879SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Value>>* args) {
380*acea8879SAndroid Build Coastguard Worker return ReadValueArgs(state, argv, args, 0, argv.size());
381*acea8879SAndroid Build Coastguard Worker }
382*acea8879SAndroid Build Coastguard Worker
ReadValueArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::unique_ptr<Value>> * args,size_t start,size_t len)383*acea8879SAndroid Build Coastguard Worker bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
384*acea8879SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) {
385*acea8879SAndroid Build Coastguard Worker if (args == nullptr) {
386*acea8879SAndroid Build Coastguard Worker return false;
387*acea8879SAndroid Build Coastguard Worker }
388*acea8879SAndroid Build Coastguard Worker if (len == 0 || start + len > argv.size()) {
389*acea8879SAndroid Build Coastguard Worker return false;
390*acea8879SAndroid Build Coastguard Worker }
391*acea8879SAndroid Build Coastguard Worker for (size_t i = start; i < start + len; ++i) {
392*acea8879SAndroid Build Coastguard Worker std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
393*acea8879SAndroid Build Coastguard Worker if (!v) {
394*acea8879SAndroid Build Coastguard Worker args->clear();
395*acea8879SAndroid Build Coastguard Worker return false;
396*acea8879SAndroid Build Coastguard Worker }
397*acea8879SAndroid Build Coastguard Worker args->push_back(std::move(v));
398*acea8879SAndroid Build Coastguard Worker }
399*acea8879SAndroid Build Coastguard Worker return true;
400*acea8879SAndroid Build Coastguard Worker }
401*acea8879SAndroid Build Coastguard Worker
402*acea8879SAndroid Build Coastguard Worker // Use printf-style arguments to compose an error message to put into
403*acea8879SAndroid Build Coastguard Worker // *state. Returns nullptr.
ErrorAbort(State * state,const char * format,...)404*acea8879SAndroid Build Coastguard Worker Value* ErrorAbort(State* state, const char* format, ...) {
405*acea8879SAndroid Build Coastguard Worker va_list ap;
406*acea8879SAndroid Build Coastguard Worker va_start(ap, format);
407*acea8879SAndroid Build Coastguard Worker android::base::StringAppendV(&state->errmsg, format, ap);
408*acea8879SAndroid Build Coastguard Worker va_end(ap);
409*acea8879SAndroid Build Coastguard Worker return nullptr;
410*acea8879SAndroid Build Coastguard Worker }
411*acea8879SAndroid Build Coastguard Worker
ErrorAbort(State * state,CauseCode cause_code,const char * format,...)412*acea8879SAndroid Build Coastguard Worker Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
413*acea8879SAndroid Build Coastguard Worker std::string err_message;
414*acea8879SAndroid Build Coastguard Worker va_list ap;
415*acea8879SAndroid Build Coastguard Worker va_start(ap, format);
416*acea8879SAndroid Build Coastguard Worker android::base::StringAppendV(&err_message, format, ap);
417*acea8879SAndroid Build Coastguard Worker va_end(ap);
418*acea8879SAndroid Build Coastguard Worker // Ensure that there's exactly one line break at the end of the error message.
419*acea8879SAndroid Build Coastguard Worker state->errmsg = android::base::Trim(err_message) + "\n";
420*acea8879SAndroid Build Coastguard Worker state->cause_code = cause_code;
421*acea8879SAndroid Build Coastguard Worker return nullptr;
422*acea8879SAndroid Build Coastguard Worker }
423*acea8879SAndroid Build Coastguard Worker
State(const std::string & script,UpdaterInterface * interface)424*acea8879SAndroid Build Coastguard Worker State::State(const std::string& script, UpdaterInterface* interface)
425*acea8879SAndroid Build Coastguard Worker : script(script), updater(interface), error_code(kNoError), cause_code(kNoCause) {}
426