From: Jens Steinhauser Date: Tue, 15 Jul 2014 20:52:35 +0000 (+0200) Subject: options: String options are only allowed once. X-Git-Tag: sigrok-cli-0.6.0~93 X-Git-Url: https://sigrok.org/gitweb/?p=sigrok-cli.git;a=commitdiff_plain;h=0894b97269117fef77fb22d06d726a38e652cee4;hp=7a638873128dedfcad1e77d87c3d2c25516abaf2;ds=sidebyside options: String options are only allowed once. --- diff --git a/options.c b/options.c index b26ca4b..9f9d912 100644 --- a/options.c +++ b/options.c @@ -47,52 +47,93 @@ gchar *opt_frames = NULL; gchar *opt_continuous = NULL; gchar *opt_set = NULL; +/* defines a callback function that generates + an error if an option occurs twice */ +#define CHECK_ONCE(option) \ +static gboolean check_ ## option \ + (const gchar *option_name, const gchar *value, \ + gpointer data, GError **error) \ +{ \ + (void)data; \ + \ + static gboolean seen = FALSE; \ + if (seen) { \ + g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, \ + "superfluous option \"%s\"", option_name); \ + return FALSE; \ + } \ + \ + option = g_strdup(value); \ + seen = TRUE; \ + return TRUE; \ +} + +CHECK_ONCE(opt_drv) +CHECK_ONCE(opt_config) +CHECK_ONCE(opt_input_format) +CHECK_ONCE(opt_output_format) +CHECK_ONCE(opt_channels) +CHECK_ONCE(opt_channel_group) +CHECK_ONCE(opt_triggers) +#ifdef HAVE_SRD +CHECK_ONCE(opt_pds) +CHECK_ONCE(opt_pd_stack) +CHECK_ONCE(opt_pd_annotations) +CHECK_ONCE(opt_pd_meta) +CHECK_ONCE(opt_pd_binary) +#endif +CHECK_ONCE(opt_time) +CHECK_ONCE(opt_samples) +CHECK_ONCE(opt_frames) + +#undef CHECK_STR_ONCE + static const GOptionEntry optargs[] = { {"version", 'V', 0, G_OPTION_ARG_NONE, &opt_version, "Show version and support list", NULL}, {"loglevel", 'l', 0, G_OPTION_ARG_INT, &opt_loglevel, "Set loglevel (5 is most verbose)", NULL}, - {"driver", 'd', 0, G_OPTION_ARG_STRING, &opt_drv, + {"driver", 'd', 0, G_OPTION_ARG_CALLBACK, &check_opt_drv, "The driver to use", NULL}, - {"config", 'c', 0, G_OPTION_ARG_STRING, &opt_config, + {"config", 'c', 0, G_OPTION_ARG_CALLBACK, &check_opt_config, "Specify device configuration options", NULL}, {"input-file", 'i', 0, G_OPTION_ARG_FILENAME, &opt_input_file, "Load input from file", NULL}, - {"input-format", 'I', 0, G_OPTION_ARG_STRING, &opt_input_format, + {"input-format", 'I', 0, G_OPTION_ARG_CALLBACK, &check_opt_input_format, "Input format", NULL}, {"output-file", 'o', 0, G_OPTION_ARG_FILENAME, &opt_output_file, "Save output to file", NULL}, - {"output-format", 'O', 0, G_OPTION_ARG_STRING, &opt_output_format, + {"output-format", 'O', 0, G_OPTION_ARG_CALLBACK, &check_opt_output_format, "Output format", NULL}, - {"channels", 'C', 0, G_OPTION_ARG_STRING, &opt_channels, + {"channels", 'C', 0, G_OPTION_ARG_CALLBACK, &check_opt_channels, "Channels to use", NULL}, - {"channel-group", 'g', 0, G_OPTION_ARG_STRING, &opt_channel_group, + {"channel-group", 'g', 0, G_OPTION_ARG_CALLBACK, &check_opt_channel_group, "Channel groups", NULL}, - {"triggers", 't', 0, G_OPTION_ARG_STRING, &opt_triggers, + {"triggers", 't', 0, G_OPTION_ARG_CALLBACK, &check_opt_triggers, "Trigger configuration", NULL}, {"wait-trigger", 'w', 0, G_OPTION_ARG_NONE, &opt_wait_trigger, "Wait for trigger", NULL}, #ifdef HAVE_SRD - {"protocol-decoders", 'P', 0, G_OPTION_ARG_STRING, &opt_pds, + {"protocol-decoders", 'P', 0, G_OPTION_ARG_CALLBACK, &check_opt_pds, "Protocol decoders to run", NULL}, - {"protocol-decoder-stack", 'S', 0, G_OPTION_ARG_STRING, &opt_pd_stack, + {"protocol-decoder-stack", 'S', 0, G_OPTION_ARG_CALLBACK, &check_opt_pd_stack, "Protocol decoder stack", NULL}, - {"protocol-decoder-annotations", 'A', 0, G_OPTION_ARG_STRING, &opt_pd_annotations, + {"protocol-decoder-annotations", 'A', 0, G_OPTION_ARG_CALLBACK, &check_opt_pd_annotations, "Protocol decoder annotation(s) to show", NULL}, - {"protocol-decoder-meta", 'M', 0, G_OPTION_ARG_STRING, &opt_pd_meta, + {"protocol-decoder-meta", 'M', 0, G_OPTION_ARG_CALLBACK, &check_opt_pd_meta, "Protocol decoder meta output to show", NULL}, - {"protocol-decoder-binary", 'B', 0, G_OPTION_ARG_STRING, &opt_pd_binary, + {"protocol-decoder-binary", 'B', 0, G_OPTION_ARG_CALLBACK, &check_opt_pd_binary, "Protocol decoder binary output to show", NULL}, #endif {"scan", 0, 0, G_OPTION_ARG_NONE, &opt_scan_devs, "Scan for devices", NULL}, {"show", 0, 0, G_OPTION_ARG_NONE, &opt_show, "Show device detail", NULL}, - {"time", 0, 0, G_OPTION_ARG_STRING, &opt_time, + {"time", 0, 0, G_OPTION_ARG_CALLBACK, &check_opt_time, "How long to sample (ms)", NULL}, - {"samples", 0, 0, G_OPTION_ARG_STRING, &opt_samples, + {"samples", 0, 0, G_OPTION_ARG_CALLBACK, &check_opt_samples, "Number of samples to acquire", NULL}, - {"frames", 0, 0, G_OPTION_ARG_STRING, &opt_frames, + {"frames", 0, 0, G_OPTION_ARG_CALLBACK, &check_opt_frames, "Number of frames to acquire", NULL}, {"continuous", 0, 0, G_OPTION_ARG_NONE, &opt_continuous, "Sample continuously", NULL},