aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Bao2015-08-20 14:10:46 -0500
committerTao Bao2015-08-20 14:11:04 -0500
commit2a5a49d3376eae890d76bb560e0d8ffc264ff5a6 (patch)
tree2aa9d806b2c6f235ea79780f6f5452927fd80df7 /edify/expr.cpp
parentad509fd4a2c597ced8e53b0817f754cb2209b98a (diff)
downloadplatform-bootable-recovery-2a5a49d3376eae890d76bb560e0d8ffc264ff5a6.tar.gz
platform-bootable-recovery-2a5a49d3376eae890d76bb560e0d8ffc264ff5a6.tar.xz
platform-bootable-recovery-2a5a49d3376eae890d76bb560e0d8ffc264ff5a6.zip
edify: Switch to C++.
Change-Id: I71aede6e29af1dc4bb858a62016c8035db5d3452
Diffstat (limited to 'edify/expr.cpp')
-rw-r--r--edify/expr.cpp507
1 files changed, 507 insertions, 0 deletions
diff --git a/edify/expr.cpp b/edify/expr.cpp
new file mode 100644
index 00000000..cd1e0872
--- /dev/null
+++ b/edify/expr.cpp
@@ -0,0 +1,507 @@
1/*
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>
22#include <unistd.h>
23
24#include "expr.h"
25
26// Functions should:
27//
28// - return a malloc()'d string
29// - if Evaluate() on any argument returns NULL, return NULL.
30
31int BooleanString(const char* s) {
32 return s[0] != '\0';
33}
34
35char* Evaluate(State* state, Expr* expr) {
36 Value* v = expr->fn(expr->name, state, expr->argc, expr->argv);
37 if (v == NULL) return NULL;
38 if (v->type != VAL_STRING) {
39 ErrorAbort(state, "expecting string, got value type %d", v->type);
40 FreeValue(v);
41 return NULL;
42 }
43 char* result = v->data;
44 free(v);
45 return result;
46}
47
48Value* EvaluateValue(State* state, Expr* expr) {
49 return expr->fn(expr->name, state, expr->argc, expr->argv);
50}
51
52Value* StringValue(char* str) {
53 if (str == NULL) return NULL;
54 Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value)));
55 v->type = VAL_STRING;
56 v->size = strlen(str);
57 v->data = str;
58 return v;
59}
60
61void FreeValue(Value* v) {
62 if (v == NULL) return;
63 free(v->data);
64 free(v);
65}
66
67Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
68 if (argc == 0) {
69 return StringValue(strdup(""));
70 }
71 char** strings = reinterpret_cast<char**>(malloc(argc * sizeof(char*)));
72 int i;
73 for (i = 0; i < argc; ++i) {
74 strings[i] = NULL;
75 }
76 char* result = NULL;
77 int length = 0;
78 for (i = 0; i < argc; ++i) {
79 strings[i] = Evaluate(state, argv[i]);
80 if (strings[i] == NULL) {
81 goto done;
82 }
83 length += strlen(strings[i]);
84 }
85
86 result = reinterpret_cast<char*>(malloc(length+1));
87 int p;
88 p = 0;
89 for (i = 0; i < argc; ++i) {
90 strcpy(result+p, strings[i]);
91 p += strlen(strings[i]);
92 }
93 result[p] = '\0';
94
95 done:
96 for (i = 0; i < argc; ++i) {
97 free(strings[i]);
98 }
99 free(strings);
100 return StringValue(result);
101}
102
103Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
104 if (argc != 2 && argc != 3) {
105 free(state->errmsg);
106 state->errmsg = strdup("ifelse expects 2 or 3 arguments");
107 return NULL;
108 }
109 char* cond = Evaluate(state, argv[0]);
110 if (cond == NULL) {
111 return NULL;
112 }
113
114 if (BooleanString(cond) == true) {
115 free(cond);
116 return EvaluateValue(state, argv[1]);
117 } else {
118 if (argc == 3) {
119 free(cond);
120 return EvaluateValue(state, argv[2]);
121 } else {
122 return StringValue(cond);
123 }
124 }
125}
126
127Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
128 char* msg = NULL;
129 if (argc > 0) {
130 msg = Evaluate(state, argv[0]);
131 }
132 free(state->errmsg);
133 if (msg) {
134 state->errmsg = msg;
135 } else {
136 state->errmsg = strdup("called abort()");
137 }
138 return NULL;
139}
140
141Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
142 int i;
143 for (i = 0; i < argc; ++i) {
144 char* v = Evaluate(state, argv[i]);
145 if (v == NULL) {
146 return NULL;
147 }
148 int b = BooleanString(v);
149 free(v);
150 if (!b) {
151 int prefix_len;
152 int len = argv[i]->end - argv[i]->start;
153 char* err_src = reinterpret_cast<char*>(malloc(len + 20));
154 strcpy(err_src, "assert failed: ");
155 prefix_len = strlen(err_src);
156 memcpy(err_src + prefix_len, state->script + argv[i]->start, len);
157 err_src[prefix_len + len] = '\0';
158 free(state->errmsg);
159 state->errmsg = err_src;
160 return NULL;
161 }
162 }
163 return StringValue(strdup(""));
164}
165
166Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
167 char* val = Evaluate(state, argv[0]);
168 if (val == NULL) {
169 return NULL;
170 }
171 int v = strtol(val, NULL, 10);
172 sleep(v);
173 return StringValue(val);
174}
175
176Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
177 int i;
178 for (i = 0; i < argc; ++i) {
179 char* v = Evaluate(state, argv[i]);
180 if (v == NULL) {
181 return NULL;
182 }
183 fputs(v, stdout);
184 free(v);
185 }
186 return StringValue(strdup(""));
187}
188
189Value* LogicalAndFn(const char* name, State* state,
190 int argc, Expr* argv[]) {
191 char* left = Evaluate(state, argv[0]);
192 if (left == NULL) return NULL;
193 if (BooleanString(left) == true) {
194 free(left);
195 return EvaluateValue(state, argv[1]);
196 } else {
197 return StringValue(left);
198 }
199}
200
201Value* LogicalOrFn(const char* name, State* state,
202 int argc, Expr* argv[]) {
203 char* left = Evaluate(state, argv[0]);
204 if (left == NULL) return NULL;
205 if (BooleanString(left) == false) {
206 free(left);
207 return EvaluateValue(state, argv[1]);
208 } else {
209 return StringValue(left);
210 }
211}
212
213Value* LogicalNotFn(const char* name, State* state,
214 int argc, Expr* argv[]) {
215 char* val = Evaluate(state, argv[0]);
216 if (val == NULL) return NULL;
217 bool bv = BooleanString(val);
218 free(val);
219 return StringValue(strdup(bv ? "" : "t"));
220}
221
222Value* SubstringFn(const char* name, State* state,
223 int argc, Expr* argv[]) {
224 char* needle = Evaluate(state, argv[0]);
225 if (needle == NULL) return NULL;
226 char* haystack = Evaluate(state, argv[1]);
227 if (haystack == NULL) {
228 free(needle);
229 return NULL;
230 }
231
232 char* result = strdup(strstr(haystack, needle) ? "t" : "");
233 free(needle);
234 free(haystack);
235 return StringValue(result);
236}
237
238Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
239 char* left = Evaluate(state, argv[0]);
240 if (left == NULL) return NULL;
241 char* right = Evaluate(state, argv[1]);
242 if (right == NULL) {
243 free(left);
244 return NULL;
245 }
246
247 char* result = strdup(strcmp(left, right) == 0 ? "t" : "");
248 free(left);
249 free(right);
250 return StringValue(result);
251}
252
253Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
254 char* left = Evaluate(state, argv[0]);
255 if (left == NULL) return NULL;
256 char* right = Evaluate(state, argv[1]);
257 if (right == NULL) {
258 free(left);
259 return NULL;
260 }
261
262 char* result = strdup(strcmp(left, right) != 0 ? "t" : "");
263 free(left);
264 free(right);
265 return StringValue(result);
266}
267
268Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
269 Value* left = EvaluateValue(state, argv[0]);
270 if (left == NULL) return NULL;
271 FreeValue(left);
272 return EvaluateValue(state, argv[1]);
273}
274
275Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
276 if (argc != 2) {
277 free(state->errmsg);
278 state->errmsg = strdup("less_than_int expects 2 arguments");
279 return NULL;
280 }
281
282 char* left;
283 char* right;
284 if (ReadArgs(state, argv, 2, &left, &right) < 0) return NULL;
285
286 bool result = false;
287 char* end;
288
289 long l_int = strtol(left, &end, 10);
290 if (left[0] == '\0' || *end != '\0') {
291 goto done;
292 }
293
294 long r_int;
295 r_int = strtol(right, &end, 10);
296 if (right[0] == '\0' || *end != '\0') {
297 goto done;
298 }
299
300 result = l_int < r_int;
301
302 done:
303 free(left);
304 free(right);
305 return StringValue(strdup(result ? "t" : ""));
306}
307
308Value* GreaterThanIntFn(const char* name, State* state,
309 int argc, Expr* argv[]) {
310 if (argc != 2) {
311 free(state->errmsg);
312 state->errmsg = strdup("greater_than_int expects 2 arguments");
313 return NULL;
314 }
315
316 Expr* temp[2];
317 temp[0] = argv[1];
318 temp[1] = argv[0];
319
320 return LessThanIntFn(name, state, 2, temp);
321}
322
323Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
324 return StringValue(strdup(name));
325}
326
327Expr* Build(Function fn, YYLTYPE loc, int count, ...) {
328 va_list v;
329 va_start(v, count);
330 Expr* e = reinterpret_cast<Expr*>(malloc(sizeof(Expr)));
331 e->fn = fn;
332 e->name = "(operator)";
333 e->argc = count;
334 e->argv = reinterpret_cast<Expr**>(malloc(count * sizeof(Expr*)));
335 int i;
336 for (i = 0; i < count; ++i) {
337 e->argv[i] = va_arg(v, Expr*);
338 }
339 va_end(v);
340 e->start = loc.start;
341 e->end = loc.end;
342 return e;
343}
344
345// -----------------------------------------------------------------
346// the function table
347// -----------------------------------------------------------------
348
349static int fn_entries = 0;
350static int fn_size = 0;
351NamedFunction* fn_table = NULL;
352
353void RegisterFunction(const char* name, Function fn) {
354 if (fn_entries >= fn_size) {
355 fn_size = fn_size*2 + 1;
356 fn_table = reinterpret_cast<NamedFunction*>(realloc(fn_table, fn_size * sizeof(NamedFunction)));
357 }
358 fn_table[fn_entries].name = name;
359 fn_table[fn_entries].fn = fn;
360 ++fn_entries;
361}
362
363static int fn_entry_compare(const void* a, const void* b) {
364 const char* na = ((const NamedFunction*)a)->name;
365 const char* nb = ((const NamedFunction*)b)->name;
366 return strcmp(na, nb);
367}
368
369void FinishRegistration() {
370 qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);
371}
372
373Function FindFunction(const char* name) {
374 NamedFunction key;
375 key.name = name;
376 NamedFunction* nf = reinterpret_cast<NamedFunction*>(bsearch(&key, fn_table, fn_entries,
377 sizeof(NamedFunction), fn_entry_compare));
378 if (nf == NULL) {
379 return NULL;
380 }
381 return nf->fn;
382}
383
384void RegisterBuiltins() {
385 RegisterFunction("ifelse", IfElseFn);
386 RegisterFunction("abort", AbortFn);
387 RegisterFunction("assert", AssertFn);
388 RegisterFunction("concat", ConcatFn);
389 RegisterFunction("is_substring", SubstringFn);
390 RegisterFunction("stdout", StdoutFn);
391 RegisterFunction("sleep", SleepFn);
392
393 RegisterFunction("less_than_int", LessThanIntFn);
394 RegisterFunction("greater_than_int", GreaterThanIntFn);
395}
396
397
398// -----------------------------------------------------------------
399// convenience methods for functions
400// -----------------------------------------------------------------
401
402// Evaluate the expressions in argv, giving 'count' char* (the ... is
403// zero or more char** to put them in). If any expression evaluates
404// to NULL, free the rest and return -1. Return 0 on success.
405int ReadArgs(State* state, Expr* argv[], int count, ...) {
406 char** args = reinterpret_cast<char**>(malloc(count * sizeof(char*)));
407 va_list v;
408 va_start(v, count);
409 int i;
410 for (i = 0; i < count; ++i) {
411 args[i] = Evaluate(state, argv[i]);
412 if (args[i] == NULL) {
413 va_end(v);
414 int j;
415 for (j = 0; j < i; ++j) {
416 free(args[j]);
417 }
418 free(args);
419 return -1;
420 }
421 *(va_arg(v, char**)) = args[i];
422 }
423 va_end(v);
424 free(args);
425 return 0;
426}
427
428// Evaluate the expressions in argv, giving 'count' Value* (the ... is
429// zero or more Value** to put them in). If any expression evaluates
430// to NULL, free the rest and return -1. Return 0 on success.
431int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
432 Value** args = reinterpret_cast<Value**>(malloc(count * sizeof(Value*)));
433 va_list v;
434 va_start(v, count);
435 int i;
436 for (i = 0; i < count; ++i) {
437 args[i] = EvaluateValue(state, argv[i]);
438 if (args[i] == NULL) {
439 va_end(v);
440 int j;
441 for (j = 0; j < i; ++j) {
442 FreeValue(args[j]);
443 }
444 free(args);
445 return -1;
446 }
447 *(va_arg(v, Value**)) = args[i];
448 }
449 va_end(v);
450 free(args);
451 return 0;
452}
453
454// Evaluate the expressions in argv, returning an array of char*
455// results. If any evaluate to NULL, free the rest and return NULL.
456// The caller is responsible for freeing the returned array and the
457// strings it contains.
458char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
459 char** args = (char**)malloc(argc * sizeof(char*));
460 int i = 0;
461 for (i = 0; i < argc; ++i) {
462 args[i] = Evaluate(state, argv[i]);
463 if (args[i] == NULL) {
464 int j;
465 for (j = 0; j < i; ++j) {
466 free(args[j]);
467 }
468 free(args);
469 return NULL;
470 }
471 }
472 return args;
473}
474
475// Evaluate the expressions in argv, returning an array of Value*
476// results. If any evaluate to NULL, free the rest and return NULL.
477// The caller is responsible for freeing the returned array and the
478// Values it contains.
479Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) {
480 Value** args = (Value**)malloc(argc * sizeof(Value*));
481 int i = 0;
482 for (i = 0; i < argc; ++i) {
483 args[i] = EvaluateValue(state, argv[i]);
484 if (args[i] == NULL) {
485 int j;
486 for (j = 0; j < i; ++j) {
487 FreeValue(args[j]);
488 }
489 free(args);
490 return NULL;
491 }
492 }
493 return args;
494}
495
496// Use printf-style arguments to compose an error message to put into
497// *state. Returns NULL.
498Value* ErrorAbort(State* state, const char* format, ...) {
499 char* buffer = reinterpret_cast<char*>(malloc(4096));
500 va_list v;
501 va_start(v, format);
502 vsnprintf(buffer, 4096, format, v);
503 va_end(v);
504 free(state->errmsg);
505 state->errmsg = buffer;
506 return NULL;
507}