auto import from //depot/cupcake/@135843
diff --git a/amend/ast.c b/amend/ast.c
new file mode 100644
index 0000000..f53efdc
--- /dev/null
+++ b/amend/ast.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2007 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 "ast.h"
+
+static const char gSpaces[] =
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " ";
+const int gSpacesMax = sizeof(gSpaces) - 1;
+
+static const char *
+pad(int level)
+{
+ level *= 4;
+ if (level > gSpacesMax) {
+ level = gSpacesMax;
+ }
+ return gSpaces + gSpacesMax - level;
+}
+
+void dumpBooleanValue(int level, const AmBooleanValue *booleanValue);
+void dumpStringValue(int level, const AmStringValue *stringValue);
+
+void
+dumpBooleanExpression(int level, const AmBooleanExpression *booleanExpression)
+{
+ const char *op;
+ bool unary = false;
+
+ switch (booleanExpression->op) {
+ case AM_BOP_NOT:
+ op = "NOT";
+ unary = true;
+ break;
+ case AM_BOP_EQ:
+ op = "EQ";
+ break;
+ case AM_BOP_NE:
+ op = "NE";
+ break;
+ case AM_BOP_AND:
+ op = "AND";
+ break;
+ case AM_BOP_OR:
+ op = "OR";
+ break;
+ default:
+ op = "??";
+ break;
+ }
+
+ printf("%sBOOLEAN %s {\n", pad(level), op);
+ dumpBooleanValue(level + 1, booleanExpression->arg1);
+ if (!unary) {
+ dumpBooleanValue(level + 1, booleanExpression->arg2);
+ }
+ printf("%s}\n", pad(level));
+}
+
+void
+dumpFunctionArguments(int level, const AmFunctionArguments *functionArguments)
+{
+ int i;
+ for (i = 0; i < functionArguments->argc; i++) {
+ dumpStringValue(level, &functionArguments->argv[i]);
+ }
+}
+
+void
+dumpFunctionCall(int level, const AmFunctionCall *functionCall)
+{
+ printf("%sFUNCTION %s (\n", pad(level), functionCall->name);
+ dumpFunctionArguments(level + 1, functionCall->args);
+ printf("%s)\n", pad(level));
+}
+
+void
+dumpStringValue(int level, const AmStringValue *stringValue)
+{
+ switch (stringValue->type) {
+ case AM_SVAL_LITERAL:
+ printf("%s\"%s\"\n", pad(level), stringValue->u.literal);
+ break;
+ case AM_SVAL_FUNCTION:
+ dumpFunctionCall(level, stringValue->u.function);
+ break;
+ default:
+ printf("%s<UNKNOWN SVAL TYPE %d>\n", pad(level), stringValue->type);
+ break;
+ }
+}
+
+void
+dumpStringComparisonExpression(int level,
+ const AmStringComparisonExpression *stringComparisonExpression)
+{
+ const char *op;
+
+ switch (stringComparisonExpression->op) {
+ case AM_SOP_LT:
+ op = "LT";
+ break;
+ case AM_SOP_LE:
+ op = "LE";
+ break;
+ case AM_SOP_GT:
+ op = "GT";
+ break;
+ case AM_SOP_GE:
+ op = "GE";
+ break;
+ case AM_SOP_EQ:
+ op = "EQ";
+ break;
+ case AM_SOP_NE:
+ op = "NE";
+ break;
+ default:
+ op = "??";
+ break;
+ }
+ printf("%sSTRING %s {\n", pad(level), op);
+ dumpStringValue(level + 1, stringComparisonExpression->arg1);
+ dumpStringValue(level + 1, stringComparisonExpression->arg2);
+ printf("%s}\n", pad(level));
+}
+
+void
+dumpBooleanValue(int level, const AmBooleanValue *booleanValue)
+{
+ switch (booleanValue->type) {
+ case AM_BVAL_EXPRESSION:
+ dumpBooleanExpression(level, &booleanValue->u.expression);
+ break;
+ case AM_BVAL_STRING_COMPARISON:
+ dumpStringComparisonExpression(level,
+ &booleanValue->u.stringComparison);
+ break;
+ default:
+ printf("%s<UNKNOWN BVAL TYPE %d>\n", pad(1), booleanValue->type);
+ break;
+ }
+}
+
+void
+dumpWordList(const AmWordList *wordList)
+{
+ int i;
+ for (i = 0; i < wordList->argc; i++) {
+ printf("%s\"%s\"\n", pad(1), wordList->argv[i]);
+ }
+}
+
+void
+dumpCommandArguments(const AmCommandArguments *commandArguments)
+{
+ if (commandArguments->booleanArgs) {
+ dumpBooleanValue(1, commandArguments->u.b);
+ } else {
+ dumpWordList(commandArguments->u.w);
+ }
+}
+
+void
+dumpCommand(const AmCommand *command)
+{
+ printf("command \"%s\" {\n", command->name);
+ dumpCommandArguments(command->args);
+ printf("}\n");
+}
+
+void
+dumpCommandList(const AmCommandList *commandList)
+{
+ int i;
+ for (i = 0; i < commandList->commandCount; i++) {
+ dumpCommand(commandList->commands[i]);
+ }
+}