Convert audioc to lopsub.
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 7 Aug 2016 22:01:19 +0000 (00:01 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 26 Mar 2017 09:02:28 +0000 (11:02 +0200)
This changes para_audioc to use the lopsub library rather than
gengetopt for parsing the command line options. The gengetopt input
file m4/gengetopt/audioc.m4 is replaced by an equivalent suite file,
audioc.c is adjusted to call the lopsub primitives instead if the
gengetopt parsers, and para_audioc is linked against lopsub. Moreover,
the manual page of audioc is now generated with lopsubgen.

Since this is the first executable which is converted, the commit
introduces a fair amount of infrastructure which will also be used
by other executables. Specifically:

* Common command line options (--help, --detailed-help, --version,
--loglevel, --history_file, --complete) are stored in per-option
files below m4/lls/include. Each of these files is included from
audioc.suite.m4. To tell make which files audioc.suite depends on,
we use the line synchronization feature of m4 and a simple awk script
to create a .m4d file which contains these dependencies, similar to
the .d files which describe dependencies of .c and .h files. The new
m4_lls_deps make variable contains the set of .m4d files.

* A generic copyright section for the man page which refers to the
COPYRIGHT_YEAR macro, defined from the make variable in Makefile.real.

* The new make variable LOGLEVELS. We need to know the set of loglevels
in the suite files as well as in the C code, so the variable avoids
to duplicate this information.

17 files changed:
Makefile.real
audioc.c
configure.ac
m4/gengetopt/audioc.m4 [deleted file]
m4/lls/audioc.suite.m4 [new file with mode: 0644]
m4/lls/copyright.m4 [new file with mode: 0644]
m4/lls/include/common-option-section.m4 [new file with mode: 0644]
m4/lls/include/complete.m4 [new file with mode: 0644]
m4/lls/include/detailed-help.m4 [new file with mode: 0644]
m4/lls/include/help.m4 [new file with mode: 0644]
m4/lls/include/history-file.m4 [new file with mode: 0644]
m4/lls/include/host.m4 [new file with mode: 0644]
m4/lls/include/loglevel.m4 [new file with mode: 0644]
m4/lls/include/per-command-options-section.m4 [new file with mode: 0644]
m4/lls/include/version.m4 [new file with mode: 0644]
m4/lls/makefile
para.h

index 5145908..045d578 100644 (file)
@@ -7,6 +7,7 @@ ifeq ("$(origin CC)", "default")
         CC := cc
 endif
 
+LOGLEVELS := LL_DEBUG,LL_INFO,LL_NOTICE,LL_WARNING,LL_ERROR,LL_CRIT,LL_EMERG
 vardir := /var/paraslash
 mandir := $(datarootdir)/man/man1
 STRIP := $(CROSS_COMPILE)strip
@@ -42,12 +43,18 @@ all_objs := $(sort $(recv_objs) $(filter_objs) $(client_objs) $(gui_objs) \
        $(audiod_objs) $(audioc_objs) $(fade_objs) $(server_objs) \
        $(write_objs) $(afh_objs) $(play_objs))
 deps := $(addprefix $(dep_dir)/, $(filter-out %.cmdline.d, $(all_objs:.o=.d)))
-m4_deps := $(addprefix $(m4depdir)/, $(addsuffix .m4d, $(executables)))
+converted_executables := audioc
+unconverted_executables := $(filter-out $(converted_executables), $(executables))
 
+audioc_objs += audioc.lsg.o
 audiod_objs += audiod_cmd.lsg.o
 server_objs += server_cmd.lsg.o
 play_objs += play_cmd.lsg.o
 
+m4_deps := $(addprefix $(m4depdir)/, $(addsuffix .m4d, $(unconverted_executables)))
+m4_lls_deps := audiod_cmd server_cmd play_cmd $(converted_executables)
+m4_lls_deps := $(addprefix $(lls_suite_dir)/, $(addsuffix .m4d, $(m4_lls_deps)))
+
 # now prefix all objects with object dir
 recv_objs := $(addprefix $(object_dir)/, $(recv_objs))
 filter_objs := $(addprefix $(object_dir)/, $(filter_objs))
@@ -79,6 +86,7 @@ include $(test_dir)/makefile.test
 ifeq ($(findstring clean, $(MAKECMDGOALS)),)
 -include $(deps)
 -include $(m4_deps)
+-include $(m4_lls_deps)
 endif
 
 $(object_dir) $(man_dir) $(ggo_dir) $(cmdline_dir) $(dep_dir) $(m4depdir) \
@@ -88,6 +96,7 @@ $(object_dir) $(man_dir) $(ggo_dir) $(cmdline_dir) $(dep_dir) $(m4depdir) \
 CPPFLAGS += -DBINDIR='"$(bindir)"'
 CPPFLAGS += -DCOPYRIGHT_YEAR='"$(COPYRIGHT_YEAR)"'
 CPPFLAGS += -DBUILD_DATE='"$(build_date)"'
+CPPFLAGS += -DLOGLEVELS='$(LOGLEVELS)'
 CPPFLAGS += -DUNAME_RS='"$(uname_rs)"'
 CPPFLAGS += -DCC_VERSION='"$(cc_version)"'
 CPPFLAGS += -I/usr/local/include
@@ -150,7 +159,13 @@ $(man_dir)/para_server.1: man_util_command_lists := $(server_command_lists)
 $(man_dir)/para_audiod.1: man_util_command_lists := $(audiod_command_lists)
 $(man_dir)/para_play.1: man_util_command_lists := $(play_command_lists)
 
-$(man_dir)/para_%.1: $(man_util_command_lists) git-version.h \
+$(man_dir)/para_%.1: $(lls_suite_dir)/%.lsg.man $(man_util_command_lists) \
+               $(lls_m4_dir)/copyright.m4 | $(man_dir)
+       @[ -z "$(Q)" ] || echo 'LLSMAN $<'
+       $(Q) cat $< $(man_util_command_lists) > $@
+       $(Q) $(M4) -D COPYRIGHT_YEAR=$(COPYRIGHT_YEAR) $(lls_m4_dir)/copyright.m4 >> $@
+
+$(man_dir)/para_%.1: $(man_util_command_lists) \
                $(ggo_dir)/%.ggo man_util.bash \
                | $(man_dir) $(help2man_dir)
        @[ -z "$(Q)" ] || echo 'MAN $<'
index dabc2f7..f2e20ba 100644 (file)
--- a/audioc.c
+++ b/audioc.c
 #include <sys/un.h>
 #include <netdb.h>
 #include <signal.h>
+#include <lopsub.h>
 
-#include "audioc.cmdline.h"
 #include "audiod_cmd.lsg.h"
+#include "audioc.lsg.h"
 
 #include "para.h"
 #include "error.h"
 #include "net.h"
 #include "string.h"
 #include "fd.h"
-#include "ggo.h"
 #include "version.h"
 
 /** Array of error strings. */
 DEFINE_PARA_ERRLIST;
 
-/** The gengetopt structure containing command line args. */
-static struct audioc_args_info conf;
 static char *socket_name;
+static struct lls_parse_result *lpr;
 
+#define CMD_PTR (lls_cmd(0, audioc_suite))
+#define OPT_RESULT(_name) \
+       (lls_opt_result(LSG_AUDIOC_PARA_AUDIOC_OPT_ ## _name, lpr))
+#define OPT_GIVEN(_name) (lls_opt_given(OPT_RESULT(_name)))
+#define OPT_STRING_VAL(_name) (lls_string_val(0, OPT_RESULT(_name)))
+#define OPT_UINT32_VAL(_name) (lls_uint32_val(0, OPT_RESULT(_name)))
 
 static int loglevel;
 INIT_STDERR_LOGGING(loglevel);
@@ -43,7 +48,8 @@ static char *concat_args(unsigned argc, char * const *argv)
        char *buf = NULL;
 
        for (i = 0; i < argc; i++) {
-               buf = para_strcat(buf, argv[i]);
+               const char *arg = argv? argv[i] : lls_input(i, lpr);
+               buf = para_strcat(buf, arg);
                if (i != argc - 1)
                        buf = para_strcat(buf, "\n");
        }
@@ -150,13 +156,15 @@ static int audioc_post_select(struct sched *s, void *context)
        char *buf = NULL;
        struct audioc_task *at = context;
        int ret = btr_node_status(at->btrn, 0, BTR_NT_ROOT);
+       size_t bufsize;
 
        if (ret < 0)
                goto out;
        if (!FD_ISSET(at->fd, &s->rfds))
                return 0;
-       buf = para_malloc(conf.bufsize_arg);
-       ret = recv_bin_buffer(at->fd, buf, conf.bufsize_arg);
+       bufsize = PARA_MAX(1024U, OPT_UINT32_VAL(BUFSIZE));
+       buf = para_malloc(bufsize);
+       ret = recv_bin_buffer(at->fd, buf, bufsize);
        PARA_DEBUG_LOG("recv: %d\n", ret);
        if (ret == 0)
                ret = -E_AUDIOC_EOF;
@@ -177,28 +185,26 @@ static struct audioc_task audioc_task, *at = &audioc_task;
 
 static int audioc_i9e_line_handler(char *line)
 {
-       char *args = NULL;
-       int ret;
+       int argc, ret;
+       char *args, **argv;
 
        PARA_DEBUG_LOG("line: %s\n", line);
-       ret = create_argv(line, " ", &conf.inputs);
+       ret = create_argv(line, " ", &argv);
        if (ret < 0)
                return ret;
-       conf.inputs_num = ret;
-       args = concat_args(conf.inputs_num, conf.inputs);
-       free_argv(conf.inputs);
+       argc = ret;
+       args = concat_args(argc, argv);
+       free_argv(argv);
        if (!args)
                return 0;
-       conf.inputs_num = 0; /* required for audioc_cmdline_parser_free() */
        ret = connect_audiod(socket_name, args);
+       free(args);
        if (ret < 0)
                goto out;
        at->fd = ret;
        ret = mark_fd_nonblocking(at->fd);
        if (ret < 0)
                goto close;
-       free(args);
-       args = NULL;
        at->btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "audioc line handler"));
        at->task = task_register(&(struct task_info) {
@@ -228,9 +234,10 @@ __noreturn static void interactive_session(void)
                .loglevel = loglevel,
                .completers = audiod_completers,
        };
+
        PARA_NOTICE_LOG("\n%s\n", version_text("audioc"));
-       if (conf.history_file_given)
-               history_file = para_strdup(conf.history_file_arg);
+       if (OPT_GIVEN(HISTORY_FILE))
+               history_file = para_strdup(OPT_STRING_VAL(HISTORY_FILE));
        else {
                char *home = para_homedir();
                history_file = make_message("%s/.paraslash/audioc.history",
@@ -256,7 +263,7 @@ __noreturn static void interactive_session(void)
        para_log = stderr_log;
 out:
        free(history_file);
-       audioc_cmdline_parser_free(&conf);
+       free(socket_name);
        if (ret < 0)
                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
        exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS);
@@ -298,13 +305,19 @@ static char *configfile_exists(void)
        return NULL;
 }
 
-__noreturn static void print_help_and_die(void)
+static void handle_help_flag(void)
 {
-       struct ggo_help h = DEFINE_GGO_HELP(audioc);
-       bool d = conf.detailed_help_given;
+       char *help;
 
-       ggo_print_help(&h, d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS);
-       exit(0);
+       if (OPT_GIVEN(DETAILED_HELP))
+               help = lls_long_help(CMD_PTR);
+       else if (OPT_GIVEN(HELP))
+               help = lls_short_help(CMD_PTR);
+       else
+               return;
+       printf("%s\n", help);
+       free(help);
+       exit(EXIT_SUCCESS);
 }
 
 /**
@@ -325,54 +338,79 @@ __noreturn static void print_help_and_die(void)
  */
 int main(int argc, char *argv[])
 {
+       const struct lls_command *cmd = CMD_PTR;
        int ret, fd;
-       char *cf, *buf = NULL, *args = NULL;
+       char *cf = NULL, *buf, *args, *errctx = NULL;
        size_t bufsize;
+       struct lls_parse_result *lpr1, *lpr2, *lpr3;
+       unsigned num_inputs;
 
-       audioc_cmdline_parser(argc, argv, &conf);
-       loglevel = get_loglevel_by_name(conf.loglevel_arg);
-       version_handle_flag("audioc", conf.version_given);
-       if (conf.help_given || conf.detailed_help_given)
-               print_help_and_die();
+       ret = lls(lls_parse(argc, argv, cmd, &lpr1, &errctx));
+       if (ret < 0)
+               goto fail;
+       lpr = lpr1;
+       loglevel = OPT_UINT32_VAL(LOGLEVEL);
+       version_handle_flag("audioc", OPT_GIVEN(VERSION));
+       handle_help_flag();
        cf = configfile_exists();
        if (cf) {
-               struct audioc_cmdline_parser_params params = {
-                       .override = 0,
-                       .initialize = 0,
-                       .check_required = 0,
-                       .check_ambiguity = 0,
-                       .print_errors = 1,
-
-               };
-               audioc_cmdline_parser_config_file(cf, &conf, &params);
-               free(cf);
-               loglevel = get_loglevel_by_name(conf.loglevel_arg);
+               void *map;
+               size_t sz;
+               int cf_argc;
+               char **cf_argv;
+               ret = mmap_full_file(cf, O_RDONLY, &map, &sz, NULL);
+               if (ret != -E_EMPTY) {
+                       if (ret < 0)
+                               goto out;
+                       ret = lls(lls_convert_config(map, sz, NULL, &cf_argv,
+                               &errctx));
+                       para_munmap(map, sz);
+                       if (ret < 0) {
+                               PARA_ERROR_LOG("syntax error in %s\n", cf);
+                               goto out;
+                       }
+                       cf_argc = ret;
+                       ret = lls(lls_parse(cf_argc, cf_argv, cmd, &lpr2,
+                               &errctx));
+                       lls_free_argv(cf_argv);
+                       if (ret < 0) {
+                               PARA_ERROR_LOG("parse error in %s\n", cf);
+                               goto out;
+                       }
+                       ret = lls(lls_merge(lpr1, lpr2, cmd, &lpr3, &errctx));
+                       lls_free_parse_result(lpr2, cmd);
+                       if (ret < 0)
+                               goto out;
+                       lls_free_parse_result(lpr1, cmd);
+                       lpr = lpr3;
+                       loglevel = OPT_UINT32_VAL(LOGLEVEL);
+               }
        }
-       if (conf.socket_given)
-               socket_name = para_strdup(conf.socket_arg);
+       if (OPT_GIVEN(COMPLETE))
+               print_completions();
+       if (OPT_GIVEN(SOCKET))
+               socket_name = para_strdup(OPT_STRING_VAL(SOCKET));
        else {
                char *hn = para_hostname();
                socket_name = make_message("/var/paraslash/audiod_socket.%s",
                        hn);
                free(hn);
        }
-
-       if (conf.complete_given)
-               print_completions();
-
-       if (conf.inputs_num == 0)
+       num_inputs = lls_num_inputs(lpr);
+       if (num_inputs == 0)
                interactive_session();
-       args = concat_args(conf.inputs_num, conf.inputs);
 
+       args = concat_args(num_inputs, NULL);
        ret = connect_audiod(socket_name, args);
        free(socket_name);
+       free(args);
        if (ret < 0)
                goto out;
        fd = ret;
        ret = mark_fd_blocking(STDOUT_FILENO);
        if (ret < 0)
                goto out;
-       bufsize = conf.bufsize_arg;
+       bufsize = PARA_MAX(1024U, OPT_UINT32_VAL(BUFSIZE));
        buf = para_malloc(bufsize);
        do {
                size_t n = ret = recv_bin_buffer(fd, buf, bufsize);
@@ -380,9 +418,14 @@ int main(int argc, char *argv[])
                        break;
                ret = write_all(STDOUT_FILENO, buf, n);
        } while (ret >= 0);
-out:
        free(buf);
-       free(args);
+out:
+       lls_free_parse_result(lpr, cmd);
+       free(cf);
+fail:
+       if (errctx)
+               PARA_ERROR_LOG("%s\n", errctx);
+       free(errctx);
        if (ret < 0)
                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
        return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;
index 36a1f4b..6087bac 100644 (file)
@@ -1015,14 +1015,12 @@ AC_DEFINE_UNQUOTED(DECLARE_WRITER_INITS, $inits, init functions of the supported
 array="$(for i in $writers; do printf '{.init = '$i'_write_init},'; done)"
 AC_DEFINE_UNQUOTED(WRITER_ARRAY, $array, array of supported writers)
 ######################################################################## audioc
-audioc_cmdline_objs="audioc"
 audioc_errlist_objs="
        audioc
        string
        net
        fd
        version
-       ggo
 "
 if test $HAVE_READLINE = yes; then
        audioc_errlist_objs="$audioc_errlist_objs
@@ -1032,7 +1030,7 @@ if test $HAVE_READLINE = yes; then
                time
        "
 fi
-audioc_objs="add_cmdline($audioc_cmdline_objs) $audioc_errlist_objs"
+audioc_objs="$audioc_errlist_objs"
 AC_SUBST(audioc_objs, add_dot_o($audioc_objs))
 ################################################################## status items
 
diff --git a/m4/gengetopt/audioc.m4 b/m4/gengetopt/audioc.m4
deleted file mode 100644 (file)
index f216204..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-args "--unamed-opts=command --conf-parser --no-handle-version --no-handle-help"
-
-purpose "Communicate with para_audiod through a local socket"
-
-include(header.m4)
-<qu>
-option "socket" s
-#~~~~~~~~~~~~~~~~
-"well-known socket (default=/var/paraslash/audiod.socket.$HOSTNAME)"
-       string typestr="filename"
-       optional
-
-
-option "bufsize" b
-#~~~~~~~~~~~~~~~~~
-"size of internal buffer"
-       int typestr="bytes"
-       default="8192"
-       optional
-</qu>
-
-define(CURRENT_PROGRAM,para_audioc)
-define(DEFAULT_HISTORY_FILE,~/.paraslash/audioc.history)
-include(loglevel.m4)
-include(history_file.m4)
-include(complete.m4)
diff --git a/m4/lls/audioc.suite.m4 b/m4/lls/audioc.suite.m4
new file mode 100644 (file)
index 0000000..1c037bc
--- /dev/null
@@ -0,0 +1,39 @@
+m4_define(PROGRAM, para_audioc)
+m4_define(DEFAULT_HISTORY_FILE, ~/.paraslash/audioc.history)
+[suite audioc]
+version-string = GIT_VERSION()
+[supercommand para_audioc]
+       purpose = communicate with para_audiod through a local socket
+       non-opts-name = [command [options]]
+       [description]
+               The client program to control para_audiod at runtime. It allows to
+               enable/disable streaming, to receive status info, or to grab the
+               audio stream at any point of the decoding process.
+
+               If no command is given, para_audioc enters interactive mode.
+       [/description]
+       m4_include(common-option-section.m4)
+       m4_include(help.m4)
+       m4_include(detailed-help.m4)
+       m4_include(version.m4)
+       m4_include(loglevel.m4)
+       m4_include(complete.m4)
+       m4_include(history-file.m4)
+       m4_include(per-command-options-section.m4)
+       [option socket]
+               short_opt = s
+               summary = path to well-known socket
+               arg_info = required_arg
+               arg_type = string
+               typestr = path
+               [help]
+                       The default path of the socket is
+                       /var/paraslash/audiod.socket.$HOSTNAME.
+               [/help]
+       [option bufsize]
+               short_opt = b
+               summary = size of internal buffer
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = bytes
+               default_val = 8192
diff --git a/m4/lls/copyright.m4 b/m4/lls/copyright.m4
new file mode 100644 (file)
index 0000000..9e5c541
--- /dev/null
@@ -0,0 +1,15 @@
+.SH COPYRIGHT
+Written by Andre Noll
+.br
+Copyright (C) COPYRIGHT_YEAR() Andre Noll
+.br
+License: GNU GPL version 2
+.br
+This is free software: you are free to change and redistribute it.
+.br
+There is NO WARRANTY, to the extent permitted by law.
+.br
+Report bugs to
+.MT <maan@tuebingen.mpg.de>
+Andre Noll
+.ME
diff --git a/m4/lls/include/common-option-section.m4 b/m4/lls/include/common-option-section.m4
new file mode 100644 (file)
index 0000000..2a3b3e6
--- /dev/null
@@ -0,0 +1,8 @@
+[option common-option-section]
+       summary = Common options
+       flag ignored
+       [help]
+               The following options are implemented generically and are available
+               for many of the commands.
+       [/help]
+
diff --git a/m4/lls/include/complete.m4 b/m4/lls/include/complete.m4
new file mode 100644 (file)
index 0000000..c9f135c
--- /dev/null
@@ -0,0 +1,8 @@
+[option complete]
+       summary = print possible command line completions
+       [help]
+               If this flag is given, the environment variables COMP_LINE and
+               COMP_POINT are examined to obtain the current command line and the
+               cursor position respectively. Possible completions are written to
+               stdout and the program exits.
+       [/help]
diff --git a/m4/lls/include/detailed-help.m4 b/m4/lls/include/detailed-help.m4
new file mode 100644 (file)
index 0000000..33a10f8
--- /dev/null
@@ -0,0 +1,3 @@
+
+[option detailed-help]
+       summary = print help, including all details, and exit
diff --git a/m4/lls/include/help.m4 b/m4/lls/include/help.m4
new file mode 100644 (file)
index 0000000..ff6ce3e
--- /dev/null
@@ -0,0 +1,3 @@
+[option help]
+       summary = print help and exit
+       short_opt = h
diff --git a/m4/lls/include/history-file.m4 b/m4/lls/include/history-file.m4
new file mode 100644 (file)
index 0000000..deb3d7e
--- /dev/null
@@ -0,0 +1,13 @@
+[option history-file]
+arg_info = required_arg
+arg_type = string
+typestr = filename
+summary = location of the file for the command history list
+[help]
+       If PROGRAM() runs in interactive mode, it reads the history file
+       on startup. Upon exit, the in-memory history is appended to the
+       history file.
+
+       If this option is not given, the history file is expected at
+       DEFAULT_HISTORY_FILE().
+[/help]
diff --git a/m4/lls/include/host.m4 b/m4/lls/include/host.m4
new file mode 100644 (file)
index 0000000..3c0f0eb
--- /dev/null
@@ -0,0 +1,10 @@
+[option host]
+       short_opt = i
+       summary = IP address or hostname
+       typestr = host
+       arg_info = required_arg
+       arg_type = string
+       default_val = localhost
+       [help]
+               Both IPv4 and IPv6 addresses are supported.
+       [/help]
diff --git a/m4/lls/include/loglevel.m4 b/m4/lls/include/loglevel.m4
new file mode 100644 (file)
index 0000000..06bea3d
--- /dev/null
@@ -0,0 +1,23 @@
+m4_define(`downcase', `m4_translit(`$*', `A-Z', `a-z')')
+m4_define(`SUITE_LOGLEVELS', `m4_patsubst(`$*', `LL_\([A-Z]+\)',
+       `LSGLL_\1 = "downcase(`\1')" ')')
+[option loglevel]
+       summary = control amount of logging
+       short_opt = l
+       arg_info = required_arg
+       arg_type = string
+       typestr = severity
+       values = {SUITE_LOGLEVELS(LOGLEVELS())}
+       default_val = warning
+       [help]
+               Log only messages with severity greater or equal than the given
+               value. Possible values:
+
+               debug: Produces really noisy output.
+               info: Still noisy, but won't fill up the disk quickly.
+               notice: Indicates normal, but significant event.
+               warning: Unexpected events that can be handled.
+               error: Unhandled error condition.
+               crit: System might be unreliable.
+               emerg: Last message before exit.
+       [/help]
diff --git a/m4/lls/include/per-command-options-section.m4 b/m4/lls/include/per-command-options-section.m4
new file mode 100644 (file)
index 0000000..a303808
--- /dev/null
@@ -0,0 +1,3 @@
+[option per-command-option-section]
+       summary = Options for PROGRAM()
+       flag ignored
diff --git a/m4/lls/include/version.m4 b/m4/lls/include/version.m4
new file mode 100644 (file)
index 0000000..a84ab9d
--- /dev/null
@@ -0,0 +1,3 @@
+[option version]
+       summary = print version and exit
+       short_opt = V
index bd36add..4d64119 100644 (file)
@@ -1,8 +1,17 @@
 .PRECIOUS: $(lls_suite_dir)/%.suite
+lls_m4_include_dir := $(lls_m4_dir)/include
+
+$(lls_suite_dir)/%.m4d: $(lls_m4_dir)/%.suite.m4 | $(lls_suite_dir)
+       @[ -z "$(Q)" ] || echo 'M4D $<'
+
+       $(Q) $(M4) -Pg -I $(lls_m4_include_dir) -s $< \
+       | awk '{if ($$1 ~ /#line/) {gsub(/"/, "", $$3); if ($$3 != "$<") \
+       print "$(lls_suite_dir)/$(*F).suite: " $$3}}' | sort | uniq > $@
 
 $(lls_suite_dir)/%.suite: $(lls_m4_dir)/%.suite.m4 | $(lls_suite_dir)
-       @[ -z "$(Q)" ] || echo 'M4 $<'
-       $(Q) $(M4) -Pg $< > $@
+       $(Q) $(M4) -Pg -I $(lls_m4_include_dir) -D GIT_VERSION=$(GIT_VERSION) \
+               -D COPYRIGHT_YEAR=$(COPYRIGHT_YEAR) -D LOGLEVELS=$(LOGLEVELS) \
+               $< > $@
 
 $(lls_suite_dir)/%.lsg.c: $(lls_suite_dir)/%.suite
        @[ -z "$(Q)" ] || echo 'LSGC $<'
diff --git a/para.h b/para.h
index 12d2363..3cd1b16 100644 (file)
--- a/para.h
+++ b/para.h
@@ -223,24 +223,9 @@ enum sample_format {SAMPLE_FORMATS};
 #define SAMPLE_FORMAT(a, b) b
 /** \endcond sample_format */
 
-/** Debug loglevel, gets really noisy. */
-#define LL_DEBUG 0
-/** Still noisy, but won't fill your disk. */
-#define LL_INFO  1
-/** Normal, but significant event. */
-#define LL_NOTICE 2
-/** Unexpected event that can be handled. */
-#define LL_WARNING 3
-/** Unhandled error condition. */
-#define LL_ERROR 4
-/** System might be unreliable. */
-#define LL_CRIT 5
-/** Last message before exit. */
-#define LL_EMERG 6
-/** Number of all loglevels. */
-#define NUM_LOGLEVELS 7
-
-/** \cond log */
+/** Debug, Info, etc. */
+enum loglevels {LOGLEVELS, NUM_LOGLEVELS};
+
 #define PARA_DEBUG_LOG(f,...) para_log(LL_DEBUG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #define PARA_INFO_LOG(f,...) para_log(LL_INFO, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #define PARA_NOTICE_LOG(f,...) para_log(LL_NOTICE, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
@@ -248,4 +233,3 @@ enum sample_format {SAMPLE_FORMATS};
 #define PARA_ERROR_LOG(f,...) para_log(LL_ERROR, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #define PARA_CRIT_LOG(f,...) para_log(LL_CRIT, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #define PARA_EMERG_LOG(f,...) para_log(LL_EMERG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
-/** \endcond log */