From 9931f7f3c1288171319e9ff7d053ebaad07db720 Mon Sep 17 00:00:00 2001 From: Doug Zongker Date: Wed, 10 Jun 2009 14:11:53 -0700 Subject: edify extensions for OTA package installation, part 1 Adds the following edify functions: mount unmount format show_progress delete delete_recursive package_extract symlink set_perm set_perm_recursive This set is enough to extract and install the system part of a (full) OTA package. Adds the updater binary that extracts an edify script from the OTA package and then executes it. Minor changes to the edify core (adds a sleep() builtin for debugging, adds "." to the set of characters that can appear in an unquoted string). --- edify/Android.mk | 17 +++++----- edify/README | 2 +- edify/expr.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ edify/expr.h | 23 ++++++++++++++ edify/lexer.l | 2 +- edify/main.c | 9 +++++- 6 files changed, 136 insertions(+), 12 deletions(-) (limited to 'edify') diff --git a/edify/Android.mk b/edify/Android.mk index 803fba207..fac0ba712 100644 --- a/edify/Android.mk +++ b/edify/Android.mk @@ -26,15 +26,14 @@ LOCAL_YACCFLAGS := -v include $(BUILD_HOST_EXECUTABLE) -# # -# # Build the device-side library -# # -# include $(CLEAR_VARS) +# +# Build the device-side library +# +include $(CLEAR_VARS) -# LOCAL_SRC_FILES := $(edify_src_files) -# LOCAL_SRC_FILES += $(edify_test_files) +LOCAL_SRC_FILES := $(edify_src_files) -# LOCAL_CFLAGS := $(edify_cflags) -# LOCAL_MODULE := libedify +LOCAL_CFLAGS := $(edify_cflags) +LOCAL_MODULE := libedify -# include $(BUILD_STATIC_LIBRARY) +include $(BUILD_STATIC_LIBRARY) diff --git a/edify/README b/edify/README index 5ccb582e8..810455cca 100644 --- a/edify/README +++ b/edify/README @@ -10,7 +10,7 @@ the old one ("amend"). This is a brief overview of the new language. understood, as are hexadecimal escapes like \x4a. - String literals consisting of only letters, numbers, colons, - underscores, and slashes don't need to be in double quotes. + underscores, slashes, and periods don't need to be in double quotes. - The following words are reserved: diff --git a/edify/expr.c b/edify/expr.c index b3b892711..129fbd96b 100644 --- a/edify/expr.c +++ b/edify/expr.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "expr.h" @@ -92,6 +93,12 @@ char* IfElseFn(const char* name, void* cookie, int argc, Expr* argv[]) { } char* AbortFn(const char* name, void* cookie, int argc, Expr* argv[]) { + char* msg = NULL; + if (argc > 0) { + msg = Evaluate(cookie, argv[0]); + } + SetError(msg == NULL ? "called abort()" : msg); + free(msg); return NULL; } @@ -105,12 +112,23 @@ char* AssertFn(const char* name, void* cookie, int argc, Expr* argv[]) { int b = BooleanString(v); free(v); if (!b) { + SetError("assert() failed"); return NULL; } } return strdup(""); } +char* SleepFn(const char* name, void* cookie, int argc, Expr* argv[]) { + char* val = Evaluate(cookie, argv[0]); + if (val == NULL) { + return NULL; + } + int v = strtol(val, NULL, 10); + sleep(v); + return val; +} + char* PrintFn(const char* name, void* cookie, int argc, Expr* argv[]) { int i; for (i = 0; i < argc; ++i) { @@ -234,6 +252,32 @@ Expr* Build(Function fn, int count, ...) { return e; } +// ----------------------------------------------------------------- +// error reporting +// ----------------------------------------------------------------- + +static char* error_message = NULL; + +void SetError(const char* message) { + if (error_message) { + free(error_message); + } + error_message = strdup(message); +} + +const char* GetError() { + return error_message; +} + +void ClearError() { + free(error_message); + error_message = NULL; +} + +// ----------------------------------------------------------------- +// the function table +// ----------------------------------------------------------------- + static int fn_entries = 0; static int fn_size = 0; NamedFunction* fn_table = NULL; @@ -276,4 +320,55 @@ void RegisterBuiltins() { RegisterFunction("concat", ConcatFn); RegisterFunction("is_substring", SubstringFn); RegisterFunction("print", PrintFn); + RegisterFunction("sleep", SleepFn); +} + + +// ----------------------------------------------------------------- +// convenience methods for functions +// ----------------------------------------------------------------- + +// Evaluate the expressions in argv, giving 'count' char* (the ... is +// zero or more char** to put them in). If any expression evaluates +// to NULL, free the rest and return -1. Return 0 on success. +int ReadArgs(void* cookie, Expr* argv[], int count, ...) { + char** args = malloc(count * sizeof(char*)); + va_list v; + va_start(v, count); + int i; + for (i = 0; i < count; ++i) { + args[i] = Evaluate(cookie, argv[i]); + if (args[i] == NULL) { + va_end(v); + int j; + for (j = 0; j < i; ++j) { + free(args[j]); + } + return -1; + } + *(va_arg(v, char**)) = args[i]; + } + va_end(v); + return 0; +} + +// Evaluate the expressions in argv, returning an array of char* +// results. If any evaluate to NULL, free the rest and return NULL. +// The caller is responsible for freeing the returned array and the +// strings it contains. +char** ReadVarArgs(void* cookie, int argc, Expr* argv[]) { + char** args = (char**)malloc(argc * sizeof(char*)); + int i = 0; + for (i = 0; i < argc; ++i) { + args[i] = Evaluate(cookie, argv[i]); + if (args[i] == NULL) { + int j; + for (j = 0; j < i; ++j) { + free(args[j]); + } + free(args); + return NULL; + } + } + return args; } diff --git a/edify/expr.h b/edify/expr.h index ac5df1869..cfbef903b 100644 --- a/edify/expr.h +++ b/edify/expr.h @@ -57,6 +57,14 @@ char* IfElseFn(const char* name, void* cookie, int argc, Expr* argv[]); char* AssertFn(const char* name, void* cookie, int argc, Expr* argv[]); char* AbortFn(const char* name, void* cookie, int argc, Expr* argv[]); + +// For setting and getting the global error string (when returning +// NULL from a function). +void SetError(const char* message); // makes a copy +const char* GetError(); // retains ownership +void ClearError(); + + typedef struct { const char* name; Function fn; @@ -77,4 +85,19 @@ void FinishRegistration(); // exists. Function FindFunction(const char* name); + +// --- convenience functions for use in functions --- + +// Evaluate the expressions in argv, giving 'count' char* (the ... is +// zero or more char** to put them in). If any expression evaluates +// to NULL, free the rest and return -1. Return 0 on success. +int ReadArgs(void* cookie, Expr* argv[], int count, ...); + +// Evaluate the expressions in argv, returning an array of char* +// results. If any evaluate to NULL, free the rest and return NULL. +// The caller is responsible for freeing the returned array and the +// strings it contains. +char** ReadVarArgs(void* cookie, int argc, Expr* argv[]); + + #endif // _EXPRESSION_H diff --git a/edify/lexer.l b/edify/lexer.l index 4faef5da0..cb5eb318a 100644 --- a/edify/lexer.l +++ b/edify/lexer.l @@ -77,7 +77,7 @@ then { gColumn += yyleng; return THEN; } else { gColumn += yyleng; return ELSE; } endif { gColumn += yyleng; return ENDIF; } -[a-zA-Z0-9_:/]+ { +[a-zA-Z0-9_:/.]+ { gColumn += yyleng; yylval.str = strdup(yytext); return STRING; diff --git a/edify/main.c b/edify/main.c index 4d65da2d8..c95968376 100644 --- a/edify/main.c +++ b/edify/main.c @@ -158,7 +158,14 @@ int main(int argc, char** argv) { printf("parse returned %d\n", error); if (error == 0) { char* result = Evaluate(NULL, root); - printf("result is [%s]\n", result == NULL ? "(NULL)" : result); + if (result == NULL) { + char* errmsg = GetError(); + printf("result was NULL, message is: %s\n", + (errmsg == NULL ? "(NULL)" : errmsg)); + ClearError(); + } else { + printf("result is [%s]\n", result); + } } return 0; } -- cgit v1.2.3