From c444732540d5245b6219293e96d29f325daa7839 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Mon, 6 Mar 2017 14:44:59 -0800 Subject: 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 --- edify/edify_parser.cpp | 9 ++-- edify/expr.cpp | 119 +++++++++++++++++++++++++++++++------------------ edify/expr.h | 83 +++++++++++++++++++--------------- edify/parser.yy | 71 +++++++++++------------------ 4 files changed, 153 insertions(+), 129 deletions(-) (limited to 'edify') diff --git a/edify/edify_parser.cpp b/edify/edify_parser.cpp index 908fcf13b..f1b56284c 100644 --- a/edify/edify_parser.cpp +++ b/edify/edify_parser.cpp @@ -27,18 +27,19 @@ #include #include +#include #include #include #include "expr.h" -static void ExprDump(int depth, const Expr* n, const std::string& script) { +static void ExprDump(int depth, const std::unique_ptr& n, const std::string& script) { printf("%*s", depth*2, ""); printf("%s %p (%d-%d) \"%s\"\n", - n->name == NULL ? "(NULL)" : n->name, n->fn, n->start, n->end, + n->name.c_str(), n->fn, n->start, n->end, script.substr(n->start, n->end - n->start).c_str()); - for (int i = 0; i < n->argc; ++i) { + for (size_t i = 0; i < n->argv.size(); ++i) { ExprDump(depth+1, n->argv[i], script); } } @@ -57,7 +58,7 @@ int main(int argc, char** argv) { return 1; } - Expr* root; + std::unique_ptr root; int error_count = 0; int error = parse_string(buffer.data(), &root, &error_count); printf("parse returned %d; %d errors encountered\n", error, error_count); diff --git a/edify/expr.cpp b/edify/expr.cpp index 329cf3acd..2b7fd7a6a 100644 --- a/edify/expr.cpp +++ b/edify/expr.cpp @@ -40,12 +40,12 @@ static bool BooleanString(const std::string& s) { return !s.empty(); } -bool Evaluate(State* state, Expr* expr, std::string* result) { +bool Evaluate(State* state, const std::unique_ptr& expr, std::string* result) { if (result == nullptr) { return false; } - std::unique_ptr v(expr->fn(expr->name, state, expr->argc, expr->argv)); + std::unique_ptr v(expr->fn(expr->name.c_str(), state, expr->argv)); if (!v) { return false; } @@ -58,8 +58,8 @@ bool Evaluate(State* state, Expr* expr, std::string* result) { return true; } -Value* EvaluateValue(State* state, Expr* expr) { - return expr->fn(expr->name, state, expr->argc, expr->argv); +Value* EvaluateValue(State* state, const std::unique_ptr& expr) { + return expr->fn(expr->name.c_str(), state, expr->argv); } Value* StringValue(const char* str) { @@ -73,12 +73,12 @@ Value* StringValue(const std::string& str) { return StringValue(str.c_str()); } -Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc == 0) { +Value* ConcatFn(const char* name, State* state, const std::vector>& argv) { + if (argv.empty()) { return StringValue(""); } std::string result; - for (int i = 0; i < argc; ++i) { + for (size_t i = 0; i < argv.size(); ++i) { std::string str; if (!Evaluate(state, argv[i], &str)) { return nullptr; @@ -89,8 +89,8 @@ Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } -Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2 && argc != 3) { +Value* IfElseFn(const char* name, State* state, const std::vector>& argv) { + if (argv.size() != 2 && argv.size() != 3) { state->errmsg = "ifelse expects 2 or 3 arguments"; return nullptr; } @@ -102,16 +102,16 @@ Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { if (!cond.empty()) { return EvaluateValue(state, argv[1]); - } else if (argc == 3) { + } else if (argv.size() == 3) { return EvaluateValue(state, argv[2]); } return StringValue(""); } -Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* AbortFn(const char* name, State* state, const std::vector>& argv) { std::string msg; - if (argc > 0 && Evaluate(state, argv[0], &msg)) { + if (!argv.empty() && Evaluate(state, argv[0], &msg)) { state->errmsg = msg; } else { state->errmsg = "called abort()"; @@ -119,8 +119,8 @@ Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } -Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { - for (int i = 0; i < argc; ++i) { +Value* AssertFn(const char* name, State* state, const std::vector>& argv) { + for (size_t i = 0; i < argv.size(); ++i) { std::string result; if (!Evaluate(state, argv[i], &result)) { return nullptr; @@ -134,7 +134,7 @@ Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(""); } -Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* SleepFn(const char* name, State* state, const std::vector>& argv) { std::string val; if (!Evaluate(state, argv[0], &val)) { return nullptr; @@ -149,8 +149,8 @@ Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(val); } -Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { - for (int i = 0; i < argc; ++i) { +Value* StdoutFn(const char* name, State* state, const std::vector>& argv) { + for (size_t i = 0; i < argv.size(); ++i) { std::string v; if (!Evaluate(state, argv[i], &v)) { return nullptr; @@ -161,7 +161,7 @@ Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { } Value* LogicalAndFn(const char* name, State* state, - int argc, Expr* argv[]) { + const std::vector>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; @@ -174,7 +174,7 @@ Value* LogicalAndFn(const char* name, State* state, } Value* LogicalOrFn(const char* name, State* state, - int argc, Expr* argv[]) { + const std::vector>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; @@ -187,7 +187,7 @@ Value* LogicalOrFn(const char* name, State* state, } Value* LogicalNotFn(const char* name, State* state, - int argc, Expr* argv[]) { + const std::vector>& argv) { std::string val; if (!Evaluate(state, argv[0], &val)) { return nullptr; @@ -197,7 +197,7 @@ Value* LogicalNotFn(const char* name, State* state, } Value* SubstringFn(const char* name, State* state, - int argc, Expr* argv[]) { + const std::vector>& argv) { std::string needle; if (!Evaluate(state, argv[0], &needle)) { return nullptr; @@ -212,7 +212,7 @@ Value* SubstringFn(const char* name, State* state, return StringValue(result); } -Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* EqualityFn(const char* name, State* state, const std::vector>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; @@ -226,7 +226,8 @@ Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } -Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* InequalityFn(const char* name, State* state, + const std::vector>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; @@ -240,7 +241,7 @@ Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } -Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* SequenceFn(const char* name, State* state, const std::vector>& argv) { std::unique_ptr left(EvaluateValue(state, argv[0])); if (!left) { return nullptr; @@ -248,14 +249,15 @@ Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { return EvaluateValue(state, argv[1]); } -Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { +Value* LessThanIntFn(const char* name, State* state, + const std::vector>& argv) { + if (argv.size() != 2) { state->errmsg = "less_than_int expects 2 arguments"; return nullptr; } std::vector args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return nullptr; } @@ -276,20 +278,34 @@ Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { } Value* GreaterThanIntFn(const char* name, State* state, - int argc, Expr* argv[]) { - if (argc != 2) { + const std::vector>& argv) { + if (argv.size() != 2) { state->errmsg = "greater_than_int expects 2 arguments"; return nullptr; } - Expr* temp[2]; - temp[0] = argv[1]; - temp[1] = argv[0]; + std::vector args; + if (!ReadArgs(state, argv, &args)) { + return nullptr; + } + + // Parse up to at least long long or 64-bit integers. + int64_t l_int; + if (!android::base::ParseInt(args[0].c_str(), &l_int)) { + state->errmsg = "failed to parse int in " + args[0]; + return nullptr; + } + + int64_t r_int; + if (!android::base::ParseInt(args[1].c_str(), &r_int)) { + state->errmsg = "failed to parse int in " + args[1]; + return nullptr; + } - return LessThanIntFn(name, state, 2, temp); + return StringValue(l_int > r_int ? "t" : ""); } -Value* Literal(const char* name, State* state, int argc, Expr* argv[]) { +Value* Literal(const char* name, State* state, const std::vector>& argv) { return StringValue(name); } @@ -329,14 +345,22 @@ void RegisterBuiltins() { // convenience methods for functions // ----------------------------------------------------------------- -// Evaluate the expressions in argv, and put the results of strings in -// args. If any expression evaluates to nullptr, free the rest and return -// false. Return true on success. -bool ReadArgs(State* state, int argc, Expr* argv[], std::vector* args) { +// Evaluate the expressions in argv, and put the results of strings in args. If any expression +// evaluates to nullptr, return false. Return true on success. +bool ReadArgs(State* state, const std::vector>& argv, + std::vector* args) { + return ReadArgs(state, argv, args, 0, argv.size()); +} + +bool ReadArgs(State* state, const std::vector>& argv, + std::vector* args, size_t start, size_t len) { if (args == nullptr) { return false; } - for (int i = 0; i < argc; ++i) { + if (len == 0 || start + len > argv.size()) { + return false; + } + for (size_t i = start; i < start + len; ++i) { std::string var; if (!Evaluate(state, argv[i], &var)) { args->clear(); @@ -347,15 +371,22 @@ bool ReadArgs(State* state, int argc, Expr* argv[], std::vector* ar return true; } -// Evaluate the expressions in argv, and put the results of Value* in -// args. If any expression evaluate to nullptr, free the rest and return -// false. Return true on success. -bool ReadValueArgs(State* state, int argc, Expr* argv[], +// Evaluate the expressions in argv, and put the results of Value* in args. If any expression +// evaluate to nullptr, return false. Return true on success. +bool ReadValueArgs(State* state, const std::vector>& argv, std::vector>* args) { + return ReadValueArgs(state, argv, args, 0, argv.size()); +} + +bool ReadValueArgs(State* state, const std::vector>& argv, + std::vector>* args, size_t start, size_t len) { if (args == nullptr) { return false; } - for (int i = 0; i < argc; ++i) { + if (len == 0 || start + len > argv.size()) { + return false; + } + for (size_t i = start; i < start + len; ++i) { std::unique_ptr v(EvaluateValue(state, argv[i])); if (!v) { args->clear(); diff --git a/edify/expr.h b/edify/expr.h index 911adbc82..4838d20c0 100644 --- a/edify/expr.h +++ b/edify/expr.h @@ -18,7 +18,10 @@ #define _EXPRESSION_H #include + +#include #include +#include #include "error_code.h" @@ -65,47 +68,49 @@ struct Value { struct Expr; -using Function = Value* (*)(const char* name, State* state, int argc, Expr* argv[]); +using Function = Value* (*)(const char* name, State* state, + const std::vector>& argv); struct Expr { - Function fn; - const char* name; - int argc; - Expr** argv; - int start, end; + Function fn; + std::string name; + std::vector> argv; + int start, end; + + Expr(Function fn, const std::string& name, int start, int end) : + fn(fn), + name(name), + start(start), + end(end) {} }; -// Take one of the Expr*s passed to the function as an argument, -// evaluate it, return the resulting Value. The caller takes -// ownership of the returned Value. -Value* EvaluateValue(State* state, Expr* expr); +// Evaluate the input expr, return the resulting Value. +Value* EvaluateValue(State* state, const std::unique_ptr& expr); -// Take one of the Expr*s passed to the function as an argument, -// evaluate it, assert that it is a string, and update the result -// parameter. This function returns true if the evaluation succeeds. -// This is a convenience function for older functions that want to -// deal only with strings. -bool Evaluate(State* state, Expr* expr, std::string* result); +// Evaluate the input expr, assert that it is a string, and update the result parameter. This +// function returns true if the evaluation succeeds. This is a convenience function for older +// functions that want to deal only with strings. +bool Evaluate(State* state, const std::unique_ptr& expr, std::string* result); // Glue to make an Expr out of a literal. -Value* Literal(const char* name, State* state, int argc, Expr* argv[]); +Value* Literal(const char* name, State* state, const std::vector>& argv); // Functions corresponding to various syntactic sugar operators. // ("concat" is also available as a builtin function, to concatenate // more than two strings.) -Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]); -Value* LogicalAndFn(const char* name, State* state, int argc, Expr* argv[]); -Value* LogicalOrFn(const char* name, State* state, int argc, Expr* argv[]); -Value* LogicalNotFn(const char* name, State* state, int argc, Expr* argv[]); -Value* SubstringFn(const char* name, State* state, int argc, Expr* argv[]); -Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]); -Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]); -Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]); +Value* ConcatFn(const char* name, State* state, const std::vector>& argv); +Value* LogicalAndFn(const char* name, State* state, const std::vector>& argv); +Value* LogicalOrFn(const char* name, State* state, const std::vector>& argv); +Value* LogicalNotFn(const char* name, State* state, const std::vector>& argv); +Value* SubstringFn(const char* name, State* state, const std::vector>& argv); +Value* EqualityFn(const char* name, State* state, const std::vector>& argv); +Value* InequalityFn(const char* name, State* state, const std::vector>& argv); +Value* SequenceFn(const char* name, State* state, const std::vector>& argv); // Global builtins, registered by RegisterBuiltins(). -Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]); -Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]); -Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]); +Value* IfElseFn(const char* name, State* state, const std::vector>& argv); +Value* AssertFn(const char* name, State* state, const std::vector>& argv); +Value* AbortFn(const char* name, State* state, const std::vector>& argv); // Register a new function. The same Function may be registered under // multiple names, but a given name should only be used once. @@ -120,15 +125,19 @@ Function FindFunction(const std::string& name); // --- convenience functions for use in functions --- -// Evaluate the expressions in argv, and put the results of strings in -// args. If any expression evaluates to nullptr, free the rest and return -// false. Return true on success. -bool ReadArgs(State* state, int argc, Expr* argv[], std::vector* args); +// Evaluate the expressions in argv, and put the results of strings in args. If any expression +// evaluates to nullptr, return false. Return true on success. +bool ReadArgs(State* state, const std::vector>& argv, + std::vector* args); +bool ReadArgs(State* state, const std::vector>& argv, + std::vector* args, size_t start, size_t len); -// Evaluate the expressions in argv, and put the results of Value* in -// args. If any expression evaluate to nullptr, free the rest and return -// false. Return true on success. -bool ReadValueArgs(State* state, int argc, Expr* argv[], std::vector>* args); +// Evaluate the expressions in argv, and put the results of Value* in args. If any +// expression evaluate to nullptr, return false. Return true on success. +bool ReadValueArgs(State* state, const std::vector>& argv, + std::vector>* args); +bool ReadValueArgs(State* state, const std::vector>& argv, + std::vector>* args, size_t start, size_t len); // Use printf-style arguments to compose an error message to put into // *state. Returns NULL. @@ -145,6 +154,6 @@ Value* StringValue(const char* str); Value* StringValue(const std::string& str); -int parse_string(const char* str, Expr** root, int* error_count); +int parse_string(const char* str, std::unique_ptr* root, int* error_count); #endif // _EXPRESSION_H diff --git a/edify/parser.yy b/edify/parser.yy index 58a8dec65..97205fe3b 100644 --- a/edify/parser.yy +++ b/edify/parser.yy @@ -19,6 +19,10 @@ #include #include +#include +#include +#include + #include "expr.h" #include "yydefs.h" #include "parser.h" @@ -26,8 +30,8 @@ extern int gLine; extern int gColumn; -void yyerror(Expr** root, int* error_count, const char* s); -int yyparse(Expr** root, int* error_count); +void yyerror(std::unique_ptr* root, int* error_count, const char* s); +int yyparse(std::unique_ptr* root, int* error_count); struct yy_buffer_state; void yy_switch_to_buffer(struct yy_buffer_state* new_buffer); @@ -38,17 +42,11 @@ struct yy_buffer_state* yy_scan_string(const char* yystr); static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { va_list v; va_start(v, count); - Expr* e = static_cast(malloc(sizeof(Expr))); - e->fn = fn; - e->name = "(operator)"; - e->argc = count; - e->argv = static_cast(malloc(count * sizeof(Expr*))); + Expr* e = new Expr(fn, "(operator)", loc.start, loc.end); for (size_t i = 0; i < count; ++i) { - e->argv[i] = va_arg(v, Expr*); + e->argv.emplace_back(va_arg(v, Expr*)); } va_end(v); - e->start = loc.start; - e->end = loc.end; return e; } @@ -59,10 +57,7 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %union { char* str; Expr* expr; - struct { - int argc; - Expr** argv; - } args; + std::vector>* args; } %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, ...) { %type expr %type arglist -%parse-param {Expr** root} +%destructor { delete $$; } expr +%destructor { delete $$; } arglist + +%parse-param {std::unique_ptr* root} %parse-param {int* error_count} %error-verbose @@ -85,17 +83,11 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %% -input: expr { *root = $1; } +input: expr { root->reset($1); } ; expr: STRING { - $$ = static_cast(malloc(sizeof(Expr))); - $$->fn = Literal; - $$->name = $1; - $$->argc = 0; - $$->argv = NULL; - $$->start = @$.start; - $$->end = @$.end; + $$ = new Expr(Literal, $1, @$.start, @$.end); } | '(' expr ')' { $$ = $2; $$->start=@$.start; $$->end=@$.end; } | expr ';' { $$ = $1; $$->start=@1.start; $$->end=@1.end; } @@ -110,41 +102,32 @@ expr: STRING { | IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); } | IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); } | STRING '(' arglist ')' { - $$ = static_cast(malloc(sizeof(Expr))); - $$->fn = FindFunction($1); - if ($$->fn == nullptr) { - char buffer[256]; - snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1); - yyerror(root, error_count, buffer); + Function fn = FindFunction($1); + if (fn == nullptr) { + std::string msg = "unknown function \"" + std::string($1) + "\""; + yyerror(root, error_count, msg.c_str()); YYERROR; } - $$->name = $1; - $$->argc = $3.argc; - $$->argv = $3.argv; - $$->start = @$.start; - $$->end = @$.end; + $$ = new Expr(fn, $1, @$.start, @$.end); + $$->argv = std::move(*$3); } ; arglist: /* empty */ { - $$.argc = 0; - $$.argv = NULL; + $$ = new std::vector>; } | expr { - $$.argc = 1; - $$.argv = static_cast(malloc(sizeof(Expr*))); - $$.argv[0] = $1; + $$ = new std::vector>; + $$->emplace_back($1); } | arglist ',' expr { - $$.argc = $1.argc + 1; - $$.argv = static_cast(realloc($$.argv, $$.argc * sizeof(Expr*))); - $$.argv[$$.argc-1] = $3; + $$->push_back(std::unique_ptr($3)); } ; %% -void yyerror(Expr** root, int* error_count, const char* s) { +void yyerror(std::unique_ptr* root, int* error_count, const char* s) { if (strlen(s) == 0) { s = "syntax error"; } @@ -152,7 +135,7 @@ void yyerror(Expr** root, int* error_count, const char* s) { ++*error_count; } -int parse_string(const char* str, Expr** root, int* error_count) { +int parse_string(const char* str, std::unique_ptr* root, int* error_count) { yy_switch_to_buffer(yy_scan_string(str)); return yyparse(root, error_count); } -- cgit v1.2.3