]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
Add the start of a command line parser
authorRay Strode <rstrode@redhat.com>
Thu, 5 Jun 2008 22:21:18 +0000 (18:21 -0400)
committerRay Strode <rstrode@redhat.com>
Sun, 8 Jun 2008 04:45:48 +0000 (00:45 -0400)
This will be useful for changing the client to use a

plymouth subcommand --option1 --option2

format

src/libply/Makefile.am
src/libply/ply-command-parser.c [new file with mode: 0644]
src/libply/ply-command-parser.h [new file with mode: 0644]
src/libply/tests/Makefile.am
src/libply/tests/ply-command-parser-test.am [new file with mode: 0644]

index 6f619d26988586e8bf3a032a7b892041917ebfd1..4a3049dfbc15e6c678aa84e153807715dc48eec9 100644 (file)
@@ -11,6 +11,8 @@ libply_la_LDFLAGS = -export-symbols-regex '^[^_].*' \
                    -no-undefined
 libply_la_SOURCES = ply-event-loop.c                                          \
                    ply-event-loop.h                                          \
+                   ply-command-parser.h                                      \
+                   ply-command-parser.c                                      \
                    ply-frame-buffer.h                                        \
                    ply-frame-buffer.c                                        \
                    ply-buffer.c                                              \
diff --git a/src/libply/ply-command-parser.c b/src/libply/ply-command-parser.c
new file mode 100644 (file)
index 0000000..b6d9a67
--- /dev/null
@@ -0,0 +1,866 @@
+/* ply-command-parser.c - command line parser
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-command-parser.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ply-buffer.h"
+#include "ply-list.h"
+
+typedef union
+{
+  bool as_boolean;
+  char *as_string;
+  int as_integer;
+} ply_command_option_result_t;
+
+typedef struct
+{
+  char *name;
+  char *description;
+  ply_command_option_type_t type;
+
+  ply_command_option_result_t result;
+} ply_command_option_t;
+
+typedef struct
+{
+  char *name;
+  char *description;
+  ply_list_t *options;
+
+  ply_command_handler_t handler;
+  void       *handler_data;
+} ply_command_t;
+
+struct _ply_command_parser
+{
+  ply_event_loop_t *loop;
+  ply_command_t *main_command;
+
+  ply_list_t *available_subcommands;
+  ply_list_t *read_subcommands;
+
+  ply_list_t *arguments;
+
+  uint32_t dispatch_is_queued : 1;
+};
+
+ply_command_option_t *
+ply_command_option_new (const char                *name,
+                        const char                *description,
+                        ply_command_option_type_t  type)
+{
+  ply_command_option_t *option;
+
+  option = calloc (1, sizeof (ply_command_option_t));
+
+  option->name = strdup (name);
+  option->description = strdup (description);
+  option->type = type;
+
+  return option;
+}
+
+void
+ply_command_option_free (ply_command_option_t *option)
+{
+  if (option == NULL)
+    return;
+
+  free (option->name);
+  free (option->description);
+  free (option);
+}
+
+ply_command_t *
+ply_command_new (const char *name,
+                 const char *description,
+                 ply_command_handler_t handler,
+                 void       *data)
+{
+  ply_command_t *command;
+
+  command = calloc (1, sizeof (ply_command_t));
+
+  command->options = ply_list_new ();
+  command->name = strdup (name);
+  command->description = strdup (description);
+  command->handler = handler;
+  command->handler_data = data;
+
+  return command;
+}
+
+void
+ply_command_free (ply_command_t *command)
+{
+  if (command == NULL)
+    return;
+
+  ply_list_free (command->options);
+  free (command);
+}
+
+static void
+append_usage_line_to_buffer (ply_command_parser_t *parser,
+                             ply_buffer_t *buffer)
+{
+  ply_list_node_t *option_node;
+
+  ply_buffer_append (buffer, "%s\n",
+                     parser->main_command->description);
+  ply_buffer_append (buffer, "USAGE: %s", parser->main_command->name);
+
+  option_node = ply_list_get_first_node (parser->main_command->options);
+  while (option_node != NULL)
+    {
+      ply_command_option_t *option;
+
+      option = (ply_command_option_t *) ply_list_node_get_data (option_node);
+      ply_buffer_append (buffer, " [--%s%s] ", option->name,
+                         option->type == PLY_COMMAND_OPTION_TYPE_BOOLEAN?
+                         "={true|false}":
+                         option->type == PLY_COMMAND_OPTION_TYPE_STRING?
+                         "=<string>":
+                         option->type == PLY_COMMAND_OPTION_TYPE_INTEGER?
+                         "=<integer>": "");
+      option_node = ply_list_get_next_node (parser->main_command->options, option_node);
+    }
+
+  ply_buffer_append (buffer, "[subcommand [options]...]\n");
+}
+
+static void
+append_command_options_to_buffer (ply_command_parser_t *parser,
+                               ply_command_t *command,
+                               ply_buffer_t *buffer)
+{
+  ply_list_node_t *option_node;
+
+  option_node = ply_list_get_first_node (command->options);
+
+  while (option_node != NULL)
+    {
+      ply_command_option_t *option;
+
+      option = (ply_command_option_t *) ply_list_node_get_data (option_node);
+      ply_buffer_append (buffer,
+                         "%-10.10s--%s%-*.*s%25s\n",
+                         "",
+                         option->name,
+                         (int) (25 - strlen (option->name)),
+                         (int) (25 - strlen (option->name)),
+                         option->type == PLY_COMMAND_OPTION_TYPE_BOOLEAN?
+                         "=[true|false]":
+                         option->type == PLY_COMMAND_OPTION_TYPE_STRING?
+                         "=<string>":
+                         option->type == PLY_COMMAND_OPTION_TYPE_INTEGER?
+                         "=<integer>": "",
+                         option->description);
+      option_node = ply_list_get_next_node (command->options, option_node);
+    }
+}
+
+char *
+ply_command_parser_get_help_string (ply_command_parser_t *parser)
+{
+  ply_buffer_t *buffer;
+  ply_list_node_t *command_node;
+  char *help_string;
+
+  buffer = ply_buffer_new ();
+
+  append_usage_line_to_buffer (parser, buffer);
+  ply_buffer_append (buffer, "\n");
+  append_command_options_to_buffer (parser, parser->main_command, buffer);
+  ply_buffer_append (buffer, "\n");
+
+  ply_buffer_append (buffer, "Available subcommands:\n");
+  command_node = ply_list_get_first_node (parser->available_subcommands);
+  while (command_node != NULL)
+    {
+      ply_command_t *command;
+
+      command = (ply_command_t *) ply_list_node_get_data (command_node);
+
+      ply_buffer_append (buffer, "\n%s%*s\n\n",
+                         command->name,
+                         (int)(62 - strlen (command->name)),
+                         command->description);
+
+      append_command_options_to_buffer (parser, command, buffer);
+
+      command_node = ply_list_get_next_node (parser->available_subcommands,
+                                             command_node);
+    }
+
+  help_string = ply_buffer_steal_bytes (buffer);
+  ply_buffer_free (buffer);
+
+  return help_string;
+}
+
+static void
+ply_command_add_option (ply_command_t *command,
+                        const char    *name,
+                        const char    *description,
+                        ply_command_option_type_t type)
+{
+  ply_command_option_t *option;
+
+  option = ply_command_option_new (name, description, type);
+
+  ply_list_append_data (command->options, option);
+}
+
+static ply_command_option_t *
+ply_command_get_option (ply_command_t *command,
+                        const char    *option_name)
+{
+  ply_command_option_t *option;
+  ply_list_node_t *node;
+
+  option = NULL;
+  node = ply_list_get_first_node (command->options);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+
+      option = (ply_command_option_t *) ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (command->options, node);
+
+      if (strcmp (option_name, option->name) == 0)
+        break;
+
+      node = next_node;
+    }
+
+  return option;
+}
+
+ply_command_parser_t *
+ply_command_parser_new (const char *name,
+                        const char *description)
+{
+  ply_command_parser_t *command_parser;
+
+  command_parser = calloc (1, sizeof (ply_command_parser_t));
+
+  command_parser->main_command = ply_command_new (name, description, NULL, NULL);
+  command_parser->available_subcommands = ply_list_new ();
+  command_parser->read_subcommands = ply_list_new ();
+
+  return command_parser;
+}
+
+void
+ply_command_parser_free (ply_command_parser_t *command_parser)
+{
+  if (command_parser == NULL)
+    return;
+
+  ply_list_free (command_parser->available_subcommands);
+  ply_list_free (command_parser->read_subcommands);
+
+  free (command_parser);
+}
+
+void
+ply_command_parser_add_options (ply_command_parser_t *parser,
+                                const char *first_variadic_argument, /*
+                                const char *option_description,
+                                ply_option_argument_type_t option_type */
+                                ...)
+{
+  va_list args;
+  const char *option_name;
+  const char *option_description;
+  ply_command_option_type_t option_type;
+
+  assert (parser != NULL);
+
+  option_name = first_variadic_argument;
+  va_start (args, first_variadic_argument);
+  while (option_name != NULL)
+    {
+      option_description = va_arg (args, const char *);
+      option_type = va_arg (args, ply_command_option_type_t);
+
+      ply_command_add_option (parser->main_command,
+                              option_name, option_description, option_type);
+
+      option_name = va_arg (args, const char *);
+    }
+  va_end (args);
+}
+
+void
+ply_command_parser_add_command (ply_command_parser_t *parser,
+                                const char *name, const char *description,
+                                ply_command_handler_t handler,
+                                void *handler_data,
+                                const char *first_variadic_argument, /*
+                                const char *option_description,
+                                ply_command_option_type_t option_type */
+                                ...)
+{
+  ply_command_t *command;
+  va_list args;
+  const char *option_name;
+  const char *option_description;
+  ply_command_option_type_t option_type;
+
+  assert (parser != NULL);
+  assert (name != NULL);
+
+  command = ply_command_new (name, description, handler, handler_data);
+
+  option_name = first_variadic_argument;
+  va_start (args, first_variadic_argument);
+  while (option_name != NULL)
+    {
+      option_description = va_arg (args, const char *);
+      option_type = va_arg (args, ply_command_option_type_t);
+
+      ply_command_add_option (command, option_name, option_description, option_type);
+
+      option_name = va_arg (args, const char *);
+    }
+  va_end (args);
+
+  ply_list_append_data (parser->available_subcommands, command);
+}
+
+static void
+ply_command_parser_set_arguments (ply_command_parser_t *parser,
+                                  char * const         *arguments,
+                                  int                   number_of_arguments)
+{
+  int i;
+
+  assert (parser != NULL);
+  assert (arguments != NULL);
+
+  ply_list_free (parser->arguments);
+  parser->arguments = ply_list_new ();
+
+  for (i = 0; arguments[i] != NULL; i++)
+    ply_list_append_data (parser->arguments, arguments[i]);
+}
+
+static ply_command_t *
+ply_command_parser_get_command (ply_command_parser_t *parser,
+                                const char *command_name)
+{
+  ply_command_t *command;
+  ply_list_node_t *node;
+
+  command = NULL;
+  node = ply_list_get_first_node (parser->available_subcommands);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+
+      command = (ply_command_t *) ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (parser->available_subcommands, node);
+
+      if (strcmp (command_name, command->name) == 0)
+        break;
+
+      node = next_node;
+    }
+
+  return command;
+}
+
+static void
+ply_command_parser_get_options_for_command (ply_command_parser_t *parser,
+                                            ply_command_t *command,
+                                            const char *option_name,
+                                            va_list args)
+{
+
+  assert (parser != NULL);
+  assert (command != NULL);
+  assert (option_name != NULL);
+
+  while (option_name != NULL)
+    {
+      ply_command_option_t *option;
+
+      option = ply_command_get_option (command, option_name);
+
+      if (option != NULL)
+        {
+          switch (option->type)
+            {
+              case PLY_COMMAND_OPTION_TYPE_BOOLEAN:
+                {
+                  bool *option_result;
+
+                  option_result = va_arg (args, bool *);
+
+                  *option_result = option->result.as_boolean;
+                }
+              break;
+
+              case PLY_COMMAND_OPTION_TYPE_STRING:
+                {
+                  char **option_result;
+
+                  option_result = va_arg (args, char **);
+                  if (option->result.as_string != NULL)
+                    *option_result = strdup (option->result.as_string);
+                  else
+                    *option_result = NULL;
+                }
+              break;
+
+              case PLY_COMMAND_OPTION_TYPE_INTEGER:
+                {
+                  int *option_result;
+
+                  option_result = va_arg (args, int *);
+
+                  *option_result = option->result.as_integer;
+                }
+              break;
+            }
+        }
+
+      option_name = va_arg (args, const char *);
+    }
+}
+
+void
+ply_command_parser_get_options (ply_command_parser_t *parser,
+                                const char *option_name, /*
+                                void *      option_result */
+                                ...)
+{
+  va_list args;
+
+  assert (parser != NULL);
+  assert (option_name != NULL);
+
+  va_start (args, option_name);
+  ply_command_parser_get_options_for_command (parser, parser->main_command, option_name, args);
+  va_end (args);
+}
+
+void
+ply_command_parser_get_command_options (ply_command_parser_t *parser,
+                                        const char *command_name,
+                                        const char *option_name, /*
+                                        void *      option_result */
+                                        ...)
+{
+  ply_command_t *command;
+  va_list args;
+
+  assert (parser != NULL);
+  assert (command_name != NULL);
+  assert (option_name != NULL);
+
+  command = ply_command_parser_get_command (parser, command_name);
+
+  if (command == NULL)
+    return;
+
+  va_start (args, option_name);
+  ply_command_parser_get_options_for_command (parser, command, option_name, args);
+  va_end (args);
+
+  ply_list_append_data (parser->available_subcommands, command);
+}
+
+static void
+ply_command_parser_detach_from_event_loop (ply_command_parser_t *parser)
+{
+  parser->loop = NULL;
+}
+
+void
+ply_command_parser_stop_parsing_arguments (ply_command_parser_t *parser)
+{
+  assert (parser != NULL);
+
+  if (parser->loop == NULL)
+    return;
+
+  ply_event_loop_stop_watching_for_exit (parser->loop,
+                                         (ply_event_loop_exit_handler_t)
+                                         ply_command_parser_detach_from_event_loop,
+                                         parser);
+}
+
+static bool
+argument_is_option (const char *argument)
+{
+  return argument[0] == '-' && argument[1] == '-';
+}
+
+static bool
+ply_command_option_read_arguments (ply_command_option_t *option,
+                                   ply_list_t           *arguments)
+
+{
+  ply_list_node_t *node;
+  const char *argument;
+
+  assert (option != NULL);
+
+  node = ply_list_get_first_node (arguments);
+
+  if (node == NULL)
+    {
+      if (option->type == PLY_COMMAND_OPTION_TYPE_BOOLEAN)
+        {
+          option->result.as_boolean = true;
+          return true;
+        }
+
+      return false;
+    }
+
+  argument = (const char *) ply_list_node_get_data (node);
+
+  assert (argument != NULL);
+
+  if (argument_is_option (argument))
+    return false;
+
+  ply_list_remove_node (arguments, node);
+
+  switch (option->type)
+    {
+      case PLY_COMMAND_OPTION_TYPE_BOOLEAN:
+          option->result.as_boolean = (bool) rpmatch (argument);
+          return true;
+
+      case PLY_COMMAND_OPTION_TYPE_STRING:
+         option->result.as_string = strdup (argument);
+        return true;
+
+      case PLY_COMMAND_OPTION_TYPE_INTEGER:
+        {
+         char *end;
+         long argument_as_long;
+
+         if (argument[0] == '\0')
+           return false;
+
+         argument_as_long = strtol (argument, &end, 0);
+
+         if (*end != '\0')
+           return false;
+
+         if (argument_as_long == LONG_MIN &&
+             errno == ERANGE)
+           return false; 
+
+         if (argument_as_long > INT_MAX)
+           return false;
+
+         option->result.as_integer = (int) argument_as_long;
+
+         return true;
+        }
+    }
+
+  return option;
+}
+
+static ply_command_option_t *
+ply_command_read_option (ply_command_t *command,
+                         ply_list_t    *arguments)
+{
+  ply_list_node_t *node;
+  const char *argument;
+  char *option_name;
+  char *option_separator;
+  ply_command_option_t *option;
+
+  node = ply_list_get_first_node (arguments);
+
+  if (node == NULL)
+    return NULL;
+
+  argument = (const char *) ply_list_node_get_data (node);
+
+  assert (argument != NULL);
+
+  if (!argument_is_option (argument))
+    return NULL;
+
+  option_name = strdup (argument + strlen ("--"));
+  option_separator = strchr (option_name, '=');
+
+  if (option_separator != NULL)
+    {
+      *option_separator = '\0';
+      ply_list_insert_data (arguments,
+                            (void *) (argument +
+                            ((ptrdiff_t) (option_separator - option_name + 1)) +
+                            strlen ("=") + 1),
+                            node);
+    }
+
+  option = ply_command_get_option (command, option_name);
+  free (option_name);
+
+  if (option == NULL)
+    return NULL;
+
+  ply_list_remove_node (arguments, node);
+
+  ply_command_option_read_arguments (option, arguments);
+
+  return option;
+}
+
+static bool
+argument_is_command (const char *argument)
+{
+  return !argument_is_option (argument);
+}
+
+static ply_command_t *
+ply_command_parser_read_command (ply_command_parser_t *parser)
+{
+  ply_list_node_t *node;
+  const char *argument;
+  ply_command_t *command;
+
+  node = ply_list_get_first_node (parser->arguments);
+
+  if (node == NULL)
+    return NULL;
+
+  argument = (const char *) ply_list_node_get_data (node);
+
+  assert (argument != NULL);
+
+  if (!argument_is_command (argument))
+    return NULL;
+
+  command = ply_command_parser_get_command (parser, argument);
+
+  if (command == NULL)
+    return NULL;
+
+  ply_list_remove_node (parser->arguments, node);
+
+  while (ply_command_read_option (command, parser->arguments) != NULL);
+
+  return command;
+}
+
+static void
+on_command_dispatch_timeout (ply_command_parser_t *parser)
+{
+
+  ply_command_t *command;
+  ply_list_node_t *node;
+
+  command = NULL;
+  node = ply_list_get_first_node (parser->read_subcommands);
+
+  if (node == NULL)
+    {
+      parser->dispatch_is_queued = false;
+      return;
+    }
+
+  command = (ply_command_t *) ply_list_node_get_data (node);
+
+  assert (command != NULL);
+
+  ply_event_loop_watch_for_timeout (parser->loop, 0.01,
+                                    (ply_event_loop_timeout_handler_t)
+                                    on_command_dispatch_timeout,
+                                    parser);
+
+  if (command->handler != NULL)
+    command->handler (command->handler_data, command->name);
+
+  ply_list_remove_node (parser->read_subcommands, node);
+}
+
+static void
+ply_command_parser_queue_command_dispatch (ply_command_parser_t *parser)
+{
+  if (parser->dispatch_is_queued)
+    return;
+
+  ply_event_loop_watch_for_timeout (parser->loop, 0.01,
+                                    (ply_event_loop_timeout_handler_t)
+                                    on_command_dispatch_timeout,
+                                    parser);
+}
+
+bool
+ply_command_parser_parse_arguments (ply_command_parser_t *parser,
+                                    ply_event_loop_t     *loop,
+                                    char * const         *arguments,
+                                    int                   number_of_arguments)
+{
+  ply_command_t *command;
+  bool parsed_arguments;
+
+  assert (parser != NULL);
+  assert (loop != NULL);
+  assert (parser->loop == NULL);
+  assert (number_of_arguments >= 1);
+
+  parsed_arguments = false;
+
+  if (number_of_arguments == 1)
+    return true;
+
+  ply_command_parser_set_arguments (parser, arguments + 1, number_of_arguments - 1);
+
+  while (ply_command_read_option (parser->main_command, parser->arguments) != NULL)
+    parsed_arguments = true;
+
+  parser->loop = loop;
+
+  ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
+                                 ply_command_parser_detach_from_event_loop,
+                                 parser);
+
+  while ((command = ply_command_parser_read_command (parser)) != NULL)
+    ply_list_append_data (parser->read_subcommands, command);
+
+  if (ply_list_get_length (parser->read_subcommands) > 0)
+    {
+      ply_command_parser_queue_command_dispatch (parser);
+      parsed_arguments = true;
+    }
+
+  return parsed_arguments;
+}
+
+#ifdef PLY_COMMAND_PARSER_ENABLE_TEST
+
+#include <stdio.h>
+
+#include "ply-command-parser.h"
+#include "ply-event-loop.h"
+#include "ply-logger.h"
+
+static void
+on_ask_for_password (ply_command_parser_t *parser,
+                     const char *command)
+{
+  char *prompt;
+  char *program;
+
+  prompt = NULL;
+  program = NULL;
+  ply_command_parser_get_command_options (parser, command, "prompt", &prompt, "command", &program, NULL);
+
+  printf ("ask for password with prompt '%s' feed result to '%s'\n", prompt, program);
+  free (prompt);
+  free (program);
+}
+
+static void
+on_show_splash (ply_command_parser_t *parser,
+                const char *command)
+{
+  char *plugin_name;
+
+  plugin_name = NULL;
+  ply_command_parser_get_command_options (parser, command, "plugin-name", &plugin_name, NULL);
+
+  printf ("show splash plugin '%s'", plugin_name);
+  free (plugin_name);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  ply_event_loop_t *loop;
+  ply_command_parser_t *parser;
+  bool should_help;
+
+  loop = ply_event_loop_new ();
+  parser = ply_command_parser_new (argv[0], "Test Program");
+
+  ply_command_parser_add_options (parser,
+                                  "help", "This help message", PLY_COMMAND_OPTION_TYPE_BOOLEAN,
+                                  NULL);
+
+  ply_command_parser_add_command (parser,
+                                  "ask-for-password",
+                                  "Ask user for password",
+                                  (ply_command_handler_t)
+                                  on_ask_for_password, parser,
+                                  "command", "command to pipe result to", PLY_COMMAND_OPTION_TYPE_STRING,
+                                  "prompt", "string to present to user", PLY_COMMAND_OPTION_TYPE_STRING,
+                                  "output-result", "print result", PLY_COMMAND_OPTION_TYPE_BOOLEAN,
+                                  NULL);
+
+  ply_command_parser_add_command (parser,
+                                  "show-splash",
+                                  "Show splash to user",
+                                  (ply_command_handler_t)
+                                  on_show_splash, parser,
+                                  "plugin-name", "name of the plugin to run", PLY_COMMAND_OPTION_TYPE_STRING,
+                                  NULL);
+
+  if (!ply_command_parser_parse_arguments (parser, loop, argv, argc))
+    {
+      ply_error ("couldn't parse arguments");
+      return 1;
+    }
+
+
+  ply_command_parser_get_options (parser, "help", &should_help, NULL);
+
+  if (should_help)
+    {
+      char *usage;
+      usage = ply_command_parser_get_help_string (parser);
+      printf ("%s\n", usage);
+      free (usage);
+      return 0;
+    }
+
+  ply_event_loop_run (loop);
+
+  ply_command_parser_free (parser);
+
+  return 0;
+}
+
+#endif
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
diff --git a/src/libply/ply-command-parser.h b/src/libply/ply-command-parser.h
new file mode 100644 (file)
index 0000000..5daa5f6
--- /dev/null
@@ -0,0 +1,71 @@
+/* ply-command-parser.h - command line parser
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Ray Strode <rstrode@redhat.com>
+ */
+#ifndef PLY_COMMAND_PARSER_H
+#define PLY_COMMAND_PARSER_H
+
+#include <stdarg.h>
+
+#include "ply-event-loop.h"
+
+typedef struct _ply_command_parser ply_command_parser_t;
+typedef void (* ply_command_handler_t) (void *data,
+                                        const char *command);
+
+typedef enum
+{
+  PLY_COMMAND_OPTION_TYPE_BOOLEAN = 0,
+  PLY_COMMAND_OPTION_TYPE_STRING,
+  PLY_COMMAND_OPTION_TYPE_INTEGER
+} ply_command_option_type_t;
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+ply_command_parser_t *ply_command_parser_new (const char *name,
+                                              const char *description);
+
+void ply_command_parser_add_options (ply_command_parser_t *parser,
+                                     const char *option_name, /*
+                                     const char *option_description,
+                                     ply_option_argument_type_t option_type */
+                                     ...);
+void ply_command_parser_add_command (ply_command_parser_t *parser,
+                                     const char *name, const char *description,
+                                     ply_command_handler_t handler,
+                                     void *handler_data,
+                                     const char *option_name, /*
+                                     const char *option_description,
+                                     ply_option_argument_type_t option_type */
+                                     ...);
+void ply_command_parser_get_command_options (ply_command_parser_t *parser,
+                                             const char *command_name,
+                                             const char *option_name, /*
+                                             void *      option_result */
+                                             ...);
+void ply_command_parser_stop_parsing_arguments (ply_command_parser_t *parser);
+
+bool ply_command_parser_parse_arguments (ply_command_parser_t *parser,
+                                         ply_event_loop_t     *loop,
+                                         char * const         *arguments,
+                                         int                   number_of_arguments);
+void ply_command_parser_free (ply_command_parser_t *command_parser);
+#endif
+
+#endif /* PLY_COMMAND_PARSER_H */
index 5f5287c6c5091a74f334d48af2e2cf7f2c9b98e4..00880c3d88c26c3369a403dacd25a296ee6b1640 100644 (file)
@@ -13,6 +13,7 @@ include $(srcdir)/ply-logger-test.am
 include $(srcdir)/ply-array-test.am
 include $(srcdir)/ply-list-test.am
 include $(srcdir)/ply-event-loop-test.am
