aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libargparser/argparser.c179
-rw-r--r--src/libargparser/argparser.h58
2 files changed, 226 insertions, 11 deletions
diff --git a/src/libargparser/argparser.c b/src/libargparser/argparser.c
index 39e5750..fc5772a 100644
--- a/src/libargparser/argparser.c
+++ b/src/libargparser/argparser.c
@@ -25,7 +25,9 @@
#include <errno.h>
-#define xfree(s) (free(s), s = NULL)
+#define xfree(s) (free(s), s = NULL)
+#define xmalloc(s, n, t) ((s = malloc((n) * sizeof(t))) == NULL)
+#define xgetenv(v) (getenv(v) ? getenv(v) : "")
/**
@@ -35,7 +37,7 @@
* @return Zero on success, -1 on error, `errno` will be set accordingly
*/
int args_initialise(args_parser_t* parser)
-{
+{
parser->state->arguments = NULL;
parser->state->files = NULL;
parser->state->message = NULL;
@@ -50,7 +52,7 @@ int args_initialise(args_parser_t* parser)
parser->state->all_options_count = 0;
parser->state->freeptr = 0;
- parser->settings->linuxvt = getenv("TERM") ? !strcmp(getenv("TERM"), "linux") : 0;
+ parser->settings->linuxvt = !strcmp(xgetenv("TERM"), "linux");
parser->settings->alternative = 0;
parser->settings->stop_at_first_file = 0;
parser->settings->use_colours = AUTO;
@@ -63,11 +65,11 @@ int args_initialise(args_parser_t* parser)
parser->settings->help_out = stderr;
parser->settings->abbreviations = args_standard_abbreviations;
- if ((parser->state->arguments = malloc(1 * sizeof(char*))) == NULL) goto fail;
- if ((parser->state->files = malloc(1 * sizeof(char*))) == NULL) goto fail;
- if ((parser->state->options = malloc(1 * sizeof(args_option_t))) == NULL) goto fail;
- if ((parser->state->all_options = malloc(1 * sizeof(char*))) == NULL) goto fail;
- if ((parser->state->freequeue = malloc(1 * sizeof(void*))) == NULL) goto fail;
+ if (xmalloc(parser->state->arguments, 1, char*)) goto fail;
+ if (xmalloc(parser->state->files, 1, char*)) goto fail;
+ if (xmalloc(parser->state->options, 1, args_option_t)) goto fail;
+ if (xmalloc(parser->state->all_options, 1, char*)) goto fail;
+ if (xmalloc(parser->state->freequeue, 1, void*)) goto fail;
return 0;
fail:
@@ -85,7 +87,7 @@ int args_initialise(args_parser_t* parser)
*
* @param parser The parser
*/
-void args_dispose(parser_t* parser)
+void args_dispose(args_parser_t* parser)
{
size_t i;
@@ -99,7 +101,10 @@ void args_dispose(parser_t* parser)
xfree(parser->state->message);
xfree(parser->state->files);
for (i = 0; i < parser->state->options_count; i++)
- free(parser->state->options[i].alternatives);
+ {
+ free(parser->state->options[i].alternatives);
+ free(parser->state->options[i].arguments);
+ }
parser->state->options_count = 0;
xfree(parser->state->options);
xfree(parser->state->all_options);
@@ -112,6 +117,28 @@ void args_dispose(parser_t* parser)
/**
+ * Maps up options that are alternatives to the standard alternative for each option
+ *
+ * @param parser The parser
+ * @return Zero on success, -1 on error
+ */
+int args_support_alternatives(args_parser_t* parser)
+{
+ size_t i;
+
+ for (i = 0; i < parser->state->all_options_count; i++)
+ {
+ const char* alternative = parser->state->all_options[i];
+ const char* standard = parser->state->all_options_standard[i];
+
+ /* TODO map `alternative` to `standard` */
+ }
+
+ return 0;
+}
+
+
+/**
* Checks the correctness of the number of used non-option arguments
*
* @param parser The parser
@@ -152,6 +179,138 @@ int args_test_files(args_parser_t* parser, size_t min, size_t max)
/**
+ * Checks for out of context option usage
+ *
+ * @param parser The parser
+ * @param ...:const char* Allowed options
+ * @return Whether only allowed options was used, -1 on error
+ */
+int args_test_allowed(args_parser_t* parser, ...)
+{
+ size_t count = 0;
+ va_list args, cp;
+ const char** list;
+ const char* elem;
+ int rc;
+
+ va_copy(cp, args);
+ va_start(cp, parser);
+ while (va_arg(cp, const char*) != NULL)
+ count++;
+ va_end(cp);
+
+ if ((list = malloc(count * sizeof(const char*))) == NULL)
+ return -1;
+
+ count = 0;
+ va_start(args, parser);
+ while ((elem = va_arg(args, const char*)) != NULL)
+ list[count++] = elem;
+ va_end(args);
+
+ rc = args_test_allowed_l(parser, list, count);
+ free(list);
+ return rc;
+}
+
+
+/**
+ * Checks for out of context option usage
+ *
+ * @param parser The parser
+ * @param allowed Allowed options
+ * @param count The number of elements in `allowed`
+ * @return Whether only allowed options was used
+ */
+int args_test_allowed_l(args_parser_t* parser, const char** allowed, size_t count)
+{
+ /* TODO print warnings */
+ size_t i, j, k;
+
+ for (i = 0; i < parser->state->options_count; i++)
+ if (parser->state->options[i].arguments_count > 0)
+ {
+ for (j = 0; j < parser->state->options[i].alternatives_count; j++)
+ for (k = 0; k < count; k++)
+ if (!strcmp(parser->state->options[i].alternatives[j], allowed[k]))
+ goto allowed;
+
+ return 0;
+ allowed:
+ continue;
+ }
+
+ return 1;
+}
+
+
+/**
+ * Checks for option conflicts
+ *
+ * @param parser The parser
+ * @param ...:const char* Mutually exclusive options
+ * @return Whether at most one exclusive option was used, -1 on error
+ */
+int args_test_exclusiveness(args_parser_t* parser, ...)
+{
+ size_t count = 0;
+ va_list args, cp;
+ const char** list;
+ const char* elem;
+ int rc;
+
+ va_copy(cp, args);
+ va_start(cp, parser);
+ while (va_arg(cp, const char*) != NULL)
+ count++;
+ va_end(cp);
+
+ if ((list = malloc(count * sizeof(const char*))) == NULL)
+ return -1;
+
+ count = 0;
+ va_start(args, parser);
+ while ((elem = va_arg(args, const char*)) != NULL)
+ list[count++] = elem;
+ va_end(args);
+
+ rc = args_test_exclusiveness_l(parser, list, count);
+ free(list);
+ return rc;
+}
+
+
+/**
+ * Checks for option conflicts
+ *
+ * @param parser The parser
+ * @param exclusives Mutually exclusive options
+ * @param count The number of elements in `exclusives`
+ * @return Whether at most one exclusive option was used
+ */
+int args_test_exclusiveness_l(args_parser_t* parser, const char** exclusives, size_t count)
+{
+ /* TODO print warnings */
+ size_t i, j, k, have_count;
+
+ for (i = 0; i < parser->state->options_count; i++)
+ if (parser->state->options[i].arguments_count > 0)
+ {
+ for (j = 0; j < parser->state->options[i].alternatives_count; j++)
+ for (k = 0; k < count; k++)
+ if (!strcmp(parser->state->options[i].alternatives[j], exclusives[k]))
+ goto exclusive;
+
+ continue;
+ exclusive:
+ have_count++;
+ }
+
+ return have_count <= 1;
+}
+
+
+/**
* Dummy trigger
*
* @param user_data User-data
diff --git a/src/libargparser/argparser.h b/src/libargparser/argparser.h
index 9809f7a..51feace 100644
--- a/src/libargparser/argparser.h
+++ b/src/libargparser/argparser.h
@@ -126,6 +126,16 @@ typedef struct args_option
void* user_data;
/**
+ * Arguments passed to the option, `NULL` when argumentless
+ */
+ char** arguments;
+
+ /**
+ * The number of elements in `arguments`
+ */
+ size_t arguments_count;
+
+ /**
* Invoked when the option is used
*
* @param user_data User-data
@@ -350,7 +360,15 @@ int args_initialise(args_parser_t* parser);
*
* @param parser The parser
*/
-void args_dispose(parser_t* parser);
+void args_dispose(args_parser_t* parser);
+
+/**
+ * Maps up options that are alternatives to the standard alternative for each option
+ *
+ * @param parser The parser
+ * @return Zero on success, -1 on error
+ */
+int args_support_alternatives(args_parser_t* parser);
/**
* Checks the correctness of the number of used non-option arguments
@@ -381,6 +399,44 @@ int args_test_files_max(args_parser_t* parser, size_t max);
int args_test_files(args_parser_t* parser, size_t min, size_t max);
/**
+ * Checks for out of context option usage
+ *
+ * @param parser The parser
+ * @param ...:const char* Allowed options
+ * @return Whether only allowed options was used, -1 on error
+ */
+int args_test_allowed(args_parser_t* parser, ...);
+
+/**
+ * Checks for out of context option usage
+ *
+ * @param parser The parser
+ * @param allowed Allowed options
+ * @param count The number of elements in `allowed`
+ * @return Whether only allowed options was used
+ */
+int args_test_allowed_l(args_parser_t* parser, const char** allowed, size_t count) ARGS_PURE;
+
+/**
+ * Checks for option conflicts
+ *
+ * @param parser The parser
+ * @param ...:const char* Mutually exclusive options
+ * @return Whether at most one exclusive option was used, -1 on error
+ */
+int args_test_exclusiveness(args_parser_t* parser, ...);
+
+/**
+ * Checks for option conflicts
+ *
+ * @param parser The parser
+ * @param exclusives Mutually exclusive options
+ * @param count The number of elements in `exclusives`
+ * @return Whether at most one exclusive option was used
+ */
+int args_test_exclusiveness_l(args_parser_t* parser, const char** exclusives, size_t count) ARGS_PURE;
+
+/**
* Dummy trigger
*
* @param user_data User-data