cli: use argpar for parsing query command's arguments
[babeltrace.git] / src / cli / babeltrace2-cfg-cli-args.c
index fd6c1156af19bce043e38808965d29abc0de9282..dd7f4725a80e55f8b4474785c19615530c64e150 100644 (file)
@@ -1344,6 +1344,31 @@ void print_expected_params_format(FILE *fp)
        fprintf(fp, "babeltrace2 from a shell.\n");
 }
 
+static
+bool help_option_is_specified(
+               const struct bt_argpar_parse_ret *argpar_parse_ret)
+{
+       int i;
+       bool specified = false;
+
+       for (i = 0; i < argpar_parse_ret->items->len; i++) {
+               struct bt_argpar_item *argpar_item =
+                       g_ptr_array_index(argpar_parse_ret->items, i);
+               struct bt_argpar_item_opt *argpar_item_opt;
+
+               if (argpar_item->type != BT_ARGPAR_ITEM_TYPE_OPT) {
+                       continue;
+               }
+
+               argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item;
+               if (argpar_item_opt->descr->id == OPT_HELP) {
+                       specified = true;
+                       break;
+               }
+       }
+
+       return specified;
+}
 
 /*
  * Prints the help command usage.
@@ -1369,13 +1394,13 @@ void print_help_usage(FILE *fp)
 }
 
 static
-struct poptOption help_long_options[] = {
-       /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
-       { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
-       { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL },
-       { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL },
-       { "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
-       { NULL, 0, '\0', NULL, 0, NULL, NULL },
+const struct bt_argpar_opt_descr help_options[] = {
+       /* id, short_name, long_name, with_arg */
+       { OPT_HELP, 'h', "help", false },
+       { OPT_OMIT_HOME_PLUGIN_PATH, '\0', "omit-home-plugin-path", false },
+       { OPT_OMIT_SYSTEM_PLUGIN_PATH, '\0', "omit-system-plugin-path", false },
+       { OPT_PLUGIN_PATH, '\0', "plugin-path", true },
+       BT_ARGPAR_OPT_DESCR_SENTINEL
 };
 
 /*
@@ -1390,13 +1415,11 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[],
                bool force_omit_home_plugin_path,
                const bt_value *initial_plugin_paths, int default_log_level)
 {
-       poptContext pc = NULL;
-       char *arg = NULL;
-       int opt;
-       int ret;
+       int ret, i;
        struct bt_config *cfg = NULL;
-       const char *leftover;
+       const char *leftover = NULL;
        char *plugin_name = NULL, *comp_cls_name = NULL;
+       struct bt_argpar_parse_ret argpar_parse_ret;
 
        *retcode = 0;
        cfg = bt_config_help_create(initial_plugin_paths, default_log_level);
@@ -1412,54 +1435,63 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[],
        }
 
        /* Parse options */
-       pc = poptGetContext(NULL, argc, (const char **) argv,
-               help_long_options, POPT_CONTEXT_KEEP_FIRST);
-       if (!pc) {
-               BT_CLI_LOGE_APPEND_CAUSE("Cannot get popt context.");
+       argpar_parse_ret = bt_argpar_parse(argc, argv, help_options, true);
+       if (argpar_parse_ret.error) {
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "While parsing `help` command's command-line arguments: %s",
+                       argpar_parse_ret.error->str);
                goto error;
        }
 
-       poptReadDefaultConfig(pc, 0);
+       if (help_option_is_specified(&argpar_parse_ret)) {
+               print_help_usage(stdout);
+               *retcode = -1;
+               BT_OBJECT_PUT_REF_AND_RESET(cfg);
+               goto end;
+       }
 
-       while ((opt = poptGetNextOpt(pc)) > 0) {
-               arg = poptGetOptArg(pc);
+       for (i = 0; i < argpar_parse_ret.items->len; i++) {
+               struct bt_argpar_item *argpar_item =
+                       g_ptr_array_index(argpar_parse_ret.items, i);
 
-               switch (opt) {
-               case OPT_PLUGIN_PATH:
-                       if (bt_config_append_plugin_paths_check_setuid_setgid(
-                                       cfg->plugin_paths, arg)) {
+               if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_OPT) {
+                       struct bt_argpar_item_opt *argpar_item_opt;
+                       const char *arg;
+                       argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item;
+                       arg = argpar_item_opt->arg;
+
+                       switch (argpar_item_opt->descr->id) {
+                       case OPT_PLUGIN_PATH:
+                               if (bt_config_append_plugin_paths_check_setuid_setgid(
+                                               cfg->plugin_paths, arg)) {
+                                       goto error;
+                               }
+                               break;
+                       case OPT_OMIT_SYSTEM_PLUGIN_PATH:
+                               cfg->omit_system_plugin_path = true;
+                               break;
+                       case OPT_OMIT_HOME_PLUGIN_PATH:
+                               cfg->omit_home_plugin_path = true;
+                               break;
+                       default:
+                               BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).",
+                                       argpar_item_opt->descr->id);
                                goto error;
                        }
-                       break;
-               case OPT_OMIT_SYSTEM_PLUGIN_PATH:
-                       cfg->omit_system_plugin_path = true;
-                       break;
-               case OPT_OMIT_HOME_PLUGIN_PATH:
-                       cfg->omit_home_plugin_path = true;
-                       break;
-               case OPT_HELP:
-                       print_help_usage(stdout);
-                       *retcode = -1;
-                       BT_OBJECT_PUT_REF_AND_RESET(cfg);
-                       goto end;
-               default:
-                       BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).",
-                               opt);
-                       goto error;
-               }
+               } else {
+                       struct bt_argpar_item_non_opt *argpar_item_non_opt
+                               = (struct bt_argpar_item_non_opt *) argpar_item;
 
-               free(arg);
-               arg = NULL;
-       }
+                       if (leftover) {
+                               BT_CLI_LOGE_APPEND_CAUSE("Extraneous command-line argument specified to `help` command: `%s`.",
+                                       argpar_item_non_opt->arg);
+                               goto error;
+                       }
 
