c4351c7910
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
218 lines
6.2 KiB
C
218 lines
6.2 KiB
C
/*
|
|
* Copyright (C) 2009 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "expr.h"
|
|
#include "parser.h"
|
|
|
|
extern int yyparse(Expr** root, int* error_count);
|
|
|
|
int expect(const char* expr_str, const char* expected, int* errors) {
|
|
Expr* e;
|
|
int error;
|
|
char* result;
|
|
|
|
printf(".");
|
|
|
|
yy_scan_string(expr_str);
|
|
int error_count = 0;
|
|
error = yyparse(&e, &error_count);
|
|
if (error > 0 || error_count > 0) {
|
|
fprintf(stderr, "error parsing \"%s\" (%d errors)\n",
|
|
expr_str, error_count);
|
|
++*errors;
|
|
return 0;
|
|
}
|
|
|
|
State state;
|
|
state.cookie = NULL;
|
|
state.script = strdup(expr_str);
|
|
state.errmsg = NULL;
|
|
|
|
result = Evaluate(&state, e);
|
|
free(state.errmsg);
|
|
free(state.script);
|
|
if (result == NULL && expected != NULL) {
|
|
fprintf(stderr, "error evaluating \"%s\"\n", expr_str);
|
|
++*errors;
|
|
return 0;
|
|
}
|
|
|
|
if (result == NULL && expected == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
if (strcmp(result, expected) != 0) {
|
|
fprintf(stderr, "evaluating \"%s\": expected \"%s\", got \"%s\"\n",
|
|
expr_str, expected, result);
|
|
++*errors;
|
|
free(result);
|
|
return 0;
|
|
}
|
|
|
|
free(result);
|
|
return 1;
|
|
}
|
|
|
|
int test() {
|
|
int errors = 0;
|
|
|
|
expect("a", "a", &errors);
|
|
expect("\"a\"", "a", &errors);
|
|
expect("\"\\x61\"", "a", &errors);
|
|
expect("# this is a comment\n"
|
|
" a\n"
|
|
" \n",
|
|
"a", &errors);
|
|
|
|
|
|
// sequence operator
|
|
expect("a; b; c", "c", &errors);
|
|
|
|
// string concat operator
|
|
expect("a + b", "ab", &errors);
|
|
expect("a + \n \"b\"", "ab", &errors);
|
|
expect("a + b +\nc\n", "abc", &errors);
|
|
|
|
// string concat function
|
|
expect("concat(a, b)", "ab", &errors);
|
|
expect("concat(a,\n \"b\")", "ab", &errors);
|
|
expect("concat(a + b,\nc,\"d\")", "abcd", &errors);
|
|
expect("\"concat\"(a + b,\nc,\"d\")", "abcd", &errors);
|
|
|
|
// logical and
|
|
expect("a && b", "b", &errors);
|
|
expect("a && \"\"", "", &errors);
|
|
expect("\"\" && b", "", &errors);
|
|
expect("\"\" && \"\"", "", &errors);
|
|
expect("\"\" && abort()", "", &errors); // test short-circuiting
|
|
expect("t && abort()", NULL, &errors);
|
|
|
|
// logical or
|
|
expect("a || b", "a", &errors);
|
|
expect("a || \"\"", "a", &errors);
|
|
expect("\"\" || b", "b", &errors);
|
|
expect("\"\" || \"\"", "", &errors);
|
|
expect("a || abort()", "a", &errors); // test short-circuiting
|
|
expect("\"\" || abort()", NULL, &errors);
|
|
|
|
// logical not
|
|
expect("!a", "", &errors);
|
|
expect("! \"\"", "t", &errors);
|
|
expect("!!a", "t", &errors);
|
|
|
|
// precedence
|
|
expect("\"\" == \"\" && b", "b", &errors);
|
|
expect("a + b == ab", "t", &errors);
|
|
expect("ab == a + b", "t", &errors);
|
|
expect("a + (b == ab)", "a", &errors);
|
|
expect("(ab == a) + b", "b", &errors);
|
|
|
|
// substring function
|
|
expect("is_substring(cad, abracadabra)", "t", &errors);
|
|
expect("is_substring(abrac, abracadabra)", "t", &errors);
|
|
expect("is_substring(dabra, abracadabra)", "t", &errors);
|
|
expect("is_substring(cad, abracxadabra)", "", &errors);
|
|
expect("is_substring(abrac, axbracadabra)", "", &errors);
|
|
expect("is_substring(dabra, abracadabrxa)", "", &errors);
|
|
|
|
// ifelse function
|
|
expect("ifelse(t, yes, no)", "yes", &errors);
|
|
expect("ifelse(!t, yes, no)", "no", &errors);
|
|
expect("ifelse(t, yes, abort())", "yes", &errors);
|
|
expect("ifelse(!t, abort(), no)", "no", &errors);
|
|
|
|
// if "statements"
|
|
expect("if t then yes else no endif", "yes", &errors);
|
|
expect("if \"\" then yes else no endif", "no", &errors);
|
|
expect("if \"\" then yes endif", "", &errors);
|
|
expect("if \"\"; t then yes endif", "yes", &errors);
|
|
|
|
// numeric comparisons
|
|
expect("less_than_int(3, 14)", "t", &errors);
|
|
expect("less_than_int(14, 3)", "", &errors);
|
|
expect("less_than_int(x, 3)", "", &errors);
|
|
expect("less_than_int(3, x)", "", &errors);
|
|
expect("greater_than_int(3, 14)", "", &errors);
|
|
expect("greater_than_int(14, 3)", "t", &errors);
|
|
expect("greater_than_int(x, 3)", "", &errors);
|
|
expect("greater_than_int(3, x)", "", &errors);
|
|
|
|
printf("\n");
|
|
|
|
return errors;
|
|
}
|
|
|
|
void ExprDump(int depth, Expr* n, char* script) {
|
|
printf("%*s", depth*2, "");
|
|
char temp = script[n->end];
|
|
script[n->end] = '\0';
|
|
printf("%s %p (%d-%d) \"%s\"\n",
|
|
n->name == NULL ? "(NULL)" : n->name, n->fn, n->start, n->end,
|
|
script+n->start);
|
|
script[n->end] = temp;
|
|
int i;
|
|
for (i = 0; i < n->argc; ++i) {
|
|
ExprDump(depth+1, n->argv[i], script);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
RegisterBuiltins();
|
|
FinishRegistration();
|
|
|
|
if (argc == 1) {
|
|
return test() != 0;
|
|
}
|
|
|
|
FILE* f = fopen(argv[1], "r");
|
|
if (f == NULL) {
|
|
printf("%s: %s: No such file or directory\n", argv[0], argv[1]);
|
|
return 1;
|
|
}
|
|
char buffer[8192];
|
|
int size = fread(buffer, 1, 8191, f);
|
|
fclose(f);
|
|
buffer[size] = '\0';
|
|
|
|
Expr* root;
|
|
int error_count = 0;
|
|
yy_scan_bytes(buffer, size);
|
|
int error = yyparse(&root, &error_count);
|
|
printf("parse returned %d; %d errors encountered\n", error, error_count);
|
|
if (error == 0 || error_count > 0) {
|
|
|
|
ExprDump(0, root, buffer);
|
|
|
|
State state;
|
|
state.cookie = NULL;
|
|
state.script = buffer;
|
|
state.errmsg = NULL;
|
|
|
|
char* result = Evaluate(&state, root);
|
|
if (result == NULL) {
|
|
printf("result was NULL, message is: %s\n",
|
|
(state.errmsg == NULL ? "(NULL)" : state.errmsg));
|
|
free(state.errmsg);
|
|
} else {
|
|
printf("result is [%s]\n", result);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|