1*acea8879SAndroid Build Coastguard Workeredify 2*acea8879SAndroid Build Coastguard Worker===== 3*acea8879SAndroid Build Coastguard Worker 4*acea8879SAndroid Build Coastguard WorkerUpdate scripts (from donut onwards) are written in a new little 5*acea8879SAndroid Build Coastguard Workerscripting language ("edify") that is superficially somewhat similar to 6*acea8879SAndroid Build Coastguard Workerthe old one ("amend"). This is a brief overview of the new language. 7*acea8879SAndroid Build Coastguard Worker 8*acea8879SAndroid Build Coastguard Worker- The entire script is a single expression. 9*acea8879SAndroid Build Coastguard Worker 10*acea8879SAndroid Build Coastguard Worker- All expressions are string-valued. 11*acea8879SAndroid Build Coastguard Worker 12*acea8879SAndroid Build Coastguard Worker- String literals appear in double quotes. \n, \t, \", and \\ are 13*acea8879SAndroid Build Coastguard Worker understood, as are hexadecimal escapes like \x4a. 14*acea8879SAndroid Build Coastguard Worker 15*acea8879SAndroid Build Coastguard Worker- String literals consisting of only letters, numbers, colons, 16*acea8879SAndroid Build Coastguard Worker underscores, slashes, and periods don't need to be in double quotes. 17*acea8879SAndroid Build Coastguard Worker 18*acea8879SAndroid Build Coastguard Worker- The following words are reserved: 19*acea8879SAndroid Build Coastguard Worker 20*acea8879SAndroid Build Coastguard Worker if then else endif 21*acea8879SAndroid Build Coastguard Worker 22*acea8879SAndroid Build Coastguard Worker They have special meaning when unquoted. (In quotes, they are just 23*acea8879SAndroid Build Coastguard Worker string literals.) 24*acea8879SAndroid Build Coastguard Worker 25*acea8879SAndroid Build Coastguard Worker- When used as a boolean, the empty string is "false" and all other 26*acea8879SAndroid Build Coastguard Worker strings are "true". 27*acea8879SAndroid Build Coastguard Worker 28*acea8879SAndroid Build Coastguard Worker- All functions are actually macros (in the Lisp sense); the body of 29*acea8879SAndroid Build Coastguard Worker the function can control which (if any) of the arguments are 30*acea8879SAndroid Build Coastguard Worker evaluated. This means that functions can act as control 31*acea8879SAndroid Build Coastguard Worker structures. 32*acea8879SAndroid Build Coastguard Worker 33*acea8879SAndroid Build Coastguard Worker- Operators (like "&&" and "||") are just syntactic sugar for builtin 34*acea8879SAndroid Build Coastguard Worker functions, so they can act as control structures as well. 35*acea8879SAndroid Build Coastguard Worker 36*acea8879SAndroid Build Coastguard Worker- ";" is a binary operator; evaluating it just means to first evaluate 37*acea8879SAndroid Build Coastguard Worker the left side, then the right. It can also appear after any 38*acea8879SAndroid Build Coastguard Worker expression. 39*acea8879SAndroid Build Coastguard Worker 40*acea8879SAndroid Build Coastguard Worker- Comments start with "#" and run to the end of the line. 41*acea8879SAndroid Build Coastguard Worker 42*acea8879SAndroid Build Coastguard Worker 43*acea8879SAndroid Build Coastguard Worker 44*acea8879SAndroid Build Coastguard WorkerSome examples: 45*acea8879SAndroid Build Coastguard Worker 46*acea8879SAndroid Build Coastguard Worker- There's no distinction between quoted and unquoted strings; the 47*acea8879SAndroid Build Coastguard Worker quotes are only needed if you want characters like whitespace to 48*acea8879SAndroid Build Coastguard Worker appear in the string. The following expressions all evaluate to the 49*acea8879SAndroid Build Coastguard Worker same string. 50*acea8879SAndroid Build Coastguard Worker 51*acea8879SAndroid Build Coastguard Worker "a b" 52*acea8879SAndroid Build Coastguard Worker a + " " + b 53*acea8879SAndroid Build Coastguard Worker "a" + " " + "b" 54*acea8879SAndroid Build Coastguard Worker "a\x20b" 55*acea8879SAndroid Build Coastguard Worker a + "\x20b" 56*acea8879SAndroid Build Coastguard Worker concat(a, " ", "b") 57*acea8879SAndroid Build Coastguard Worker "concat"(a, " ", "b") 58*acea8879SAndroid Build Coastguard Worker 59*acea8879SAndroid Build Coastguard Worker As shown in the last example, function names are just strings, 60*acea8879SAndroid Build Coastguard Worker too. They must be string *literals*, however. This is not legal: 61*acea8879SAndroid Build Coastguard Worker 62*acea8879SAndroid Build Coastguard Worker ("con" + "cat")(a, " ", b) # syntax error! 63*acea8879SAndroid Build Coastguard Worker 64*acea8879SAndroid Build Coastguard Worker 65*acea8879SAndroid Build Coastguard Worker- The ifelse() builtin takes three arguments: it evaluates exactly 66*acea8879SAndroid Build Coastguard Worker one of the second and third, depending on whether the first one is 67*acea8879SAndroid Build Coastguard Worker true. There is also some syntactic sugar to make expressions that 68*acea8879SAndroid Build Coastguard Worker look like if/else statements: 69*acea8879SAndroid Build Coastguard Worker 70*acea8879SAndroid Build Coastguard Worker # these are all equivalent 71*acea8879SAndroid Build Coastguard Worker ifelse(something(), "yes", "no") 72*acea8879SAndroid Build Coastguard Worker if something() then yes else no endif 73*acea8879SAndroid Build Coastguard Worker if something() then "yes" else "no" endif 74*acea8879SAndroid Build Coastguard Worker 75*acea8879SAndroid Build Coastguard Worker The else part is optional. 76*acea8879SAndroid Build Coastguard Worker 77*acea8879SAndroid Build Coastguard Worker if something() then "yes" endif # if something() is false, 78*acea8879SAndroid Build Coastguard Worker # evaluates to false 79*acea8879SAndroid Build Coastguard Worker 80*acea8879SAndroid Build Coastguard Worker ifelse(condition(), "", abort()) # abort() only called if 81*acea8879SAndroid Build Coastguard Worker # condition() is false 82*acea8879SAndroid Build Coastguard Worker 83*acea8879SAndroid Build Coastguard Worker The last example is equivalent to: 84*acea8879SAndroid Build Coastguard Worker 85*acea8879SAndroid Build Coastguard Worker assert(condition()) 86*acea8879SAndroid Build Coastguard Worker 87*acea8879SAndroid Build Coastguard Worker 88*acea8879SAndroid Build Coastguard Worker- The && and || operators can be used similarly; they evaluate their 89*acea8879SAndroid Build Coastguard Worker second argument only if it's needed to determine the truth of the 90*acea8879SAndroid Build Coastguard Worker expression. Their value is the value of the last-evaluated 91*acea8879SAndroid Build Coastguard Worker argument: 92*acea8879SAndroid Build Coastguard Worker 93*acea8879SAndroid Build Coastguard Worker file_exists("/data/system/bad") && delete("/data/system/bad") 94*acea8879SAndroid Build Coastguard Worker 95*acea8879SAndroid Build Coastguard Worker file_exists("/data/system/missing") || create("/data/system/missing") 96*acea8879SAndroid Build Coastguard Worker 97*acea8879SAndroid Build Coastguard Worker get_it() || "xxx" # returns value of get_it() if that value is 98*acea8879SAndroid Build Coastguard Worker # true, otherwise returns "xxx" 99*acea8879SAndroid Build Coastguard Worker 100*acea8879SAndroid Build Coastguard Worker 101*acea8879SAndroid Build Coastguard Worker- The purpose of ";" is to simulate imperative statements, of course, 102*acea8879SAndroid Build Coastguard Worker but the operator can be used anywhere. Its value is the value of 103*acea8879SAndroid Build Coastguard Worker its right side: 104*acea8879SAndroid Build Coastguard Worker 105*acea8879SAndroid Build Coastguard Worker concat(a;b;c, d, e;f) # evaluates to "cdf" 106*acea8879SAndroid Build Coastguard Worker 107*acea8879SAndroid Build Coastguard Worker A more useful example might be something like: 108*acea8879SAndroid Build Coastguard Worker 109*acea8879SAndroid Build Coastguard Worker ifelse(condition(), 110*acea8879SAndroid Build Coastguard Worker (first_step(); second_step();), # second ; is optional 111*acea8879SAndroid Build Coastguard Worker alternative_procedure()) 112