fixes to edify and updater script

A few more changes to edify:

  - fix write_raw_image(); my last change neglected to close the write
    context, so the written image was corrupt.

  - each expression tracks the span of the source code from which it
    was compiled, so that assert()'s error message can include the
    source of the expression that failed.

  - the 'cookie' argument to each Function is replaced with a State
    object, which contains the cookie, the source script (for use with
    the above spans), and the current error message (replacing the
    global variables that were used for this purpose).

  - in the recovery image, a new command "ui_print" can be sent back
    through the command pipe to cause text to appear on the screen.
    Add a new ui_print() function to print things from scripts.
    Rename existing "print" function to "stdout".
diff --git a/updater/updater.c b/updater/updater.c
index 0977625..5a2ed2c 100644
--- a/updater/updater.c
+++ b/updater/updater.c
@@ -94,12 +94,26 @@
     updater_info.cmd_pipe = cmd_pipe;
     updater_info.package_zip = &za;
 
-    char* result = Evaluate(&updater_info, root);
+    State state;
+    state.cookie = &updater_info;
+    state.script = script;
+    state.errmsg = NULL;
+
+    char* result = Evaluate(&state, root);
     if (result == NULL) {
-        const char* errmsg = GetError();
-        fprintf(stderr, "script aborted with error: %s\n",
-                errmsg == NULL ? "(none)" : errmsg);
-        ClearError();
+        if (state.errmsg == NULL) {
+            fprintf(stderr, "script aborted (no error message)\n");
+            fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
+        } else {
+            fprintf(stderr, "script aborted: %s\n", state.errmsg);
+            char* line = strtok(state.errmsg, "\n");
+            while (line) {
+                fprintf(cmd_pipe, "ui_print %s\n", line);
+                line = strtok(NULL, "\n");
+            }
+            fprintf(cmd_pipe, "ui_print\n");
+        }
+        free(state.errmsg);
         return 7;
     } else {
         fprintf(stderr, "script result was [%s]\n", result);
@@ -107,6 +121,7 @@
     }
 
     mzCloseZipArchive(&za);
+    free(script);
 
     return 0;
 }