• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
BooleanString(const char * s)31  int BooleanString(const char* s) {
32      return s[0] != '\0';
33  }
34  
Evaluate(State * state,Expr * expr)35  char* 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  
EvaluateValue(State * state,Expr * expr)48  Value* EvaluateValue(State* state, Expr* expr) {
49      return expr->fn(expr->name, state, expr->argc, expr->argv);
50  }
51  
StringValue(char * str)52  Value* StringValue(char* str) {
53      if (str == NULL) return NULL;
54      Value* v = malloc(sizeof(Value));
55      v->type = VAL_STRING;
56      v->size = strlen(str);
57      v->data = str;
58      return v;
59  }
60  
FreeValue(Value * v)61  void FreeValue(Value* v) {
62      if (v == NULL) return;
63      free(v->data);
64      free(v);
65  }
66  
ConcatFn(const char * name,State * state,int argc,Expr * argv[])67  Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
68      if (argc == 0) {
69          return StringValue(strdup(""));
70      }
71      char** strings = 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 = malloc(length+1);
87      int p = 0;
88      for (i = 0; i < argc; ++i) {
89          strcpy(result+p, strings[i]);
90          p += strlen(strings[i]);
91      }
92      result[p] = '\0';
93  
94    done:
95      for (i = 0; i < argc; ++i) {
96          free(strings[i]);
97      }
98      free(strings);
99      return StringValue(result);
100  }
101  
IfElseFn(const char * name,State * state,int argc,Expr * argv[])102  Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
103      if (argc != 2 && argc != 3) {
104          free(state->errmsg);
105          state->errmsg = strdup("ifelse expects 2 or 3 arguments");
106          return NULL;
107      }
108      char* cond = Evaluate(state, argv[0]);
109      if (cond == NULL) {
110          return NULL;
111      }
112  
113      if (BooleanString(cond) == true) {
114          free(cond);
115          return EvaluateValue(state, argv[1]);
116      } else {
117          if (argc == 3) {
118              free(cond);
119              return EvaluateValue(state, argv[2]);
120          } else {
121              return StringValue(cond);
122          }
123      }
124  }
125  
AbortFn(const char * name,State * state,int argc,Expr * argv[])126  Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
127      char* msg = NULL;
128      if (argc > 0) {
129          msg = Evaluate(state, argv[0]);
130      }
131      free(state->errmsg);
132      if (msg) {
133          state->errmsg = msg;
134      } else {
135          state->errmsg = strdup("called abort()");
136      }
137      return NULL;
138  }
139  
AssertFn(const char * name,State * state,int argc,Expr * argv[])140  Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
141      int i;
142      for (i = 0; i < argc; ++i) {
143          char* v = Evaluate(state, argv[i]);
144          if (v == NULL) {
145              return NULL;
146          }
147          int b = BooleanString(v);
148          free(v);
149          if (!b) {
150              int prefix_len;
151              int len = argv[i]->end - argv[i]->start;
152              char* err_src = malloc(len + 20);
153              strcpy(err_src, "assert failed: ");
154              prefix_len = strlen(err_src);
155              memcpy(err_src + prefix_len, state->script + argv[i]->start, len);
156              err_src[prefix_len + len] = '\0';
157              free(state->errmsg);
158              state->errmsg = err_src;
159              return NULL;
160          }
161      }
162      return StringValue(strdup(""));
163  }
164  
SleepFn(const char * name,State * state,int argc,Expr * argv[])165  Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
166      char* val = Evaluate(state, argv[0]);
167      if (val == NULL) {
168          return NULL;
169      }
170      int v = strtol(val, NULL, 10);
171      sleep(v);
172      return StringValue(val);
173  }
174  
StdoutFn(const char * name,State * state,int argc,Expr * argv[])175  Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
176      int i;
177      for (i = 0; i < argc; ++i) {
178          char* v = Evaluate(state, argv[i]);
179          if (v == NULL) {
180              return NULL;
181          }
182          fputs(v, stdout);
183          free(v);
184      }
185      return StringValue(strdup(""));
186  }
187  
LogicalAndFn(const char * name,State * state,int argc,Expr * argv[])188  Value* LogicalAndFn(const char* name, State* state,
189                     int argc, Expr* argv[]) {
190      char* left = Evaluate(state, argv[0]);
191      if (left == NULL) return NULL;
192      if (BooleanString(left) == true) {
193          free(left);
194          return EvaluateValue(state, argv[1]);
195      } else {
196          return StringValue(left);
197      }
198  }
199  
LogicalOrFn(const char * name,State * state,int argc,Expr * argv[])200  Value* LogicalOrFn(const char* name, State* state,
201                     int argc, Expr* argv[]) {
202      char* left = Evaluate(state, argv[0]);
203      if (left == NULL) return NULL;
204      if (BooleanString(left) == false) {
205          free(left);
206          return EvaluateValue(state, argv[1]);
207      } else {
208          return StringValue(left);
209      }
210  }
211  
LogicalNotFn(const char * name,State * state,int argc,Expr * argv[])212  Value* LogicalNotFn(const char* name, State* state,
213                      int argc, Expr* argv[]) {
214      char* val = Evaluate(state, argv[0]);
215      if (val == NULL) return NULL;
216      bool bv = BooleanString(val);
217      free(val);
218      return StringValue(strdup(bv ? "" : "t"));
219  }
220  
SubstringFn(const char * name,State * state,int argc,Expr * argv[])221  Value* SubstringFn(const char* name, State* state,
222                     int argc, Expr* argv[]) {
223      char* needle = Evaluate(state, argv[0]);
224      if (needle == NULL) return NULL;
225      char* haystack = Evaluate(state, argv[1]);
226      if (haystack == NULL) {
227          free(needle);
228          return NULL;
229      }
230  
231      char* result = strdup(strstr(haystack, needle) ? "t" : "");
232      free(needle);
233      free(haystack);
234      return StringValue(result);
235  }
236  
EqualityFn(const char * name,State * state,int argc,Expr * argv[])237  Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
238      char* left = Evaluate(state, argv[0]);
239      if (left == NULL) return NULL;
240      char* right = Evaluate(state, argv[1]);
241      if (right == NULL) {
242          free(left);
243          return NULL;
244      }
245  
246      char* result = strdup(strcmp(left, right) == 0 ? "t" : "");
247      free(left);
248      free(right);
249      return StringValue(result);
250  }
251  
InequalityFn(const char * name,State * state,int argc,Expr * argv[])252  Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
253      char* left = Evaluate(state, argv[0]);
254      if (left == NULL) return NULL;
255      char* right = Evaluate(state, argv[1]);
256      if (right == NULL) {
257          free(left);
258          return NULL;
259      }
260  
261      char* result = strdup(strcmp(left, right) != 0 ? "t" : "");
262      free(left);
263      free(right);
264      return StringValue(result);
265  }
266  
SequenceFn(const char * name,State * state,int argc,Expr * argv[])267  Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
268      Value* left = EvaluateValue(state, argv[0]);
269      if (left == NULL) return NULL;
270      FreeValue(left);
271      return EvaluateValue(state, argv[1]);
272  }
273  
LessThanIntFn(const char * name,State * state,int argc,Expr * argv[])274  Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
275      if (argc != 2) {
276          free(state->errmsg);
277          state->errmsg = strdup("less_than_int expects 2 arguments");
278          return NULL;
279      }
280  
281      char* left;
282      char* right;
283      if (ReadArgs(state, argv, 2, &left, &right) < 0) return NULL;
284  
285      bool result = false;
286      char* end;
287  
288      long l_int = strtol(left, &end, 10);
289      if (left[0] == '\0' || *end != '\0') {
290          fprintf(stderr, "[%s] is not an int\n", left);
291          goto done;
292      }
293  
294      long r_int = strtol(right, &end, 10);
295      if (right[0] == '\0' || *end != '\0') {
296          fprintf(stderr, "[%s] is not an int\n", right);
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  
GreaterThanIntFn(const char * name,State * state,int argc,Expr * argv[])308  Value* 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  
Literal(const char * name,State * state,int argc,Expr * argv[])323  Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
324      return StringValue(strdup(name));
325  }
326  
Build(Function fn,YYLTYPE loc,int count,...)327  Expr* Build(Function fn, YYLTYPE loc, int count, ...) {
328      va_list v;
329      va_start(v, count);
330      Expr* e = malloc(sizeof(Expr));
331      e->fn = fn;
332      e->name = "(operator)";
333      e->argc = count;
334      e->argv = 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  
349  static int fn_entries = 0;
350  static int fn_size = 0;
351  NamedFunction* fn_table = NULL;
352  
RegisterFunction(const char * name,Function fn)353  void RegisterFunction(const char* name, Function fn) {
354      if (fn_entries >= fn_size) {
355          fn_size = fn_size*2 + 1;
356          fn_table = 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  
fn_entry_compare(const void * a,const void * b)363  static 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  
FinishRegistration()369  void FinishRegistration() {
370      qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);
371  }
372  
FindFunction(const char * name)373  Function FindFunction(const char* name) {
374      NamedFunction key;
375      key.name = name;
376      NamedFunction* nf = 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  
RegisterBuiltins()384  void 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.
ReadArgs(State * state,Expr * argv[],int count,...)405  int ReadArgs(State* state, Expr* argv[], int count, ...) {
406      char** args = 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.
ReadValueArgs(State * state,Expr * argv[],int count,...)431  int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
432      Value** args = 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.
ReadVarArgs(State * state,int argc,Expr * argv[])458  char** 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.
ReadValueVarArgs(State * state,int argc,Expr * argv[])479  Value** 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.
ErrorAbort(State * state,const char * format,...)498  Value* ErrorAbort(State* state, const char* format, ...) {
499      char* buffer = 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  }
508