Browse Source

edify: Some clean-ups to libedify.

- Remove dead declarations in expr.h: SetError(), GetError(),
  ClearError().
- Remove the declaration of Build() out of expr.h.
- Use std::unordered_map to implement RegisterFunction() and
  FindFunction(); kill FinishRegistration().
- Add a testcase for calling unknown functions.

Test: mmma bootable/recovery; recovery_component_test passes.
Change-Id: I9af6825ae677f92b22d716a4a5682f58522af03b
Tao Bao 5 years ago
parent
commit
39119ad8ec
8 changed files with 70 additions and 98 deletions
  1. 3
    0
      edify/README.md
  2. 0
    1
      edify/edify_parser.cpp
  3. 13
    52
      edify/expr.cpp
  4. 7
    33
      edify/expr.h
  5. 24
    5
      edify/parser.yy
  6. 23
    5
      tests/component/edify_test.cpp
  7. 0
    1
      tests/component/updater_test.cpp
  8. 0
    1
      updater/updater.cpp

edify/README → edify/README.md View File

@@ -1,3 +1,6 @@
1
+edify
2
+=====
3
+
1 4
 Update scripts (from donut onwards) are written in a new little
2 5
 scripting language ("edify") that is superficially somewhat similar to
3 6
 the old one ("amend").  This is a brief overview of the new language.

+ 0
- 1
edify/edify_parser.cpp View File

@@ -45,7 +45,6 @@ static void ExprDump(int depth, const Expr* n, const std::string& script) {
45 45
 
46 46
 int main(int argc, char** argv) {
47 47
     RegisterBuiltins();
48
-    FinishRegistration();
49 48
 
50 49
     if (argc != 2) {
51 50
         printf("Usage: %s <edify script>\n", argv[0]);

+ 13
- 52
edify/expr.cpp View File

@@ -14,20 +14,20 @@
14 14
  * limitations under the License.
15 15
  */
16 16
 
17
-#include <string.h>
18
-#include <stdbool.h>
17
+#include "expr.h"
18
+
19
+#include <stdarg.h>
19 20
 #include <stdio.h>
20 21
 #include <stdlib.h>
21
-#include <stdarg.h>
22
+#include <string.h>
22 23
 #include <unistd.h>
23 24
 
24 25
 #include <string>
26
+#include <unordered_map>
25 27
 
26 28
 #include <android-base/stringprintf.h>
27 29
 #include <android-base/strings.h>
28 30
 
29
-#include "expr.h"
30
-
31 31
 // Functions should:
32 32
 //
33 33
 //    - return a malloc()'d string
@@ -319,61 +319,22 @@ Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
319 319
     return StringValue(strdup(name));
320 320
 }
321 321
 
322
-Expr* Build(Function fn, YYLTYPE loc, int count, ...) {
323
-    va_list v;
324
-    va_start(v, count);
325
-    Expr* e = reinterpret_cast<Expr*>(malloc(sizeof(Expr)));
326
-    e->fn = fn;
327
-    e->name = "(operator)";
328
-    e->argc = count;
329
-    e->argv = reinterpret_cast<Expr**>(malloc(count * sizeof(Expr*)));
330
-    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;
338
-}
339
-
340 322
 // -----------------------------------------------------------------
341 323
 //   the function table
342 324
 // -----------------------------------------------------------------
343 325
 
344
-static int fn_entries = 0;
345
-static int fn_size = 0;
346
-NamedFunction* fn_table = NULL;
326
+static std::unordered_map<std::string, Function> fn_table;
347 327
 
348
-void RegisterFunction(const char* name, Function fn) {
349
-    if (fn_entries >= fn_size) {
350
-        fn_size = fn_size*2 + 1;
351
-        fn_table = reinterpret_cast<NamedFunction*>(realloc(fn_table, fn_size * sizeof(NamedFunction)));
352
-    }
353
-    fn_table[fn_entries].name = name;
354
-    fn_table[fn_entries].fn = fn;
355
-    ++fn_entries;
328
+void RegisterFunction(const std::string& name, Function fn) {
329
+    fn_table[name] = fn;
356 330
 }
357 331
 
358
-static int fn_entry_compare(const void* a, const void* b) {
359
-    const char* na = ((const NamedFunction*)a)->name;
360
-    const char* nb = ((const NamedFunction*)b)->name;
361
-    return strcmp(na, nb);
362
-}
363
-
364
-void FinishRegistration() {
365
-    qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);
366
-}
367
-
368
-Function FindFunction(const char* name) {
369
-    NamedFunction key;
370
-    key.name = name;
371
-    NamedFunction* nf = reinterpret_cast<NamedFunction*>(bsearch(&key, fn_table, fn_entries,
372
-            sizeof(NamedFunction), fn_entry_compare));
373
-    if (nf == NULL) {
374
-        return NULL;
332
+Function FindFunction(const std::string& name) {
333
+    if (fn_table.find(name) == fn_table.end()) {
334
+        return nullptr;
335
+    } else {
336
+        return fn_table[name];
375 337
     }
376
-    return nf->fn;
377 338
 }
378 339
 
379 340
 void RegisterBuiltins() {

+ 7
- 33
edify/expr.h View File

@@ -21,11 +21,6 @@
21 21
 #include <string>
22 22
 
23 23
 #include "error_code.h"
24
-#include "yydefs.h"
25
-
26
-#define MAX_STRING_LEN 1024
27
-
28
-typedef struct Expr Expr;
29 24
 
30 25
 struct State {
31 26
     State(const std::string& script, void* cookie);
@@ -56,14 +51,15 @@ struct State {
56 51
 #define VAL_STRING  1  // data will be NULL-terminated; size doesn't count null
57 52
 #define VAL_BLOB    2
58 53
 
59
-typedef struct {
54
+struct Value {
60 55
     int type;
61 56
     ssize_t size;
62 57
     char* data;
63
-} Value;
58
+};
64 59
 
65
-typedef Value* (*Function)(const char* name, State* state,
66
-                           int argc, Expr* argv[]);
60
+struct Expr;
61
+
62
+using Function = Value* (*)(const char* name, State* state, int argc, Expr* argv[]);
67 63
 
68 64
 struct Expr {
69 65
     Function fn;
@@ -100,43 +96,21 @@ Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]);
100 96
 Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]);
101 97
 Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]);
102 98
 
103
-// Convenience function for building expressions with a fixed number
104
-// of arguments.
105
-Expr* Build(Function fn, YYLTYPE loc, int count, ...);
106
-
107 99
 // Global builtins, registered by RegisterBuiltins().
108 100
 Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]);