-       /* Check for option parsing error */
-       if (opt < -1) {
-               BT_CLI_LOGE_APPEND_CAUSE("While parsing command-line options, at option %s: `%s`.",
-                       poptBadOption(pc, 0), poptStrerror(opt));
-               goto error;
+                       leftover = argpar_item_non_opt->arg;
+               }
        }
 
-       leftover = poptGetArg(pc);
        if (leftover) {
                plugin_comp_cls_names(leftover, NULL,
                        &plugin_name, &comp_cls_name,
@@ -1499,11 +1531,8 @@ end:
        g_free(plugin_name);
        g_free(comp_cls_name);
 
-       if (pc) {
-               poptFreeContext(pc);
-       }
+       bt_argpar_parse_ret_fini(&argpar_parse_ret);
 
-       free(arg);
        return cfg;
 }
 
@@ -1530,14 +1559,14 @@ void print_query_usage(FILE *fp)
 }
 
 static
-struct poptOption query_long_options[] = {
-       /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
-       { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
-       { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL },
-       { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL },
-       { "params", 'p', POPT_ARG_STRING, NULL, OPT_PARAMS, NULL, NULL },
-       { "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
-       { NULL, 0, '\0', NULL, 0, NULL, NULL },
+const struct bt_argpar_opt_descr query_options[] = {
+       /* id, short_name, long_name, with_arg */
+       { OPT_HELP, 'h', "help", false },
+       { OPT_OMIT_HOME_PLUGIN_PATH, '\0', "omit-home-plugin-path", false },
+       { OPT_OMIT_SYSTEM_PLUGIN_PATH, '\0', "omit-system-plugin-path", false },
+       { OPT_PARAMS, 'p', "params", true },
+       { OPT_PLUGIN_PATH, '\0', "plugin-path", true },
+       BT_ARGPAR_OPT_DESCR_SENTINEL
 };
 
 /*
@@ -1553,14 +1582,13 @@ struct bt_config *bt_config_query_from_args(int argc, const char *argv[],
                const bt_value *initial_plugin_paths,
                int default_log_level)
 {
-       poptContext pc = NULL;
-       char *arg = NULL;
-       int opt;
-       int ret;
+       int ret, i;
        struct bt_config *cfg = NULL;
-       const char *leftover;
+       const char *component_class_spec = NULL;
+       const char *query_object = NULL;
        bt_value *params;
        GString *error_str = NULL;
+       struct bt_argpar_parse_ret argpar_parse_ret;
 
        params = bt_value_null;
        bt_value_get_ref(bt_value_null);
@@ -1585,110 +1613,105 @@ struct bt_config *bt_config_query_from_args(int argc, const char *argv[],
        }
 
        /* Parse options */
-       pc = poptGetContext(NULL, argc, (const char **) argv,
-               query_long_options, POPT_CONTEXT_KEEP_FIRST);
-       if (!pc) {
-               BT_CLI_LOGE_APPEND_CAUSE("Cannot get popt context.");
+       argpar_parse_ret = bt_argpar_parse(argc, argv, query_options, true);
+       if (argpar_parse_ret.error) {
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "While parsing `query` command's command-line arguments: %s",
+                       argpar_parse_ret.error->str);
                goto error;
        }
 
-       poptReadDefaultConfig(pc, 0);
-
-       while ((opt = poptGetNextOpt(pc)) > 0) {
-               arg = poptGetOptArg(pc);
+       if (help_option_is_specified(&argpar_parse_ret)) {
+               print_query_usage(stdout);
+               *retcode = -1;
+               BT_OBJECT_PUT_REF_AND_RESET(cfg);
+               goto end;
+       }
 
-               switch (opt) {
-               case OPT_PLUGIN_PATH:
-                       if (bt_config_append_plugin_paths_check_setuid_setgid(
-                                       cfg->plugin_paths, arg)) {
+       for (i = 0; i < argpar_parse_ret.items->len; i++) {
+               struct bt_argpar_item *argpar_item =
+                       g_ptr_array_index(argpar_parse_ret.items, i);
+
+               if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_OPT) {
+                       struct bt_argpar_item_opt *argpar_item_opt =
+                               (struct bt_argpar_item_opt *) argpar_item;
+                       const char *arg = argpar_item_opt->arg;
+
+                       switch (argpar_item_opt->descr->id) {
+                       case OPT_PLUGIN_PATH:
+                               if (bt_config_append_plugin_paths_check_setuid_setgid(
+                                               cfg->plugin_paths, arg)) {
+                                       goto error;
+                               }
+                               break;
+                       case OPT_OMIT_SYSTEM_PLUGIN_PATH:
+                               cfg->omit_system_plugin_path = true;
+                               break;
+                       case OPT_OMIT_HOME_PLUGIN_PATH:
+                               cfg->omit_home_plugin_path = true;
+                               break;
+                       case OPT_PARAMS:
+                       {
+                               bt_value_put_ref(params);
+                               params = cli_value_from_arg(arg, error_str);
+                               if (!params) {
+                                       BT_CLI_LOGE_APPEND_CAUSE("Invalid format for --params option's argument:\n    %s",
+                                               error_str->str);
+                                       goto error;
+                               }
+                               break;
+                       }
+                       default:
+                               BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).",
+                                       argpar_item_opt->descr->id);
                                goto error;
                        }
-                       break;
-               case OPT_OMIT_SYSTEM_PLUGIN_PATH:
-                       cfg->omit_system_plugin_path = true;
-                       break;
-               case OPT_OMIT_HOME_PLUGIN_PATH:
-                       cfg->omit_home_plugin_path = true;
-                       break;
-               case OPT_PARAMS:
-               {
-                       bt_value_put_ref(params);
-                       params = cli_value_from_arg(arg, error_str);
-                       if (!params) {
-                               BT_CLI_LOGE_APPEND_CAUSE("Invalid format for --params option's argument:\n    %s",
-                                       error_str->str);
+               } else {
+                       struct bt_argpar_item_non_opt *argpar_item_non_opt
+                               = (struct bt_argpar_item_non_opt *) argpar_item;
+
+                       /*
+                        * We need exactly two leftover arguments which are the
+                        * mandatory component class specification and query object.
+                        */
+                       if (!component_class_spec) {
+                               component_class_spec = argpar_item_non_opt->arg;
+                       } else if (!query_object) {
+                               query_object = argpar_item_non_opt->arg;
+                       } else {
+                               BT_CLI_LOGE_APPEND_CAUSE("Extraneous command-line argument specified to `query` command: `%s`.",
+                                       argpar_item_non_opt->arg);
                                goto error;
                        }
-                       break;
                }
-               case OPT_HELP:
-                       print_query_usage(stdout);
-                       *retcode = -1;
-                       BT_OBJECT_PUT_REF_AND_RESET(cfg);
-                       goto end;
-               default:
-                       BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).",
-                               opt);
-                       goto error;
-               }
-
-               free(arg);
-               arg = NULL;
-       }
-
-       /* Check for option parsing error */
-       if (opt < -1) {
-               BT_CLI_LOGE_APPEND_CAUSE("While parsing command-line options, at option %s: `%s`.",
-                       poptBadOption(pc, 0), poptStrerror(opt));
-               goto error;
        }
 
-       /*
-        * We need exactly two leftover arguments which are the
-        * mandatory component class specification and query object.
-        */
-       leftover = poptGetArg(pc);
-       if (leftover) {
-               cfg->cmd_data.query.cfg_component =
-                       bt_config_component_from_arg(leftover,
-                               default_log_level);
-               if (!cfg->cmd_data.query.cfg_component) {
-                       BT_CLI_LOGE_APPEND_CAUSE("Invalid format for component class specification:\n    %s",
-                               leftover);
-                       goto error;
-               }
-
-               BT_ASSERT(params);
-               BT_OBJECT_MOVE_REF(cfg->cmd_data.query.cfg_component->params,
-                       params);
-       } else {
+       if (!component_class_spec || !query_object) {
                print_query_usage(stdout);
                *retcode = -1;
                BT_OBJECT_PUT_REF_AND_RESET(cfg);
                goto end;
        }
 
-       leftover = poptGetArg(pc);
-       if (leftover) {
-               if (strlen(leftover) == 0) {
-                       BT_CLI_LOGE_APPEND_CAUSE("Invalid empty object.");
-                       goto error;
-               }
-
-               g_string_assign(cfg->cmd_data.query.object, leftover);
-       } else {
-               print_query_usage(stdout);
-               *retcode = -1;
-               BT_OBJECT_PUT_REF_AND_RESET(cfg);
-               goto end;
+       cfg->cmd_data.query.cfg_component =
+               bt_config_component_from_arg(component_class_spec,
+                       default_log_level);
+       if (!cfg->cmd_data.query.cfg_component) {
+               BT_CLI_LOGE_APPEND_CAUSE("Invalid format for component class specification:\n    %s",
+                       component_class_spec);
+               goto error;
        }
 
-       leftover = poptGetArg(pc);
-       if (leftover) {
-               BT_CLI_LOGE_APPEND_CAUSE("Unexpected argument: `%s`.", leftover);
+       BT_ASSERT(params);
+       BT_OBJECT_MOVE_REF(cfg->cmd_data.query.cfg_component->params, params);
+
+       if (strlen(query_object) == 0) {
+               BT_CLI_LOGE_APPEND_CAUSE("Invalid empty object.");
                goto error;
        }
 
+       g_string_assign(cfg->cmd_data.query.object, query_object);
+
        if (append_home_and_system_plugin_paths_cfg(cfg)) {
                goto error;
        }
@@ -1700,16 +1723,13 @@ error:
        BT_OBJECT_PUT_REF_AND_RESET(cfg);
 
 end:
-       if (pc) {
-               poptFreeContext(pc);
-       }
+       bt_argpar_parse_ret_fini(&argpar_parse_ret);
 
        if (error_str) {
                g_string_free(error_str, TRUE);
        }
 
        bt_value_put_ref(params);
-       free(arg);
        return cfg;
 }
 
@@ -1736,13 +1756,13 @@ void print_list_plugins_usage(FILE *fp)
 }
 
 static
-struct poptOption list_plugins_long_options[] = {
-       /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
-       { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
-       { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL },
-       { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL },
-       { "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
-       { NULL, 0, '\0', NULL, 0, NULL, NULL },
+const struct bt_argpar_opt_descr list_plugins_options[] = {
+       /* id, short_name, long_name, with_arg */
+       { OPT_HELP, 'h', "help", false },
+       { OPT_OMIT_HOME_PLUGIN_PATH, '\0', "omit-home-plugin-path", false },
+       { OPT_OMIT_SYSTEM_PLUGIN_PATH, '\0', "omit-system-plugin-path", false },
+       { OPT_PLUGIN_PATH, '\0', "plugin-path", true },
+       BT_ARGPAR_OPT_DESCR_SENTINEL
 };
 
 /*
@@ -1757,12 +1777,9 @@ struct bt_config *bt_config_list_plugins_from_args(int argc, const char *argv[],
                bool force_omit_home_plugin_path,
                const bt_value *initial_plugin_paths)
 {
-       poptContext pc = NULL;
-       char *arg = NULL;
-       int opt;
-       int ret;
+       int ret, i;
        struct bt_config *cfg = NULL;
-       const char *leftover;
+       struct bt_argpar_parse_ret argpar_parse_ret = { 0 };
 
        *retcode = 0;
        cfg = bt_config_list_plugins_create(initial_plugin_paths);
@@ -1778,19 +1795,40 @@ struct bt_config *bt_config_list_plugins_from_args(int argc, const char *argv[],
        }
 
        /* Parse options */
-       pc = poptGetContext(NULL, argc, (const char **) argv,
-               list_plugins_long_options, POPT_CONTEXT_KEEP_FIRST);
-       if (!pc) {
-               BT_CLI_LOGE_APPEND_CAUSE("Cannot get popt context.");
+       argpar_parse_ret = bt_argpar_parse(argc, argv, list_plugins_options, true);
+       if (argpar_parse_ret.error) {
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "While parsing `list-plugins` command's command-line arguments: %s",
+                       argpar_parse_ret.error->str);
                goto error;
        }
 
-       poptReadDefaultConfig(pc, 0);
+       if (help_option_is_specified(&argpar_parse_ret)) {
+               print_list_plugins_usage(stdout);
+               *retcode = -1;
+               BT_OBJECT_PUT_REF_AND_RESET(cfg);
+               goto end;
+       }
 
-       while ((opt = poptGetNextOpt(pc)) > 0) {
-               arg = poptGetOptArg(pc);
+       for (i = 0; i < argpar_parse_ret.items->len; i++) {
+               struct bt_argpar_item *argpar_item =
+                       g_ptr_array_index(argpar_parse_ret.items, i);
+               struct bt_argpar_item_opt *argpar_item_opt;
+               const char *arg;
 
-               switch (opt) {
+               if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_NON_OPT) {
+                       struct bt_argpar_item_non_opt *argpar_item_non_opt
+                               = (struct bt_argpar_item_non_opt *) argpar_item;
+
+                       BT_CLI_LOGE_APPEND_CAUSE("Unexpected argument: `%s`.",
+                               argpar_item_non_opt->arg);
+                       goto error;
+               }
+
+               argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item;
+               arg = argpar_item_opt->arg;
+
+               switch (argpar_item_opt->descr->id) {
                case OPT_PLUGIN_PATH:
                        if (bt_config_append_plugin_paths_check_setuid_setgid(
                                        cfg->plugin_paths, arg)) {
@@ -1803,32 +1841,11 @@ struct bt_config *bt_config_list_plugins_from_args(int argc, const char *argv[],
                case OPT_OMIT_HOME_PLUGIN_PATH:
                        cfg->omit_home_plugin_path = true;
                        break;
-               case OPT_HELP:
-                       print_list_plugins_usage(stdout);
-                       *retcode = -1;
-                       BT_OBJECT_PUT_REF_AND_RESET(cfg);
-                       goto end;
                default:
                        BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).",
-                               opt);
+                               argpar_item_opt->descr->id);
                        goto error;
                }
-
-               free(arg);
-               arg = NULL;
-       }
-
-       /* Check for option parsing error */
-       if (opt < -1) {
-               BT_CLI_LOGE_APPEND_CAUSE("While parsing command-line options, at option %s: %s",
-                       poptBadOption(pc, 0), poptStrerror(opt));
-               goto error;
-       }
-
-       leftover = poptGetArg(pc);
-       if (leftover) {
-               BT_CLI_LOGE_APPEND_CAUSE("Unexpected argument: `%s`.", leftover);
-               goto error;
        }
 
        if (append_home_and_system_plugin_paths_cfg(cfg)) {
@@ -1842,11 +1859,8 @@ error:
        BT_OBJECT_PUT_REF_AND_RESET(cfg);
 
 end:
-       if (pc) {
-               poptFreeContext(pc);
-       }
+       bt_argpar_parse_ret_fini(&argpar_parse_ret);
 
-       free(arg);
        return cfg;
 }
 
@@ -1943,13 +1957,11 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[],
                bool force_omit_home_plugin_path,
                const bt_value *initial_plugin_paths, int default_log_level)
 {
-       poptContext pc = NULL;
-       char *arg = NULL;
        struct bt_config_component *cur_cfg_comp = NULL;
        enum bt_config_component_dest cur_cfg_comp_dest =
                        BT_CONFIG_COMPONENT_DEST_UNKNOWN;
        bt_value *cur_base_params = NULL;
-       int opt, ret = 0;
+       int ret = 0;
        struct bt_config *cfg = NULL;
        bt_value *instance_names = NULL;
        bt_value *connection_args = NULL;
@@ -1957,20 +1969,23 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[],
        long retry_duration = -1;
        bt_value_map_extend_status extend_status;
        GString *error_str = NULL;
-       struct poptOption run_long_options[] = {
-               { "base-params", 'b', POPT_ARG_STRING, NULL, OPT_BASE_PARAMS, NULL, NULL },
-               { "component", 'c', POPT_ARG_STRING, NULL, OPT_COMPONENT, NULL, NULL },
-               { "connect", 'x', POPT_ARG_STRING, NULL, OPT_CONNECT, NULL, NULL },
-               { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
-               { "log-level", 'l', POPT_ARG_STRING, NULL, OPT_LOG_LEVEL, NULL, NULL },
-               { "name", 'n', POPT_ARG_STRING, NULL, OPT_NAME, NULL, NULL },
-               { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL },
-               { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL },
-               { "params", 'p', POPT_ARG_STRING, NULL, OPT_PARAMS, NULL, NULL },
-               { "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
-               { "reset-base-params", 'r', POPT_ARG_NONE, NULL, OPT_RESET_BASE_PARAMS, NULL, NULL },
-               { "retry-duration", '\0', POPT_ARG_LONG, &retry_duration, OPT_RETRY_DURATION, NULL, NULL },
-               { NULL, 0, '\0', NULL, 0, NULL, NULL },
+       struct bt_argpar_parse_ret argpar_parse_ret = { 0 };
+       int i;
+
+       static const struct bt_argpar_opt_descr run_options[] = {
+               { OPT_BASE_PARAMS, 'b', "base-params", true },
+               { OPT_COMPONENT, 'c', "component", true },
+               { OPT_CONNECT, 'x', "connect", true },
+               { OPT_HELP, 'h', "help", false },
+               { OPT_LOG_LEVEL, 'l', "log-level", true },
+               { OPT_NAME, 'n', "name", true },
+               { OPT_OMIT_HOME_PLUGIN_PATH, '\0', "omit-home-plugin-path", false },
+               { OPT_OMIT_SYSTEM_PLUGIN_PATH, '\0', "omit-system-plugin-path", false },
+               { OPT_PARAMS, 'p', "params", true },
+               { OPT_PLUGIN_PATH, '\0', "plugin-path", true },
+               { OPT_RESET_BASE_PARAMS, 'r', "reset-base-params", false },
+               { OPT_RETRY_DURATION, '\0', "retry-duration", true },
+               BT_ARGPAR_OPT_DESCR_SENTINEL
        };
 
        *retcode = 0;
@@ -2019,19 +2034,41 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[],
        }
 
        /* Parse options */
-       pc = poptGetContext(NULL, argc, (const char **) argv,
-               run_long_options, POPT_CONTEXT_KEEP_FIRST);
-       if (!pc) {
-               BT_CLI_LOGE_APPEND_CAUSE("Cannot get popt context.");
+       argpar_parse_ret = bt_argpar_parse(argc, argv, run_options, true);
+       if (argpar_parse_ret.error) {
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "While parsing `run` command's command-line arguments: %s",
+                       argpar_parse_ret.error->str);
                goto error;
        }
 
-       poptReadDefaultConfig(pc, 0);
+       if (help_option_is_specified(&argpar_parse_ret)) {
+               print_run_usage(stdout);
+               *retcode = -1;
+               BT_OBJECT_PUT_REF_AND_RESET(cfg);
+               goto end;
+       }
+
+       for (i = 0; i < argpar_parse_ret.items->len; i++) {
+               struct bt_argpar_item *argpar_item =
+                       g_ptr_array_index(argpar_parse_ret.items, i);
+               struct bt_argpar_item_opt *argpar_item_opt;
+               const char *arg;
+
+               /* This command does not accept leftover arguments. */
+               if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_NON_OPT) {
+                       struct bt_argpar_item_non_opt *argpar_nonopt_item =
+                               (struct bt_argpar_item_non_opt *) argpar_item;
+
+                       BT_CLI_LOGE_APPEND_CAUSE("Unexpected argument: `%s`",
+                               argpar_nonopt_item->arg);
+                       goto error;
+               }
 
-       while ((opt = poptGetNextOpt(pc)) > 0) {
-               arg = poptGetOptArg(pc);
+               argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item;
+               arg = argpar_item_opt->arg;
 
-               switch (opt) {
+               switch (argpar_item_opt->descr->id) {
                case OPT_PLUGIN_PATH:
                        if (bt_config_append_plugin_paths_check_setuid_setgid(
                                        cfg->plugin_paths, arg)) {
@@ -2173,7 +2210,19 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[],
                                goto error;
                        }
                        break;
-               case OPT_RETRY_DURATION:
+               case OPT_RETRY_DURATION: {
+                       gchar *end;
+                       size_t arg_len = strlen(argpar_item_opt->arg);
+
+                       retry_duration = g_ascii_strtoll(argpar_item_opt->arg, &end, 10);
+
+                       if (arg_len == 0 || end != (argpar_item_opt->arg + arg_len)) {
+                               BT_CLI_LOGE_APPEND_CAUSE(
+                                       "Could not parse --retry-duration option's argument as an unsigned integer: `%s`",
+                                       argpar_item_opt->arg);
+                               goto error;
+                       }
+
                        if (retry_duration < 0) {
                                BT_CLI_LOGE_APPEND_CAUSE("--retry-duration option's argument must be positive or 0: %ld",
                                        retry_duration);
@@ -2183,32 +2232,12 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[],
                        cfg->cmd_data.run.retry_duration_us =
                                (uint64_t) retry_duration;
                        break;
-               case OPT_HELP:
-                       print_run_usage(stdout);
-                       *retcode = -1;
-                       BT_OBJECT_PUT_REF_AND_RESET(cfg);
-                       goto end;
+               }
                default:
                        BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).",
-                               opt);
+                               argpar_item_opt->descr->id);
                        goto error;
                }
-
-               free(arg);
-               arg = NULL;
-       }
-
-       /* Check for option parsing error */
-       if (opt < -1) {
-               BT_CLI_LOGE_APPEND_CAUSE("While parsing command-line options, at option %s: %s",
-                       poptBadOption(pc, 0), poptStrerror(opt));
-               goto error;
-       }
-
-       /* This command does not accept leftover arguments */
-       if (poptPeekArg(pc)) {
-               BT_CLI_LOGE_APPEND_CAUSE("Unexpected argument: %s", poptPeekArg(pc));
-               goto error;
        }
 
        /* Add current component */
@@ -2250,15 +2279,11 @@ error:
        BT_OBJECT_PUT_REF_AND_RESET(cfg);
 
 end:
-       if (pc) {
-               poptFreeContext(pc);
-       }
-
        if (error_str) {
                g_string_free(error_str, TRUE);
        }
 
-       free(arg);
+       bt_argpar_parse_ret_fini(&argpar_parse_ret);
        BT_OBJECT_PUT_REF_AND_RESET(cur_cfg_comp);
        BT_VALUE_PUT_REF_AND_RESET(cur_base_params);
        BT_VALUE_PUT_REF_AND_RESET(instance_names);
@@ -2449,46 +2474,46 @@ void print_convert_usage(FILE *fp)
 }
 
 static
-struct poptOption convert_long_options[] = {
-       /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
-       { "begin", 'b', POPT_ARG_STRING, NULL, OPT_BEGIN, NULL, NULL },
-       { "clock-cycles", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_CYCLES, NULL, NULL },
-       { "clock-date", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_DATE, NULL, NULL },
-       { "clock-force-correlate", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_FORCE_CORRELATE, NULL, NULL },
-       { "clock-gmt", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_GMT, NULL, NULL },
-       { "clock-offset", '\0', POPT_ARG_STRING, NULL, OPT_CLOCK_OFFSET, NULL, NULL },
-       { "clock-offset-ns", '\0', POPT_ARG_STRING, NULL, OPT_CLOCK_OFFSET_NS, NULL, NULL },
-       { "clock-seconds", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_SECONDS, NULL, NULL },
-       { "color", '\0', POPT_ARG_STRING, NULL, OPT_COLOR, NULL, NULL },
-       { "component", 'c', POPT_ARG_STRING, NULL, OPT_COMPONENT, NULL, NULL },
-       { "debug", 'd', POPT_ARG_NONE, NULL, OPT_DEBUG, NULL, NULL },
-       { "debug-info-dir", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_DIR, NULL, NULL },
-       { "debug-info-full-path", 0, POPT_ARG_NONE, NULL, OPT_DEBUG_INFO_FULL_PATH, NULL, NULL },
-       { "debug-info-target-prefix", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_TARGET_PREFIX, NULL, NULL },
-       { "end", 'e', POPT_ARG_STRING, NULL, OPT_END, NULL, NULL },
-       { "fields", 'f', POPT_ARG_STRING, NULL, OPT_FIELDS, NULL, NULL },
-       { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
-       { "input-format", 'i', POPT_ARG_STRING, NULL, OPT_INPUT_FORMAT, NULL, NULL },
-       { "log-level", 'l', POPT_ARG_STRING, NULL, OPT_LOG_LEVEL, NULL, NULL },
-       { "name", '\0', POPT_ARG_STRING, NULL, OPT_NAME, NULL, NULL },
-       { "names", 'n', POPT_ARG_STRING, NULL, OPT_NAMES, NULL, NULL },
-       { "debug-info", '\0', POPT_ARG_NONE, NULL, OPT_DEBUG_INFO, NULL, NULL },
-       { "no-delta", '\0', POPT_ARG_NONE, NULL, OPT_NO_DELTA, NULL, NULL },
-       { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL },
-       { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL },
-       { "output", 'w', POPT_ARG_STRING, NULL, OPT_OUTPUT, NULL, NULL },
-       { "output-format", 'o', POPT_ARG_STRING, NULL, OPT_OUTPUT_FORMAT, NULL, NULL },
-       { "params", 'p', POPT_ARG_STRING, NULL, OPT_PARAMS, NULL, NULL },
-       { "path", 'P', POPT_ARG_STRING, NULL, OPT_PATH, NULL, NULL },
-       { "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
-       { "retry-duration", '\0', POPT_ARG_STRING, NULL, OPT_RETRY_DURATION, NULL, NULL },
-       { "run-args", '\0', POPT_ARG_NONE, NULL, OPT_RUN_ARGS, NULL, NULL },
-       { "run-args-0", '\0', POPT_ARG_NONE, NULL, OPT_RUN_ARGS_0, NULL, NULL },
-       { "stream-intersection", '\0', POPT_ARG_NONE, NULL, OPT_STREAM_INTERSECTION, NULL, NULL },
-       { "timerange", '\0', POPT_ARG_STRING, NULL, OPT_TIMERANGE, NULL, NULL },
-       { "url", 'u', POPT_ARG_STRING, NULL, OPT_URL, NULL, NULL },
-       { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL },
-       { NULL, 0, '\0', NULL, 0, NULL, NULL },
+const struct bt_argpar_opt_descr convert_options[] = {
+       /* id, short_name, long_name, with_arg */
+       { OPT_BEGIN, 'b', "begin", true },
+       { OPT_CLOCK_CYCLES, '\0', "clock-cycles", false },
+       { OPT_CLOCK_DATE, '\0', "clock-date", false },
+       { OPT_CLOCK_FORCE_CORRELATE, '\0', "clock-force-correlate", false },
+       { OPT_CLOCK_GMT, '\0', "clock-gmt", false },
+       { OPT_CLOCK_OFFSET, '\0', "clock-offset", true },
+       { OPT_CLOCK_OFFSET_NS, '\0', "clock-offset-ns", true },
+       { OPT_CLOCK_SECONDS, '\0', "clock-seconds", false },
+       { OPT_COLOR, '\0', "color", true },
+       { OPT_COMPONENT, 'c', "component", true },
+       { OPT_DEBUG, 'd', "debug", false },
+       { OPT_DEBUG_INFO_DIR, '\0', "debug-info-dir", true },
+       { OPT_DEBUG_INFO_FULL_PATH, '\0', "debug-info-full-path", false },
+       { OPT_DEBUG_INFO_TARGET_PREFIX, '\0', "debug-info-target-prefix", true },
+       { OPT_END, 'e', "end", true },
+       { OPT_FIELDS, 'f', "fields", true },
+       { OPT_HELP, 'h', "help", false },
+       { OPT_INPUT_FORMAT, 'i', "input-format", true },
+       { OPT_LOG_LEVEL, 'l', "log-level", true },
+       { OPT_NAME, '\0', "name", true },
+       { OPT_NAMES, 'n', "names", true },
+       { OPT_DEBUG_INFO, '\0', "debug-info", false },
+       { OPT_NO_DELTA, '\0', "no-delta", false },
+       { OPT_OMIT_HOME_PLUGIN_PATH, '\0', "omit-home-plugin-path", false },
+       { OPT_OMIT_SYSTEM_PLUGIN_PATH, '\0', "omit-system-plugin-path", false },
+       { OPT_OUTPUT, 'w', "output", true },
+       { OPT_OUTPUT_FORMAT, 'o', "output-format", true },
+       { OPT_PARAMS, 'p', "params", true },
+       { OPT_PATH, 'P', "path", true },
+       { OPT_PLUGIN_PATH, '\0', "plugin-path", true },
+       { OPT_RETRY_DURATION, '\0', "retry-duration", true },
+       { OPT_RUN_ARGS, '\0', "run-args", false },
+       { OPT_RUN_ARGS_0, '\0', "run-args-0", false },
+       { OPT_STREAM_INTERSECTION, '\0', "stream-intersection", false },
+       { OPT_TIMERANGE, '\0', "timerange", true },
+       { OPT_URL, 'u', "url", true },
+       { OPT_VERBOSE, 'v', "verbose", false },
+       BT_ARGPAR_OPT_DESCR_SENTINEL
 };
 
 static
@@ -3341,11 +3366,9 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                bool force_omit_home_plugin_path,
                const bt_value *initial_plugin_paths, int *default_log_level)
 {
-       poptContext pc = NULL;
-       char *arg = NULL;
        enum bt_config_component_dest cur_comp_dest =
                        BT_CONFIG_COMPONENT_DEST_UNKNOWN;
-       int opt, ret = 0;
+       int ret = 0;
        struct bt_config *cfg = NULL;
        bool got_input_format_opt = false;
        bool got_output_format_opt = false;
@@ -3354,7 +3377,6 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
        bool stream_intersection_mode = false;
        GString *cur_name = NULL;
        GString *cur_name_prefix = NULL;
-       const char *leftover = NULL;
        bool print_run_args = false;
        bool print_run_args_0 = false;
        bool print_ctf_metadata = false;
@@ -3378,6 +3400,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
        char *output = NULL;
        struct auto_source_discovery auto_disc = { NULL };
        GString *auto_disc_comp_name = NULL;
+       struct bt_argpar_parse_ret argpar_parse_ret = { 0 };
 
        /*
         * Array of `struct implicit_component_args *` created for the sources
@@ -3504,23 +3527,38 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
         * Also it appends the plugin paths of --plugin-path to
         * `plugin_paths`.
         */
-       pc = poptGetContext(NULL, argc, (const char **) argv,
-               convert_long_options, POPT_CONTEXT_KEEP_FIRST);
-       if (!pc) {
-               BT_CLI_LOGE_APPEND_CAUSE("Cannot get popt context.");
+       argpar_parse_ret = bt_argpar_parse(argc, argv, convert_options, true);
+       if (argpar_parse_ret.error) {
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "While parsing `convert` command's command-line arguments: %s",
+                       argpar_parse_ret.error->str);
                goto error;
        }
 
-       poptReadDefaultConfig(pc, 0);
+       if (help_option_is_specified(&argpar_parse_ret)) {
+               print_convert_usage(stdout);
+               *retcode = -1;
+               BT_OBJECT_PUT_REF_AND_RESET(cfg);
+               goto end;
+       }
 
-       while ((opt = poptGetNextOpt(pc)) > 0) {
+       for (i = 0; i < argpar_parse_ret.items->len; i++) {
+               struct bt_argpar_item *argpar_item =
+                       g_ptr_array_index(argpar_parse_ret.items, i);
+               struct bt_argpar_item_opt *argpar_item_opt;
                char *name = NULL;
                char *plugin_name = NULL;
                char *comp_cls_name = NULL;
+               const char *arg;
+
+               if (argpar_item->type != BT_ARGPAR_ITEM_TYPE_OPT) {
+                       continue;
+               }
 
-               arg = poptGetOptArg(pc);
+               argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item;
+               arg = argpar_item_opt->arg;
 
-               switch (opt) {
+               switch (argpar_item_opt->descr->id) {
                case OPT_COMPONENT:
                {
                        bt_component_class_type type;
@@ -3714,11 +3752,6 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                                goto error;
                        }
                        break;
-               case OPT_HELP:
-                       print_convert_usage(stdout);
-                       *retcode = -1;
-                       BT_OBJECT_PUT_REF_AND_RESET(cfg);
-                       goto end;
                case OPT_BEGIN:
                case OPT_CLOCK_CYCLES:
                case OPT_CLOCK_DATE:
@@ -3749,12 +3782,9 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                        break;
                default:
                        BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).",
-                               opt);
+                               argpar_item_opt->descr->id);
                        goto error;
                }
-
-               free(arg);
-               arg = NULL;
        }
 
        /* Append current component's name if needed */
@@ -3765,35 +3795,25 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                goto error;
        }
 
-       /* Check for option parsing error */
-       if (opt < -1) {
-               BT_CLI_LOGE_APPEND_CAUSE("While parsing command-line options, at option `%s`: %s.",
-                       poptBadOption(pc, 0), poptStrerror(opt));
-               goto error;
-       }
-
-       poptFreeContext(pc);
-       free(arg);
-       arg = NULL;
-
        /*
         * Second pass: transform the convert-specific options and
         * arguments into implicit component instances for the run
         * command.
         */
-       pc = poptGetContext(NULL, argc, (const char **) argv,
-               convert_long_options, POPT_CONTEXT_KEEP_FIRST);
-       if (!pc) {
-               BT_CLI_LOGE_APPEND_CAUSE("Cannot get popt context.");
-               goto error;
-       }
+       for (i = 0; i < argpar_parse_ret.items->len; i++) {
+               struct bt_argpar_item *argpar_item =
+                       g_ptr_array_index(argpar_parse_ret.items, i);
+               struct bt_argpar_item_opt *argpar_item_opt;
+               const char *arg;
 
-       poptReadDefaultConfig(pc, 0);
+               if (argpar_item->type != BT_ARGPAR_ITEM_TYPE_OPT) {
+                       continue;
+               }
 
-       while ((opt = poptGetNextOpt(pc)) > 0) {
-               arg = poptGetOptArg(pc);
+               argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item;
+               arg = argpar_item_opt->arg;
 
-               switch (opt) {
+               switch (argpar_item_opt->descr->id) {
                case OPT_BEGIN:
                        if (trimmer_has_begin) {
                                printf("At --begin option: --begin or --timerange option already specified\n    %s\n",
@@ -4069,16 +4089,6 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                default:
                        break;
                }
-
-               free(arg);
-               arg = NULL;
-       }
-
-       /* Check for option parsing error */
-       if (opt < -1) {
-               BT_CLI_LOGE_APPEND_CAUSE("While parsing command-line options, at option %s: %s",
-                       poptBadOption(pc, 0), poptStrerror(opt));
-               goto error;
        }
 
        /*
@@ -4103,8 +4113,18 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
        }
 
        /* Consume and keep leftover arguments */
-       while ((leftover = poptGetArg(pc))) {
-               if (bt_value_array_append_string_element(leftovers, leftover) !=
+       for (i = 0; i < argpar_parse_ret.items->len; i++) {
+               struct bt_argpar_item *argpar_item =
+                       g_ptr_array_index(argpar_parse_ret.items, i);
+               struct bt_argpar_item_non_opt *argpar_item_non_opt;
+
+               if (argpar_item->type != BT_ARGPAR_ITEM_TYPE_NON_OPT) {
+                       continue;
+               }
+
+               argpar_item_non_opt = (struct bt_argpar_item_non_opt *) argpar_item;
+
+               if (bt_value_array_append_string_element(leftovers, argpar_item_non_opt->arg) !=
                                BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) {
                        BT_CLI_LOGE_APPEND_CAUSE_OOM();
                        goto error;
@@ -4557,11 +4577,8 @@ end:
                *default_log_level = cli_default_log_level;
        }
 
-       if (pc) {
-               poptFreeContext(pc);
-       }
+       bt_argpar_parse_ret_fini(&argpar_parse_ret);
 
-       free(arg);
        free(output);
 
        if (cur_name) {
This page took 0.039383 seconds and 4 git commands to generate.