Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: nucleo_ucmd_helloworld
Revision 0:9e2fc73e5a12, committed 2015-10-12
- Comitter:
- kyourek
- Date:
- Mon Oct 12 21:09:07 2015 +0000
- Commit message:
- Initial commit of the ucmd library for mbed.; https://github.com/kyourek/ucmd
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucArgOpt.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,252 @@
+#include <stdlib.h>
+#include "ucmd_internal.h"
+
+static const char *boolean_arg_name = "<boolean>";
+static const char *numeric_arg_name = "<numeric>";
+
+ucMemoryManager_INIT(ucArgOpt, ucArgOpt_COUNT);
+
+static ucArgOpt *create(const char *name, const char *desc, ucBool is_required, int min_tok_count, int max_tok_count, ucBool is_boolean, ucBool is_numeric, ucArgOpt_NUMERIC_TYPE numeric_min, ucArgOpt_NUMERIC_TYPE numeric_max, ucArgOpt *next) {
+ return ucArgOpt_init(ucMemoryManager_create(), name, desc, is_required, min_tok_count, max_tok_count, is_boolean, is_numeric, numeric_min, numeric_max, next);
+}
+
+static const char *format_is_required_validation_err(ucArgOpt *p, ucCmdLine *cmd, ucArgTok *arg_tok, const char *switch_name, const char *prefix) {
+
+ /* check if this argument is required */
+ if (ucOpt_is_required((ucOpt*)p)) {
+
+ /* the argument is required, so check that the argument
+ token exists */
+ if (NULL == arg_tok) {
+
+ /* the argument is required, but the token does NOT exist,
+ so there's an error here. Return the appropriate error
+ message */
+ return NULL == switch_name
+ ? ucCmdLine_format_response(cmd, "%sthe argument \"%s\" is required.", prefix, ucOpt_get_name((ucOpt*)p))
+ : ucCmdLine_format_response(cmd, "%sthe argument \"%s\" is required for switch \"%s\".", prefix, ucOpt_get_name((ucOpt*)p), switch_name);
+ }
+ }
+
+ /* return no error */
+ return NULL;
+}
+
+static const char *format_is_boolean_validation_err(ucArgOpt *p, ucCmdLine *cmd, ucArgTok *arg_tok, const char *switch_name, const char *prefix) {
+ ucBool is_bool;
+ if (ucArgOpt_is_boolean(p)) {
+ if (arg_tok) {
+ is_bool = ucTok_is_boolean((ucTok*)arg_tok);
+ if (!is_bool) {
+ return NULL == switch_name
+ ? ucCmdLine_format_response(cmd, "%sthe argument \"%s\" is not boolean.", prefix, ucTok_get_value(arg_tok))
+ : ucCmdLine_format_response(cmd, "%sthe \"%s\" argument \"%s\" is not boolean.", prefix, switch_name, ucTok_get_value(arg_tok));
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static const char *format_is_numeric_validation_err(ucArgOpt *p, ucCmdLine *cmd, ucArgTok *arg_tok, const char *switch_name, const char *prefix) {
+ ucBool is_num;
+ double arg_num;
+
+ /* Check if this argument option must be numeric. */
+ if (ucArgOpt_is_numeric(p)) {
+
+ /* Check if the argument token was provided. */
+ if (arg_tok) {
+
+ /* Parse the argument token into a number. */
+ is_num = ucTok_try_parse_numeric((ucTok*)arg_tok, &arg_num);
+ if (!is_num) {
+
+ /* The argument option requires a number, but the
+ provided token is not numeric, so return the
+ appropriate error message. */
+ return NULL == switch_name
+ ? ucCmdLine_format_response(cmd, "%sthe argument \"%s\" is not numeric.", prefix, ucTok_get_value(arg_tok))
+ : ucCmdLine_format_response(cmd, "%sthe \"%s\" argument \"%s\" is not numeric.", prefix, switch_name, ucTok_get_value(arg_tok));
+ }
+
+ /* Check that that number is above the lower bound. */
+ if (ucArgOpt_get_numeric_min(p) > arg_num) {
+
+ /* The number is below the lower bound, so return the
+ appropriate error message. */
+ return NULL == switch_name
+ ? ucCmdLine_format_response(cmd, "%sthe argument \"%f\" is above the minimum value of \"%f\".", prefix, arg_num, ucArgOpt_get_numeric_min(p))
+ : ucCmdLine_format_response(cmd, "%sthe \"%s\" argument \"%f\" is above the minimum value of \"%f\".", prefix, switch_name, arg_num, ucArgOpt_get_numeric_min(p));
+ }
+
+ /* Check that the number is below the upper bound. */
+ if (ucArgOpt_get_numeric_max(p) < arg_num) {
+
+ /* The number is above the upper bound, so return the
+ appropriate error message. */
+ return NULL == switch_name
+ ? ucCmdLine_format_response(cmd, "%sthe argument \"%f\" is below the maximum value of \"%f\".", prefix, arg_num, ucArgOpt_get_numeric_max(p))
+ : ucCmdLine_format_response(cmd, "%sthe \"%s\" argument \"%f\" is below the maximum value of \"%f\".", prefix, switch_name, arg_num, ucArgOpt_get_numeric_max(p));
+ }
+ }
+ }
+
+ /* Return no error. */
+ return NULL;
+}
+
+static const char *format_arg_tok_validation_err(ucArgOpt *p, ucCmdLine *cmd, ucArgTok *arg_tok, const char *switch_name, const char *prefix) {
+ const char *err;
+
+ err = format_is_required_validation_err(p, cmd, arg_tok, switch_name, prefix);
+ if (err) return err;
+
+ err = format_is_boolean_validation_err(p, cmd, arg_tok, switch_name, prefix);
+ if (err) return err;
+
+ err = format_is_numeric_validation_err(p, cmd, arg_tok, switch_name, prefix);
+ if (err) return err;
+
+ return NULL;
+}
+
+int ucArgOpt_get_min_tok_count(ucArgOpt *p) {
+ if (NULL == p) return 0;
+ return p->min_tok_count;
+}
+
+int ucArgOpt_get_max_tok_count(ucArgOpt *p) {
+ if (NULL == p) return 0;
+ return p->max_tok_count;
+}
+
+ucBool ucArgOpt_is_boolean(ucArgOpt *p) {
+ if (NULL == p) return ucBool_FALSE;
+ return p->is_boolean;
+}
+
+ucBool ucArgOpt_is_numeric(ucArgOpt *p) {
+ if (NULL == p) return ucBool_FALSE;
+ return p->is_numeric;
+}
+
+ucArgOpt_NUMERIC_TYPE ucArgOpt_get_numeric_min(ucArgOpt *p) {
+ if (NULL == p) return 0;
+ return p->numeric_min;
+}
+
+ucArgOpt_NUMERIC_TYPE ucArgOpt_get_numeric_max(ucArgOpt* p) {
+ if (NULL == p) return 0;
+ return p->numeric_max;
+}
+
+ucArgOpt *ucArgOpt_get_next(ucArgOpt* p) {
+ if (NULL == p) return NULL;
+ return p->next;
+}
+
+ucArgOpt *ucArgOpt_init(ucArgOpt *p, const char *name, const char *desc, ucBool is_required, int min_tok_count, int max_tok_count, ucBool is_boolean, ucBool is_numeric, ucArgOpt_NUMERIC_TYPE numeric_min, ucArgOpt_NUMERIC_TYPE numeric_max, ucArgOpt *next) {
+
+ if (NULL == p) return NULL;
+ if (NULL == ucOpt_init((ucOpt*)p, name, desc, is_required)) return NULL;
+
+ p->min_tok_count = min_tok_count;
+ p->max_tok_count = max_tok_count;
+ p->is_boolean = is_boolean;
+ p->is_numeric = is_numeric;
+ p->numeric_min = numeric_min;
+ p->numeric_max = numeric_max;
+ p->next = next;
+
+ return p;
+}
+
+ucArgOpt *ucArgOpt_create(const char *name, const char *desc, ucArgOpt *next) {
+ return create(name, desc, ucBool_FALSE, 0, 1, ucBool_FALSE, ucBool_FALSE, 0, 0, next);
+}
+
+ucArgOpt *ucArgOpt_create_multiple(const char *name, const char *desc, int min_tok_count, int max_tok_count) {
+ return create(name, desc, min_tok_count > 0 ? ucBool_TRUE : ucBool_FALSE, min_tok_count, max_tok_count, ucBool_FALSE, ucBool_FALSE, 0, 0, NULL);
+}
+
+ucArgOpt *ucArgOpt_create_required(const char *name, const char *desc, ucArgOpt *next) {
+ return create(name, desc, ucBool_TRUE, 1, 1, ucBool_FALSE, ucBool_FALSE, 0, 0, next);
+}
+
+ucArgOpt *ucArgOpt_create_boolean(const char *desc, ucArgOpt *next) {
+ return create(boolean_arg_name, desc, ucBool_FALSE, 0, 1, ucBool_TRUE, ucBool_FALSE, 0, 0, next);
+}
+
+ucArgOpt *ucArgOpt_create_required_boolean(const char *desc, ucArgOpt *next) {
+ return create(boolean_arg_name, desc, ucBool_TRUE, 0, 1, ucBool_TRUE, ucBool_FALSE, 0, 0, next);
+}
+
+ucArgOpt *ucArgOpt_create_numeric(const char *desc, ucArgOpt_NUMERIC_TYPE numeric_min, ucArgOpt_NUMERIC_TYPE numeric_max, ucArgOpt *next) {
+ return create(numeric_arg_name, desc, ucBool_FALSE, 0, 1, ucBool_FALSE, ucBool_TRUE, numeric_min, numeric_max, next);
+}
+
+ucArgOpt *ucArgOpt_create_multiple_numeric(const char *desc, int min_tok_count, int max_tok_count, ucArgOpt_NUMERIC_TYPE numeric_min, ucArgOpt_NUMERIC_TYPE numeric_max) {
+ return create(numeric_arg_name, desc, min_tok_count > 0 ? ucBool_TRUE : ucBool_FALSE, min_tok_count, max_tok_count, ucBool_FALSE, ucBool_TRUE, numeric_min, numeric_max, NULL);
+}
+
+ucArgOpt *ucArgOpt_create_required_numeric(const char *desc, ucArgOpt_NUMERIC_TYPE numeric_min, ucArgOpt_NUMERIC_TYPE numeric_max, ucArgOpt *next) {
+ return create(numeric_arg_name, desc, ucBool_TRUE, 1, 1, ucBool_FALSE, ucBool_TRUE, numeric_min, numeric_max, next);
+}
+
+const char *ucArgOpt_format_validation_err(ucArgOpt *p, ucCmdLine *cmd, ucArgTok *arg_tok, const char *switch_name) {
+ int tok_count, max_tok_count;
+
+ /* if a switch name was given, then this argument belongs
+ to a switch. Otherwise, it's a command argument. */
+ const char *prefix = switch_name == NULL ? ucOpt_validation_err_invalid_argument_prefix : ucOpt_validation_err_invalid_switch_argument_prefix;
+
+ /* validate the current argument token */
+ const char *err = format_arg_tok_validation_err(p, cmd, arg_tok, switch_name, prefix);
+ if (err) return err;
+
+ /* check if this argument option allows multiple tokens */
+ max_tok_count = ucArgOpt_get_max_tok_count(p);
+ if (1 < max_tok_count) {
+
+ /* loop through the argument tokens */
+ tok_count = arg_tok ? 1 : 0;
+ while (arg_tok) {
+
+ /* get the next argument token in the list */
+ arg_tok = ucArgTok_get_next(arg_tok);
+
+ /* check if this token exists */
+ if (arg_tok) {
+
+ /* increment the number of tokens and make sure it is valid */
+ tok_count++;
+ if (tok_count > max_tok_count) return ucCmdLine_format_response(cmd, "%stoo many arguments for %s.", prefix, ucOpt_get_name((ucOpt*)p));
+
+ /* validate this token */
+ err = format_arg_tok_validation_err(p, cmd, arg_tok, switch_name, prefix);
+ if (err) return err;
+ }
+ }
+
+ /* make sure we have enough tokens */
+ if (tok_count < ucArgOpt_get_min_tok_count(p)) return ucCmdLine_format_response(cmd, "%snot enough arguments for %s.", prefix, ucOpt_get_name((ucOpt*)p));
+ }
+
+ /* if we got here, then no error was found */
+ return NULL;
+}
+
+void ucArgOpt_destroy(ucArgOpt *p) {
+ ucMemoryManager_destroy(p);
+}
+
+void ucArgOpt_destroy_chain(ucArgOpt *p) {
+ ucArgOpt *next = p;
+ while (NULL != next) {
+ p = next;
+ next = ucArgOpt_get_next(p);
+ ucArgOpt_destroy(p);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucArgOptOwner.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,72 @@
+#include "ucmd_internal.h"
+
+ucArgOpt *ucArgOptOwner_get_arg_opt(ucArgOptOwner *p) {
+ if (NULL == p) return NULL;
+ return p->arg_opt;
+}
+
+ucArgOptOwner *ucArgOptOwner_init(ucArgOptOwner *p, const char *name, const char *desc, ucBool is_required, ucArgOpt *arg_opt) {
+ if (NULL == p) return NULL;
+ if (NULL == ucOpt_init((ucOpt*)p, name, desc, is_required)) return NULL;
+ p->arg_opt = arg_opt;
+ return p;
+}
+
+const char *ucArgOptOwner_format_validation_err(ucArgOptOwner *p, ucCmdLine *cmd, ucArgTok *arg_tok, const char *switch_name) {
+ int max_arg_tok_count;
+
+ /* set the prefix for error messages */
+ const char *validation, *prefix = switch_name == NULL ? ucOpt_validation_err_invalid_argument_prefix : ucOpt_validation_err_invalid_switch_argument_prefix;
+
+ /* get the first argument option */
+ ucArgOpt *arg_opt = ucArgOptOwner_get_arg_opt(p);
+
+ /* check if an argument option does NOT exist */
+ if (NULL == arg_opt) {
+
+ /* check if the argumen token DOES exist */
+ if (NULL != arg_tok) {
+
+ /* the option does NOT exist, but the token DOES, so there's an error */
+ return NULL == switch_name
+ ? ucCmdLine_format_response(cmd, "%sno argument options exist for command \"%s\".", prefix, ucTok_get_value(ucCmdLine_get_cmd_tok(cmd)))
+ : ucCmdLine_format_response(cmd, "%sno argument options exist for switch \"%s\".", prefix, switch_name);
+ }
+
+ /* neither the option nor the token exist, so no error here */
+ return NULL;
+ }
+
+ /* loop through all the argument options */
+ max_arg_tok_count = 0;
+ while (NULL != arg_opt) {
+
+ /* validate this argument option agains the current token */
+ validation = ucArgOpt_format_validation_err(arg_opt, cmd, arg_tok, switch_name);
+ if (NULL != validation) return validation;
+
+ /* get the number of tokens that this option allows */
+ max_arg_tok_count = ucArgOpt_get_max_tok_count(arg_opt);
+
+ /* move to the next option and the next token */
+ arg_opt = ucArgOpt_get_next(arg_opt);
+ arg_tok = ucArgTok_get_next(arg_tok);
+ }
+
+ /* check if we have any remaining tokens */
+ if (NULL != arg_tok) {
+
+ /* check if the last argument option does NOT allow multiple tokens */
+ if (2 > max_arg_tok_count) {
+
+ /* we have remaining tokens but no arguments for them, so there's an error */
+ return NULL == switch_name
+ ? ucCmdLine_format_response(cmd, "%sno option exists for argument \"%s\".", prefix, ucTok_get_value(arg_tok))
+ : ucCmdLine_format_response(cmd, "%sno option exists for \"%s\" argument \"%s\".", prefix, switch_name, ucTok_get_value(arg_tok));
+ }
+ }
+
+ /* return no error */
+ return NULL;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucArgTok.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,34 @@
+#include "ucmd_internal.h"
+
+ucArgTok *ucArgTok_get_next(ucArgTok* p) {
+ ucTok *tok;
+ if (NULL == p) return NULL;
+ tok = ucTok_get_next((ucTok*)p);
+ if (NULL == tok) return NULL;
+ if (ucTok_is_switch(tok)) return NULL;
+ return (ucArgTok*)tok;
+}
+
+int ucArgTok_count(ucArgTok* p) {
+ int count = 0;
+ while (NULL != p) {
+ count++;
+ p = ucArgTok_get_next(p);
+ }
+ return count;
+}
+
+ucArgTok *ucArgTok_find(ucArgTok *p, const char *arg_value) {
+ while (NULL != p) {
+ if (ucTok_equals((ucTok*)p, arg_value)) {
+ return p;
+ }
+ p = ucArgTok_get_next(p);
+ }
+ return NULL;
+}
+
+ucBool ucArgTok_contains(ucArgTok* p, const char *arg_value) {
+ return NULL == ucArgTok_find(p, arg_value) ? ucBool_FALSE : ucBool_TRUE;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucArgTokOwner.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,12 @@
+#include "ucmd_internal.h"
+
+ucArgTok *ucArgTokOwner_get_arg(ucArgTokOwner *p) {
+ ucTok* tok;
+ if (NULL == p) return NULL;
+
+ tok = ucTok_get_next((ucTok*)p);
+ if (ucTok_is_switch(tok)) return NULL;
+
+ return (ucArgTok*)tok;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucCmdLine.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,199 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include "ucmd_internal.h"
+
+ucCmdLine *ucCmdLine_init(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ p->cmd_tok = NULL;
+ p->command_acknowledgment = NULL;
+ p->transmit = NULL;
+ p->transmit_state = NULL;
+ p->is_quiet = ucBool_FALSE;
+ p->is_canceled = NULL;
+ p->is_canceled_state = NULL;
+ p->handle_invalid_command = NULL;
+ p->handle_invalid_command_state = NULL;
+ p->response_terminator = NULL;
+ return p;
+}
+
+ucCmdLine *ucCmdLine_get_instance(void) {
+ static ucCmdLine instance = { 0 };
+ static ucCmdLine *pointer = NULL;
+ if (pointer == NULL) {
+ pointer = ucCmdLine_init(&instance);
+ }
+ return pointer;
+}
+
+ucCmdTok *ucCmdLine_get_cmd_tok(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ return p->cmd_tok;
+}
+
+void ucCmdLine_set_cmd_tok(ucCmdLine *p, ucCmdTok *value) {
+ if (NULL == p) return;
+ p->cmd_tok = value;
+}
+
+ucCmdLineToks *ucCmdLine_get_cmd_toks(ucCmdLine *p, ucCmdLineToks *buffer) {
+ if (NULL == p) return NULL;
+ if (NULL == buffer) return NULL;
+
+ buffer->cmd_tok = ucCmdLine_get_cmd_tok(p);
+ buffer->arg_tok = ucCmdTok_get_arg(buffer->cmd_tok);
+ buffer->switch_tok = ucCmdTok_get_switch(buffer->cmd_tok);
+
+ return buffer;
+}
+
+const char *ucCmdLine_format_response_va(ucCmdLine *p, const char *format, va_list arg_list) {
+ if (NULL == p) return NULL;
+
+ /* TODO: Buffer and copy were added because "usage" uses the command's response in the arg list.
+ TODO: There's probably a better-performing way to handle that, though. */
+ vsnprintf(p->response_buffer, sizeof(p->response_buffer) - 1, format, arg_list);
+ strcpy(p->response, p->response_buffer);
+ return p->response;
+}
+
+const char *ucCmdLine_format_response(ucCmdLine *p, const char *format, ...) {
+ va_list arg_list;
+ const char *response;
+
+ va_start(arg_list, format);
+ response = ucCmdLine_format_response_va(p, format, arg_list);
+ va_end(arg_list);
+
+ return response;
+}
+
+void ucCmdLine_respond(ucCmdLine *p, const char *response) {
+ if (NULL == p) return;
+ if (NULL == p->transmit) return;
+ if (p->is_quiet) return;
+ p->transmit(response, p->transmit_state);
+}
+
+void ucCmdLine_set_transmit(ucCmdLine *p, ucCmdLine_TransmitFunc *value) {
+ if (NULL == p) return;
+ p->transmit = value;
+}
+
+ucCmdLine_TransmitFunc *ucCmdLine_get_transmit(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ return p->transmit;
+}
+
+ucBool ucCmdLine_is_canceled(ucCmdLine *p) {
+ if (NULL == p) return ucBool_FALSE;
+ if (NULL == p->is_canceled) return ucBool_FALSE;
+ return p->is_canceled(p->is_canceled_state);
+}
+
+void ucCmdLine_set_is_canceled(ucCmdLine *p, ucCmdLine_IsCanceledFunc *value) {
+ if (NULL == p) return;
+ p->is_canceled = value;
+}
+
+ucCmdLine_IsCanceledFunc *ucCmdLine_get_is_canceled(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ return p->is_canceled;
+}
+
+void *ucCmdLine_get_transmit_state(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ return p->transmit_state;
+}
+
+uc_EXPORTED void ucCmdLine_set_transmit_state(ucCmdLine *p, void *value) {
+ if (NULL == p) return;
+ p->transmit_state = value;
+}
+
+void *ucCmdLine_get_is_canceled_state(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ return p->is_canceled_state;
+}
+
+void ucCmdLine_set_is_canceled_state(ucCmdLine *p, void *value) {
+ if (NULL == p) return;
+ p->is_canceled_state = value;
+}
+
+void ucCmdLine_set_is_quiet(ucCmdLine *p, ucBool value) {
+ if (NULL == p) return;
+ p->is_quiet = value;
+}
+
+ucBool ucCmdLine_get_is_quiet(ucCmdLine *p) {
+ if (NULL == p) return ucBool_FALSE;
+ return p->is_quiet;
+}
+
+void ucCmdLine_set_handle_invalid_command(ucCmdLine *p, ucCmdLine_HandleInvalidCommandFunc *value) {
+ if (NULL == p) return;
+ p->handle_invalid_command = value;
+}
+
+ucCmdLine_HandleInvalidCommandFunc *ucCmdLine_get_handle_invalid_command(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ return p->handle_invalid_command;
+}
+
+void ucCmdLine_set_handle_invalid_command_state(ucCmdLine *p, void *value) {
+ if (NULL == p) return;
+ p->handle_invalid_command_state = value;
+}
+
+void *ucCmdLine_get_handle_invalid_command_state(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ return p->handle_invalid_command_state;
+}
+
+ucBool ucCmdLine_handle_invalid_command(ucCmdLine *p, const char *invalid_command) {
+ if (NULL == p) return ucBool_FALSE;
+ if (NULL == p->handle_invalid_command) return ucBool_FALSE;
+ return p->handle_invalid_command(invalid_command, p->handle_invalid_command_state);
+}
+
+size_t ucCmdLine_get_response_size_max(ucCmdLine *p) {
+ if (NULL == p) return 0;
+ return sizeof(p->response);
+}
+
+void ucCmdLine_set_response_terminator(ucCmdLine *p, const char *value) {
+ if (NULL == p) return;
+ p->response_terminator = value;
+}
+
+const char *ucCmdLine_get_response_terminator(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ return p->response_terminator;
+}
+
+void ucCmdLine_set_command_acknowledgment(ucCmdLine *p, const char *value) {
+ if (NULL == p) return;
+ p->command_acknowledgment = value;
+}
+
+const char *ucCmdLine_get_command_acknowledgment(ucCmdLine *p) {
+ if (NULL == p) return NULL;
+ return p->command_acknowledgment;
+}
+
+void ucCmdLine_acknowledge_command(ucCmdLine *p) {
+ const char *command_acknowledgment = ucCmdLine_get_command_acknowledgment(p);
+ if (command_acknowledgment) {
+ ucCmdLine_respond(p, command_acknowledgment);
+ }
+}
+
+void ucCmdLine_terminate_response(ucCmdLine *p) {
+ const char *response_terminator = ucCmdLine_get_response_terminator(p);
+ if (response_terminator) {
+ ucCmdLine_respond(p, response_terminator);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucCmdLineApp.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,214 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ucmd_internal.h"
+
+typedef struct HelpState {
+ ucCmdLineApp *app;
+ ucCmdLineOpt *cmd_opt;
+} HelpState;
+
+typedef struct QuitState {
+ ucCmdLineApp *app;
+} QuitState;
+
+static const char *quit(ucCmdLine *cmd, void *state) {
+ QuitState *s = (QuitState*)state;
+ return ucCmdLineApp_get_escape_response(s->app);
+}
+
+static const char *help(ucCmdLine *cmd, void *state) {
+ HelpState *s;
+ ucArgTok *arg_tok;
+ ucCmdLineOpt *cmd_opt;
+
+ s = (HelpState*)state;
+ cmd_opt = s->cmd_opt;
+
+ arg_tok = ucCmdTok_get_arg(ucCmdLine_get_cmd_tok(cmd));
+ if (NULL != arg_tok) {
+ cmd_opt = ucCmdLineOpt_find_by_name(cmd_opt, ucTok_get_value(arg_tok));
+ if (NULL != cmd_opt) {
+ ucCmdLineOpt_send_help(cmd_opt, cmd);
+ return 0;
+ }
+ ucCmdLine_respond(cmd, ucCmdLine_format_response(cmd, "Invalid command: no option found for \"%s\".", ucTok_get_value(arg_tok)));
+ return 0;
+ }
+
+ ucCmdLine_respond(cmd, "Commands");
+ while (NULL != cmd_opt) {
+ ucOpt_send_help((ucOpt*)cmd_opt, cmd, "\t");
+ cmd_opt = ucCmdLineOpt_get_next(cmd_opt);
+ }
+ ucCmdLine_respond(cmd, ucCmdLine_format_response(cmd, "Type \"%s\" followed by a command name for additional help with that command.", ucCmdLineApp_get_help_command(s->app)));
+
+ return 0;
+}
+
+static ucErr run(ucCmdLineApp *p, ucCmdLineOpt *cmd_opt) {
+ char *command;
+ const char *response;
+ ucCmdTok *cmd_tok;
+ ucCmdLine *cmd;
+ ucCmdLineOpt *quit_opt, *main_opt;
+ HelpState HelpState_s;
+ QuitState QuitState_s;
+
+ if (NULL == p) return -1;
+
+ /* Create options for help and quit. */
+ quit_opt = ucCmdLineOpt_create(quit, &QuitState_s, ucCmdLineApp_get_quit_command(p), "Exits the command interface.", NULL, NULL, cmd_opt);
+ main_opt = ucCmdLineOpt_create(help, &HelpState_s, ucCmdLineApp_get_help_command(p), "Shows command information.", ucArgOpt_create("<command>", "If provided, help is shown for the given command.", NULL), NULL, quit_opt);
+
+ /* Set the state used for the help and quit commands. */
+ QuitState_s.app = p;
+ HelpState_s.app = p;
+ HelpState_s.cmd_opt = main_opt;
+
+ /* Get this app's command object. */
+ cmd = ucCmdLineApp_get_cmd(p);
+
+ /* Show the banner. */
+ ucCmdLine_respond(cmd, ucCmdLine_format_response(cmd, "Type %s to quit.", ucCmdLineApp_get_quit_command(p)));
+ ucCmdLine_respond(cmd, ucCmdLine_format_response(cmd, "Type %s for help.", ucCmdLineApp_get_help_command(p)));
+
+ /* Loop until quit. */
+ for (;;) {
+
+ /* Read the command. */
+ command = ucCmdLineApp_receive(p);
+
+ /* Parse the input into a command token. */
+ cmd_tok = ucCmdParser_parse(ucCmdLineApp_get_cmd_parser(p), command);
+
+ /* Set the command's parsed command token. */
+ ucCmdLine_set_cmd_tok(cmd, cmd_tok);
+
+ /* Process the command. */
+ response = ucCmdLineOpt_process(main_opt, cmd);
+
+ /* Check if we got a response. */
+ if (response) {
+
+ /* Check if the response is the escape response. */
+ if (0 == strcmp(response, ucCmdLineApp_get_escape_response(p))) {
+
+ /* We've been signaled to quit the app. */
+ break;
+ }
+ }
+ }
+
+ /* Clear the options we created. */
+ ucCmdLineOpt_destroy(quit_opt);
+ ucCmdLineOpt_destroy(main_opt);
+
+ /* If we got here, then the app was quit. */
+ return ucErr_NONE;
+}
+
+void ucCmdLineApp_set_escape_response(ucCmdLineApp *p, const char *value) {
+ if (NULL == p) return;
+ p->escape_response = value;
+}
+
+const char *ucCmdLineApp_get_escape_response(ucCmdLineApp *p) {
+ if (NULL == p) return NULL;
+ return p->escape_response;
+}
+
+void ucCmdLineApp_set_receive(ucCmdLineApp *p, ucCmdLineApp_ReceiveFunc *value) {
+ if (NULL == p) return;
+ p->receive = value;
+}
+
+ucCmdLineApp_ReceiveFunc *ucCmdLineApp_get_receive(ucCmdLineApp *p) {
+ if (NULL == p) return NULL;
+ return p->receive;
+}
+
+void *ucCmdLineApp_get_receive_state(ucCmdLineApp *p) {
+ if (NULL == p) return NULL;
+ return p->receive_state;
+}
+
+void ucCmdLineApp_set_receive_state(ucCmdLineApp *p, void *value) {
+ if (NULL == p) return;
+ p->receive_state = value;
+}
+
+void ucCmdLineApp_set_quit_command(ucCmdLineApp *p, const char *value) {
+ if (NULL == p) return;
+ p->quit_command = value;
+}
+
+const char *ucCmdLineApp_get_quit_command(ucCmdLineApp *p) {
+ if (NULL == p) return NULL;
+ return p->quit_command;
+}
+
+void ucCmdLineApp_set_help_command(ucCmdLineApp *p, const char *value) {
+ if (NULL == p) return;
+ p->help_command = value;
+}
+
+const char *ucCmdLineApp_get_help_command(ucCmdLineApp *p) {
+ if (NULL == p) return NULL;
+ return p->help_command;
+}
+
+void ucCmdLineApp_set_cmd(ucCmdLineApp *p, ucCmdLine *value) {
+ if (NULL == p) return;
+ p->cmd = value;
+}
+
+ucCmdLine *ucCmdLineApp_get_cmd(ucCmdLineApp *p) {
+ if (NULL == p) return NULL;
+ return p->cmd;
+}
+
+ucCmdParser *ucCmdLineApp_get_cmd_parser(ucCmdLineApp *p) {
+ if (NULL == p) return NULL;
+ return p->cmd_parser;
+}
+
+ucCmdLineApp *ucCmdLineApp_init(ucCmdLineApp *p, ucCmdParser *cmd_parser, ucCmdLine *cmd) {
+ if (NULL == p) return NULL;
+ p->cmd = cmd;
+ p->cmd_parser = cmd_parser;
+ p->run = run;
+ p->receive = NULL;
+ p->receive_state = NULL;
+ p->help_command = "help";
+ p->quit_command = "quit";
+ p->escape_response = "\x1b";
+ return p;
+}
+
+ucCmdLineApp *ucCmdLineApp_get_instance(void) {
+ static ucCmdLineApp instance = { 0 };
+ static ucCmdLineApp *pointer = NULL;
+ if (pointer == NULL) {
+ pointer = ucCmdLineApp_init(&instance, ucCmdParser_get_instance(), ucCmdLine_get_instance());
+ }
+ return pointer;
+}
+
+ucErr ucCmdLineApp_run(ucCmdLineApp *p, ucCmdLineOpt *cmd_opt) {
+ if (NULL == p) return -1;
+ if (NULL == p->run) return -2;
+ return p->run(p, cmd_opt);
+}
+
+char *ucCmdLineApp_receive(ucCmdLineApp *p) {
+ if (NULL == p) return NULL;
+ if (NULL == p->receive) return NULL;
+ return p->receive(p->cmd_str, sizeof(p->cmd_str), p->receive_state);
+}
+
+size_t ucCmdLineApp_get_cmd_str_size_max(ucCmdLineApp *p) {
+ if (NULL == p) return 0;
+ return ucCmdLineApp_CMD_STR_SIZE;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucCmdLineOpt.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,266 @@
+#include <string.h>
+#include "ucmd_internal.h"
+
+ucMemoryManager_INIT(ucCmdLineOpt, ucCmdLineOpt_COUNT);
+
+static ucCmdLineOpt *create_cmd_line_opt(void) {
+ return ucMemoryManager_create();
+}
+
+static const char *add_opt_to_usage_response(ucOpt *opt, ucCmdLine *cmd, const char *response) {
+ static const char *required_format = "%s %s";
+ static const char *optional_format = "%s [%s]";
+ return ucCmdLine_format_response(
+ cmd,
+ ucOpt_is_required(opt) ? required_format : optional_format,
+ response,
+ ucOpt_get_name(opt)
+ );
+}
+
+static const char *add_arg_opts_to_usage_response(ucArgOpt *arg_opt, ucCmdLine *cmd, const char *response) {
+
+ while (NULL != arg_opt) {
+ response = add_opt_to_usage_response((ucOpt*)arg_opt, cmd, response);
+ arg_opt = ucArgOpt_get_next(arg_opt);
+ }
+
+ return response;
+}
+
+static void send_arg_opts_help(ucArgOpt *arg_opt, ucCmdLine *cmd, const char *prefix) {
+ while (NULL != arg_opt) {
+ ucOpt_send_help((ucOpt*)arg_opt, cmd, prefix);
+ arg_opt = ucArgOpt_get_next(arg_opt);
+ }
+}
+
+ucCmdLineOpt *ucCmdLineOpt_get_next(ucCmdLineOpt *p) {
+ if (NULL == p) return NULL;
+ return p->next;
+}
+
+ucArgOpt *ucCmdLineOpt_get_arg_opt(ucCmdLineOpt *p) {
+ if (NULL == p) return NULL;
+ return ucArgOptOwner_get_arg_opt((ucArgOptOwner*)p);
+}
+
+ucSwitchOpt *ucCmdLineOpt_get_switch_opt(ucCmdLineOpt *p) {
+ if (NULL == p) return NULL;
+ return p->switch_opt;
+}
+
+ucCmdLineOpt *ucCmdLineOpt_init(ucCmdLineOpt *p, ucCmdLineOpt_Func *func, void* state, const char *name, const char *desc, ucArgOpt *arg_opt, ucSwitchOpt *switch_opt, ucCmdLineOpt* next) {
+ if (NULL == p) return NULL;
+ if (NULL == ucArgOptOwner_init((ucArgOptOwner*)p, name, desc, ucBool_TRUE, arg_opt)) return NULL;
+ p->func = func;
+ p->state = state;
+ p->switch_opt = switch_opt;
+ p->next = next;
+ return p;
+}
+
+ucCmdLineOpt *ucCmdLineOpt_create(ucCmdLineOpt_Func *func, void *state, const char *name, const char *desc, ucArgOpt* arg_opt, ucSwitchOpt *switch_opt, ucCmdLineOpt *next) {
+ return ucCmdLineOpt_init(create_cmd_line_opt(), func, state, name, desc, arg_opt, switch_opt, next);
+}
+
+ucCmdLineOpt *ucCmdLineOpt_find_by_name(ucCmdLineOpt* p, const char *name) {
+ while (NULL != p) {
+ if (0 == strcmp(name, ucOpt_get_name((ucOpt*)p))) {
+ return p;
+ }
+ p = ucCmdLineOpt_get_next(p);
+ }
+ return NULL;
+}
+
+ucCmdLineOpt_Func *ucCmdLineOpt_get_func(ucCmdLineOpt *p) {
+ if (NULL == p) return NULL;
+ return p->func;
+}
+
+void *ucCmdLineOpt_get_state(ucCmdLineOpt *p) {
+ if (NULL == p) return NULL;
+ return p->state;
+}
+
+void ucCmdLineOpt_send_usage(ucCmdLineOpt *p, ucCmdLine *cmd) {
+ ucSwitchOpt *switch_opt;
+
+ /* start the usage string with the name of the command */
+ const char *response = ucCmdLine_format_response(cmd, "%s", ucOpt_get_name((ucOpt*)p));
+
+ /* add each available argument option of the command
+ to the usage string */
+ response = add_arg_opts_to_usage_response(ucCmdLineOpt_get_arg_opt(p), cmd, response);
+
+ /* loop through each available switch option */
+ switch_opt = ucCmdLineOpt_get_switch_opt(p);
+ while (NULL != switch_opt) {
+
+ /* add it to the usage string */
+ response = add_opt_to_usage_response((ucOpt*)switch_opt, cmd, response);
+
+ /* also add each of the switch's argument options to the
+ usage string */
+ response = add_arg_opts_to_usage_response(ucSwitchOpt_get_arg_opt(switch_opt), cmd, response);
+
+ /* go to the next switch */
+ switch_opt = ucSwitchOpt_get_next(switch_opt);
+ }
+
+ /* send the completed usage string */
+ ucCmdLine_respond(cmd, response);
+}
+
+void ucCmdLineOpt_send_help(ucCmdLineOpt *p, ucCmdLine *cmd) {
+ static const char *single_tab = "\t";
+ static const char *double_tab = "\t\t";
+
+ ucSwitchOpt *switch_opt;
+
+ ucCmdLineOpt_send_usage(p, cmd);
+
+ ucOpt_send_help((ucOpt*)p, cmd, "");
+ send_arg_opts_help(ucCmdLineOpt_get_arg_opt(p), cmd, single_tab);
+
+ switch_opt = ucCmdLineOpt_get_switch_opt(p);
+ while (NULL != switch_opt) {
+ ucOpt_send_help((ucOpt*)switch_opt, cmd, single_tab);
+ send_arg_opts_help(ucSwitchOpt_get_arg_opt(switch_opt), cmd, double_tab);
+ switch_opt = ucSwitchOpt_get_next(switch_opt);
+ }
+}
+
+const char *ucCmdLineOpt_format_validation_err(ucCmdLineOpt *p, ucCmdLine *cmd) {
+ static const char *invalid_switch = "Invalid switch: ";
+
+ ucCmdTok *cmd_tok;
+ ucSwitchOpt *switch_opt, *found_switch_opt, *next_switch_opt;
+ ucSwitchTok *switch_tok, *found_switch_tok, *next_switch_tok;
+ const char *switch_name, *validation;
+
+ cmd_tok = ucCmdLine_get_cmd_tok(cmd);
+
+ validation = ucArgOptOwner_format_validation_err((ucArgOptOwner*)p, cmd, ucCmdTok_get_arg(cmd_tok), NULL);
+ if (NULL != validation) return validation;
+
+ switch_tok = ucCmdTok_get_switch(cmd_tok);
+ switch_opt = ucCmdLineOpt_get_switch_opt(p);
+
+ if (NULL == switch_opt) {
+ if (NULL != switch_tok) {
+ return ucCmdLine_format_response(cmd, "%sno switch options exist for command \"%s\".", invalid_switch, ucTok_get_value((ucTok*)cmd_tok));
+ }
+ return NULL;
+ }
+
+ next_switch_tok = switch_tok;
+
+ while (NULL != next_switch_tok) {
+ found_switch_opt = ucSwitchOpt_find(switch_opt, ucTok_get_value((ucTok*)next_switch_tok));
+ if (NULL == found_switch_opt) {
+ return ucCmdLine_format_response(cmd, "%sno option exists for switch \"%s\".", invalid_switch, ucTok_get_value(next_switch_tok));
+ }
+ next_switch_tok = ucSwitchTok_get_next(next_switch_tok);
+ }
+
+ next_switch_opt = switch_opt;
+
+ while (NULL != next_switch_opt) {
+ switch_name = ucOpt_get_name((ucOpt*)next_switch_opt);
+ found_switch_tok = ucSwitchTok_find(switch_tok, switch_name);
+
+ if (ucOpt_is_required((ucOpt*)next_switch_opt)) {
+ if (NULL == found_switch_tok) {
+ return ucCmdLine_format_response(cmd, "%sthe switch \"%s\" is required.", invalid_switch, switch_name);
+ }
+ }
+
+ if (NULL != found_switch_tok) {
+ validation = ucSwitchOpt_format_validation_err(next_switch_opt, cmd, found_switch_tok);
+ if (NULL != validation) return validation;
+ }
+
+ next_switch_opt = ucSwitchOpt_get_next(next_switch_opt);
+ }
+
+ return NULL;
+}
+
+static const char *internal_process(ucCmdLineOpt *p, ucCmdLine *cmd, ucBool *invalid_command_handled) {
+ ucCmdTok *cmd_tok;
+ ucCmdLineOpt *opt;
+ ucCmdLineOpt_Func *func;
+ const char *cmd_value;
+ const char *validation;
+
+ /* Get the command token of the command structure. */
+ cmd_tok = ucCmdLine_get_cmd_tok(cmd);
+
+ /* Get the command option that we'll process by finding
+ the one that matches the name of the command. */
+ cmd_value = ucTok_get_value((ucTok*)cmd_tok);
+ opt = ucCmdLineOpt_find_by_name(p, cmd_value);
+ if (NULL == opt) {
+
+ /* The command is invalid (meaning it doesn't exist).
+ Try to handle it. */
+ *invalid_command_handled = ucCmdLine_handle_invalid_command(cmd, cmd_value);
+
+ /* If the command was handled, then we don't return an error. */
+ if (*invalid_command_handled) {
+ return NULL;
+ }
+ }
+
+ /* Send an indication that the command was received. */
+ ucCmdLine_acknowledge_command(cmd);
+
+ /* Check to see if the command is unknown. */
+ if (NULL == opt) return ucCmdLine_format_response(cmd, "Invalid command: no option found for \"%s\"", cmd_value);
+
+ /* Validate the command structure against the option.
+ If validation fails, then return the validation result. */
+ validation = ucCmdLineOpt_format_validation_err(opt, cmd);
+ if (validation) return validation;
+
+ /* Get the function callback from the command option. */
+ func = ucCmdLineOpt_get_func(opt);
+ if (NULL == func) return "Invalid function: null pointer";
+
+ /* Invoke the callback. */
+ return func(cmd, ucCmdLineOpt_get_state(opt));
+}
+
+const char *ucCmdLineOpt_process(ucCmdLineOpt* p, ucCmdLine *cmd) {
+ ucBool invalid_command_handled = ucBool_FALSE;
+ const char *response = internal_process(p, cmd, &invalid_command_handled);
+ if (invalid_command_handled) {
+ return response;
+ }
+
+ if (response) {
+ ucCmdLine_respond(cmd, response);
+ }
+
+ ucCmdLine_terminate_response(cmd);
+
+ return response;
+}
+
+void ucCmdLineOpt_destroy(ucCmdLineOpt *p) {
+ ucMemoryManager_destroy(p);
+}
+
+void ucCmdLineOpt_destroy_chain(ucCmdLineOpt *p) {
+ ucCmdLineOpt *next = p;
+ while (NULL != next) {
+ p = next;
+ next = ucCmdLineOpt_get_next(p);
+ ucArgOpt_destroy_chain(ucCmdLineOpt_get_arg_opt(p));
+ ucSwitchOpt_destroy_chain(ucCmdLineOpt_get_switch_opt(p));
+ ucCmdLineOpt_destroy(p);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucCmdLineToks.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,17 @@
+#include "ucmd_internal.h"
+
+ucCmdTok *ucCmdLineToks_get_cmd_tok(ucCmdLineToks *p) {
+ if (NULL == p) return NULL;
+ return p->cmd_tok;
+}
+
+ucArgTok *ucCmdLineToks_get_arg_tok(ucCmdLineToks *p) {
+ if (NULL == p) return NULL;
+ return p->arg_tok;
+}
+
+ucSwitchTok *ucCmdLineToks_get_switch_tok(ucCmdLineToks *p) {
+ if (NULL == p) return NULL;
+ return p->switch_tok;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucCmdParser.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,121 @@
+#include <string.h>
+#include "ucmd_internal.h"
+
+static ucBool is_char_white_space(char c) {
+ /* The native isspace function in ctype.h was giving some weird behavior in the uVision simulator. */
+ return (((c >= 0x09) && (c <= 0x0D)) || (c == 0x020)) ? ucBool_TRUE : ucBool_FALSE;
+}
+
+static char is_char_a_quote(char c) {
+ if (c == '"') return '"';
+ if (c == '\'') return '\'';
+ return 0;
+}
+
+static void remove_cmd_char(char *cmd, int index) {
+ if (NULL == cmd) return;
+ while (cmd[index] != uc_cmd_terminator) {
+ cmd[index] = cmd[index + 1];
+ index++;
+ }
+}
+
+static ucCmdTok *parse(ucCmdParser *p, char *cmd) {
+ int i, j, len;
+ char quote, current_quote;
+
+ if (NULL == cmd) return NULL;
+
+ /* get the length of the whole command */
+ len = strlen(cmd);
+
+ /* replace any command-terminating characters in the string with a space */
+ for (i = 0; i < len; i++) {
+ if (cmd[i] == uc_cmd_terminator) {
+ cmd[i] = ' ';
+ }
+ }
+
+ /* append a command terminator */
+ cmd[len + 1] = uc_cmd_terminator;
+
+ /* loop through each character in the command */
+ i = 0;
+ current_quote = 0;
+ while (cmd[i] != uc_cmd_terminator) {
+
+ /* check if this command character is a quote */
+ quote = is_char_a_quote(cmd[i]);
+ if (quote) {
+
+ /* check if this is our current quote */
+ if (quote == current_quote) {
+
+ /* remove the quote only if this is
+ not an empty quote */
+ if ((0 < i) && (current_quote != cmd[i - 1])) {
+ cmd[i] = ' ';
+ }
+
+ /* the quoted item is finished */
+ current_quote = 0;
+ }
+ else {
+
+ /* check if we're NOT in a quote */
+ if (!current_quote) {
+
+ /* we've started a quote */
+ current_quote = quote;
+
+ /* remove the quote character
+ only if this is not an empty
+ quote */
+ if (current_quote != cmd[i + 1]) {
+ remove_cmd_char(cmd, i);
+ }
+ }
+ }
+ }
+
+ /* check if we're not in a quoted string */
+ if (!current_quote) {
+
+ /* check if we're in a token separator */
+ if (is_char_white_space(cmd[i])) {
+
+ /* separate this token */
+ cmd[i] = ucTok_separator;
+
+ /* remove any remaining white space */
+ j = i + 1;
+ while (is_char_white_space(cmd[j])) {
+ remove_cmd_char(cmd, j);
+ }
+ }
+ }
+
+ /* go to the next character */
+ i++;
+ }
+
+ /* we're done parsing */
+ return (ucCmdTok*)cmd;
+}
+
+ucCmdTok *ucCmdParser_parse(ucCmdParser *p, char *cmd) {
+ if (NULL == p) return NULL;
+ if (NULL == p->parse) return NULL;
+ return p->parse(p, cmd);
+}
+
+ucCmdParser *ucCmdParser_get_instance(void) {
+ static ucCmdParser instance;
+ static ucCmdParser *p = NULL;
+ if (NULL == p) {
+ p = &instance;
+ p->parse = parse;
+ }
+ return p;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucCmdTok.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,19 @@
+#include "ucmd_internal.h"
+
+ucArgTok *ucCmdTok_get_arg(ucCmdTok *p) {
+ return ucArgTokOwner_get_arg((ucArgTokOwner*)p);
+}
+
+ucSwitchTok *ucCmdTok_get_switch(ucCmdTok *p) {
+ ucTok *tok;
+ if (NULL == p) return NULL;
+ tok = ucTok_get_next((ucTok*)p);
+ while (NULL != tok) {
+ if (ucTok_is_switch(tok)) {
+ return (ucSwitchTok*)tok;
+ }
+ tok = ucTok_get_next(tok);
+ }
+ return NULL;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucOpt.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,41 @@
+#include "ucmd_internal.h"
+
+const char *ucOpt_validation_err_invalid_argument_prefix = "Invalid argument: ";
+const char *ucOpt_validation_err_invalid_switch_prefix = "Invalid switch: ";
+const char *ucOpt_validation_err_invalid_switch_argument_prefix = "Invalid switch argument: ";
+
+const char *ucOpt_get_name(ucOpt *p) {
+ if (NULL == p) return NULL;
+ return p->name;
+}
+
+const char *ucOpt_get_desc(ucOpt *p) {
+ if (NULL == p) return NULL;
+ return p->desc;
+}
+
+ucBool ucOpt_is_required(ucOpt *p) {
+ if (NULL == p) return ucBool_FALSE;
+ return p->is_required;
+}
+
+void ucOpt_send_help(ucOpt *p, ucCmdLine *cmd, const char *prefix) {
+ static const char *required_format = "%s%s: %s";
+ static const char *optional_format = "%s[%s]: %s";
+ ucCmdLine_respond(cmd, ucCmdLine_format_response(
+ cmd,
+ ucOpt_is_required(p) ? required_format : optional_format,
+ prefix,
+ ucOpt_get_name(p),
+ ucOpt_get_desc(p)
+ ));
+}
+
+ucOpt *ucOpt_init(ucOpt *p, const char *name, const char *desc, ucBool is_required) {
+ if (NULL == p) return NULL;
+ p->name = name;
+ p->desc = desc;
+ p->is_required = is_required;
+ return p;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucSwitchOpt.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,81 @@
+#include <string.h>
+#include "ucmd_internal.h"
+
+ucMemoryManager_INIT(ucSwitchOpt, ucSwitchOpt_COUNT);
+
+static ucSwitchOpt *create_switch_opt(void) {
+ return ucMemoryManager_create();
+}
+
+ucArgOpt *ucSwitchOpt_get_arg_opt(ucSwitchOpt *p) {
+ return ucArgOptOwner_get_arg_opt((ucArgOptOwner*)p);
+}
+
+ucSwitchOpt *ucSwitchOpt_get_next(ucSwitchOpt *p) {
+ if (NULL == p) return NULL;
+ return p->next;
+}
+
+ucSwitchOpt *ucSwitchOpt_find(ucSwitchOpt *p, const char *name) {
+ while (NULL != p) {
+ if (0 == strcmp(ucOpt_get_name((ucOpt*)p), name)) {
+ return p;
+ }
+ p = ucSwitchOpt_get_next(p);
+ }
+ return NULL;
+}
+
+ucSwitchOpt *ucSwitchOpt_init(ucSwitchOpt *p, const char *name, const char *desc, ucBool is_required, ucArgOpt *arg_opt, ucSwitchOpt *next) {
+ if (NULL == p) return NULL;
+ if (NULL == ucArgOptOwner_init((ucArgOptOwner*)p, name, desc, is_required, arg_opt)) return NULL;
+
+ p->next = next;
+ return p;
+}
+
+ucSwitchOpt *ucSwitchOpt_create(const char *name, const char *desc, ucArgOpt *arg_opt, ucSwitchOpt *next) {
+ return ucSwitchOpt_init(create_switch_opt(), name, desc, ucBool_FALSE, arg_opt, next);
+}
+
+ucSwitchOpt *ucSwitchOpt_create_required(const char *name, const char *desc, ucArgOpt *arg_opt, ucSwitchOpt *next) {
+ return ucSwitchOpt_init(create_switch_opt(), name, desc, ucBool_TRUE, arg_opt, next);
+}
+
+void ucSwitchOpt_destroy(ucSwitchOpt *p) {
+ ucMemoryManager_destroy(p);
+}
+
+void ucSwitchOpt_destroy_chain(ucSwitchOpt *p) {
+ ucSwitchOpt *next = p;
+ while (NULL != next) {
+ p = next;
+ next = ucSwitchOpt_get_next(p);
+ ucArgOpt_destroy_chain(ucSwitchOpt_get_arg_opt(p));
+ ucSwitchOpt_destroy(p);
+ }
+}
+
+const char *ucSwitchOpt_format_validation_err(ucSwitchOpt *p, ucCmdLine *cmd, ucSwitchTok *switch_tok) {
+
+ /* check if the switch option is required */
+ if (ucOpt_is_required((ucOpt*)p)) {
+
+ /* check if the switch token is missing */
+ if (NULL == switch_tok) {
+
+ /* the switch is required, but it is not
+ present, so send the error */
+ return ucCmdLine_format_response(cmd, "%sthe switch \"%s\" is required.", ucOpt_validation_err_invalid_switch_prefix, ucOpt_get_name((ucOpt*)p));
+ }
+ }
+
+ /* return the result of the argument validation */
+ return ucArgOptOwner_format_validation_err(
+ (ucArgOptOwner*)p,
+ cmd,
+ ucSwitchTok_get_arg(switch_tok),
+ ucOpt_get_name((ucOpt*)p)
+ );
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucSwitchTok.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,40 @@
+#include "ucmd_internal.h"
+
+ucArgTok *ucSwitchTok_get_arg(ucSwitchTok *p) {
+ return ucArgTokOwner_get_arg((ucArgTokOwner*)p);
+}
+
+ucSwitchTok *ucSwitchTok_get_next(ucSwitchTok *p) {
+ ucTok *tok;
+ if (NULL == p) return NULL;
+ tok = ucTok_get_next((ucTok*)p);
+ while (NULL != tok) {
+ if (ucTok_is_switch(tok)) return (ucSwitchTok*)tok;
+ tok = ucTok_get_next((ucTok*)tok);
+ }
+ return NULL;
+}
+
+int ucSwitchTok_count(ucSwitchTok* p) {
+ int count = 0;
+ while (NULL != p) {
+ count++;
+ p = ucSwitchTok_get_next(p);
+ }
+ return count;
+}
+
+ucSwitchTok *ucSwitchTok_find(ucSwitchTok *p, const char *switch_value) {
+ while (NULL != p) {
+ if (ucTok_equals((ucTok*)p, switch_value)) {
+ return p;
+ }
+ p = ucSwitchTok_get_next(p);
+ }
+ return NULL;
+}
+
+ucBool ucSwitchTok_contains(ucSwitchTok* p, const char *switch_value) {
+ return NULL == ucSwitchTok_find(p, switch_value) ? ucBool_FALSE : ucBool_TRUE;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucTok.c Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,248 @@
+#include <stdlib.h>
+#include <string.h>
+#include "ucmd_internal.h"
+
+const char ucTok_separator = '\0';
+const char uc_cmd_terminator = '\n';
+
+static ucBool is_char_digit(char c) {
+ /* The native isdigit function in ctype.h was giving some weird behavior in the uVision simulator. */
+ static const char *digits = "0123456789";
+ const char *d;
+ for (d = digits; *d; d++) {
+ if (*d == c) {
+ return ucBool_TRUE;
+ }
+ }
+ return ucBool_FALSE;
+}
+
+int ucTok_get_length(ucTok *p) {
+ int length;
+ if (NULL == p) return 0;
+
+ for (length = 0; *p != ucTok_separator; length++, p++);
+
+ return length;
+}
+
+const char *ucTok_get_value(ucTok *p) {
+ if (NULL == p) return NULL;
+ return (const char*)p;
+}
+
+ucBool ucTok_equals(ucTok *p, const char *value) {
+ int i, len;
+
+ /* check if these pointers are the same */
+ if (value == p) return ucBool_TRUE;
+
+ /* make sure neither arg is null */
+ if (NULL == p) return ucBool_FALSE;
+ if (NULL == value) return ucBool_FALSE;
+
+ /* check if the string lengths are the same */
+ len = ucTok_get_length(p);
+ if (strlen(value) != len) return ucBool_FALSE;
+
+ /* check for character equality */
+ for (i = 0; i < len; i++) {
+ if (p[i] != value[i]) {
+ return ucBool_FALSE;
+ }
+ }
+
+ /* if we got here, then the strings are equal */
+ return ucBool_TRUE;
+}
+
+ucBool ucTok_is_numeric(ucTok *p) {
+ int i, len;
+ ucBool dec_found;
+
+ /* check if p is NULL */
+ if (NULL == p) return ucBool_FALSE;
+
+ /* get the length of the string */
+ len = ucTok_get_length(p);
+
+ /* numbers need to have at least 1 character */
+ if (len < 1) return ucBool_FALSE;
+
+ /* we are allowed to start with a '-' or '.' for negative numbers and decimals */
+ if ((p[0] == '-') || (p[0] == '.')) {
+
+ /* but we need more than 1 char if we do */
+ if (len < 2) return ucBool_FALSE;
+ }
+
+ // initialize vars
+ dec_found = ucBool_FALSE;
+
+ /* loop through the chars */
+ for (i = 0; i < len; i++) {
+
+ switch(p[i]) {
+
+ /* allow a dash only at the beginning */
+ case '-':
+ if (i != 0) return ucBool_FALSE;
+ break;
+
+ /* allow only 1 dot */
+ case '.':
+ if (dec_found) return ucBool_FALSE;
+ dec_found = ucBool_TRUE;
+ break;
+
+ /* everything else has to be a number */
+ default:
+ if (is_char_digit(p[i]) == ucBool_FALSE) return ucBool_FALSE;
+ break;
+ }
+ }
+
+ /* if we got here, it's a number */
+ return ucBool_TRUE;
+}
+
+ucBool ucTok_try_parse_numeric(ucTok *p, double *value) {
+ if (ucTok_is_numeric(p)) {
+ if (value) {
+ *value = atof(ucTok_get_value(p));
+ }
+ return ucBool_TRUE;
+ }
+ return ucBool_FALSE;
+}
+
+double ucTok_parse_numeric(ucTok *p) {
+ double value = 0;
+ ucTok_try_parse_numeric(p, &value);
+ return value;
+}
+
+ucBool ucTok_is_boolean(ucTok *p) {
+ int i, len;
+ const char *b[] = { ucTok_BOOLEAN_FALSE, ucTok_BOOLEAN_TRUE };
+ if (NULL == p) return ucBool_FALSE;
+ len = sizeof(b) / sizeof(b[0]);
+ for (i = 0; i < len; i++) {
+ if (ucTok_equals(p, b[i])) {
+ return ucBool_TRUE;
+ }
+ }
+ return ucBool_FALSE;
+}
+
+ucBool ucTok_try_parse_boolean(ucTok *p, ucBool *value) {
+ int i, len;
+ const char *t[] = { ucTok_BOOLEAN_TRUE };
+ const char *f[] = { ucTok_BOOLEAN_FALSE };
+ len = sizeof(t) / sizeof(t[0]);
+ for (i = 0; i < len; i++) {
+ if (ucTok_equals(p, t[i])) {
+ if (value) {
+ *value = ucBool_TRUE;
+ }
+ return ucBool_TRUE;
+ }
+ }
+ len = sizeof(f) / sizeof(f[0]);
+ for (i = 0; i < len; i++) {
+ if (ucTok_equals(p, f[i])) {
+ if (value) {
+ *value = ucBool_FALSE;
+ }
+ return ucBool_TRUE;
+ }
+ }
+ return ucBool_FALSE;
+}
+
+ucBool ucTok_parse_boolean(ucTok *p) {
+ ucBool value = ucBool_FALSE;
+ ucTok_try_parse_boolean(p, &value);
+ return value;
+}
+
+ucBool ucTok_is_switch(ucTok* p) {
+ int len = 0;
+
+ /* check for a null pointer */
+ if (NULL == p) return ucBool_FALSE;
+
+ /* get the length so we can use it */
+ len = ucTok_get_length(p);
+
+ /* check for at least 2 characters (one '-' and at least another char) */
+ if (len < 2) return ucBool_FALSE;
+
+ /* check if it starts with a '-' */
+ if (p[0] != '-') return ucBool_FALSE;
+
+ /* check if this is a numeric argument (negative numbers aren't switches) */
+ if (ucTok_is_numeric(p)) return ucBool_FALSE;
+
+ /* ok, it's a switch */
+ return ucBool_TRUE;
+}
+
+ucTok *ucTok_get_next(ucTok *p) {
+ int i;
+ if (NULL == p) return NULL;
+
+ /* loop until we've hit the max length */
+ i = 0;
+ while (ucTok_LENGTH_MAX > ++i) {
+
+ /* check if the previous character was a separator */
+ if (ucTok_separator == p[i - 1]) {
+
+ /* check if this character is the terminator */
+ if (uc_cmd_terminator == p[i]) {
+
+ /* it is, so no more tokens exist */
+ return NULL;
+ }
+
+ /* make sure this character isn't another separator */
+ if (ucTok_separator == p[i]) {
+ continue;
+ }
+
+ /* the previous character was a separator,
+ and this character is NOT the terminator,
+ OR another separator, so this character is
+ the start of a new token */
+ return (ucTok*)&p[i];
+ }
+ }
+
+ /* the max length was exceeded,
+ which probably means something
+ went wrong. */
+ return NULL;
+}
+
+int ucTok_count(ucTok *p) {
+ int count;
+
+ /* make sure we have a pointer */
+ if (NULL == p) return 0;
+
+ /* if the first character is the terminator, then we have no tokens */
+ if (p[0] == uc_cmd_terminator) return 0;
+
+ /* start off the count according to whether or not
+ we're starting at a token */
+ count = ucTok_separator == p[0] ? -1 : 0;
+
+ /* count the tokens in the chain */
+ while (NULL != p) {
+ count++;
+ p = ucTok_get_next(p);
+ }
+ return count;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucmd.h Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,1223 @@
+#ifndef UCMD_H
+#define UCMD_H
+
+#include <stdarg.h>
+#include <stddef.h>
+
+/* Sets the size of the command buffer when using
+ the command-line application framework. All
+ entered commands must have a size equal to or
+ less than this buffer's size. */
+#ifndef ucCmdLineApp_CMD_STR_SIZE
+#define ucCmdLineApp_CMD_STR_SIZE 200
+#endif
+
+/* Sets the size of the command response buffer.
+ All response strings must have a size equal to
+ or less than the size of this buffer to avoid
+ truncation. */
+#ifndef ucCmdLine_RESPONSE_SIZE
+#define ucCmdLine_RESPONSE_SIZE 200
+#endif
+
+/* Sets the number of available command options.
+ The number of created command options must be
+ equal to or less than this number. */
+#ifndef ucCmdLineOpt_COUNT
+#define ucCmdLineOpt_COUNT 10
+#endif
+
+/* Sets the number of available switch options.
+ The number of created switch options must be
+ equal to or less than this number. */
+#ifndef ucSwitchOpt_COUNT
+#define ucSwitchOpt_COUNT 50
+#endif
+
+/* Sets the number of available argument options.
+ This is the total number of options available
+ to commands and switches, combined. */
+#ifndef ucArgOpt_COUNT
+#define ucArgOpt_COUNT 50
+#endif
+
+/* Sets the maximum expected length of a single
+ token in a command line. */
+#ifndef ucTok_LENGTH_MAX
+#define ucTok_LENGTH_MAX ucCmdLineApp_CMD_STR_SIZE
+#endif
+
+#ifndef ucTok_BOOLEAN_TRUE
+#define ucTok_BOOLEAN_TRUE "1", "on", "yes", "true"
+#endif
+
+#ifndef ucTok_BOOLEAN_FALSE
+#define ucTok_BOOLEAN_FALSE "0", "off", "no", "false"
+#endif
+
+/* Sets the numeric type of numeric argument
+ options. */
+#ifndef ucArgOpt_NUMERIC_TYPE
+#define ucArgOpt_NUMERIC_TYPE double
+#endif
+
+/* Include this def when using the library with another
+ program on Windows.
+ Exported functions will be decorated with dllimport
+ to make them available to external programs. */
+#ifdef uc_DECLSPEC_DLLIMPORT
+#define uc_EXPORTED uc_EXTERN_C __declspec(dllimport)
+#endif
+
+/* Include this def when compiling this program on
+ Windows.
+ Exported functions will be decorated with dllexport
+ to make them available to external programs. */
+#ifdef uc_DECLSPEC_DLLEXPORT
+#define uc_EXPORTED uc_EXTERN_C __declspec(dllexport)
+#endif
+
+/* Prepend extern "C" if we're in a C++
+ compiler. */
+#ifdef __cplusplus
+#define uc_EXTERN_C extern "C"
+#else
+#define uc_EXTERN_C
+#endif
+
+/* Default to setting uc_EXPORTED to the result
+ of our extern "C" check. */
+#ifndef uc_EXPORTED
+#define uc_EXPORTED uc_EXTERN_C
+#endif
+
+/* Define NULL, if it hasn't been defined. */
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+/*
+ * Summary:
+ * Definition for the type returned
+ * by functions that use an error code.
+ */
+typedef int ucErr;
+
+/*
+ * Summary:
+ * Defines the value that represents no error.
+ */
+#define ucErr_NONE 0
+
+/*
+ * Summary:
+ * Boolean type definition. This definition is used
+ * to increase the readability of the source by replacing
+ * integer representations of boolean values with the
+ * more familiar "true" and "false" values.
+ */
+typedef enum ucBool {
+ ucBool_FALSE = 0,
+ ucBool_TRUE = !ucBool_FALSE
+} ucBool;
+
+/*
+ * Summary:
+ * Base structure for tokenized values in a command.
+ */
+typedef const char ucTok;
+
+/*
+ * Summary:
+ * Gets the length of the token.
+ * Returns:
+ * The number of characters in the token.
+ */
+uc_EXPORTED int ucTok_get_length(ucTok*);
+
+/*
+ * Summary:
+ * Determines whether or not the given token equals the value.
+ * Parameters:
+ * value: The value against which the token is checked for equality.
+ * Returns:
+ * ucBool_TRUE if the token value equals the given value. Otherwise, ucBool_FALSE.
+ */
+uc_EXPORTED ucBool ucTok_equals(ucTok*, const char *value);
+
+/*
+ * Summary:
+ * Determines whether or not the given token is considered numeric.
+ * Returns:
+ * ucBool_TRUE if the token is considered numeric. Otherwise, ucBool_FALSE.
+ */
+uc_EXPORTED ucBool ucTok_is_numeric(ucTok*);
+uc_EXPORTED ucBool ucTok_try_parse_numeric(ucTok*, double *value);
+uc_EXPORTED double ucTok_parse_numeric(ucTok*);
+uc_EXPORTED ucBool ucTok_is_boolean(ucTok*);
+uc_EXPORTED ucBool ucTok_try_parse_boolean(ucTok*, ucBool *value);
+uc_EXPORTED ucBool ucTok_parse_boolean(ucTok*);
+
+/*
+ * Summary:
+ * Determines whether or not the given token is considered a switch.
+ * Returns:
+ * ucBool_TRUE if the token is a switch. Otherwise, ucBool_FALSE.
+ */
+uc_EXPORTED ucBool ucTok_is_switch(ucTok*);
+
+/*
+ * Summary:
+ * Gets the next token in the list.
+ * Returns:
+ * A pointer to the token that comes next in the list, or NULL
+ * if no further tokens exist.
+ */
+uc_EXPORTED ucTok *ucTok_get_next(ucTok*);
+
+/*
+ * Summary:
+ * Counts the number of tokens in the linked list.
+ * Returns:
+ * The number of tokens in the list.
+ */
+uc_EXPORTED int ucTok_count(ucTok*);
+
+/*
+ * Summary:
+ * Gets the value of the token.
+ * Returns:
+ * The string value of the token.
+ */
+uc_EXPORTED const char *ucTok_get_value(ucTok*);
+
+/*
+ * Summary:
+ * An argument token. This type is a child of the
+ * base token type. All functions that take an
+ * instance of the base type can be used with an
+ * instance of this type.
+ */
+typedef const char ucArgTok;
+
+/*
+ * Summary:
+ * Gets the next argument after the given argument.
+ * Returns:
+ * The next argument in the list.
+ */
+uc_EXPORTED ucArgTok *ucArgTok_get_next(ucArgTok*);
+
+/*
+ * Summary:
+ * Counts the number of arguments in the linked list.
+ * Returns:
+ * The number of arguments in the list.
+ */
+uc_EXPORTED int ucArgTok_count(ucArgTok*);
+
+/*
+ * Summary:
+ * Finds the argument in the list with the specified value.
+ * Parameters:
+ * arg_value: The value of the argument to find.
+ * Returns:
+ * The argument with the specified value, or NULL if none exists.
+ */
+uc_EXPORTED ucArgTok *ucArgTok_find(ucArgTok*, const char *arg_value);
+
+/*
+ * Summary:
+ * Gets a value indicating whether or not the value exists in
+ * the argument list.
+ * Parameters:
+ * arg_value: The value of the argument to be found.
+ * Returns:
+ * ucBool_TRUE if an argument token with the given value is found.
+ * Otherwise, ucBool_FALSE.
+ */
+uc_EXPORTED ucBool ucArgTok_contains(ucArgTok*, const char *arg_value);
+
+/*
+ * Summary:
+ * Type definition for tokens (i.e. switch and command tokens)
+ * that contain arguments. This type is a child of the base
+ * token type. All functions that take an instance of the base
+ * type can be used with an instance of this type.
+ */
+typedef const char ucArgTokOwner;
+
+/*
+ * Summary
+ * Gets the first argument that belongs to the given owner.
+ * Returns:
+ * The first argument that belongs to the owner, or NULL if
+ * no arguments exist.
+ */
+uc_EXPORTED ucArgTok *ucArgTokOwner_get_arg(ucArgTokOwner*);
+
+/*
+ * Summary:
+ * A switch token. This type is a child of the
+ * base token type. All functions that take an
+ * instance of the base type can be used with an
+ * instance of this type.
+ */
+typedef const char ucSwitchTok;
+
+/*
+ * Summary:
+ * Gets the next switch token after the given token.
+ * Returns:
+ * The next switch token after the given token.
+ */
+uc_EXPORTED ucSwitchTok *ucSwitchTok_get_next(ucSwitchTok*);
+
+/*
+ * Summary:
+ * Counts the number of switches in the linked list.
+ * Returns:
+ * The number of switches in the list.
+ */
+uc_EXPORTED int ucSwitchTok_count(ucSwitchTok*);
+
+/*
+ * Summary:
+ * Finds the switch with the specified value.
+ * Parameters:
+ * switch_value: The value of the switch to be found.
+ * Returns:
+ * The switch with the specified value, or NULL if none exist.
+ */
+uc_EXPORTED ucSwitchTok *ucSwitchTok_find(ucSwitchTok*, const char *switch_value);
+
+/*
+ * Summary:
+ * Gets a value indicating whether or not a value exists in the switch list.
+ * Parameters:
+ * switch_value: The value of the switch to be found.
+ * Returns:
+ * ucBool_TRUE if a switch with the given value was found in the list. Otherwise,
+ * ucBool_FALSE.
+ */
+uc_EXPORTED ucBool ucSwitchTok_contains(ucSwitchTok*, const char *switch_value);
+
+/*
+ * Summary:
+ * Gets the first argument token of the switch.
+ * Returns:
+ * A pointer to the first argument of the switch, or NULL
+ * if no arguments exist.
+ */
+uc_EXPORTED ucArgTok *ucSwitchTok_get_arg(ucSwitchTok*);
+
+/*
+ * Summary:
+ * Type definition for a command token. This is
+ * the first token (the command part) in a list
+ * of tokens. This type is a child of the base
+ * token type. All functions that take an instance
+ * of the base type can be used with an instance
+ * of this type.
+ */
+typedef const char ucCmdTok;
+
+/*
+ * Summary:
+ * Gets the first argument of the command.
+ * Returns:
+ * A pointer to the first argument token, or NULL if no arguments
+ * exist for the command.
+ */
+uc_EXPORTED ucArgTok *ucCmdTok_get_arg(ucCmdTok*);
+
+/*
+ * Summary:
+ * Gets the first switch of the command.
+ * Returns:
+ * A pointer to the first switch token of the command, or NULL
+ * if no switches exist.
+ */
+uc_EXPORTED ucSwitchTok *ucCmdTok_get_switch(ucCmdTok*);
+
+/*
+ * Summary:
+ * A group of tokens that represent the first
+ * of each token type in a command.
+ */
+typedef struct ucCmdLineToks {
+
+ /*
+ * Summary:
+ * The command token of the command. This token's
+ * value is the invoked command.
+ */
+ ucCmdTok *cmd_tok;
+
+ /*
+ * Summary:
+ * The command's first argument token, or
+ * NULL if no arguments exist.
+ */
+ ucArgTok *arg_tok;
+
+ /*
+ * Summary:
+ * The command's first switch token, or
+ * NULL if no switches exist.
+ */
+ ucSwitchTok *switch_tok;
+
+} ucCmdLineToks;
+
+/*
+ * Summary:
+ * Gets the command token of the command. This token's
+ * value is the invoked command.
+ * Returns:
+ * A pointer to the command token.
+ */
+uc_EXPORTED ucCmdTok *ucCmdLineToks_get_cmd_tok(ucCmdLineToks*);
+
+/*
+ * Summary:
+ * The command's first argument token, or
+ * NULL if no arguments exist.
+ * Returns:
+ * A pointer to the argument token, or NULL if no argument
+ * tokens exist.
+ */
+uc_EXPORTED ucArgTok *ucCmdLineToks_get_arg_tok(ucCmdLineToks*);
+
+/*
+ * Summary:
+ * The command's first switch token, or
+ * NULL if no switches exist.
+ * Returns:
+ * A pointer to the switch token, or NULL if no switch tokens exist.
+ */
+uc_EXPORTED ucSwitchTok *ucCmdLineToks_get_switch_tok(ucCmdLineToks*);
+
+/*
+ * Summary:
+ * A command structure. This structure consists
+ * of the parsed command and the ability to respond.
+ */
+typedef struct ucCmdLine ucCmdLine;
+
+/*
+ * Summary:
+ * The type of function used by a command structure
+ * to transmit responses.
+ * Parameters:
+ * response: The string to be transmitted.
+ * state: A stateful object.
+ */
+typedef void (ucCmdLine_TransmitFunc)(const char *response, void *state);
+
+/*
+ * Summary:
+ * The type of function used by a command structure
+ * to determine whether or not the command is canceled.
+ * Parameters:
+ * state: A stateful object.
+ * Returns:
+ * ucBool_TRUE if the command has been canceled. Otherwise, ucBool_FALSE.
+ */
+typedef ucBool (ucCmdLine_IsCanceledFunc)(void *state);
+
+/*
+ * Summary:
+ * The type of the function that is invoked when an
+ * invalid command is encountered. An invalid command
+ * is one that does not exist in the list of command
+ * options.
+ * Parameters:
+ * invalid_command: The invalid command string that was encountered.
+ * state: The stateful object for this callback.
+ * Returns:
+ * ucBool_TRUE if the invalid command was handeled. Otherwise, ucBool_FALSE.
+ */
+typedef ucBool (ucCmdLine_HandleInvalidCommandFunc)(const char *invalid_command, void *state);
+
+/*
+ * Summary:
+ * Gets the command token from the command structure.
+ * Returns:
+ * A pointer to the command token of the structure.
+ */
+uc_EXPORTED ucCmdTok *ucCmdLine_get_cmd_tok(ucCmdLine*);
+
+/*
+ * Summary:
+ * Sets the command token for the structure.
+ * Parameters:
+ * value: The command token.
+ */
+uc_EXPORTED void ucCmdLine_set_cmd_tok(ucCmdLine*, ucCmdTok *value);
+
+/*
+ * Summary:
+ * Fills the buffer with the specified tokens of the command structure.
+ * Parameters:
+ * buffer: A pointer to the token structure whose properties will be set per the command.
+ * Returns:
+ * A pointer to the buffer.
+ */
+uc_EXPORTED ucCmdLineToks *ucCmdLine_get_cmd_toks(ucCmdLine*, ucCmdLineToks *buffer);
+
+/*
+ * Summary:
+ * Sets the function used by the command structure to transmit responses.
+ * Parameters:
+ * value: A pointer to the function used to transmit responses.
+ */
+uc_EXPORTED void ucCmdLine_set_transmit(ucCmdLine*, ucCmdLine_TransmitFunc *value);
+
+/*
+ * Summary:
+ * Gets the function used by the command structure to transmit responses.
+ * Returns:
+ * A pointer to the function used by the structure to transmit responses.
+ */
+uc_EXPORTED ucCmdLine_TransmitFunc *ucCmdLine_get_transmit(ucCmdLine*);
+
+/*
+ * Summary:
+ * Gets the stateful object passed to the command's transmit function.
+ * Returns:
+ * A pointer to the stateful object passed to the command's transmit function.
+ */
+uc_EXPORTED void *ucCmdLine_get_transmit_state(ucCmdLine*);
+
+/*
+ * Summary:
+ * Sets the stateful object passed to the command's transmit function.
+ * Parameters:
+ * value: A pointer to the stateful object that is passed to the command's transmit function.
+ */
+uc_EXPORTED void ucCmdLine_set_transmit_state(ucCmdLine*, void *value);
+
+/*
+ * Summary:
+ * Determines whether or not the command has been canceled.
+ * Returns:
+ * ucBool_TRUE if the command has been canceled. Otherwise, ucBool_FALSE.
+ */
+uc_EXPORTED ucBool ucCmdLine_is_canceled(ucCmdLine*);
+
+/*
+ * Summary:
+ * Sets the function used by the command structure to check for cancellation.
+ * Parameters:
+ * value: A pointer to the function used to check for cancellation.
+ */
+uc_EXPORTED void ucCmdLine_set_is_canceled(ucCmdLine*, ucCmdLine_IsCanceledFunc *value);
+
+/*
+ * Summary:
+ * Gets the function used by the command structure to check for cancellation.
+ * Returns:
+ * A pointer to the function used to check for cancellation.
+ */
+uc_EXPORTED ucCmdLine_IsCanceledFunc *ucCmdLine_get_is_canceled(ucCmdLine*);
+
+/*
+ * Summary:
+ * Gets the stateful object passed to the command's cancellation function.
+ * Returns:
+ * A pointer to the stateful object passed to the command's cancellation function.
+ */
+uc_EXPORTED void *ucCmdLine_get_is_canceled_state(ucCmdLine*);
+
+/*
+ * Summary:
+ * Sets the stateful object passed to the command's cancellation function.
+ * Parameters:
+ * value: The stateful object passed to the command's cancellation function.
+ */
+uc_EXPORTED void ucCmdLine_set_is_canceled_state(ucCmdLine*, void *value);
+
+uc_EXPORTED void ucCmdLine_set_handle_invalid_command(ucCmdLine*, ucCmdLine_HandleInvalidCommandFunc *value);
+
+uc_EXPORTED ucCmdLine_HandleInvalidCommandFunc *ucCmdLine_get_handle_invalid_command(ucCmdLine*);
+
+uc_EXPORTED void ucCmdLine_set_handle_invalid_command_state(ucCmdLine*, void *value);
+
+uc_EXPORTED void *ucCmdLine_get_handle_invalid_command_state(ucCmdLine*);
+
+uc_EXPORTED size_t ucCmdLine_get_response_size_max(ucCmdLine*);
+
+/*
+ * Summary:
+ * Gets a static, default instance of the command structure.
+ * Returns:
+ * The static, default instance of the command structure.
+ */
+uc_EXPORTED ucCmdLine *ucCmdLine_get_instance(void);
+
+/*
+ * Summary:
+ * Formats the command's response using the given parameters.
+ * Parameters:
+ * format: The format string.
+ * ...: Parameters to the format string.
+ * Returns:
+ * The formatted string.
+ */
+uc_EXPORTED const char *ucCmdLine_format_response(ucCmdLine*, const char *format, ...);
+
+/*
+ * Summary:
+ * Formats the command's response using the given parameters.
+ * Parameters:
+ * format: The format string.
+ * arg_list: A variable length argument list with parameters to the format string.
+ * Returns:
+ * The formatted string.
+ */
+uc_EXPORTED const char *ucCmdLine_format_response_va(ucCmdLine*, const char *format, va_list arg_list);
+
+/*
+ * Summary
+ * Responds to the command.
+ * Parameters:
+ * response: The response string.
+ */
+uc_EXPORTED void ucCmdLine_respond(ucCmdLine*, const char *response);
+
+/*
+ * Summary:
+ * Sets whether or not the command structure is quiet, meaning no response
+ * strings will be sent.
+ * Parameters:
+ * value: A boolean true value if the command structure should not send
+ * any response strings. Otherwise, false.
+ */
+uc_EXPORTED void ucCmdLine_set_is_quiet(ucCmdLine*, ucBool value);
+
+/*
+ * Summary:
+ * Gets a flag that indicates whether or not the command structure is quiet,
+ * meaning no response strings are sent.
+ * Returns:
+ * A boolean true value if the command structure is not sending any
+ * response strings. Otherwise, false.
+ */
+uc_EXPORTED ucBool ucCmdLine_get_is_quiet(ucCmdLine*);
+
+uc_EXPORTED void ucCmdLine_acknowledge_command(ucCmdLine*);
+uc_EXPORTED const char* ucCmdLine_get_command_acknowledgment(ucCmdLine*);
+uc_EXPORTED const char* ucCmdLine_get_response_terminator(ucCmdLine*);
+uc_EXPORTED void ucCmdLine_set_response_terminator(ucCmdLine*, const char *value);
+uc_EXPORTED void ucCmdLine_set_command_acknowledgment(ucCmdLine*, const char *value);
+uc_EXPORTED void ucCmdLine_terminate_response(ucCmdLine*);
+
+/*
+ * Summary:
+ * Base type for command, argument, and switch options.
+ */
+typedef struct ucOpt ucOpt;
+
+/*
+ * Summary:
+ * Gets the name of the option.
+ * Returns:
+ * The name of the option.
+ */
+uc_EXPORTED const char* ucOpt_get_name(ucOpt*);
+
+/*
+ * Summary:
+ * Gets the description of the option.
+ * Returns:
+ * The description of the option.
+ */
+uc_EXPORTED const char *ucOpt_get_desc(ucOpt*);
+
+/*
+ * Summary:
+ * Gets a flag that indicates whether or not the option
+ * is required.
+ * Returns:
+ * ucBool_TRUE if the option is required. Otherwise, ucBool_FALSE.
+ */
+uc_EXPORTED ucBool ucOpt_is_required(ucOpt*);
+
+/*
+ * Summary:
+ * Uses the provided command structure to send help information
+ * for this option.
+ * Parameters:
+ * cmd: A pointer to the command structure used to respond
+ * with the help information.
+ * prefix: A string used to prefix the help information.
+ */
+uc_EXPORTED void ucOpt_send_help(ucOpt*, ucCmdLine *cmd, const char *prefix);
+
+/*
+ * Summary:
+ * An argument option. This type is a child
+ * of the base option type.
+ */
+typedef struct ucArgOpt ucArgOpt;
+
+/*
+ * Summary:
+ * Gets the minimum allowed token count of the argument option.
+ * Returns:
+ * The minimum number of argument tokens allowed for this option.
+ */
+uc_EXPORTED int ucArgOpt_get_min_tok_count(ucArgOpt*);
+
+/*
+ * Summary:
+ * Gets the maximum allowed token count of the argument option.
+ * Returns:
+ * The maximum number of argument tokens allowed for this option.
+ */
+uc_EXPORTED int ucArgOpt_get_max_tok_count(ucArgOpt*);
+
+uc_EXPORTED ucBool ucArgOpt_is_boolean(ucArgOpt*);
+
+/*
+ * Summary:
+ * Gets a flag that indicates whether or not this argument option
+ * is numeric.
+ * Returns:
+ * ucBool_TRUE if the argument is numeric. Otherwise, ucBool_FALSE.
+ */
+uc_EXPORTED ucBool ucArgOpt_is_numeric(ucArgOpt*);
+
+/*
+ * Summary:
+ * Gets the minimum value if this argument option is numeric.
+ * Returns:
+ * The minimum numeric value of the argument.
+ */
+uc_EXPORTED ucArgOpt_NUMERIC_TYPE ucArgOpt_get_numeric_min(ucArgOpt*);
+
+/*
+ * Summary:
+ * Gets the maximum value if this argument is numeric.
+ * Returns:
+ * The maximum numeric value of the argument.
+ */
+uc_EXPORTED ucArgOpt_NUMERIC_TYPE ucArgOpt_get_numeric_max(ucArgOpt*);
+
+/*
+ * Summary:
+ * Creates a new argument option.
+ * Parameters:
+ * name: The name of the option.
+ * desc: The description of the option.
+ * next: The next option in the chain that the created option precedes,
+ * or NULL if the created option is the last.
+ * Returns:
+ * A pointer to the newly created argument option.
+ */
+uc_EXPORTED ucArgOpt *ucArgOpt_create(const char *name, const char *desc, ucArgOpt *next);
+
+/*
+ * Summary:
+ * Creates a new argument option that allows multiple tokens.
+ * Parameters:
+ * name: The name of the option.
+ * desc: The description of the option.
+ * min_tok_count: The minimum number of argument tokens allowed for this option.
+ * max_tok_count: The maximum number of argument tokens allowed for this option.
+ * Returns:
+ * A pointer to the newly created argument option.
+ */
+uc_EXPORTED ucArgOpt *ucArgOpt_create_multiple(const char *name, const char *desc, int min_tok_count, int max_tok_count);
+
+/*
+ * Summary:
+ * Creates a new, required argument option.
+ * Parameters:
+ * name: The name of the option.
+ * desc: The description of the option.
+ * next: The next option in the chain that the created option precedes,
+ * or NULL if the created option is the last.
+ * Returns:
+ * A pointer to the newly created argument option. The option will have its
+ * 'required' property set to true.
+ */
+uc_EXPORTED ucArgOpt *ucArgOpt_create_required(const char *name, const char *desc, ucArgOpt *next);
+
+uc_EXPORTED ucArgOpt *ucArgOpt_create_boolean(const char *desc, ucArgOpt *next);
+uc_EXPORTED ucArgOpt *ucArgOpt_create_required_boolean(const char *desc, ucArgOpt *next);
+
+/*
+ * Summary:
+ * Creates a new, numeric argument option.
+ * Parameters:
+ * desc: The description of the argument.
+ * numeric_min: The minimum value of the argument.
+ * numeric_max: The maximum value of the argument.
+ * next: A pointer to the next option in the chain that the created option precedes,
+ * or NULL if the created option is the last.
+ * Returns:
+ * A pointer to the newly created argument option.
+ */
+uc_EXPORTED ucArgOpt *ucArgOpt_create_numeric(const char *desc, ucArgOpt_NUMERIC_TYPE numeric_min, ucArgOpt_NUMERIC_TYPE numeric_max, ucArgOpt *next);
+
+/*
+ * Summary:
+ * Creates a new, numeric argument option that accepts multiple argument tokens.
+ * Parameters:
+ * desc: The description of the argument.
+ * min_tok_count: The minimum number of allowed argument tokens.
+ * max_tok_count: The maximum number of allowed argument tokens.
+ * numeric_min: The minimum value of the argument.
+ * numeric_max: The maximum value of the argument.
+ * Returns:
+ * A pointer to the newly created argument option.
+ */
+uc_EXPORTED ucArgOpt *ucArgOpt_create_multiple_numeric(const char *desc, int min_tok_count, int max_tok_count, ucArgOpt_NUMERIC_TYPE numeric_min, ucArgOpt_NUMERIC_TYPE numeric_max);
+
+/*
+ * Summary:
+ * Creates a new, numeric, required argument option.
+ * Parameters:
+ * desc: The description of the argument.
+ * numeric_min: The minimum value of the argument.
+ * numeric_max: The maximum value of the argument.
+ * next: A pointer to the next option in the chain that the created option precedes,
+ * or NULL if the created option is the last.
+ * Returns:
+ * A pointer to the newly created argument option. The option will have its
+ * 'required' property set to true.
+ */
+uc_EXPORTED ucArgOpt *ucArgOpt_create_required_numeric(const char *desc, ucArgOpt_NUMERIC_TYPE numeric_min, ucArgOpt_NUMERIC_TYPE numeric_max, ucArgOpt *next);
+
+/*
+ * Summary:
+ * Gets the next argument option after the given option.
+ * Returns:
+ * A pointer to the option that the given option precedes,
+ * or NULL of no further options exist.
+ */
+uc_EXPORTED ucArgOpt *ucArgOpt_get_next(ucArgOpt*);
+
+/*
+ * Summary:
+ * Releases memory used by the argument option.
+ */
+uc_EXPORTED void ucArgOpt_destroy(ucArgOpt*);
+
+/*
+ * Summary:
+ * Releases memory used by the argument option
+ * and all proceeding options in the list.
+ */
+uc_EXPORTED void ucArgOpt_destroy_chain(ucArgOpt*);
+
+/*
+ * Summary:
+ * Base structure for options (switches and commands)
+ * that contain argument options. This type is a child
+ * of the base option type.
+ */
+typedef struct ucArgOptOwner ucArgOptOwner;
+
+/*
+ * Summary:
+ * Gets the first argument option of the given option owner.
+ * Returns:
+ * A pointer to the first argument option of the given option owner.
+ */
+uc_EXPORTED ucArgOpt *ucArgOptOwner_get_arg_opt(ucArgOptOwner*);
+
+/*
+ * Summary:
+ * A command switch option. This type is a child
+ * of the base option type.
+ */
+typedef struct ucSwitchOpt ucSwitchOpt;
+
+/*
+ * Summary:
+ * Creates a new switch option.
+ * Parameters:
+ * name: The name of the switch.
+ * desc: A description of the switch.
+ * arg_opt: The first argument option of the switch.
+ * next: The switch option that the created option precedes,
+ * or NULL if no further switch options exist.
+ * Returns:
+ * A pointer to the newly created switch option.
+ */
+uc_EXPORTED ucSwitchOpt *ucSwitchOpt_create(const char *name, const char *desc, ucArgOpt *arg_opt, ucSwitchOpt *next);
+
+/*
+ * Summary:
+ * Creates a new, required switch option.
+ * Parameters:
+ * name: The name of the switch.
+ * desc: A description of the switch.
+ * arg_opt: The first argument option of the switch.
+ * next: The switch option that the created option precedes,
+ * or NULL if no further switch options exist.
+ * Returns:
+ * A pointer to the newly created switch option. The option's
+ * 'required' property will be set to true.
+ */
+uc_EXPORTED ucSwitchOpt *ucSwitchOpt_create_required(const char *name, const char *desc, ucArgOpt *arg_opt, ucSwitchOpt *next);
+
+/*
+ * Summary:
+ * Gets the first argument option of the given switch.
+ * Returns:
+ * A pointer to the first argument option of the switch, or NULL
+ * if no argument options exist.
+ */
+uc_EXPORTED ucArgOpt *ucSwitchOpt_get_arg_opt(ucSwitchOpt*);
+
+/*
+ * Summary:
+ * Finds the switch option in the linked list with the given name.
+ * Parameters:
+ * name: The name of the switch option to be found.
+ * Returns:
+ * The switch option with the given name, or NULL if
+ * no switch option is found.
+ */
+uc_EXPORTED ucSwitchOpt *ucSwitchOpt_find(ucSwitchOpt*, const char *name);
+
+/*
+ * Summary:
+ * Gets the next switch option.
+ * Returns:
+ * A pointer to the next switch option in the list, or NULL
+ * if no further options exist.
+ */
+uc_EXPORTED ucSwitchOpt *ucSwitchOpt_get_next(ucSwitchOpt*);
+
+/*
+ * Summary:
+ * Releases memory used by the switch option.
+ */
+uc_EXPORTED void ucSwitchOpt_destroy(ucSwitchOpt*);
+
+/*
+ * Summary:
+ * Releases memory used by the switch option and all
+ * proceeding options in the list. All memory used by
+ * any argument options belonging to the switches in
+ * the list is also released.
+ */
+uc_EXPORTED void ucSwitchOpt_destroy_chain(ucSwitchOpt*);
+
+/*
+ * Summary:
+ * Type that can be used to parse command lines.
+ * The result of the parse can be used as the command
+ * token for a command structure.
+ */
+typedef struct ucCmdParser ucCmdParser;
+
+/*
+ * Summary:
+ * Gets a static, default instance of the parser.
+ * Returns:
+ * The static, default instance of the parser, or NULL
+ * if an error occurred.
+ */
+uc_EXPORTED ucCmdParser *ucCmdParser_get_instance(void);
+
+/*
+ * Summary:
+ * Parses a command so that it can be used as a command token.
+ * Parameters:
+ * cmd: The command string to be parsed. This string is mutated.
+ * Returns:
+ * A pointer to the command token that was parsed, or NULL if an
+ * error occurred.
+ */
+uc_EXPORTED ucCmdTok *ucCmdParser_parse(ucCmdParser*, char *cmd);
+
+/*
+ * Summary:
+ * A command option. This type is a child of the
+ * base option type.
+ */
+typedef struct ucCmdLineOpt ucCmdLineOpt;
+
+/*
+ * Summary:
+ * Defines the signature of the function called when a command option is processed.
+ * Parameters:
+ * cmd: The parsed command structure that represents the function parameters.
+ * state: The state pointer with which the command option was created.
+ * Returns:
+ * A message that can be used to respond to the command.
+ */
+typedef const char *(ucCmdLineOpt_Func)(ucCmdLine *cmd, void *state);
+
+/*
+ * Summary:
+ * Creates a new command option.
+ * Parameters:
+ * func: A pointer to the function that is called when this command is invoked or selected.
+ * state: A pointer that gets passed to the function to maintain state.
+ * name: The name of the command.
+ * desc: The description of the command.
+ * arg_opt: The argument options available to the command.
+ * switch_opt: The switch options available to the command.
+ * next: The next command that the created command precedes, or NULL if no further commands exist.
+ * Returns:
+ * A pointer to the newly created command option.
+ */
+uc_EXPORTED ucCmdLineOpt *ucCmdLineOpt_create(ucCmdLineOpt_Func *func, void *state, const char *name, const char *desc, ucArgOpt *arg_opt, ucSwitchOpt *switch_opt, ucCmdLineOpt* next);
+
+/*
+ * Summary:
+ * Gets the next command option after the given option.
+ * Returns:
+ * A pointer to the next command option.
+ */
+uc_EXPORTED ucCmdLineOpt *ucCmdLineOpt_get_next(ucCmdLineOpt*);
+
+/*
+ * Summary:
+ * Gets the first argument option of the command.
+ * Returns:
+ * A pointer to the first argument option of the command,
+ * or NULL if no argument options exist.
+ */
+uc_EXPORTED ucArgOpt *ucCmdLineOpt_get_arg_opt(ucCmdLineOpt*);
+
+/*
+ * Summary:
+ * Gets the first switch option of the command option.
+ * Returns:
+ * A pointer to the first switch option of the command option,
+ * or NULL if no switch options exist.
+ */
+uc_EXPORTED ucSwitchOpt *ucCmdLineOpt_get_switch_opt(ucCmdLineOpt*);
+
+/*
+ * Summary:
+ * Finds the command option that matches the given name.
+ * Parameters:
+ * name: The name of the command whose option is to be found.
+ * Returns:
+ * A pointer to the command option that matches the given name, or NULL
+ * if no option is found.
+ */
+uc_EXPORTED ucCmdLineOpt *ucCmdLineOpt_find_by_name(ucCmdLineOpt*, const char *name);
+
+/*
+ * Summary:
+ * Gets the pointer to the function invoked when the command option
+ * is processed.
+ * Returns:
+ * A pointer to the function invoked when the command option is processed.
+ */
+uc_EXPORTED ucCmdLineOpt_Func *ucCmdLineOpt_get_func(ucCmdLineOpt*);
+
+/*
+ * Summary:
+ * Gets the state pointer that is passed to the command option's function
+ * when it is invoked.
+ * Returns:
+ * A pointer to the command option's state.
+ */
+uc_EXPORTED void *ucCmdLineOpt_get_state(ucCmdLineOpt*);
+
+/*
+ * Summary:
+ * Releases memory used by the command option.
+ */
+uc_EXPORTED void ucCmdLineOpt_destroy(ucCmdLineOpt*);
+
+/*
+ * Summary:
+ * Releases memory used by the command option and all proceeding options
+ * in the list. All memory used by any argument options, switch options,
+ * and switch-argument options is also released.
+ */
+uc_EXPORTED void ucCmdLineOpt_destroy_chain(ucCmdLineOpt*);
+
+/*
+ * Summary:
+ * Invokes the function of the command option that matches the command structure.
+ * Parameters:
+ * cmd: The command structure whose option is invoked.
+ * Returns:
+ * The response to the command.
+ */
+uc_EXPORTED const char *ucCmdLineOpt_process(ucCmdLineOpt*, ucCmdLine *cmd);
+
+/*
+ * Summary:
+ * Uses the provided command structure to respond with a usage string
+ * for this command option.
+ * Parameters:
+ * cmd: The command structure used to respond with the usage string.
+ */
+uc_EXPORTED void ucCmdLineOpt_send_usage(ucCmdLineOpt*, ucCmdLine *cmd);
+
+/*
+ * Summary:
+ * Uses the provided command structure to respond with help information
+ * for the this command option.
+ * Parameters:
+ * cmd: The command structure used to respond with the help information.
+ */
+uc_EXPORTED void ucCmdLineOpt_send_help(ucCmdLineOpt*, ucCmdLine *cmd);
+
+/*
+ * Summary:
+ * An application that runs with a set of command options.
+ */
+typedef struct ucCmdLineApp ucCmdLineApp;
+
+/*
+ * Summary:
+ * The type of the function used by an application to
+ * receive data.
+ * Parameters:
+ * buf: A string buffer that can be used to store the data received.
+ * buf_size: The size of the string buffer used to store received data.
+ * state: A stateful object.
+ * Returns:
+ * The data that was received.
+ */
+typedef char *(ucCmdLineApp_ReceiveFunc)(char *buf, size_t buf_size, void *state);
+
+/*
+ * Summary:
+ * Sets the escape string that will cause the app to exit.
+ * Parameters:
+ * value: The escape string that, when returned in a response,
+ * causes the app to exit.
+ */
+uc_EXPORTED void ucCmdLineApp_set_escape_response(ucCmdLineApp*, const char *value);
+
+/*
+ * Summary:
+ * Gets the escape string that causes the app to exit.
+ * Returns:
+ * The escape string that, when returned in a response,
+ * causes the app to exit.
+ */
+uc_EXPORTED const char *ucCmdLineApp_get_escape_response(ucCmdLineApp*);
+
+/*
+ * Summary:
+ * Runs the application with the given options.
+ * Parameters:
+ * cmd_opt: A pointer to the first command option for the app.
+ * Returns:
+ * An error code, if one occurred.
+ */
+uc_EXPORTED ucErr ucCmdLineApp_run(ucCmdLineApp*, ucCmdLineOpt *cmd_opt);
+
+/*
+ * Summary:
+ * Gets a static, default instance of the application.
+ * Returns:
+ * The static, default instance of the application.
+ */
+uc_EXPORTED ucCmdLineApp *ucCmdLineApp_get_instance(void);
+
+/*
+ * Summary:
+ * Sets the function that the app uses to receive data.
+ * Parameters:
+ * value: A pointer to the function used to receive data.
+ */
+uc_EXPORTED void ucCmdLineApp_set_receive(ucCmdLineApp*, ucCmdLineApp_ReceiveFunc *value);
+
+/*
+ * Summary:
+ * Gets the function that the app uses to receive data.
+ * Returns:
+ * A pointer to the function used to receive data.
+ */
+uc_EXPORTED ucCmdLineApp_ReceiveFunc *ucCmdLineApp_get_receive(ucCmdLineApp*);
+
+/*
+ * Summary:
+ * Gets the stateful object passed to the application's receive function.
+ * Returns:
+ * A pointer to the stateful object passed to the application's receive function.
+ */
+uc_EXPORTED void *ucCmdLineApp_get_receive_state(ucCmdLineApp*);
+
+/*
+ * Summary:
+ * Sets the stateful object passed to the application's receive function.
+ * Parameters:
+ * value: The stateful object passed to the application's receive function.
+ */
+uc_EXPORTED void ucCmdLineApp_set_receive_state(ucCmdLineApp*, void *value);
+
+/*
+ * Summary:
+ * Sets the command used to quit the application.
+ * Parameters:
+ * value: The value of the command that quits the application.
+ */
+uc_EXPORTED void ucCmdLineApp_set_quit_command(ucCmdLineApp*, const char *value);
+
+/*
+ * Summary:
+ * Gets the value of the command that quits the application.
+ * Returns:
+ * The value of the command that quits the application.
+ */
+uc_EXPORTED const char *ucCmdLineApp_get_quit_command(ucCmdLineApp*);
+
+/*
+ * Summary:
+ * Sets the value of the command that shows help information.
+ * Parameters:
+ * value: The value of the command that shows help information.
+ */
+uc_EXPORTED void ucCmdLineApp_set_help_command(ucCmdLineApp*, const char *value);
+
+/*
+ * Summary:
+ * Gets the value of the command that shows help information.
+ * Returns:
+ * The value of the command that shows help information.
+ */
+uc_EXPORTED const char *ucCmdLineApp_get_help_command(ucCmdLineApp*);
+
+/*
+ * Summary:
+ * Sets the command structure that the application uses.
+ * Parameters:
+ * value: The command structure to be used by the application.
+ */
+uc_EXPORTED void ucCmdLineApp_set_cmd(ucCmdLineApp*, ucCmdLine *value);
+
+/*
+ * Summary:
+ * Gets the command structure used by the application.
+ * Returns:
+ * A pointer to the command structure used by the application.
+ */
+uc_EXPORTED ucCmdLine *ucCmdLineApp_get_cmd(ucCmdLineApp*);
+
+/*
+ * Summary:
+ * Gets the command parser used by the application.
+ * Returns:
+ * A pointer to the command parser used by the application.
+ */
+uc_EXPORTED ucCmdParser *ucCmdLineApp_get_cmd_parser(ucCmdLineApp*);
+
+/*
+ * Summary:
+ * Gets the size of the application's command-string buffer.
+ * Returns:
+ * The size of the command-string buffer.
+ */
+uc_EXPORTED size_t ucCmdLineApp_get_cmd_str_size_max(ucCmdLineApp *p);
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ucmd_internal.h Mon Oct 12 21:09:07 2015 +0000
@@ -0,0 +1,131 @@
+#ifndef UCMD_INTERNAL_H
+#define UCMD_INTERNAL_H
+
+#include "ucmd.h"
+
+extern const char uc_cmd_terminator;
+extern const char ucTok_separator;
+extern const char* ucOpt_validation_err_invalid_argument_prefix;
+extern const char* ucOpt_validation_err_invalid_switch_prefix;
+extern const char* ucOpt_validation_err_invalid_switch_argument_prefix;
+
+ struct ucCmdParser {
+ ucCmdTok* (*parse)(ucCmdParser *p, char *cmd); };
+
+uc_EXPORTED ucOpt* ucOpt_init(ucOpt*, const char *name, const char *desc, ucBool is_required);
+ struct ucOpt {
+ const char* name;
+ const char* desc;
+ ucBool is_required; };
+
+uc_EXPORTED const char* ucArgOpt_format_validation_err(ucArgOpt*, ucCmdLine *cmd, ucArgTok *arg_tok, const char *switch_name);
+uc_EXPORTED ucArgOpt* ucArgOpt_init(ucArgOpt*, const char *name, const char *desc, ucBool is_required, int min_tok_count, int max_tok_count, ucBool is_boolean, ucBool is_numeric, ucArgOpt_NUMERIC_TYPE numeric_min, ucArgOpt_NUMERIC_TYPE numeric_max, ucArgOpt *next);
+ struct ucArgOpt {
+ ucOpt base;
+ ucBool is_boolean;
+ ucBool is_numeric;
+ ucArgOpt_NUMERIC_TYPE numeric_min;
+ ucArgOpt_NUMERIC_TYPE numeric_max;
+ int max_tok_count;
+ int min_tok_count;
+ ucArgOpt* next; };
+
+uc_EXPORTED const char* ucArgOptOwner_format_validation_err(ucArgOptOwner*, ucCmdLine *cmd, ucArgTok *arg_tok, const char *switch_name);
+uc_EXPORTED ucArgOptOwner* ucArgOptOwner_init(ucArgOptOwner*, const char *name, const char *desc, ucBool is_required, ucArgOpt *arg_opt);
+ struct ucArgOptOwner {
+ ucOpt base;
+ ucArgOpt* arg_opt; };
+
+uc_EXPORTED const char* ucSwitchOpt_format_validation_err(ucSwitchOpt*, ucCmdLine *cmd, ucSwitchTok *switch_tok);
+uc_EXPORTED ucSwitchOpt* ucSwitchOpt_init(ucSwitchOpt*, const char *name, const char *desc, ucBool is_required, ucArgOpt *arg_opt, ucSwitchOpt *next);
+ struct ucSwitchOpt {
+ ucArgOptOwner base;
+ ucSwitchOpt* next; };
+
+uc_EXPORTED ucBool ucCmdLine_handle_invalid_command(ucCmdLine*, const char *invalid_command);
+uc_EXPORTED ucCmdLine* ucCmdLine_init(ucCmdLine*);
+ struct ucCmdLine {
+ ucCmdTok* cmd_tok;
+ ucCmdLine_TransmitFunc* transmit;
+ ucCmdLine_IsCanceledFunc* is_canceled;
+ ucCmdLine_HandleInvalidCommandFunc* handle_invalid_command;
+ void* transmit_state;
+ void* is_canceled_state;
+ void* handle_invalid_command_state;
+ const char* response_terminator;
+ const char* command_acknowledgment;
+ char response[ucCmdLine_RESPONSE_SIZE];
+ char response_buffer[ucCmdLine_RESPONSE_SIZE];
+ ucBool is_quiet; };
+
+uc_EXPORTED const char* ucCmdLineOpt_format_validation_err(ucCmdLineOpt*, ucCmdLine *cmd);
+uc_EXPORTED ucCmdLineOpt* ucCmdLineOpt_init(ucCmdLineOpt*, ucCmdLineOpt_Func *func, void* state, const char *name, const char *desc, ucArgOpt* arg_opt, ucSwitchOpt *switch_opt, ucCmdLineOpt *next);
+ struct ucCmdLineOpt {
+ ucArgOptOwner base;
+ ucCmdLineOpt_Func* func;
+ void* state;
+ ucSwitchOpt* switch_opt;
+ ucCmdLineOpt* next; };
+
+uc_EXPORTED ucCmdLineApp* ucCmdLineApp_init(ucCmdLineApp*, ucCmdParser*, ucCmdLine*);
+uc_EXPORTED char* ucCmdLineApp_receive(ucCmdLineApp*);
+ struct ucCmdLineApp {
+ ucCmdLine* cmd;
+ ucCmdParser* cmd_parser;
+ ucCmdLineApp_ReceiveFunc* receive;
+ void* receive_state;
+ ucErr (*run)(ucCmdLineApp *p, ucCmdLineOpt *cmd_opt);
+ const char* help_command;
+ const char* quit_command;
+ const char* escape_response;
+ char cmd_str[ucCmdLineApp_CMD_STR_SIZE + 1]; };
+
+/*
+ * Summary:
+ * Defines a macro that is used to provide a dynamic
+ * feel to static-memory allocation. Calling it in a
+ * source file exposes functions to create and destroy
+ * objects of the specified type.
+ * Parameters:
+ * TYPE: The type of the object instances that are
+ * created and destroyed using the manager.
+ * COUNT: The number of object instances that is
+ * available to the program. Once this number
+ * is exceeded, NULL is returned from the
+ * create function until instances are released
+ * using the destroy function.
+ */
+#define ucMemoryManager_INIT(TYPE, COUNT) \
+ typedef struct ucMemoryManager_Instance { \
+ TYPE inst; \
+ char used; \
+ } ucMemoryManager_Instance; \
+ \
+ static ucMemoryManager_Instance ucMemoryManager_Instances[COUNT] = { 0 }; \
+ \
+ static TYPE *ucMemoryManager_create(void) { \
+ int i; \
+ ucMemoryManager_Instance *inst; \
+ for (i = 0; i < COUNT; i++) { \
+ inst = &ucMemoryManager_Instances[i]; \
+ if (inst->used == 0) { \
+ inst->used = 1; \
+ return &inst->inst; \
+ } \
+ } \
+ return NULL; \
+ } \
+ \
+ static void ucMemoryManager_destroy(TYPE *p) { \
+ int i; \
+ ucMemoryManager_Instance *inst; \
+ for (i = 0; i < COUNT; i++) { \
+ inst = &ucMemoryManager_Instances[i]; \
+ if (p == (&inst->inst)) { \
+ inst->used = 0; \
+ } \
+ } \
+ }
+
+#endif /* #ifndef UCMD_INTERNAL_H */
+