+include $(srcdir)/ply-command-parser-test.am
 endif
 
 noinst_PROGRAMS = $(TESTS)
diff --git a/src/libply/tests/ply-command-parser-test.am b/src/libply/tests/ply-command-parser-test.am
new file mode 100644 (file)
index 0000000..91649d5
--- /dev/null
@@ -0,0 +1,18 @@
+TESTS += ply-command-parser-test
+
+ply_command_parser_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_COMMAND_PARSER_ENABLE_TEST
+ply_command_parser_test_LDADD = $(PLYMOUTH_LIBS)
+
+ply_command_parser_test_SOURCES =                                            \
+                          $(srcdir)/../ply-buffer.h                          \
+                          $(srcdir)/../ply-buffer.c                          \
+                          $(srcdir)/../ply-event-loop.h                      \
+                          $(srcdir)/../ply-event-loop.c                      \
+                          $(srcdir)/../ply-list.h                            \
+                          $(srcdir)/../ply-list.c                            \
+                          $(srcdir)/../ply-logger.h                          \
+                          $(srcdir)/../ply-logger.c                          \
+                          $(srcdir)/../ply-utils.h                           \
+                          $(srcdir)/../ply-utils.c                           \
+                          $(srcdir)/../ply-command-parser.h                  \
+                          $(srcdir)/../ply-command-parser.c