109 101
 Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]);
110 102
 Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]);
111 103
 
112
-
113
-// For setting and getting the global error string (when returning
114
-// NULL from a function).
115
-void SetError(const char* message);  // makes a copy
116
-const char* GetError();              // retains ownership
117
-void ClearError();
118
-
119
-
120
-typedef struct {
121
-  const char* name;
122
-  Function fn;
123
-} NamedFunction;
124
-
125 104
 // Register a new function.  The same Function may be registered under
126 105
 // multiple names, but a given name should only be used once.
127
-void RegisterFunction(const char* name, Function fn);
106
+void RegisterFunction(const std::string& name, Function fn);
128 107
 
129 108
 // Register all the builtins.
130 109
 void RegisterBuiltins();
131 110
 
132
-// Call this after all calls to RegisterFunction() but before parsing
133
-// any scripts to finish building the function table.
134
-void FinishRegistration();
135
-
136 111
 // Find the Function for a given name; return NULL if no such function
137 112
 // exists.
138
-Function FindFunction(const char* name);
139
-
113
+Function FindFunction(const std::string& name);
140 114
 
141 115
 // --- convenience functions for use in functions ---
142 116
 

+ 24
- 5
edify/parser.yy View File

@@ -33,6 +33,25 @@ struct yy_buffer_state;
33 33
 void yy_switch_to_buffer(struct yy_buffer_state* new_buffer);
34 34
 struct yy_buffer_state* yy_scan_string(const char* yystr);
35 35
 
36
+// Convenience function for building expressions with a fixed number
37
+// of arguments.
38
+static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) {
39
+    va_list v;
40
+    va_start(v, count);
41
+    Expr* e = static_cast<Expr*>(malloc(sizeof(Expr)));
42
+    e->fn = fn;
43
+    e->name = "(operator)";
44
+    e->argc = count;
45
+    e->argv = static_cast<Expr**>(malloc(count * sizeof(Expr*)));
46
+    for (size_t i = 0; i < count; ++i) {
47
+        e->argv[i] = va_arg(v, Expr*);
48
+    }
49
+    va_end(v);
50
+    e->start = loc.start;
51
+    e->end = loc.end;
52
+    return e;
53
+}
54
+
36 55
 %}
37 56
 
38 57
 %locations
@@ -70,7 +89,7 @@ input:  expr           { *root = $1; }
70 89
 ;
71 90
 
