From: Andre Noll Date: Fri, 12 Apr 2013 11:54:37 +0000 (+0200) Subject: Revamp ggo help. X-Git-Tag: v0.4.13~23^2~7 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=aa74a903545250506fd4c29791e6f4aef3a01c41 Revamp ggo help. This adds usage and description fields to struct ggo_help and changes ggo_print_help() to optionally print these. The boolean detailed_help flag of ggo_print_help() is replaced by a bitmask which lets the caller specify what to print. Four pre-defined masks are used to print the normal help, the detailed help, the help for modules (receivers, filters, writers) and the detailed module help. The new macro DEFINE_GGO_HELP can be employed to create a struct ggo_help from a gengetopt structure. --- diff --git a/afh_recv.c b/afh_recv.c index 96f0d7ec..5c17dab7 100644 --- a/afh_recv.c +++ b/afh_recv.c @@ -254,9 +254,6 @@ void afh_recv_init(struct receiver *r) r->parse_config = afh_recv_parse_config; r->free_config = afh_recv_free_config; r->execute = afh_execute; - r->help = (struct ggo_help) { - .short_help = afh_recv_args_info_help, - .detailed_help = afh_recv_args_info_detailed_help - }; + r->help = (struct ggo_help)DEFINE_GGO_HELP(afh_recv); afh_recv_cmdline_parser_free(&dummy); } diff --git a/alsa_write.c b/alsa_write.c index 88e48b45..a3912c11 100644 --- a/alsa_write.c +++ b/alsa_write.c @@ -361,9 +361,6 @@ void alsa_write_init(struct writer *w) w->post_select = alsa_write_post_select; w->parse_config_or_die = alsa_parse_config_or_die; w->free_config = alsa_free_config; - w->help = (struct ggo_help) { - .short_help = alsa_write_args_info_help, - .detailed_help = alsa_write_args_info_detailed_help - }; + w->help = (struct ggo_help)DEFINE_GGO_HELP(alsa_write); alsa_write_cmdline_parser_free(&dummy); } diff --git a/amp_filter.c b/amp_filter.c index a6bfca25..f62ea8a2 100644 --- a/amp_filter.c +++ b/amp_filter.c @@ -137,8 +137,5 @@ void amp_filter_init(struct filter *f) f->post_select = amp_post_select; f->parse_config = amp_parse_config; f->free_config = amp_free_config; - f->help = (struct ggo_help) { - .short_help = amp_filter_args_info_help, - .detailed_help = amp_filter_args_info_detailed_help - }; + f->help = (struct ggo_help)DEFINE_GGO_HELP(amp_filter); } diff --git a/ao_write.c b/ao_write.c index 9d204ff3..fdae8eea 100644 --- a/ao_write.c +++ b/ao_write.c @@ -371,9 +371,7 @@ void ao_write_init(struct writer *w) w->post_select = aow_post_select; w->parse_config_or_die = aow_parse_config_or_die; w->free_config = aow_free_config; - w->help = (struct ggo_help) { - .short_help = ao_write_args_info_help, - }; + w->help = (struct ggo_help)DEFINE_GGO_HELP(ao_write); /* create detailed help containing all supported drivers/options */ for (i = 0; ao_write_args_info_detailed_help[i]; i++) ; /* nothing */ diff --git a/audiod.c b/audiod.c index c183491f..8552af6b 100644 --- a/audiod.c +++ b/audiod.c @@ -1301,17 +1301,17 @@ static void set_initial_status(void) __noreturn static void print_help_and_die(void) { - int d = conf.detailed_help_given; - const char **p = d? audiod_args_info_detailed_help - : audiod_args_info_help; - - printf_or_die("%s\n\n", version_single_line("audiod")); - printf_or_die("%s\n\n", audiod_args_info_usage); - for (; *p; p++) - printf_or_die("%s\n", *p); - print_receiver_helps(d); - print_filter_helps(d); - print_writer_helps(d); + struct ggo_help h = DEFINE_GGO_HELP(audiod); + bool d = conf.detailed_help_given; + unsigned flags; + + flags = d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS; + ggo_print_help(&h, flags); + + flags = d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS; + print_receiver_helps(flags); + print_filter_helps(flags); + print_writer_helps(flags); exit(0); } diff --git a/compress_filter.c b/compress_filter.c index d7162791..f6108c75 100644 --- a/compress_filter.c +++ b/compress_filter.c @@ -153,8 +153,5 @@ void compress_filter_init(struct filter *f) f->post_select = compress_post_select; f->parse_config = compress_parse_config; f->free_config = compress_free_config; - f->help = (struct ggo_help) { - .short_help = compress_filter_args_info_help, - .detailed_help = compress_filter_args_info_detailed_help - }; + f->help = (struct ggo_help)DEFINE_GGO_HELP(compress_filter); } diff --git a/configure.ac b/configure.ac index 0bd47916..e3d1b40e 100644 --- a/configure.ac +++ b/configure.ac @@ -138,7 +138,7 @@ audiod_audio_formats="wma" afh_cmdline_objs="add_cmdline(afh)" afh_errlist_objs="afh string fd mp3_afh afh_common time wma_afh wma_common - version" + version ggo" afh_ldflags="" write_cmdline_objs="add_cmdline(write file_write)" diff --git a/dccp_recv.c b/dccp_recv.c index 875d8384..c751f2f7 100644 --- a/dccp_recv.c +++ b/dccp_recv.c @@ -180,9 +180,6 @@ void dccp_recv_init(struct receiver *r) r->post_select = dccp_recv_post_select; r->parse_config = dccp_recv_parse_config; r->free_config = dccp_recv_free_config; - r->help = (struct ggo_help) { - .short_help = dccp_recv_args_info_help, - .detailed_help = dccp_recv_args_info_detailed_help - }; + r->help = (struct ggo_help)DEFINE_GGO_HELP(dccp_recv); dccp_recv_cmdline_parser_free(&dummy); } diff --git a/file_write.c b/file_write.c index cea21cb3..f7b2b307 100644 --- a/file_write.c +++ b/file_write.c @@ -157,9 +157,6 @@ void file_write_init(struct writer *w) w->parse_config_or_die = file_write_parse_config_or_die; w->free_config = file_write_free_config; w->close = file_write_close; - w->help = (struct ggo_help) { - .short_help = file_write_args_info_help, - .detailed_help = file_write_args_info_detailed_help - }; + w->help = (struct ggo_help)DEFINE_GGO_HELP(file_write); file_write_cmdline_parser_free(&dummy); } diff --git a/filter.c b/filter.c index 9ece0635..3b688573 100644 --- a/filter.c +++ b/filter.c @@ -47,15 +47,11 @@ INIT_STDERR_LOGGING(loglevel); __noreturn static void print_help_and_die(void) { - int d = conf.detailed_help_given; - const char **p = d? filter_args_info_detailed_help - : filter_args_info_help; - - printf_or_die("%s\n\n", version_single_line("filter")); - printf_or_die("%s\n\n", filter_args_info_usage); - for (; *p; p++) - printf_or_die("%s\n", *p); - print_filter_helps(d); + struct ggo_help h = DEFINE_GGO_HELP(filter); + bool d = conf.detailed_help_given; + + ggo_print_help(&h, d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS); + print_filter_helps(d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS); exit(0); } diff --git a/filter.h b/filter.h index 9c57904e..1cda119f 100644 --- a/filter.h +++ b/filter.h @@ -121,7 +121,7 @@ struct filter { void filter_init(void); int check_filter_arg(char *filter_arg, void **conf); -void print_filter_helps(int detailed); +void print_filter_helps(unsigned flags); void generic_filter_pre_select(struct sched *s, struct task *t); int decoder_execute(const char *cmd, unsigned sample_rate, unsigned channels, char **result); diff --git a/filter_common.c b/filter_common.c index 6eb550e8..787255af 100644 --- a/filter_common.c +++ b/filter_common.c @@ -101,9 +101,9 @@ int check_filter_arg(char *fa, void **conf) /** * Print help text of each filter to stdout. * - * \param detailed If non-zero, print detailed help. + * \param flags Passed to \ref ggo_print_help(). */ -void print_filter_helps(int detailed) +void print_filter_helps(unsigned flags) { int i, num = 0; @@ -122,8 +122,8 @@ void print_filter_helps(int detailed) if (!f->help.short_help) continue; - printf_or_die("Options for %s:\n", f->name); - ggo_print_help(&f->help, detailed); + printf_or_die("\nOptions for %s:", f->name); + ggo_print_help(&f->help, flags); } } diff --git a/ggo.c b/ggo.c index e3aa5794..d8d56c03 100644 --- a/ggo.c +++ b/ggo.c @@ -9,6 +9,7 @@ #include "para.h" #include "ggo.h" +#include "version.h" /** * Wrapper for printf() that exits on errors. @@ -32,20 +33,25 @@ __printf_1_2 int printf_or_die(const char *fmt, ...) * Print one of the two given help texts. * * \param help contains the help texts. - * \param detailed_help Whether to print the detailed help text. + * \param flags What to print, see \ref ggo_print_help_flags. */ -void ggo_print_help(struct ggo_help *help, int detailed_help) +void ggo_print_help(struct ggo_help *help, unsigned flags) { const char **p; - if (!help) - return; - if (detailed_help) + if (flags & GPH_PRINT_NAME_VERSION) + printf_or_die("%s\n", version_single_line(help->prefix)); + if (help->usage && (flags & GPH_PRINT_USAGE)) + printf_or_die("\n%s\n", help->usage); + if (help->description && (flags & GPH_PRINT_DESCRIPTION)) + printf_or_die("\n%s\n", help->description); + printf_or_die("\n"); + if (flags & GPH_DETAILED) p = help->detailed_help; else p = help->short_help; if (!p) return; for (; *p; p++) - printf_or_die("\t%s\n", *p); + printf_or_die("%s\n", *p); } diff --git a/ggo.h b/ggo.h index be85a1b4..12574dba 100644 --- a/ggo.h +++ b/ggo.h @@ -7,14 +7,61 @@ /** \file ggo.h Functions and structures for help text handling. */ /** - * Used by executables that can not use gengetopt's generated help function. + * Information extracted from the .cmdline.h header files. */ struct ggo_help { - /** The lines of the short help text. */ + /** Program or module (receiver, filter, writer) name. */ + const char *prefix; + /** Generated by gengetopt from the options in the .ggo file. */ const char **short_help; - /** The lines of the detailed help text. */ + /** Like \a short_help, plus the \a details section. */ const char **detailed_help; + /** Generated by gengetopt and exported via the *.cmdline.h file. */ + const char *usage; + /** The description text given in the .ggo file. */ + const char *description; }; -void ggo_print_help(struct ggo_help *help, int detailed_help); +/** + * Control the output of \ref ggo_print_help(). + * + * Any combination of these flags may be passed to ggo_print_help(). + * Note that the list of supported options is always printed. + */ +enum ggo_print_help_flags { + /** Whether to print the short help or the detailed help. */ + GPH_DETAILED = 1 << 0, + /** Print the program or module name, git version and codename. */ + GPH_PRINT_NAME_VERSION = 1 << 1, + /** Print the synopsis. */ + GPH_PRINT_USAGE = 1 << 2, + /** Print the description text. */ + GPH_PRINT_DESCRIPTION = 1 << 3, +}; + +/** Used to print the normal help of programs (--help) */ +#define GPH_STANDARD_FLAGS \ + (GPH_PRINT_NAME_VERSION | GPH_PRINT_USAGE) + +/** Additional information for --detailed-help. */ +#define GPH_STANDARD_FLAGS_DETAILED \ + (GPH_STANDARD_FLAGS | GPH_DETAILED | GPH_PRINT_DESCRIPTION) + +/** For module help embedded in a program help. */ +#define GPH_MODULE_FLAGS 0 + +/** Modules help with detailed descriptions. */ +#define GPH_MODULE_FLAGS_DETAILED GPH_DETAILED | GPH_PRINT_DESCRIPTION + +/** Make a ggo_help structure using information from the .cmdline.h file. */ +#define DEFINE_GGO_HELP(_prefix) \ + { \ + .prefix = #_prefix, \ + .short_help = _prefix ## _args_info_help, \ + .detailed_help = _prefix ## _args_info_detailed_help, \ + .usage = _prefix ## _args_info_usage, \ + .description = _prefix ## _args_info_description, \ + } + +void ggo_print_help(struct ggo_help *help, unsigned flags); __printf_1_2 int printf_or_die(const char *fmt, ...); diff --git a/http_recv.c b/http_recv.c index 8cb984ff..7db8ba19 100644 --- a/http_recv.c +++ b/http_recv.c @@ -193,9 +193,6 @@ void http_recv_init(struct receiver *r) r->post_select = http_recv_post_select; r->parse_config = http_recv_parse_config; r->free_config = http_recv_free_config; - r->help = (struct ggo_help) { - .short_help = http_recv_args_info_help, - .detailed_help = http_recv_args_info_detailed_help - }; + r->help = (struct ggo_help)DEFINE_GGO_HELP(http_recv); http_recv_cmdline_parser_free(&dummy); } diff --git a/mp3dec_filter.c b/mp3dec_filter.c index 98627504..33c0dfc9 100644 --- a/mp3dec_filter.c +++ b/mp3dec_filter.c @@ -221,8 +221,5 @@ void mp3dec_filter_init(struct filter *f) f->pre_select = generic_filter_pre_select; f->post_select = mp3dec_post_select; f->execute = mp3dec_execute; - f->help = (struct ggo_help) { - .short_help = mp3dec_filter_args_info_help, - .detailed_help = mp3dec_filter_args_info_detailed_help - }; + f->help = (struct ggo_help)DEFINE_GGO_HELP(mp3dec_filter); } diff --git a/oss_write.c b/oss_write.c index cd327243..3c61a445 100644 --- a/oss_write.c +++ b/oss_write.c @@ -235,9 +235,6 @@ void oss_write_init(struct writer *w) w->post_select = oss_post_select; w->parse_config_or_die = oss_parse_config_or_die; w->free_config = oss_free_config; - w->help = (struct ggo_help) { - .short_help = oss_write_args_info_help, - .detailed_help = oss_write_args_info_detailed_help - }; + w->help = (struct ggo_help)DEFINE_GGO_HELP(oss_write); oss_write_cmdline_parser_free(&dummy); } diff --git a/osx_write.c b/osx_write.c index 41b19030..f1e308d8 100644 --- a/osx_write.c +++ b/osx_write.c @@ -366,9 +366,6 @@ void osx_write_init(struct writer *w) w->post_select = osx_write_post_select; w->parse_config_or_die = osx_write_parse_config_or_die; w->free_config = osx_free_config; - w->help = (struct ggo_help) { - .short_help = osx_write_args_info_help, - .detailed_help = osx_write_args_info_detailed_help - }; + w->help = (struct ggo_help)DEFINE_GGO_HELP(osx_write); osx_write_cmdline_parser_free(&dummy); } diff --git a/play.c b/play.c index 7c1ee932..35b25119 100644 --- a/play.c +++ b/play.c @@ -139,16 +139,11 @@ static void check_afh_receiver_or_die(void) __noreturn static void print_help_and_die(void) { - int d = conf.detailed_help_given; - const char **p = d? play_args_info_detailed_help - : play_args_info_help; - - printf_or_die("%s\n\n", version_single_line("play")); - printf_or_die("%s\n\n", play_args_info_usage); - if (d) - printf_or_die("%s\n", play_args_info_description); - for (; *p; p++) - printf_or_die("%s\n", *p); + struct ggo_help help = DEFINE_GGO_HELP(play); + unsigned flags = conf.detailed_help_given? + GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS; + + ggo_print_help(&help, flags); exit(0); } diff --git a/prebuffer_filter.c b/prebuffer_filter.c index 0759d678..655c981b 100644 --- a/prebuffer_filter.c +++ b/prebuffer_filter.c @@ -123,8 +123,5 @@ void prebuffer_filter_init(struct filter *f) f->free_config = prebuffer_free_config; f->pre_select = prebuffer_pre_select; f->post_select = prebuffer_post_select; - f->help = (struct ggo_help) { - .short_help = prebuffer_filter_args_info_help, - .detailed_help = prebuffer_filter_args_info_detailed_help - }; + f->help = (struct ggo_help)DEFINE_GGO_HELP(prebuffer_filter); } diff --git a/recv.c b/recv.c index a3fdd30d..7a5549aa 100644 --- a/recv.c +++ b/recv.c @@ -39,15 +39,11 @@ INIT_RECV_ERRLISTS; __noreturn static void print_help_and_die(void) { - int d = conf.detailed_help_given; - const char **p = d? recv_args_info_detailed_help - : recv_args_info_help; - - printf_or_die("%s\n\n", version_single_line("recv")); - printf_or_die("%s\n\n", recv_args_info_usage); - for (; *p; p++) - printf_or_die("%s\n", *p); - print_receiver_helps(d); + struct ggo_help h = DEFINE_GGO_HELP(recv); + bool d = conf.detailed_help_given; + + ggo_print_help(&h, d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS); + print_receiver_helps(d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS); exit(0); } diff --git a/recv.h b/recv.h index cc44a602..008af39a 100644 --- a/recv.h +++ b/recv.h @@ -141,7 +141,7 @@ struct receiver { void recv_init(void); void *check_receiver_arg(char *ra, int *receiver_num); -void print_receiver_helps(int detailed); +void print_receiver_helps(unsigned flags); int generic_recv_pre_select(struct sched *s, struct task *t); /** \cond receiver */ diff --git a/recv_common.c b/recv_common.c index f899c301..fe745917 100644 --- a/recv_common.c +++ b/recv_common.c @@ -92,22 +92,22 @@ void *check_receiver_arg(char *ra, int *receiver_num) /** * Print out the help texts to all receivers. * - * \param detailed Whether the detailed help should be printed. + * \param flags Passed to \ref ggo_print_help(). */ -void print_receiver_helps(int detailed) +void print_receiver_helps(unsigned flags) { int i; - printf_or_die("\nAvailable receivers: \n\t"); + printf_or_die("\nAvailable receivers: "); FOR_EACH_RECEIVER(i) printf_or_die("%s%s", i? " " : "", receivers[i].name); - printf_or_die("\n\n"); + printf_or_die("\n"); FOR_EACH_RECEIVER(i) { struct receiver *r = receivers + i; if (!r->help.short_help) continue; - printf_or_die("Options for %s:\n", r->name); - ggo_print_help(&r->help, detailed); + printf_or_die("\nOptions for %s:", r->name); + ggo_print_help(&r->help, flags); } } diff --git a/resample_filter.c b/resample_filter.c index bd8ece91..5ad584de 100644 --- a/resample_filter.c +++ b/resample_filter.c @@ -310,8 +310,5 @@ void resample_filter_init(struct filter *f) f->parse_config = resample_parse_config; f->free_config = resample_free_config; f->execute = resample_execute; - f->help = (struct ggo_help) { - .short_help = resample_filter_args_info_help, - .detailed_help = resample_filter_args_info_detailed_help - }; + f->help = (struct ggo_help)DEFINE_GGO_HELP(resample_filter); } diff --git a/udp_recv.c b/udp_recv.c index cff55f2d..436b298c 100644 --- a/udp_recv.c +++ b/udp_recv.c @@ -220,9 +220,6 @@ void udp_recv_init(struct receiver *r) r->post_select = udp_recv_post_select; r->parse_config = udp_recv_parse_config; r->free_config = udp_recv_free_config; - r->help = (struct ggo_help) { - .short_help = udp_recv_args_info_help, - .detailed_help = udp_recv_args_info_detailed_help - }; + r->help = (struct ggo_help)DEFINE_GGO_HELP(udp_recv); udp_recv_cmdline_parser_free(&dummy); } diff --git a/write.c b/write.c index 73cddf8c..6799db41 100644 --- a/write.c +++ b/write.c @@ -35,15 +35,11 @@ INIT_STDERR_LOGGING(loglevel) __noreturn static void print_help_and_die(void) { - int d = conf.detailed_help_given; - const char **p = d? write_args_info_detailed_help - : write_args_info_help; - - printf_or_die("%s\n\n", version_single_line("write")); - printf_or_die("%s\n\n", write_args_info_usage); - for (; *p; p++) - printf_or_die("%s\n", *p); - print_writer_helps(d); + struct ggo_help h = DEFINE_GGO_HELP(write); + bool d = conf.detailed_help_given; + + ggo_print_help(&h, d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS); + print_writer_helps(d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS); exit(0); } diff --git a/write_common.c b/write_common.c index 44ccf88a..b61b9384 100644 --- a/write_common.c +++ b/write_common.c @@ -121,23 +121,23 @@ void register_writer_node(struct writer_node *wn, struct btr_node *parent, /** * Print the help text of all writers to stdout. * - * \param detailed Whether to print the detailed help text. + * \param flags Passed to \ref ggo_print_help(). */ -void print_writer_helps(int detailed) +void print_writer_helps(unsigned flags) { int i; - printf_or_die("\nAvailable writers: \n\t"); + printf_or_die("\nAvailable writers: "); FOR_EACH_WRITER(i) printf_or_die("%s%s", i? " " : "", writer_names[i]); - printf_or_die("\n\n"); + printf_or_die("\n"); FOR_EACH_WRITER(i) { struct writer *w = writers + i; if (!w->help.short_help) continue; - printf_or_die("Options for %s:\n", writer_names[i]); - ggo_print_help(&w->help, detailed); + printf_or_die("\nOptions for %s:", writer_names[i]); + ggo_print_help(&w->help, flags); } } diff --git a/write_common.h b/write_common.h index 8788a4cf..ecad2d18 100644 --- a/write_common.h +++ b/write_common.h @@ -8,7 +8,7 @@ void writer_init(void); void *check_writer_arg_or_die(const char *wa, int *writer_num); -void print_writer_helps(int detailed); +void print_writer_helps(unsigned flags); void register_writer_node(struct writer_node *wn, struct btr_node *parent, struct sched *s); void get_btr_sample_rate(struct btr_node *btrn, int32_t *result);