summaryrefslogtreecommitdiffstats
path: root/amend/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'amend/commands.c')
-rw-r--r--amend/commands.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/amend/commands.c b/amend/commands.c
new file mode 100644
index 000000000..75ff82840
--- /dev/null
+++ b/amend/commands.c
@@ -0,0 +1,273 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "symtab.h"
+#include "commands.h"
+
+#if 1
+#define TRACE(...) printf(__VA_ARGS__)
+#else
+#define TRACE(...) /**/
+#endif
+
+typedef enum {
+ CMD_TYPE_UNKNOWN = -1,
+ CMD_TYPE_COMMAND = 0,
+ CMD_TYPE_FUNCTION
+} CommandType;
+
+typedef struct {
+ const char *name;
+ void *cookie;
+ CommandType type;
+ CommandArgumentType argType;
+ CommandHook hook;
+} CommandEntry;
+
+static struct {
+ SymbolTable *symbolTable;
+ bool commandStateInitialized;
+} gCommandState;
+
+int
+commandInit()
+{
+ if (gCommandState.commandStateInitialized) {
+ return -1;
+ }
+ gCommandState.symbolTable = createSymbolTable();
+ if (gCommandState.symbolTable == NULL) {
+ return -1;
+ }
+ gCommandState.commandStateInitialized = true;
+ return 0;
+}
+
+void
+commandCleanup()
+{
+ if (gCommandState.commandStateInitialized) {
+ gCommandState.commandStateInitialized = false;
+ deleteSymbolTable(gCommandState.symbolTable);
+ gCommandState.symbolTable = NULL;
+//xxx need to free the entries and names in the symbol table
+ }
+}
+
+static int
+registerCommandInternal(const char *name, CommandType type,
+ CommandArgumentType argType, CommandHook hook, void *cookie)
+{
+ CommandEntry *entry;
+
+ if (!gCommandState.commandStateInitialized) {
+ return -1;
+ }
+ if (name == NULL || hook == NULL) {
+ return -1;
+ }
+ if (type != CMD_TYPE_COMMAND && type != CMD_TYPE_FUNCTION) {
+ return -1;
+ }
+ if (argType != CMD_ARGS_BOOLEAN && argType != CMD_ARGS_WORDS) {
+ return -1;
+ }
+
+ entry = (CommandEntry *)malloc(sizeof(CommandEntry));
+ if (entry != NULL) {
+ entry->name = strdup(name);
+ if (entry->name != NULL) {
+ int ret;
+
+ entry->cookie = cookie;
+ entry->type = type;
+ entry->argType = argType;
+ entry->hook = hook;
+ ret = addToSymbolTable(gCommandState.symbolTable,
+ entry->name, entry->type, entry);
+ if (ret == 0) {
+ return 0;
+ }
+ }
+ free(entry);
+ }
+
+ return -1;
+}
+
+int
+registerCommand(const char *name,
+ CommandArgumentType argType, CommandHook hook, void *cookie)
+{
+ return registerCommandInternal(name,
+ CMD_TYPE_COMMAND, argType, hook, cookie);
+}
+
+int
+registerFunction(const char *name, FunctionHook hook, void *cookie)
+{
+ return registerCommandInternal(name,
+ CMD_TYPE_FUNCTION, CMD_ARGS_WORDS, (CommandHook)hook, cookie);
+}
+
+Command *
+findCommand(const char *name)
+{
+ return (Command *)findInSymbolTable(gCommandState.symbolTable,
+ name, CMD_TYPE_COMMAND);
+}
+
+Function *
+findFunction(const char *name)
+{
+ return (Function *)findInSymbolTable(gCommandState.symbolTable,
+ name, CMD_TYPE_FUNCTION);
+}
+
+CommandArgumentType
+getCommandArgumentType(Command *cmd)
+{
+ CommandEntry *entry = (CommandEntry *)cmd;
+
+ if (entry != NULL) {
+ return entry->argType;
+ }
+ return CMD_ARGS_UNKNOWN;
+}
+
+static int
+callCommandInternal(CommandEntry *entry, int argc, const char *argv[],
+ PermissionRequestList *permissions)
+{
+ if (entry != NULL && entry->argType == CMD_ARGS_WORDS &&
+ (argc == 0 || (argc > 0 && argv != NULL)))
+ {
+ if (permissions == NULL) {
+ int i;
+ for (i = 0; i < argc; i++) {
+ if (argv[i] == NULL) {
+ goto bail;
+ }
+ }
+ }
+ TRACE("calling command %s\n", entry->name);
+ return entry->hook(entry->name, entry->cookie, argc, argv, permissions);
+//xxx if permissions, make sure the entry has added at least one element.
+ }
+bail:
+ return -1;
+}
+
+static int
+callBooleanCommandInternal(CommandEntry *entry, bool arg,
+ PermissionRequestList *permissions)
+{
+ if (entry != NULL && entry->argType == CMD_ARGS_BOOLEAN) {
+ TRACE("calling boolean command %s\n", entry->name);
+ return entry->hook(entry->name, entry->cookie, arg ? 1 : 0, NULL,
+ permissions);
+//xxx if permissions, make sure the entry has added at least one element.
+ }
+ return -1;
+}
+
+int
+callCommand(Command *cmd, int argc, const char *argv[])
+{
+ return callCommandInternal((CommandEntry *)cmd, argc, argv, NULL);
+}
+
+int
+callBooleanCommand(Command *cmd, bool arg)
+{
+ return callBooleanCommandInternal((CommandEntry *)cmd, arg, NULL);
+}
+
+int
+getCommandPermissions(Command *cmd, int argc, const char *argv[],
+ PermissionRequestList *permissions)
+{
+ if (permissions != NULL) {
+ return callCommandInternal((CommandEntry *)cmd, argc, argv,
+ permissions);
+ }
+ return -1;
+}
+
+int
+getBooleanCommandPermissions(Command *cmd, bool arg,
+ PermissionRequestList *permissions)
+{
+ if (permissions != NULL) {
+ return callBooleanCommandInternal((CommandEntry *)cmd, arg,
+ permissions);
+ }
+ return -1;
+}
+
+int
+callFunctionInternal(CommandEntry *entry, int argc, const char *argv[],
+ char **result, size_t *resultLen, PermissionRequestList *permissions)
+{
+ if (entry != NULL && entry->argType == CMD_ARGS_WORDS &&
+ (argc == 0 || (argc > 0 && argv != NULL)))
+ {
+ if ((permissions == NULL && result != NULL) ||
+ (permissions != NULL && result == NULL))
+ {
+ if (permissions == NULL) {
+ /* This is the actual invocation of the function,
+ * which means that none of the arguments are allowed
+ * to be NULL.
+ */
+ int i;
+ for (i = 0; i < argc; i++) {
+ if (argv[i] == NULL) {
+ goto bail;
+ }
+ }
+ }
+ TRACE("calling function %s\n", entry->name);
+ return ((FunctionHook)entry->hook)(entry->name, entry->cookie,
+ argc, argv, result, resultLen, permissions);
+//xxx if permissions, make sure the entry has added at least one element.
+ }
+ }
+bail:
+ return -1;
+}
+
+int
+callFunction(Function *fn, int argc, const char *argv[],
+ char **result, size_t *resultLen)
+{
+ return callFunctionInternal((CommandEntry *)fn, argc, argv,
+ result, resultLen, NULL);
+}
+
+int
+getFunctionPermissions(Function *fn, int argc, const char *argv[],
+ PermissionRequestList *permissions)
+{
+ if (permissions != NULL) {
+ return callFunctionInternal((CommandEntry *)fn, argc, argv,
+ NULL, NULL, permissions);
+ }
+ return -1;
+}