android_bootable_recovery/edify
Doug Zongker c4351c7910 refactor applypatch and friends
Change the applypatch function to take meaningful arguments instead of
argc and argv.  Move all the parsing of arguments into main.c (for the
standalone binary) and into install.c (for the updater function).
applypatch() takes patches as Value objects, so we can pass in blobs
extracted from the package without ever writing them to temp files.

The patching code is changed to read the patch from memory instead of
a file.

A bunch of compiler warnings (mostly about signed vs unsigned types)
are fixed.

Support for the IMGDIFF1 format is dropped.  (We've been generating
IMGDIFF2 packages for some time now.)

Change-Id: I217563c500012750f27110db821928a06211323f
2010-02-22 15:30:33 -08:00
..
Android.mk edify extensions for OTA package installation, part 1 2009-06-11 16:25:29 -07:00
expr.c relocate applypatch; add type system and new functions to edify 2010-02-18 14:22:12 -08:00
expr.h add missing includes to fix mac build (maybe) 2010-02-19 16:07:57 -08:00
lexer.l add missing includes to fix mac build (maybe) 2010-02-19 16:07:57 -08:00
main.c refactor applypatch and friends 2010-02-22 15:30:33 -08:00
parser.y fixes to edify and updater script 2009-06-12 14:05:03 -07:00
README edify extensions for OTA package installation, part 1 2009-06-11 16:25:29 -07:00
yydefs.h refactor applypatch and friends 2010-02-22 15:30:33 -08:00

Update scripts (from donut onwards) are written in a new little
scripting language ("edify") that is superficially somewhat similar to
the old one ("amend").  This is a brief overview of the new language.

- The entire script is a single expression.

- All expressions are string-valued.

- String literals appear in double quotes.  \n, \t, \", and \\ are
  understood, as are hexadecimal escapes like \x4a.

- String literals consisting of only letters, numbers, colons,
  underscores, slashes, and periods don't need to be in double quotes.

- The following words are reserved:

       if    then    else   endif

  They have special meaning when unquoted.  (In quotes, they are just
  string literals.)

- When used as a boolean, the empty string is "false" and all other
  strings are "true".

- All functions are actually macros (in the Lisp sense); the body of
  the function can control which (if any) of the arguments are
  evaluated.  This means that functions can act as control
  structures.

- Operators (like "&&" and "||") are just syntactic sugar for builtin
  functions, so they can act as control structures as well.

- ";" is a binary operator; evaluating it just means to first evaluate
  the left side, then the right.  It can also appear after any
  expression.

- Comments start with "#" and run to the end of the line.



Some examples:

- There's no distinction between quoted and unquoted strings; the
  quotes are only needed if you want characters like whitespace to
  appear in the string.  The following expressions all evaluate to the
  same string.

     "a b"
     a + " " + b
     "a" + " " + "b"
     "a\x20b"
     a + "\x20b"
     concat(a, " ", "b")
     "concat"(a, " ", "b")

  As shown in the last example, function names are just strings,
  too.  They must be string *literals*, however.  This is not legal:

     ("con" + "cat")(a, " ", b)         # syntax error!


- The ifelse() builtin takes three arguments:  it evaluates exactly
  one of the second and third, depending on whether the first one is
  true.  There is also some syntactic sugar to make expressions that
  look like if/else statements:

     # these are all equivalent
     ifelse(something(), "yes", "no")
     if something() then yes else no endif
     if something() then "yes" else "no" endif

  The else part is optional.

     if something() then "yes" endif    # if something() is false,
                                        # evaluates to false

     ifelse(condition(), "", abort())   # abort() only called if
                                        # condition() is false

  The last example is equivalent to:

     assert(condition())


- The && and || operators can be used similarly; they evaluate their
  second argument only if it's needed to determine the truth of the
  expression.  Their value is the value of the last-evaluated
  argument:

     file_exists("/data/system/bad") && delete("/data/system/bad")

     file_exists("/data/system/missing") || create("/data/system/missing")

     get_it() || "xxx"     # returns value of get_it() if that value is
                           # true, otherwise returns "xxx"


- The purpose of ";" is to simulate imperative statements, of course,
  but the operator can be used anywhere.  Its value is the value of
  its right side:

     concat(a;b;c, d, e;f)     # evaluates to "cdf"

  A more useful example might be something like:

     ifelse(condition(),
            (first_step(); second_step();),   # second ; is optional
            alternative_procedure())