X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=write_common.c;h=14cc98a4189a5f74907f8bfcf416f62bcc2515c5;hp=e191c49ad2ec2240534b6c420ac6d146ac3efc49;hb=57a338b4f7a8346708636de18780eaec52750e96;hpb=56df9bb38aa4725f9244a7898d765608d8a1fffa diff --git a/write_common.c b/write_common.c index e191c49a..14cc98a4 100644 --- a/write_common.c +++ b/write_common.c @@ -1,96 +1,125 @@ -/* - * Copyright (C) 2006-2014 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2006 Andre Noll , see file COPYING. */ /** \file write_common.c common functions of para_audiod and para_write */ #include +#include +#include "write_cmd.lsg.h" #include "para.h" #include "string.h" #include "list.h" #include "sched.h" -#include "ggo.h" #include "buffer_tree.h" #include "write.h" #include "error.h" -#include "write_common.h" -/** the array containing the names of all supported writers */ -const char *writer_names[] ={WRITER_NAMES}; +/** Loop over all writers. */ +#define FOR_EACH_WRITER(i) for (i = 1; lls_cmd(i, write_cmd_suite); i++) -/** the array of supported writers */ -struct writer writers[NUM_SUPPORTED_WRITERS] = {WRITER_ARRAY}; -/** - * Call the init function of each supported paraslash writer. - */ -void writer_init(void) +static inline bool writer_supported(int wid) +{ + return lls_user_data(WRITE_CMD(wid)); +} + +/* simply return the first available writer */ +static int default_writer_id(void) { int i; FOR_EACH_WRITER(i) - writers[i].init(&writers[i]); + if (writer_supported(i)) + return i; + assert(0); /* the file writer should always be available */ } + /** - * Check if given string is a valid command line for any writer. + * Return the writer structure from a writer ID. * - * \param \wa String of the form writer_name:options. - * \param writer_num Contains the number of the writer upon success. + * \param wid If non-positive, a pointer to the default writer is returned. + * + * \return Pointer to a (constant) struct writer. + */ +const struct writer *writer_get(int wid) +{ + if (wid < 0) + wid = default_writer_id(); + return lls_user_data(WRITE_CMD(wid)); +} + +/** + * Return name of the writer identified by a writer ID. * - * This function checks whether \a wa starts with the name of a supported - * paraslash writer, optionally followed by a colon and any options for that - * writer. If a valid writer name was found and further are present, the - * remaining part of \a wa is passed to that writer's config parser. + * \param wid If non-positive, the name of the default writer is returned. * - * \return On success, a pointer to the gengetopt args info struct is returned - * and \a writer_num contains the number of the writer. Otherwise this function - * prints an error message and calls exit(). + * \return The returned buffer must not be freed by the caller. */ -void *check_writer_arg_or_die(const char *wa, int *writer_num) +const char *writer_name(int wid) { - int i, ret, argc; - const char *cmdline; - char **argv; - void *conf; + if (wid <= 0) + wid = default_writer_id(); + return lls_command_name(WRITE_CMD(wid)); +} - if (!wa || !*wa) { - i = DEFAULT_WRITER; - cmdline = NULL; - goto check; - } - PARA_INFO_LOG("checking %s\n", wa); - FOR_EACH_WRITER(i) { - const char *name = writer_names[i]; - size_t len = strlen(name); - char c; +/** + * Check if the given string is a valid command line for any writer. + * + * \param wa String of the form writer_name options. + * \param lprp Contains the parsed command line on success. + * + * If wa is \p NULL, the (configuration-dependent) default writer is assumed. + * Otherwise, the function checks whether \a wa starts with the name of a + * supported writer. If a valid writer name was found, the rest of the command + * line is passed to the config parser of this writer. + * + * \return On success, the positive writer ID is returned. Otherwise the + * function prints an error message and calls exit(). + */ +int check_writer_arg_or_die(const char *wa, struct lls_parse_result **lprp) +{ + int ret, writer_num, argc; + char **argv = NULL, *errctx = NULL; + const struct lls_command *cmd; - if (strlen(wa) < len) - continue; - if (strncmp(name, wa, len)) - continue; - c = wa[len]; - if (!c || c == ' ') { - cmdline = c? wa + len + 1 : NULL; - goto check; - } - } - PARA_EMERG_LOG("invalid writer %s\n", wa); - exit(EXIT_FAILURE); -check: - ret = create_shifted_argv(cmdline, " \t", &argv); - if (ret < 0) { - PARA_EMERG_LOG("%s: %s\n", wa, para_strerror(-ret)); - exit(EXIT_FAILURE); + if (!wa || !*wa) { + writer_num = default_writer_id(); + cmd = WRITE_CMD(writer_num); + argv = para_malloc(2 * sizeof(char *)); + argc = 1; + argv[0] = para_strdup(lls_command_name(cmd)); + argv[1] = NULL; + goto parse; } + ret = create_argv(wa, " \t\n", &argv); + if (ret < 0) + goto fail; argc = ret; - argv[0] = make_message("%s_write", writer_names[i]); - *writer_num = i; - conf = writers[i].parse_config_or_die(argc, argv); + ret = lls(lls_lookup_subcmd(argv[0], write_cmd_suite, &errctx)); + if (ret < 0) + goto free_argv; + writer_num = ret; + cmd = WRITE_CMD(writer_num); + if (!writer_supported(writer_num)) { + ret = -ERRNO_TO_PARA_ERROR(EINVAL); + errctx = make_message("%s writer is not supported", + lls_command_name(cmd)); + goto free_argv; + } +parse: + ret = lls(lls_parse(argc, argv, cmd, lprp, &errctx)); + if (ret >= 0) + ret = writer_num; +free_argv: free_argv(argv); - return conf; + if (ret >= 0) + return ret; +fail: + if (errctx) + PARA_ERROR_LOG("%s\n", errctx); + free(errctx); + PARA_EMERG_LOG("%s\n", para_strerror(-ret)); + exit(EXIT_FAILURE); } /** @@ -99,47 +128,49 @@ check: * \param wn The writer node to open. * \param parent The parent btr node (the source for the writer node). * \param s The scheduler instance to register the task to. - * - * The configuration of the writer node stored in \p wn->conf must be - * initialized before this function may be called. */ void register_writer_node(struct writer_node *wn, struct btr_node *parent, struct sched *s) { - struct writer *w = writers + wn->writer_num; - char *name = make_message("%s writer", writer_names[wn->writer_num]); + const struct writer *w = writer_get(wn->wid); wn->btrn = btr_new_node(&(struct btr_node_description) - EMBRACE(.name = name, .parent = parent, + EMBRACE(.name = writer_name(wn->wid), .parent = parent, .handler = w->execute, .context = wn)); - strcpy(wn->task.status, name); - free(name); - wn->task.pre_select = w->pre_select; - wn->task.post_select = w->post_select; - register_task(s, &wn->task); + wn->task = task_register(&(struct task_info) { + .name = writer_name(wn->wid), + .pre_select = w->pre_select, + .post_select = w->post_select, + .context = wn, + }, s); } /** * Print the help text of all writers to stdout. * - * \param flags Passed to \ref ggo_print_help(). + * \param detailed Whether to print the short or the detailed help. */ -void print_writer_helps(unsigned flags) +void print_writer_helps(bool detailed) { int i; - printf_or_die("\nAvailable writers: "); - FOR_EACH_WRITER(i) - printf_or_die("%s%s", i? " " : "", writer_names[i]); - printf_or_die("\n"); + printf("\nAvailable writers: "); FOR_EACH_WRITER(i) { - struct writer *w = writers + i; - - if (!w->help.short_help) + if (!writer_supported(i)) + continue; + printf("%s%s", i? " " : "", writer_name(i)); + } + printf("\n"); + FOR_EACH_WRITER(i) { + const struct lls_command *cmd = WRITE_CMD(i); + char *help; + if (!writer_supported(i)) + continue; + help = detailed? lls_long_help(cmd) : lls_short_help(cmd); + if (!help) continue; - printf_or_die("\n%s: %s", writer_names[i], - w->help.purpose); - ggo_print_help(&w->help, flags); + printf("%s\n", help); + free(help); } }