blob: aa3a55a879bf1936118ee29f7759e1c35f985639 [file] [log] [blame]
Doug Zongker37bee622009-06-08 17:35:39 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <string.h>
18#include <stdbool.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <stdarg.h>
Doug Zongker9931f7f2009-06-10 14:11:53 -070022#include <unistd.h>
Doug Zongker37bee622009-06-08 17:35:39 -070023
Tianjie Xu16255832016-04-30 11:49:59 -070024#include <string>
25
26#include <android-base/stringprintf.h>
27#include <android-base/strings.h>
28
Doug Zongker37bee622009-06-08 17:35:39 -070029#include "expr.h"
30
31// Functions should:
32//
33// - return a malloc()'d string
34// - if Evaluate() on any argument returns NULL, return NULL.
35
36int BooleanString(const char* s) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -070037 return s[0] != '\0';
Doug Zongker37bee622009-06-08 17:35:39 -070038}
39
Doug Zongkerd9c9d102009-06-12 12:24:39 -070040char* Evaluate(State* state, Expr* expr) {
Doug Zongker512536a2010-02-17 16:11:44 -080041 Value* v = expr->fn(expr->name, state, expr->argc, expr->argv);
42 if (v == NULL) return NULL;
43 if (v->type != VAL_STRING) {
Tianjie Xu16255832016-04-30 11:49:59 -070044 ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
Doug Zongker512536a2010-02-17 16:11:44 -080045 FreeValue(v);
46 return NULL;
47 }
48 char* result = v->data;
49 free(v);
50 return result;
51}
52
53Value* EvaluateValue(State* state, Expr* expr) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -070054 return expr->fn(expr->name, state, expr->argc, expr->argv);
Doug Zongker37bee622009-06-08 17:35:39 -070055}
56
Doug Zongker512536a2010-02-17 16:11:44 -080057Value* StringValue(char* str) {
Doug Zongker5b695f32010-02-24 15:03:47 -080058 if (str == NULL) return NULL;
Tao Bao2a5a49d2015-08-20 12:10:46 -070059 Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value)));
Doug Zongker512536a2010-02-17 16:11:44 -080060 v->type = VAL_STRING;
61 v->size = strlen(str);
62 v->data = str;
63 return v;
64}
65
66void FreeValue(Value* v) {
67 if (v == NULL) return;
68 free(v->data);
69 free(v);
70}
71
72Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -070073 if (argc == 0) {
Doug Zongker512536a2010-02-17 16:11:44 -080074 return StringValue(strdup(""));
Doug Zongker37bee622009-06-08 17:35:39 -070075 }
Tao Bao2a5a49d2015-08-20 12:10:46 -070076 char** strings = reinterpret_cast<char**>(malloc(argc * sizeof(char*)));
Doug Zongkerd9c9d102009-06-12 12:24:39 -070077 int i;
78 for (i = 0; i < argc; ++i) {
79 strings[i] = NULL;
80 }
81 char* result = NULL;
82 int length = 0;
83 for (i = 0; i < argc; ++i) {
84 strings[i] = Evaluate(state, argv[i]);
85 if (strings[i] == NULL) {
86 goto done;
87 }
88 length += strlen(strings[i]);
89 }
Doug Zongker37bee622009-06-08 17:35:39 -070090
Tao Bao2a5a49d2015-08-20 12:10:46 -070091 result = reinterpret_cast<char*>(malloc(length+1));
92 int p;
93 p = 0;
Doug Zongkerd9c9d102009-06-12 12:24:39 -070094 for (i = 0; i < argc; ++i) {
95 strcpy(result+p, strings[i]);
96 p += strlen(strings[i]);
97 }
98 result[p] = '\0';
Doug Zongker37bee622009-06-08 17:35:39 -070099
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700100 done:
101 for (i = 0; i < argc; ++i) {
102 free(strings[i]);
103 }
Kenny Root21854cc2010-02-17 18:31:48 -0800104 free(strings);
Doug Zongker512536a2010-02-17 16:11:44 -0800105 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700106}
107
Doug Zongker512536a2010-02-17 16:11:44 -0800108Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700109 if (argc != 2 && argc != 3) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700110 state->errmsg = "ifelse expects 2 or 3 arguments";
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700111 return NULL;
112 }
113 char* cond = Evaluate(state, argv[0]);
114 if (cond == NULL) {
115 return NULL;
116 }
Doug Zongker37bee622009-06-08 17:35:39 -0700117
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700118 if (BooleanString(cond) == true) {
119 free(cond);
Doug Zongker512536a2010-02-17 16:11:44 -0800120 return EvaluateValue(state, argv[1]);
Doug Zongker37bee622009-06-08 17:35:39 -0700121 } else {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700122 if (argc == 3) {
123 free(cond);
Doug Zongker512536a2010-02-17 16:11:44 -0800124 return EvaluateValue(state, argv[2]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700125 } else {
Doug Zongker512536a2010-02-17 16:11:44 -0800126 return StringValue(cond);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700127 }
Doug Zongker37bee622009-06-08 17:35:39 -0700128 }
Doug Zongker37bee622009-06-08 17:35:39 -0700129}
130
Doug Zongker512536a2010-02-17 16:11:44 -0800131Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700132 char* msg = NULL;
133 if (argc > 0) {
134 msg = Evaluate(state, argv[0]);
Doug Zongker37bee622009-06-08 17:35:39 -0700135 }
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700136 if (msg) {
137 state->errmsg = msg;
138 } else {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700139 state->errmsg = "called abort()";
Doug Zongker37bee622009-06-08 17:35:39 -0700140 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700141 return NULL;
Doug Zongker9931f7f2009-06-10 14:11:53 -0700142}
143
Doug Zongker512536a2010-02-17 16:11:44 -0800144Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700145 int i;
146 for (i = 0; i < argc; ++i) {
147 char* v = Evaluate(state, argv[i]);
148 if (v == NULL) {
149 return NULL;
150 }
151 int b = BooleanString(v);
152 free(v);
153 if (!b) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700154 int len = argv[i]->end - argv[i]->start;
Tao Bao59dcb9c2016-10-03 18:06:46 -0700155 state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700156 return NULL;
157 }
Doug Zongker37bee622009-06-08 17:35:39 -0700158 }
Doug Zongker512536a2010-02-17 16:11:44 -0800159 return StringValue(strdup(""));
Doug Zongker37bee622009-06-08 17:35:39 -0700160}
161
Doug Zongker512536a2010-02-17 16:11:44 -0800162Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700163 char* val = Evaluate(state, argv[0]);
164 if (val == NULL) {
165 return NULL;
166 }
167 int v = strtol(val, NULL, 10);
168 sleep(v);
Doug Zongker512536a2010-02-17 16:11:44 -0800169 return StringValue(val);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700170}
171
Doug Zongker512536a2010-02-17 16:11:44 -0800172Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700173 int i;
174 for (i = 0; i < argc; ++i) {
175 char* v = Evaluate(state, argv[i]);
176 if (v == NULL) {
177 return NULL;
178 }
179 fputs(v, stdout);
180 free(v);
181 }
Doug Zongker512536a2010-02-17 16:11:44 -0800182 return StringValue(strdup(""));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700183}
184
Doug Zongker512536a2010-02-17 16:11:44 -0800185Value* LogicalAndFn(const char* name, State* state,
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700186 int argc, Expr* argv[]) {
187 char* left = Evaluate(state, argv[0]);
188 if (left == NULL) return NULL;
189 if (BooleanString(left) == true) {
190 free(left);
Doug Zongker512536a2010-02-17 16:11:44 -0800191 return EvaluateValue(state, argv[1]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700192 } else {
Doug Zongker512536a2010-02-17 16:11:44 -0800193 return StringValue(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700194 }
195}
196
Doug Zongker512536a2010-02-17 16:11:44 -0800197Value* LogicalOrFn(const char* name, State* state,
198 int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700199 char* left = Evaluate(state, argv[0]);
200 if (left == NULL) return NULL;
201 if (BooleanString(left) == false) {
202 free(left);
Doug Zongker512536a2010-02-17 16:11:44 -0800203 return EvaluateValue(state, argv[1]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700204 } else {
Doug Zongker512536a2010-02-17 16:11:44 -0800205 return StringValue(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700206 }
207}
208
Doug Zongker512536a2010-02-17 16:11:44 -0800209Value* LogicalNotFn(const char* name, State* state,
210 int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700211 char* val = Evaluate(state, argv[0]);
212 if (val == NULL) return NULL;
213 bool bv = BooleanString(val);
214 free(val);
Doug Zongker512536a2010-02-17 16:11:44 -0800215 return StringValue(strdup(bv ? "" : "t"));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700216}
217
Doug Zongker512536a2010-02-17 16:11:44 -0800218Value* SubstringFn(const char* name, State* state,
219 int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700220 char* needle = Evaluate(state, argv[0]);
221 if (needle == NULL) return NULL;
222 char* haystack = Evaluate(state, argv[1]);
223 if (haystack == NULL) {
224 free(needle);
225 return NULL;
226 }
227
228 char* result = strdup(strstr(haystack, needle) ? "t" : "");
Doug Zongker37bee622009-06-08 17:35:39 -0700229 free(needle);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700230 free(haystack);
Doug Zongker512536a2010-02-17 16:11:44 -0800231 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700232}
233
Doug Zongker512536a2010-02-17 16:11:44 -0800234Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700235 char* left = Evaluate(state, argv[0]);
236 if (left == NULL) return NULL;
237 char* right = Evaluate(state, argv[1]);
238 if (right == NULL) {
239 free(left);
240 return NULL;
241 }
242
243 char* result = strdup(strcmp(left, right) == 0 ? "t" : "");
Doug Zongker37bee622009-06-08 17:35:39 -0700244 free(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700245 free(right);
Doug Zongker512536a2010-02-17 16:11:44 -0800246 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700247}
248
Doug Zongker512536a2010-02-17 16:11:44 -0800249Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700250 char* left = Evaluate(state, argv[0]);
251 if (left == NULL) return NULL;
252 char* right = Evaluate(state, argv[1]);
253 if (right == NULL) {
254 free(left);
255 return NULL;
256 }
257
258 char* result = strdup(strcmp(left, right) != 0 ? "t" : "");
Doug Zongker37bee622009-06-08 17:35:39 -0700259 free(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700260 free(right);
Doug Zongker512536a2010-02-17 16:11:44 -0800261 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700262}
263
Doug Zongker512536a2010-02-17 16:11:44 -0800264Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
265 Value* left = EvaluateValue(state, argv[0]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700266 if (left == NULL) return NULL;
Doug Zongker512536a2010-02-17 16:11:44 -0800267 FreeValue(left);
268 return EvaluateValue(state, argv[1]);
Doug Zongker37bee622009-06-08 17:35:39 -0700269}
270
Doug Zongker512536a2010-02-17 16:11:44 -0800271Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700272 if (argc != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700273 state->errmsg = "less_than_int expects 2 arguments";
Doug Zongkere3da02e2009-06-12 16:13:52 -0700274 return NULL;
275 }
276
277 char* left;
278 char* right;
279 if (ReadArgs(state, argv, 2, &left, &right) < 0) return NULL;
280
281 bool result = false;
282 char* end;
283
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700284 // Parse up to at least long long or 64-bit integers.
285 int64_t l_int = static_cast<int64_t>(strtoll(left, &end, 10));
Doug Zongkere3da02e2009-06-12 16:13:52 -0700286 if (left[0] == '\0' || *end != '\0') {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700287 goto done;
288 }
289
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700290 int64_t r_int;
291 r_int = static_cast<int64_t>(strtoll(right, &end, 10));
Doug Zongkere3da02e2009-06-12 16:13:52 -0700292 if (right[0] == '\0' || *end != '\0') {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700293 goto done;
294 }
295
296 result = l_int < r_int;
297
298 done:
299 free(left);
300 free(right);
Doug Zongker512536a2010-02-17 16:11:44 -0800301 return StringValue(strdup(result ? "t" : ""));
Doug Zongkere3da02e2009-06-12 16:13:52 -0700302}
303
Doug Zongker512536a2010-02-17 16:11:44 -0800304Value* GreaterThanIntFn(const char* name, State* state,
305 int argc, Expr* argv[]) {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700306 if (argc != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700307 state->errmsg = "greater_than_int expects 2 arguments";
Doug Zongkere3da02e2009-06-12 16:13:52 -0700308 return NULL;
309 }
310
311 Expr* temp[2];
312 temp[0] = argv[1];
313 temp[1] = argv[0];
314
315 return LessThanIntFn(name, state, 2, temp);
316}
317
Doug Zongker512536a2010-02-17 16:11:44 -0800318Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
319 return StringValue(strdup(name));
Doug Zongker37bee622009-06-08 17:35:39 -0700320}
321
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700322Expr* Build(Function fn, YYLTYPE loc, int count, ...) {
323 va_list v;
324 va_start(v, count);
Tao Bao2a5a49d2015-08-20 12:10:46 -0700325 Expr* e = reinterpret_cast<Expr*>(malloc(sizeof(Expr)));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700326 e->fn = fn;
327 e->name = "(operator)";
328 e->argc = count;
Tao Bao2a5a49d2015-08-20 12:10:46 -0700329 e->argv = reinterpret_cast<Expr**>(malloc(count * sizeof(Expr*)));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700330 int i;
331 for (i = 0; i < count; ++i) {
332 e->argv[i] = va_arg(v, Expr*);
333 }
334 va_end(v);
335 e->start = loc.start;
336 e->end = loc.end;
337 return e;
Doug Zongker9931f7f2009-06-10 14:11:53 -0700338}
339
340// -----------------------------------------------------------------
341// the function table
342// -----------------------------------------------------------------
343
Doug Zongker37bee622009-06-08 17:35:39 -0700344static int fn_entries = 0;
345static int fn_size = 0;
346NamedFunction* fn_table = NULL;
347
348void RegisterFunction(const char* name, Function fn) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700349 if (fn_entries >= fn_size) {
350 fn_size = fn_size*2 + 1;
Tao Bao2a5a49d2015-08-20 12:10:46 -0700351 fn_table = reinterpret_cast<NamedFunction*>(realloc(fn_table, fn_size * sizeof(NamedFunction)));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700352 }
353 fn_table[fn_entries].name = name;
354 fn_table[fn_entries].fn = fn;
355 ++fn_entries;
Doug Zongker37bee622009-06-08 17:35:39 -0700356}
357
358static int fn_entry_compare(const void* a, const void* b) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700359 const char* na = ((const NamedFunction*)a)->name;
360 const char* nb = ((const NamedFunction*)b)->name;
361 return strcmp(na, nb);
Doug Zongker37bee622009-06-08 17:35:39 -0700362}
363
364void FinishRegistration() {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700365 qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);
Doug Zongker37bee622009-06-08 17:35:39 -0700366}
367
368Function FindFunction(const char* name) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700369 NamedFunction key;
370 key.name = name;
Tao Bao2a5a49d2015-08-20 12:10:46 -0700371 NamedFunction* nf = reinterpret_cast<NamedFunction*>(bsearch(&key, fn_table, fn_entries,
372 sizeof(NamedFunction), fn_entry_compare));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700373 if (nf == NULL) {
374 return NULL;
375 }
376 return nf->fn;
Doug Zongker37bee622009-06-08 17:35:39 -0700377}
378
379void RegisterBuiltins() {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700380 RegisterFunction("ifelse", IfElseFn);
381 RegisterFunction("abort", AbortFn);
382 RegisterFunction("assert", AssertFn);
383 RegisterFunction("concat", ConcatFn);
384 RegisterFunction("is_substring", SubstringFn);
385 RegisterFunction("stdout", StdoutFn);
386 RegisterFunction("sleep", SleepFn);
Doug Zongkere3da02e2009-06-12 16:13:52 -0700387
388 RegisterFunction("less_than_int", LessThanIntFn);
389 RegisterFunction("greater_than_int", GreaterThanIntFn);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700390}
391
392
393// -----------------------------------------------------------------
394// convenience methods for functions
395// -----------------------------------------------------------------
396
397// Evaluate the expressions in argv, giving 'count' char* (the ... is
398// zero or more char** to put them in). If any expression evaluates
399// to NULL, free the rest and return -1. Return 0 on success.
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700400int ReadArgs(State* state, Expr* argv[], int count, ...) {
Tao Bao2a5a49d2015-08-20 12:10:46 -0700401 char** args = reinterpret_cast<char**>(malloc(count * sizeof(char*)));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700402 va_list v;
403 va_start(v, count);
404 int i;
405 for (i = 0; i < count; ++i) {
406 args[i] = Evaluate(state, argv[i]);
407 if (args[i] == NULL) {
408 va_end(v);
409 int j;
410 for (j = 0; j < i; ++j) {
411 free(args[j]);
412 }
Kenny Root21854cc2010-02-17 18:31:48 -0800413 free(args);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700414 return -1;
415 }
416 *(va_arg(v, char**)) = args[i];
Doug Zongker9931f7f2009-06-10 14:11:53 -0700417 }
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700418 va_end(v);
Kenny Root21854cc2010-02-17 18:31:48 -0800419 free(args);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700420 return 0;
Doug Zongker9931f7f2009-06-10 14:11:53 -0700421}
422
Doug Zongker512536a2010-02-17 16:11:44 -0800423// Evaluate the expressions in argv, giving 'count' Value* (the ... is
424// zero or more Value** to put them in). If any expression evaluates
425// to NULL, free the rest and return -1. Return 0 on success.
426int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
Tao Bao2a5a49d2015-08-20 12:10:46 -0700427 Value** args = reinterpret_cast<Value**>(malloc(count * sizeof(Value*)));
Doug Zongker512536a2010-02-17 16:11:44 -0800428 va_list v;
429 va_start(v, count);
430 int i;
431 for (i = 0; i < count; ++i) {
432 args[i] = EvaluateValue(state, argv[i]);
433 if (args[i] == NULL) {
434 va_end(v);
435 int j;
436 for (j = 0; j < i; ++j) {
437 FreeValue(args[j]);
438 }
439 free(args);
440 return -1;
441 }
442 *(va_arg(v, Value**)) = args[i];
443 }
444 va_end(v);
445 free(args);
446 return 0;
447}
448
Doug Zongker9931f7f2009-06-10 14:11:53 -0700449// Evaluate the expressions in argv, returning an array of char*
450// results. If any evaluate to NULL, free the rest and return NULL.
451// The caller is responsible for freeing the returned array and the
452// strings it contains.
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700453char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
454 char** args = (char**)malloc(argc * sizeof(char*));
455 int i = 0;
456 for (i = 0; i < argc; ++i) {
457 args[i] = Evaluate(state, argv[i]);
458 if (args[i] == NULL) {
459 int j;
460 for (j = 0; j < i; ++j) {
461 free(args[j]);
462 }
463 free(args);
464 return NULL;
465 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700466 }
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700467 return args;
Doug Zongker37bee622009-06-08 17:35:39 -0700468}
Doug Zongker47cace92009-06-18 10:11:50 -0700469
Doug Zongker512536a2010-02-17 16:11:44 -0800470// Evaluate the expressions in argv, returning an array of Value*
471// results. If any evaluate to NULL, free the rest and return NULL.
472// The caller is responsible for freeing the returned array and the
473// Values it contains.
474Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) {
475 Value** args = (Value**)malloc(argc * sizeof(Value*));
476 int i = 0;
477 for (i = 0; i < argc; ++i) {
478 args[i] = EvaluateValue(state, argv[i]);
479 if (args[i] == NULL) {
480 int j;
481 for (j = 0; j < i; ++j) {
482 FreeValue(args[j]);
483 }
484 free(args);
485 return NULL;
486 }
487 }
488 return args;
489}
490
Tianjie Xu16255832016-04-30 11:49:59 -0700491// Use printf-style arguments to compose an error message to put into
492// *state. Returns nullptr.
493Value* ErrorAbort(State* state, const char* format, ...) {
494 va_list ap;
495 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700496 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700497 va_end(ap);
498 return nullptr;
499}
500
501Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
502 va_list ap;
503 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700504 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700505 va_end(ap);
506 state->cause_code = cause_code;
507 return nullptr;
Doug Zongker47cace92009-06-18 10:11:50 -0700508}
Tao Bao59dcb9c2016-10-03 18:06:46 -0700509
510State::State(const std::string& script, void* cookie) :
511 script(script),
512 cookie(cookie) {
513}
514