aboutsummaryrefslogtreecommitdiffstats
path: root/edify
diff options
context:
space:
mode:
authorTianjie Xu2017-03-06 16:44:59 -0600
committerTianjie Xu2017-03-22 16:20:57 -0500
commitc444732540d5245b6219293e96d29f325daa7839 (patch)
treed66338f891ad8b440a36e781988fae89cca1da7f /edify
parentd882b8892a1592101b901dd474de41e56c31b17b (diff)
downloadplatform-bootable-recovery-c444732540d5245b6219293e96d29f325daa7839.tar.gz
platform-bootable-recovery-c444732540d5245b6219293e96d29f325daa7839.tar.xz
platform-bootable-recovery-c444732540d5245b6219293e96d29f325daa7839.zip
Remove malloc in edify functions
And switch them to std::vector & std::unique_ptr Bug: 32117870 Test: recovery tests passed on sailfish Change-Id: I5a45951c4bdf895be311d6d760e52e7a1b0798c3
Diffstat (limited to 'edify')
-rw-r--r--edify/edify_parser.cpp9
-rw-r--r--edify/expr.cpp119
-rw-r--r--edify/expr.h83
-rw-r--r--edify/parser.yy71
4 files changed, 153 insertions, 129 deletions
diff --git a/edify/edify_parser.cpp b/edify/edify_parser.cpp
index 908fcf13..f1b56284 100644
--- a/edify/edify_parser.cpp
+++ b/edify/edify_parser.cpp
@@ -27,18 +27,19 @@
27#include <errno.h> 27#include <errno.h>
28#include <stdio.h> 28#include <stdio.h>
29 29
30#include <memory>
30#include <string> 31#include <string>
31 32
32#include <android-base/file.h> 33#include <android-base/file.h>
33 34
34#include "expr.h" 35#include "expr.h"
35 36
36static void ExprDump(int depth, const Expr* n, const std::string& script) { 37static void ExprDump(int depth, const std::unique_ptr<Expr>& n, const std::string& script) {
37 printf("%*s", depth*2, ""); 38 printf("%*s", depth*2, "");
38 printf("%s %p (%d-%d) \"%s\"\n", 39 printf("%s %p (%d-%d) \"%s\"\n",
39 n->name == NULL ? "(NULL)" : n->name, n->fn, n->start, n->end, 40 n->name.c_str(), n->fn, n->start, n->end,
40 script.substr(n->start, n->end - n->start).c_str()); 41 script.substr(n->start, n->end - n->start).c_str());
41 for (int i = 0; i < n->argc; ++i) { 42 for (size_t i = 0; i < n->argv.size(); ++i) {
42 ExprDump(depth+1, n->argv[i], script); 43 ExprDump(depth+1, n->argv[i], script);
43 } 44 }
44} 45}
@@ -57,7 +58,7 @@ int main(int argc, char** argv) {
57 return 1; 58 return 1;
58 } 59 }
59 60
60 Expr* root; 61 std::unique_ptr<Expr> root;
61 int error_count = 0; 62 int error_count = 0;
62 int error = parse_string(buffer.data(), &root, &error_count); 63 int error = parse_string(buffer.data(), &root, &error_count);
63 printf("parse returned %d; %d errors encountered\n", error, error_count); 64 printf("parse returned %d; %d errors encountered\n", error, error_count);
diff --git a/edify/expr.cpp b/edify/expr.cpp
index 329cf3ac..2b7fd7a6 100644
--- a/edify/expr.cpp
+++ b/edify/expr.cpp
@@ -40,12 +40,12 @@ static bool BooleanString(const std::string& s) {
40 return !s.empty(); 40 return !s.empty();
41} 41}
42 42
43bool Evaluate(State* state, Expr* expr, std::string* result) { 43bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) {
44 if (result == nullptr) { 44 if (result == nullptr) {
45 return false; 45 return false;
46 } 46 }
47 47
48 std::unique_ptr<Value> v(expr->fn(expr->name, state, expr->argc, expr->argv)); 48 std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv));
49 if (!v) { 49 if (!v) {
50 return false; 50 return false;
51 } 51 }
@@ -58,8 +58,8 @@ bool Evaluate(State* state, Expr* expr, std::string* result) {
58 return true; 58 return true;
59} 59}
60 60
61Value* EvaluateValue(State* state, Expr* expr) { 61Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) {
62 return expr->fn(expr->name, state, expr->argc, expr->argv); 62 return expr->fn(expr->name.c_str(), state, expr->argv);
63} 63}
64 64
65Value* StringValue(const char* str) { 65Value* StringValue(const char* str) {
@@ -73,12 +73,12 @@ Value* StringValue(const std::string& str) {
73 return StringValue(str.c_str()); 73 return StringValue(str.c_str());
74} 74}
75 75
76Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { 76Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
77 if (argc == 0) { 77 if (argv.empty()) {
78 return StringValue(""); 78 return StringValue("");
79 } 79 }
80 std::string result; 80 std::string result;
81 for (int i = 0; i < argc; ++i) { 81 for (size_t i = 0; i < argv.size(); ++i) {
82 std::string str; 82 std::string str;
83 if (!Evaluate(state, argv[i], &str)) { 83 if (!Evaluate(state, argv[i], &str)) {
84 return nullptr; 84 return nullptr;
@@ -89,8 +89,8 @@ Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
89 return StringValue(result); 89 return StringValue(result);
90} 90}
91 91
92Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { 92Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
93 if (argc != 2 && argc != 3) { 93 if (argv.size() != 2 && argv.size() != 3) {
94 state->errmsg = "ifelse expects 2 or 3 arguments"; 94 state->errmsg = "ifelse expects 2 or 3 arguments";
95 return nullptr; 95 return nullptr;
96 } 96 }
@@ -102,16 +102,16 @@ Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
102 102
103 if (!cond.empty()) { 103 if (!cond.empty()) {
104 return EvaluateValue(state, argv[1]); 104 return EvaluateValue(state, argv[1]);
105 } else if (argc == 3) { 105 } else if (argv.size() == 3) {
106 return EvaluateValue(state, argv[2]); 106 return EvaluateValue(state, argv[2]);
107 } 107 }
108 108
109 return StringValue(""); 109 return StringValue("");
110} 110}
111 111
112Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { 112Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
113 std::string msg; 113 std::string msg;
114 if (argc > 0 && Evaluate(state, argv[0], &msg)) { 114 if (!argv.empty() && Evaluate(state, argv[0], &msg)) {
115 state->errmsg = msg; 115 state->errmsg = msg;
116 } else { 116 } else {
117 state->errmsg = "called abort()"; 117 state->errmsg = "called abort()";
@@ -119,8 +119,8 @@ Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
119 return nullptr; 119 return nullptr;
120} 120}
121 121
122Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { 122Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
123 for (int i = 0; i < argc; ++i) { 123 for (size_t i = 0; i < argv.size(); ++i) {
124 std::string result; 124 std::string result;
125 if (!Evaluate(state, argv[i], &result)) { 125 if (!Evaluate(state, argv[i], &result)) {
126 return nullptr; 126 return nullptr;
@@ -134,7 +134,7 @@ Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
134 return StringValue(""); 134 return StringValue("");
135} 135}
136 136
137Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { 137Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
138 std::string val; 138 std::string val;
139 if (!Evaluate(state, argv[0], &val)) { 139 if (!Evaluate(state, argv[0], &val)) {
140 return nullptr; 140 return nullptr;
@@ -149,8 +149,8 @@ Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
149 return StringValue(val); 149 return StringValue(val);
150} 150}
151 151
152Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { 152Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
153 for (int i = 0; i < argc; ++i) { 153 for (size_t i = 0; i < argv.size(); ++i) {
154 std::string v; 154 std::string v;
155 if (!Evaluate(state, argv[i], &v)) { 155 if (!Evaluate(state, argv[i], &v)) {
156 return nullptr; 156 return nullptr;
@@ -161,7 +161,7 @@ Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
161} 161}
162 162
163Value* LogicalAndFn(const char* name, State* state, 163Value* LogicalAndFn(const char* name, State* state,
164 int argc, Expr* argv[]) { 164 const std::vector<std::unique_ptr<Expr>>& argv) {
165 std::string left; 165 std::string left;
166 if (!Evaluate(state, argv[0], &left)) { 166 if (!Evaluate(state, argv[0], &left)) {
167 return nullptr; 167 return nullptr;
@@ -174,7 +174,7 @@ Value* LogicalAndFn(const char* name, State* state,
174} 174}
175 175
176Value* LogicalOrFn(const char* name, State* state, 176Value* LogicalOrFn(const char* name, State* state,
177 int argc, Expr* argv[]) { 177 const std::vector<std::unique_ptr<Expr>>& argv) {
178 std::string left; 178 std::string left;
179 if (!Evaluate(state, argv[0], &left)) { 179 if (!Evaluate(state, argv[0], &left)) {
180 return nullptr; 180 return nullptr;
@@ -187,7 +187,7 @@ Value* LogicalOrFn(const char* name, State* state,
187} 187}
188 188
189Value* LogicalNotFn(const char* name, State* state, 189Value* LogicalNotFn(const char* name, State* state,
190 int argc, Expr* argv[]) { 190 const std::vector<std::unique_ptr<Expr>>& argv) {
191 std::string val; 191 std::string val;
192 if (!Evaluate(state, argv[0], &val)) { 192 if (!Evaluate(state, argv[0], &val)) {
193 return nullptr; 193 return nullptr;
@@ -197,7 +197,7 @@ Value* LogicalNotFn(const char* name, State* state,
197} 197}
198 198
199Value* SubstringFn(const char* name, State* state, 199Value* SubstringFn(const char* name, State* state,
200 int argc, Expr* argv[]) { 200 const std::vector<std::unique_ptr<Expr>>& argv) {
201 std::string needle; 201 std::string needle;
202 if (!Evaluate(state, argv[0], &needle)) { 202 if (!Evaluate(state, argv[0], &needle)) {
203 return nullptr; 203 return nullptr;
@@ -212,7 +212,7 @@ Value* SubstringFn(const char* name, State* state,
212 return StringValue(result); 212 return StringValue(result);
213} 213}
214 214
215Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { 215Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
216 std::string left; 216 std::string left;
217 if (!Evaluate(state, argv[0], &left)) { 217 if (!Evaluate(state, argv[0], &left)) {
218 return nullptr; 218 return nullptr;
@@ -226,7 +226,8 @@ Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
226 return StringValue(result); 226 return StringValue(result);
227} 227}
228 228
229Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { 229Value* InequalityFn(const char* name, State* state,
230 const std::vector<std::unique_ptr<Expr>>& argv) {
230 std::string left; 231 std::string left;
231 if (!Evaluate(state, argv[0], &left)) { 232 if (!Evaluate(state, argv[0], &left)) {
232 return nullptr; 233 return nullptr;
@@ -240,7 +241,7 @@ Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
240 return StringValue(result); 241 return StringValue(result);
241} 242}
242 243
243Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { 244Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
244 std::unique_ptr<Value> left(EvaluateValue(state, argv[0])); 245 std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
245 if (!left) { 246 if (!left) {
246 return nullptr; 247 return nullptr;
@@ -248,14 +249,15 @@ Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
248 return EvaluateValue(state, argv[1]); 249 return EvaluateValue(state, argv[1]);
249} 250}
250 251
251Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { 252Value* LessThanIntFn(const char* name, State* state,
252 if (argc != 2) { 253 const std::vector<std::unique_ptr<Expr>>& argv) {
254 if (argv.size() != 2) {
253 state->errmsg = "less_than_int expects 2 arguments"; 255 state->errmsg = "less_than_int expects 2 arguments";
254 return nullptr; 256 return nullptr;
255 } 257 }
256 258
257 std::vector<std::string> args; 259 std::vector<std::string> args;
258 if (!ReadArgs(state, 2, argv, &args)) { 260 if (!ReadArgs(state, argv, &args)) {
259 return nullptr; 261 return nullptr;
260 } 262 }
261 263
@@ -276,20 +278,34 @@ Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
276} 278}
277 279
278Value* GreaterThanIntFn(const char* name, State* state, 280Value* GreaterThanIntFn(const char* name, State* state,
279 int argc, Expr* argv[]) { 281 const std::vector<std::unique_ptr<Expr>>& argv) {
280 if (argc != 2) { 282 if (argv.size() != 2) {
281 state->errmsg = "greater_than_int expects 2 arguments"; 283 state->errmsg = "greater_than_int expects 2 arguments";
282 return nullptr; 284 return nullptr;
283 } 285 }
284 286
285 Expr* temp[2]; 287 std::vector<std::string> args;
286 temp[0] = argv[1]; 288 if (!ReadArgs(state, argv, &args)) {
287 temp[1] = argv[0]; 289 return nullptr;
290 }
291
292 // Parse up to at least long long or 64-bit integers.
293 int64_t l_int;
294 if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
295 state->errmsg = "failed to parse int in " + args[0];
296 return nullptr;
297 }
298
299 int64_t r_int;
300 if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
301 state->errmsg = "failed to parse int in " + args[1];
302 return nullptr;
303 }
288 304
289 return LessThanIntFn(name, state, 2, temp); 305 return StringValue(l_int > r_int ? "t" : "");
290} 306}
291 307
292Value* Literal(const char* name, State* state, int argc, Expr* argv[]) { 308Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
293 return StringValue(name); 309 return StringValue(name);
294} 310}
295 311
@@ -329,14 +345,22 @@ void RegisterBuiltins() {
329// convenience methods for functions 345// convenience methods for functions
330// ----------------------------------------------------------------- 346// -----------------------------------------------------------------
331 347
332// Evaluate the expressions in argv, and put the results of strings in 348// Evaluate the expressions in argv, and put the results of strings in args. If any expression
333// args. If any expression evaluates to nullptr, free the rest and return 349// evaluates to nullptr, return false. Return true on success.
334// false. Return true on success. 350bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
335bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args) { 351 std::vector<std::string>* args) {
352 return ReadArgs(state, argv, args, 0, argv.size());
353}
354
355bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
356 std::vector<std::string>* args, size_t start, size_t len) {
336 if (args == nullptr) { 357 if (args == nullptr) {
337 return false; 358 return false;
338 } 359 }
339 for (int i = 0; i < argc; ++i) { 360 if (len == 0 || start + len > argv.size()) {
361 return false;
362 }
363 for (size_t i = start; i < start + len; ++i) {
340 std::string var; 364 std::string var;
341 if (!Evaluate(state, argv[i], &var)) { 365 if (!Evaluate(state, argv[i], &var)) {
342 args->clear(); 366 args->clear();
@@ -347,15 +371,22 @@ bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* ar
347 return true; 371 return true;
348} 372}
349 373
350// Evaluate the expressions in argv, and put the results of Value* in 374// Evaluate the expressions in argv, and put the results of Value* in args. If any expression
351// args. If any expression evaluate to nullptr, free the rest and return 375// evaluate to nullptr, return false. Return true on success.
352// false. Return true on success. 376bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
353bool ReadValueArgs(State* state, int argc, Expr* argv[],
354 std::vector<std::unique_ptr<Value>>* args) { 377 std::vector<std::unique_ptr<Value>>* args) {
378 return ReadValueArgs(state, argv, args, 0, argv.size());
379}
380
381bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
382 std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) {
355 if (args == nullptr) { 383 if (args == nullptr) {
356 return false; 384 return false;
357 } 385 }
358 for (int i = 0; i < argc; ++i) { 386 if (len == 0 || start + len > argv.size()) {
387 return false;
388 }
389 for (size_t i = start; i < start + len; ++i) {
359 std::unique_ptr<Value> v(EvaluateValue(state, argv[i])); 390 std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
360 if (!v) { 391 if (!v) {
361 args->clear(); 392 args->clear();
diff --git a/edify/expr.h b/edify/expr.h
index 911adbc8..4838d20c 100644
--- a/edify/expr.h
+++ b/edify/expr.h
@@ -18,7 +18,10 @@
18#define _EXPRESSION_H 18#define _EXPRESSION_H
19 19
20#include <unistd.h> 20#include <unistd.h>
21
22#include <memory>
21#include <string> 23#include <string>
24#include <vector>
22 25
23#include "error_code.h" 26#include "error_code.h"
24 27
@@ -65,47 +68,49 @@ struct Value {
65 68
66struct Expr; 69struct Expr;
67 70
68using Function = Value* (*)(const char* name, State* state, int argc, Expr* argv[]); 71using Function = Value* (*)(const char* name, State* state,
72 const std::vector<std::unique_ptr<Expr>>& argv);
69 73
70struct Expr { 74struct Expr {
71 Function fn; 75 Function fn;
72 const char* name; 76 std::string name;
73 int argc; 77 std::vector<std::unique_ptr<Expr>> argv;
74 Expr** argv; 78 int start, end;
75 int start, end; 79
80 Expr(Function fn, const std::string& name, int start, int end) :
81 fn(fn),
82 name(name),
83 start(start),
84 end(end) {}
76}; 85};
77 86
78// Take one of the Expr*s passed to the function as an argument, 87// Evaluate the input expr, return the resulting Value.
79// evaluate it, return the resulting Value. The caller takes 88Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr);
80// ownership of the returned Value.
81Value* EvaluateValue(State* state, Expr* expr);
82 89
83// Take one of the Expr*s passed to the function as an argument, 90// Evaluate the input expr, assert that it is a string, and update the result parameter. This
84// evaluate it, assert that it is a string, and update the result 91// function returns true if the evaluation succeeds. This is a convenience function for older
85// parameter. This function returns true if the evaluation succeeds. 92// functions that want to deal only with strings.
86// This is a convenience function for older functions that want to 93bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result);
87// deal only with strings.
88bool Evaluate(State* state, Expr* expr, std::string* result);
89 94
90// Glue to make an Expr out of a literal. 95// Glue to make an Expr out of a literal.
91Value* Literal(const char* name, State* state, int argc, Expr* argv[]); 96Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
92 97
93// Functions corresponding to various syntactic sugar operators. 98// Functions corresponding to various syntactic sugar operators.
94// ("concat" is also available as a builtin function, to concatenate 99// ("concat" is also available as a builtin function, to concatenate
95// more than two strings.) 100// more than two strings.)
96Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]); 101Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
97Value* LogicalAndFn(const char* name, State* state, int argc, Expr* argv[]); 102Value* LogicalAndFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
98Value* LogicalOrFn(const char* name, State* state, int argc, Expr* argv[]); 103Value* LogicalOrFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
99Value* LogicalNotFn(const char* name, State* state, int argc, Expr* argv[]); 104Value* LogicalNotFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
100Value* SubstringFn(const char* name, State* state, int argc, Expr* argv[]); 105Value* SubstringFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
101Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]); 106Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
102Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]); 107Value* InequalityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
103Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]); 108Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
104 109
105// Global builtins, registered by RegisterBuiltins(). 110// Global builtins, registered by RegisterBuiltins().
106Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]); 111Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
107Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]); 112Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
108Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]); 113Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
109 114
110// Register a new function. The same Function may be registered under 115// Register a new function. The same Function may be registered under
111// multiple names, but a given name should only be used once. 116// multiple names, but a given name should only be used once.
@@ -120,15 +125,19 @@ Function FindFunction(const std::string& name);
120 125
121// --- convenience functions for use in functions --- 126// --- convenience functions for use in functions ---
122 127
123// Evaluate the expressions in argv, and put the results of strings in 128// Evaluate the expressions in argv, and put the results of strings in args. If any expression
124// args. If any expression evaluates to nullptr, free the rest and return 129// evaluates to nullptr, return false. Return true on success.
125// false. Return true on success. 130bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
126bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args); 131 std::vector<std::string>* args);
132bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
133 std::vector<std::string>* args, size_t start, size_t len);
127 134
128// Evaluate the expressions in argv, and put the results of Value* in 135// Evaluate the expressions in argv, and put the results of Value* in args. If any
129// args. If any expression evaluate to nullptr, free the rest and return 136// expression evaluate to nullptr, return false. Return true on success.
130// false. Return true on success. 137bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
131bool ReadValueArgs(State* state, int argc, Expr* argv[], std::vector<std::unique_ptr<Value>>* args); 138 std::vector<std::unique_ptr<Value>>* args);
139bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
140 std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len);
132 141
133// Use printf-style arguments to compose an error message to put into 142// Use printf-style arguments to compose an error message to put into
134// *state. Returns NULL. 143// *state. Returns NULL.
@@ -145,6 +154,6 @@ Value* StringValue(const char* str);
145 154
146Value* StringValue(const std::string& str); 155Value* StringValue(const std::string& str);
147 156
148int parse_string(const char* str, Expr** root, int* error_count); 157int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count);
149 158
150#endif // _EXPRESSION_H 159#endif // _EXPRESSION_H
diff --git a/edify/parser.yy b/edify/parser.yy
index 58a8dec6..97205fe3 100644
--- a/edify/parser.yy
+++ b/edify/parser.yy
@@ -19,6 +19,10 @@
19#include <stdlib.h> 19#include <stdlib.h>
20#include <string.h> 20#include <string.h>
21 21
22#include <memory>
23#include <string>
24#include <vector>
25
22#include "expr.h" 26#include "expr.h"
23#include "yydefs.h" 27#include "yydefs.h"
24#include "parser.h" 28#include "parser.h"
@@ -26,8 +30,8 @@
26extern int gLine; 30extern int gLine;
27extern int gColumn; 31extern int gColumn;
28 32
29void yyerror(Expr** root, int* error_count, const char* s); 33void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s);
30int yyparse(Expr** root, int* error_count); 34int yyparse(std::unique_ptr<Expr>* root, int* error_count);
31 35
32struct yy_buffer_state; 36struct yy_buffer_state;
33void yy_switch_to_buffer(struct yy_buffer_state* new_buffer); 37void yy_switch_to_buffer(struct yy_buffer_state* new_buffer);
@@ -38,17 +42,11 @@ struct yy_buffer_state* yy_scan_string(const char* yystr);
38static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { 42static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) {
39 va_list v; 43 va_list v;
40 va_start(v, count); 44 va_start(v, count);
41 Expr* e = static_cast<Expr*>(malloc(sizeof(Expr))); 45 Expr* e = new Expr(fn, "(operator)", loc.start, loc.end);
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) { 46 for (size_t i = 0; i < count; ++i) {
47 e->argv[i] = va_arg(v, Expr*); 47 e->argv.emplace_back(va_arg(v, Expr*));
48 } 48 }
49 va_end(v); 49 va_end(v);
50 e->start = loc.start;
51 e->end = loc.end;
52 return e; 50 return e;
53} 51}
54 52
@@ -59,10 +57,7 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) {
59%union { 57%union {
60 char* str; 58 char* str;
61 Expr* expr; 59 Expr* expr;
62 struct { 60 std::vector<std::unique_ptr<Expr>>* args;
63 int argc;
64 Expr** argv;
65 } args;
66} 61}
67 62
68%token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF 63%token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF
@@ -70,7 +65,10 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) {
70%type <expr> expr 65%type <expr> expr
71%type <args> arglist 66%type <args> arglist
72 67
73%parse-param {Expr** root} 68%destructor { delete $$; } expr
69%destructor { delete $$; } arglist
70
71%parse-param {std::unique_ptr<Expr>* root}
74%parse-param {int* error_count} 72%parse-param {int* error_count}
75%error-verbose 73%error-verbose
76 74
@@ -85,17 +83,11 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) {
85 83
86%% 84%%
87 85
88input: expr { *root = $1; } 86input: expr { root->reset($1); }
89; 87;
90 88
91expr: STRING { 89expr: STRING {
92 $$ = static_cast<Expr*>(malloc(sizeof(Expr))); 90 $$ = new Expr(Literal, $1, @$.start, @$.end);
93 $$->fn = Literal;
94 $$->name = $1;
95 $$->argc = 0;
96 $$->argv = NULL;
97 $$->start = @$.start;
98 $$->end = @$.end;
99} 91}
100| '(' expr ')' { $$ = $2; $$->start=@$.start; $$->end=@$.end; } 92| '(' expr ')' { $$ = $2; $$->start=@$.start; $$->end=@$.end; }
101| expr ';' { $$ = $1; $$->start=@1.start; $$->end=@1.end; } 93| expr ';' { $$ = $1; $$->start=@1.start; $$->end=@1.end; }
@@ -110,41 +102,32 @@ expr: STRING {
110| IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); } 102| IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); }
111| IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); } 103| IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); }
112| STRING '(' arglist ')' { 104| STRING '(' arglist ')' {
113 $$ = static_cast<Expr*>(malloc(sizeof(Expr))); 105 Function fn = FindFunction($1);
114 $$->fn = FindFunction($1); 106 if (fn == nullptr) {
115 if ($$->fn == nullptr) { 107 std::string msg = "unknown function \"" + std::string($1) + "\"";
116 char buffer[256]; 108 yyerror(root, error_count, msg.c_str());
117 snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1);
118 yyerror(root, error_count, buffer);
119 YYERROR; 109 YYERROR;
120 } 110 }
121 $$->name = $1; 111 $$ = new Expr(fn, $1, @$.start, @$.end);
122 $$->argc = $3.argc; 112 $$->argv = std::move(*$3);
123 $$->argv = $3.argv;
124 $$->start = @$.start;
125 $$->end = @$.end;
126} 113}
127; 114;
128 115
129arglist: /* empty */ { 116arglist: /* empty */ {
130 $$.argc = 0; 117 $$ = new std::vector<std::unique_ptr<Expr>>;
131 $$.argv = NULL;
132} 118}
133| expr { 119| expr {
134 $$.argc = 1; 120 $$ = new std::vector<std::unique_ptr<Expr>>;
135 $$.argv = static_cast<Expr**>(malloc(sizeof(Expr*))); 121 $$->emplace_back($1);
136 $$.argv[0] = $1;
137} 122}
138| arglist ',' expr { 123| arglist ',' expr {
139 $$.argc = $1.argc + 1; 124 $$->push_back(std::unique_ptr<Expr>($3));
140 $$.argv = static_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*)));
141 $$.argv[$$.argc-1] = $3;
142} 125}
143; 126;
144 127
145%% 128%%
146 129
147void yyerror(Expr** root, int* error_count, const char* s) { 130void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s) {
148 if (strlen(s) == 0) { 131 if (strlen(s) == 0) {
149 s = "syntax error"; 132 s = "syntax error";
150 } 133 }
@@ -152,7 +135,7 @@ void yyerror(Expr** root, int* error_count, const char* s) {
152 ++*error_count; 135 ++*error_count;
153} 136}
154 137
155int parse_string(const char* str, Expr** root, int* error_count) { 138int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count) {
156 yy_switch_to_buffer(yy_scan_string(str)); 139 yy_switch_to_buffer(yy_scan_string(str));
157 return yyparse(root, error_count); 140 return yyparse(root, error_count);
158} 141}