Home | History | Annotate | Download | only in edify
      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 
     31 int BooleanString(const char* s) {
     32     return s[0] != '\0';
     33 }
     34 
     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 
     48 Value* EvaluateValue(State* state, Expr* expr) {
     49     return expr->fn(expr->name, state, expr->argc, expr->argv);
     50 }
     51 
     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 
     61 void FreeValue(Value* v) {
     62     if (v == NULL) return;
     63     free(v->data);
     64     free(v);
     65 }
     66 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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         printf("[%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         printf("[%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 
    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 
    323 Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
    324     return StringValue(strdup(name));
    325 }
    326 
    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 
    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 
    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 
    369 void FinishRegistration() {
    370     qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);
    371 }
    372 
    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 
    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.
    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.
    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.
    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.
    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.
    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