]> mj.ucw.cz Git - libucw.git/commitdiff
Opt: Added OPT_BREAK
authorMartin Mares <mj@ucw.cz>
Fri, 27 Jun 2014 15:27:25 +0000 (17:27 +0200)
committerMartin Mares <mj@ucw.cz>
Fri, 27 Jun 2014 15:27:25 +0000 (17:27 +0200)
This is useful for programs, which wish to process all their
positional arguments by themselves without having to copy them
to a different data structure. For example, this frequently happens
with programs which have sub-commands.

ucw/opt-internal.h
ucw/opt.c
ucw/opt.h

index 99514c29a278016a1f938e9d45c427685ec42310..21c67a6e16e5ff9a906631aa180fb31270727dee 100644 (file)
@@ -30,7 +30,7 @@ struct opt_context {
   int hook_count;
   int positional_max;
   int positional_count;
-  bool stop_parsing;
+  int stop_parsing;
   enum opt_conf_state conf_state;
 };
 
index e8d7cbeebe9308f7d7a39c1c39faf753b22b91a9..713ee784d3f384bbc501553f8d4ab74781ea75ac 100644 (file)
--- a/ucw/opt.c
+++ b/ucw/opt.c
@@ -225,6 +225,9 @@ static void opt_parse_value(struct opt_context * oc, struct opt_precomputed * op
        item->u.call(item, value, data);
        break;
       }
+    case OPT_CL_BREAK:
+      oc->stop_parsing = 2;
+      break;
     default:
       ASSERT(0);
   }
@@ -388,8 +391,9 @@ int opt_parse(const struct opt_section * options, char ** argv) {
   opt_prepare_items(oc, options);
 
   int force_positional = 0;
-  int i;
+  int i, start_i = 0;
   for (i=0; argv[i] && !oc->stop_parsing; i++) {
+    start_i = i;
     char *arg = argv[i];
     opt_invoke_hooks(oc, OPT_HOOK_BEFORE_ARG, NULL, NULL);
     if (arg[0] != '-' || force_positional)
@@ -409,5 +413,5 @@ int opt_parse(const struct opt_section * options, char ** argv) {
 
   opt_check_required(oc);
   opt_invoke_hooks(oc, OPT_HOOK_FINAL, NULL, NULL);
-  return i;
+  return (oc->stop_parsing < 2 ? i : start_i);
 }
index 695f607e421e9bbf5e81e31c19c165dbe09103ed..3f1be8127511327eeb8b9ba0c5b36ffdf1f1b3cd 100644 (file)
--- a/ucw/opt.h
+++ b/ucw/opt.h
@@ -63,6 +63,8 @@
  *   contents of another list of options.
  * - `OPT_CL_HELP`: no option, just print a help text.
  * - `OPT_CL_HOOK`: no option, but a definition of a <<hooks,hook>>.
+ * - `OPT_CL_BREAK`: when a given option occurs, stop parsing and keep
+ *   the option in the argument list.
  ***/
 
 enum opt_class {
@@ -76,6 +78,7 @@ enum opt_class {
   OPT_CL_SECTION,
   OPT_CL_HELP,
   OPT_CL_HOOK,
+  OPT_CL_BREAK,
 };
 
 /***
@@ -206,6 +209,9 @@ struct opt_item {
 /** Incrementing option. @target should be a variable of type `int`. **/
 #define OPT_INC(shortopt, longopt, target, fl, desc) { .letter = shortopt, .name = longopt, .ptr = CHECK_PTR_TYPE(&target, int *), .flags = fl, .help = desc, .cls = OPT_CL_INC, .type = CT_INT }
 
+/** Breakpoint option. When this option occurs, parsing is terminated and the option is kept in the argument array. **/
+#define OPT_BREAK(shortopt, longopt, fl) { .letter = shortopt, .name = longopt, .flags = fl, .cls = OPT_CL_BREAK }
+
 /* FIXME: Backwards compatibility only, should not be used anymore. */
 #define OPT_UNS OPT_UINT
 #define OPT_UNS_MULTIPLE OPT_UINT_MULTIPLE