72 91
 expr:  STRING {
73
-    $$ = reinterpret_cast<Expr*>(malloc(sizeof(Expr)));
92
+    $$ = static_cast<Expr*>(malloc(sizeof(Expr)));
74 93
     $$->fn = Literal;
75 94
     $$->name = $1;
76 95
     $$->argc = 0;
@@ -91,9 +110,9 @@ expr:  STRING {
91 110
 |  IF expr THEN expr ENDIF           { $$ = Build(IfElseFn, @$, 2, $2, $4); }
92 111
 |  IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); }
93 112
 | STRING '(' arglist ')' {
94
-    $$ = reinterpret_cast<Expr*>(malloc(sizeof(Expr)));
113
+    $$ = static_cast<Expr*>(malloc(sizeof(Expr)));
95 114
     $$->fn = FindFunction($1);
96
-    if ($$->fn == NULL) {
115
+    if ($$->fn == nullptr) {
97 116
         char buffer[256];
98 117
         snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1);
99 118
         yyerror(root, error_count, buffer);
@@ -113,12 +132,12 @@ arglist:    /* empty */ {
113 132
 }
114 133
 | expr {
115 134
     $$.argc = 1;
116
-    $$.argv = reinterpret_cast<Expr**>(malloc(sizeof(Expr*)));
135
+    $$.argv = static_cast<Expr**>(malloc(sizeof(Expr*)));
117 136
     $$.argv[0] = $1;
118 137
 }
119 138
 | arglist ',' expr {
120 139
     $$.argc = $1.argc + 1;
121
-    $$.argv = reinterpret_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*)));
140
+    $$.argv = static_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*)));
122 141
     $$.argv[$$.argc-1] = $3;
123 142
 }
124 143
 ;

+ 23
- 5
tests/component/edify_test.cpp View File

@@ -22,17 +22,18 @@
22 22
 
23 23
 static void expect(const char* expr_str, const char* expected) {
24 24
     Expr* e;
25
-    int error_count;
26
-    EXPECT_EQ(parse_string(expr_str, &e, &error_count), 0);
25
+    int error_count = 0;
26
+    EXPECT_EQ(0, parse_string(expr_str, &e, &error_count));
27
+    EXPECT_EQ(0, error_count);
27 28
 
28 29
     State state(expr_str, nullptr);
29 30
 
30 31
     char* result = Evaluate(&state, e);
31 32
 
32 33
     if (expected == nullptr) {
33
-        EXPECT_EQ(result, nullptr);
34
+        EXPECT_EQ(nullptr, result);
34 35
     } else {
35
-        EXPECT_STREQ(result, expected);
36
+        EXPECT_STREQ(expected, result);
36 37
     }
37 38
 
38 39
     free(result);
@@ -42,7 +43,6 @@ class EdifyTest : public ::testing::Test {
42 43
   protected:
43 44
     virtual void SetUp() {
44 45
         RegisterBuiltins();
45
-        FinishRegistration();
46 46
     }
47 47
 };
48 48
 
@@ -149,3 +149,21 @@ TEST_F(EdifyTest, big_string) {
149 149
     expect(std::string(8192, 's').c_str(), std::string(8192, 's').c_str());
150 150
 }
151 151
 
152
+TEST_F(EdifyTest, unknown_function) {
153
+    // unknown function
154
+    const char* script1 = "unknown_function()";
155
+    Expr* expr;
156
+    int error_count = 0;
157
+    EXPECT_EQ(1, parse_string(script1, &expr, &error_count));
158
+    EXPECT_EQ(1, error_count);
159
+
160
+    const char* script2 = "abc; unknown_function()";
161
+    error_count = 0;
162
+    EXPECT_EQ(1, parse_string(script2, &expr, &error_count));
163
+    EXPECT_EQ(1, error_count);
164
+
165
+    const char* script3 = "unknown_function1() || yes";
166
+    error_count = 0;
167
+    EXPECT_EQ(1, parse_string(script3, &expr, &error_count));
168
+    EXPECT_EQ(1, error_count);
169
+}

+ 0
- 1
tests/component/updater_test.cpp View File

@@ -54,7 +54,6 @@ class UpdaterTest : public ::testing::Test {
54 54
     virtual void SetUp() {
55 55
         RegisterBuiltins();
56 56
         RegisterInstallFunctions();
57
-        FinishRegistration();
58 57
     }
59 58
 };
60 59
 

+ 0
- 1
updater/updater.cpp View File

@@ -111,7 +111,6 @@ int main(int argc, char** argv) {
111 111
     RegisterInstallFunctions();
112 112
     RegisterBlockImageFunctions();
113 113
     RegisterDeviceExtensions();
114
-    FinishRegistration();
115 114
 
116 115
     // Parse the script.
117 116