diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-02-16 13:09:28 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-02-16 13:09:28 +0200 |
commit | b0f10ec7274144b4e048953b11f2a4d98e055810 (patch) | |
tree | 4bcc06122d183582d0b53fe2b8ba4c87b289b96f | |
parent | 169a680208f2de8f92b4a2a4977953d4452e981f (diff) | |
download | wydawca-b0f10ec7274144b4e048953b11f2a4d98e055810.tar.gz wydawca-b0f10ec7274144b4e048953b11f2a4d98e055810.tar.bz2 |
Improve argument parsing
* src/cmdline.opt, src/getopt.m4: New files.
* src/wydawca.c: Switch to new way of command line parsing.
* src/wydawca.h (gettext): Define.
* bootstrap.conf: Add formatting flags for gconf_warning and gconf_error
* gconf-preproc.c (pp_list_find): Minor change.
* gconf/gconf.h (gconf_warning,gconf_error): Mark as printflike.
* src/.gitignore: Add cmdline.h
* src/Makefile.am (wydawca_SOURCES): Add cmdline.h.
(.opt.h): New rule.
* src/config.c (cb_archive): Archive is now a block statement (unless type
"none" is declared).
(all functions): Tighten input checking
* src/update-2.0.awk: Reflect the above change.
* src/directive.c (process_directives): Minor change.
* src/diskio.c (symlink_file): Minor change.
-rw-r--r-- | bootstrap.conf | 8 | ||||
-rw-r--r-- | gconf/gconf-preproc.c | 5 | ||||
-rw-r--r-- | gconf/gconf.h | 6 | ||||
-rw-r--r-- | src/.gitignore | 1 | ||||
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/cmdline.opt | 90 | ||||
-rw-r--r-- | src/config.c | 170 | ||||
-rw-r--r-- | src/directive.c | 2 | ||||
-rw-r--r-- | src/diskio.c | 2 | ||||
-rw-r--r-- | src/getopt.m4 | 517 | ||||
-rw-r--r-- | src/update-2.0.awk | 41 | ||||
-rw-r--r-- | src/wydawca.c | 75 | ||||
-rw-r--r-- | src/wydawca.h | 1 |
13 files changed, 760 insertions, 167 deletions
diff --git a/bootstrap.conf b/bootstrap.conf index 1d1a1fa..6119189 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -39,8 +39,4 @@ XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\ --flag=asnprintf:3:c-format --flag=vasnprintf:3:c-format\\\ - --flag=argp_error:2:c-format\\\ - --flag=__argp_error:2:c-format\\\ - --flag=argp_failure:4:c-format\\\ - --flag=__argp_failure:4:c-format\\\ - --flag=argp_fmtstream_printf:2:c-format\\\ - --flag=__argp_fmtstream_printf:2:c-format\\\ + --flag=gconf_warning:3:c-format\\\ + --flag=gconf_error:3:c-format\\\ ' diff --git a/gconf/gconf-preproc.c b/gconf/gconf-preproc.c index af26d1a..eb50474 100644 --- a/gconf/gconf-preproc.c +++ b/gconf/gconf-preproc.c @@ -260,3 +260,3 @@ pp_list_find (gl_list_t list, struct file_data *dptr) - while (gl_list_iterator_next (&itr, &p, NULL)) + while (!dptr->found && gl_list_iterator_next (&itr, &p, NULL)) { @@ -272,4 +272,3 @@ pp_list_find (gl_list_t list, struct file_data *dptr) strcat (dptr->buf, dptr->name); - if (dptr->found = (access (dptr->buf, F_OK) == 0)) - break; + dptr->found = access (dptr->buf, F_OK) == 0; } diff --git a/gconf/gconf.h b/gconf/gconf.h index 8c04b6d..f88e87a 100644 --- a/gconf/gconf.h +++ b/gconf/gconf.h @@ -103,4 +103,6 @@ extern void gconf_print_diag(gconf_locus_t *, int, int, const char*); -void gconf_warning(gconf_locus_t *locus, int errcode, const char *fmt, ...); -void gconf_error(gconf_locus_t *locus, int errcode, const char *fmt, ...); +void gconf_warning(gconf_locus_t *locus, int errcode, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +void gconf_error(gconf_locus_t *locus, int errcode, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); void gconf_set_keywords(struct gconf_keyword *kwd); diff --git a/src/.gitignore b/src/.gitignore index 2e5d6fc..02f7682 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1,3 @@ .gdbinit +cmdline.h wydawca diff --git a/src/Makefile.am b/src/Makefile.am index a6611af..10a6b60 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,2 +18,3 @@ sbin_PROGRAMS=wydawca wydawca_SOURCES=\ + cmdline.h\ config.c\ @@ -35,3 +36,9 @@ wydawca_SOURCES=\ -EXTRA_DIST=pp-setup +BUILT_SOURCES=cmdline.h +EXTRA_DIST=cmdline.opt getopt.m4 pp-setup + +SUFFIXES=.opt .c .h + +.opt.h: + m4 -s $(srcdir)/getopt.m4 $< | sed '1d' > $@ diff --git a/src/cmdline.opt b/src/cmdline.opt new file mode 100644 index 0000000..00bbedc --- /dev/null +++ b/src/cmdline.opt @@ -0,0 +1,90 @@ +/* wydawca - automatic release submission daemon + Copyright (C) 2007, 2009 Sergey Poznyakoff + + Wydawca is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or (at your + option) any later version. + + Wydawca is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with wydawca. If not, see <http://www.gnu.org/licenses/>. */ + +OPTIONS_BEGIN(gnu, "wydawca", + [<wydawca synchronizes files from a set of upload directories with the corresponding distribution sites>]) + +OPTION(config-file,c,FILE, + [<use FILE instead of the default configuration>]) +BEGIN + conffile = optarg; +END + +OPTION(cron,,, + [<log to syslog>]) +ALIAS(syslog) +BEGIN + log_to_stderr = 0; +END + +OPTION(stderr,e,, + [<log to stderr>]) +BEGIN +END + +OPTION(debug,d,, + [<increase debugging level>]) +BEGIN +END + +OPTION(include-directory,I,[DIR], + [<add include directory>]) +BEGIN + gconf_preproc_add_include_dir (optarg); +END + +OPTION(dry-run,n,, + [<do nothing, print almost everything; implies `--debug --stderr', + use additional `--debug' options to get even more info>]) +BEGIN + log_to_stderr = 1; + debug_level++; + dry_run_mode = 1; +END + +OPTION(lint,t,, + [<parse configuration file and exit>]) +BEGIN + lint_mode = 1; + log_to_stderr = 1; +END + +OPTION(dump-grammar-trace,,, + [<dump configuration grammar traces>]) +BEGIN + gconf_gram_trace (1); +END + +OPTION(dump-lex-trace,,, + [<dump lexical analyzer traces>]) +BEGIN + gconf_lex_trace (1); +END + +OPTION(config-help,,, + [<show configuration file summary>]) +BEGIN + config_help (); + exit (0); +END + +OPTIONS_END + +void +parse_options(int argc, char *argv[]) +{ + GETOPT(argc, argv) +} diff --git a/src/config.c b/src/config.c index 3545e05..32b54dd 100644 --- a/src/config.c +++ b/src/config.c @@ -220,3 +220,3 @@ assert_string_arg (gconf_locus_t *locus, enum gconf_callback_command cmd, - gconf_value_t *value) + const gconf_value_t *value) { @@ -227,5 +227,5 @@ assert_string_arg (gconf_locus_t *locus, } - if (value->type != GCONF_TYPE_STRING) + if (!value || value->type != GCONF_TYPE_STRING) { - gconf_error (locus, 0, _("expected scalar value but found list")); + gconf_error (locus, 0, _("expected scalar value as a tag")); return 1; @@ -269,5 +269,5 @@ cb_mailer (enum gconf_callback_command cmd, } - if (value->type != GCONF_TYPE_STRING) + if (!value || value->type != GCONF_TYPE_STRING) { - gconf_error (locus, 0, _("expected scalar value but found list")); + gconf_error (locus, 0, _("expected scalar value")); return 1; @@ -573,3 +573,3 @@ cb_sql (enum gconf_callback_command cmd, case gconf_callback_section_begin: - if (value->type != GCONF_TYPE_STRING || !value->v.string) + if (!value || value->type != GCONF_TYPE_STRING) { @@ -616,5 +616,2 @@ cb_syslog_facility (enum gconf_callback_command cmd, { - struct sqlconn *pconn = varptr; - char *p; - if (assert_string_arg (locus, cmd, value)) @@ -643,3 +640,3 @@ cb_define_message (enum gconf_callback_command cmd, } - if (value->type != GCONF_TYPE_ARRAY || value->v.arg.c != 2) + if (!value || value->type != GCONF_TYPE_ARRAY || value->v.arg.c != 2) { @@ -738,2 +735,26 @@ get_backup_version (gconf_locus_t *locus, const char *ctx, static int +cb_backup (enum gconf_callback_command cmd, + gconf_locus_t *locus, + void *varptr, + gconf_value_t *value, + void *cb_data) +{ + enum backup_type *ptype = varptr; + + if (assert_string_arg (locus, cmd, value)) + return 1; + *ptype = get_backup_version (locus, NULL, value->v.string); + return 0; +} + +static struct gconf_keyword archive_kw[] = { + { "name", N_("file-or-dir"), N_("Name of archive file or directory"), + gconf_type_string, NULL, offsetof(struct archive_descr, name) }, + { "backup", N_("type"), N_("Define backup type"), + gconf_type_string, NULL, offsetof(struct archive_descr, backup_type), + cb_backup }, + { NULL } +}; + +static int cb_archive (enum gconf_callback_command cmd, @@ -745,66 +766,56 @@ cb_archive (enum gconf_callback_command cmd, struct archive_descr *arch = varptr; - gconf_value_t *argp; - const char *type; - - if (cmd != gconf_callback_set_value) - { - gconf_error (locus, 0, _("Unexpected block statement")); - return 1; - } - - if (value->type != GCONF_TYPE_ARRAY || value->v.arg.c > 3) - { - gconf_error (locus, 0, _("expected 1-3 arguments")); - return 1; - } - - argp = get_arg (locus, value, 0, GCONF_TYPE_STRING); - if (!argp) - return 1; + void **pdata = cb_data; - type = argp->v.string; - if (strcmp (type, "none") == 0) - { - arch->type = archive_none; - if (value->v.arg.c > 1) - gconf_warning (locus, 0, - _("rest of line ignored for archive type `none'")); - } - else + switch (cmd) { - argp = get_arg (locus, value, 1, GCONF_TYPE_STRING); - if (!argp) - return 1; - arch->name = safe_file_name (xstrdup (argp->v.string)); - if (!arch->name) - { - gconf_error (locus, 0, _("invalid archive name: %s"), - argp->v.string); + case gconf_callback_section_begin: + *pdata = arch; + /* fallthrough */ + case gconf_callback_set_value: + if (!value) + { + gconf_error (locus, 0, _("expected tag")); return 1; } - - if (strcmp (type, "tar") == 0) + + if (value->type != GCONF_TYPE_STRING) { - arch->type = archive_tar; - if (value->v.arg.c > 2) - gconf_warning (locus, 0, - _("junk after the archive name ignored")); + gconf_error (locus, 0, _("expected scalar value but found list")); + return 1; } - else if (strcmp (type, "directory") == 0) + + if (strcmp (value->v.string, "none") == 0) + arch->type = archive_none; + else if (strcmp (value->v.string, "tar") == 0) + arch->type = archive_tar; + else if (strcmp (value->v.string, "directory") == 0) + arch->type = archive_directory; + else { - arch->type = archive_directory; - if (value->v.arg.c > 2) - { - argp = get_arg (locus, value, 2, GCONF_TYPE_STRING); - arch->backup_type = get_backup_version (locus, NULL, - argp->v.string); - } - else - get_backup_version (locus, - "VERSION_CONTROL environment variable", - getenv ("VERSION_CONTROL")); + gconf_error (locus, 0, _("unknown archive type")); + return 1; } - else - gconf_warning (locus, 0, _("unknown archive type")); + if (cmd == gconf_callback_section_begin) + return 0; + break; + + case gconf_callback_section_end: + break; + } + + if (arch->type == archive_none) + return 0; + + if (arch->name == NULL) + { + gconf_error (locus, 0, _("at least archive name must be set")); + return 1; + } + + if (arch->type == archive_tar && arch->backup_type != no_backups) + { + gconf_warning (locus, 0, _("backup type ignored for this archive type")); + return 1; } + return 0; @@ -945,3 +956,3 @@ cb_access_method_params (enum gconf_callback_command cmd, } - if (value->type != GCONF_TYPE_LIST) + if (!value || value->type != GCONF_TYPE_LIST) { @@ -956,3 +967,3 @@ cb_access_method_params (enum gconf_callback_command cmd, { - gconf_value_t *vp = gl_list_get_at (value->v.list, 0); + const gconf_value_t *vp = gl_list_get_at (value->v.list, 0); @@ -1025,3 +1036,3 @@ cb_access_method (enum gconf_callback_command cmd, case gconf_callback_section_begin: - if (value->type != GCONF_TYPE_STRING || !value->v.string) + if (!value || value->type != GCONF_TYPE_STRING) { @@ -1081,7 +1092,5 @@ static struct gconf_keyword directory_kw[] = { cb_access_method, NULL, access_method_kw }, - { "archive", - N_("<type: string> <archive-name: string> [<backup-method: method>]"), - N_("Set up archivation"), - gconf_type_string, NULL, offsetof(struct directory_pair, archive), - cb_archive }, + { "archive", N_("type: string"), N_("Set up archivation"), + gconf_type_section, NULL, offsetof(struct directory_pair, archive), + cb_archive, NULL, archive_kw }, { NULL } @@ -1103,3 +1112,3 @@ cb_directory (enum gconf_callback_command cmd, case gconf_callback_section_begin: - if (value->type != GCONF_TYPE_STRING || !value->v.string) + if (!value || value->type != GCONF_TYPE_STRING) { @@ -1126,4 +1135,3 @@ cb_directory (enum gconf_callback_command cmd, if (ec) - gconf_error (locus, ec, _("cannot access %s"), - dpair->source_dir, strerror (ec)); + gconf_error (locus, ec, _("cannot access %s"), dpair->source_dir); else @@ -1135,4 +1143,3 @@ cb_directory (enum gconf_callback_command cmd, if (ec) - gconf_error (locus, ec, _("cannot access %s"), - dpair->dest_dir, strerror (ec)); + gconf_error (locus, ec, _("cannot access %s"), dpair->dest_dir); else @@ -1204,6 +1211,5 @@ static struct gconf_keyword wydawca_kw[] = { - { "archive", - N_("<type: string> <archive-name: string> [<backup-method: method>]"), - N_("Set up archivation"), - gconf_type_string, &default_archive_descr, 0, cb_archive }, + { "archive", N_("type: string"), N_("Set up archivation"), + gconf_type_section, &default_archive_descr, 0, + cb_archive, NULL, archive_kw }, diff --git a/src/directive.c b/src/directive.c index eeb82c1..ed28cc5 100644 --- a/src/directive.c +++ b/src/directive.c @@ -365,3 +365,3 @@ process_directives (struct file_triplet *trp, struct directory_pair *dpair) - if (rc = argcv_get (val, NULL, NULL, &argc, &argv)) + if ((rc = argcv_get (val, NULL, NULL, &argc, &argv))) { diff --git a/src/diskio.c b/src/diskio.c index 3cffd10..2148abd 100644 --- a/src/diskio.c +++ b/src/diskio.c @@ -645,3 +645,3 @@ symlink_file (struct file_triplet *trp, struct directory_pair *dpair, "file %s exists and is not a symbolic link", - dst, strerror (errno)); + dst); rc = 1; diff --git a/src/getopt.m4 b/src/getopt.m4 new file mode 100644 index 0000000..d6f5580 --- /dev/null +++ b/src/getopt.m4 @@ -0,0 +1,517 @@ +dnl This file is part of GNU Rush. +dnl Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff. +dnl +dnl GNU Rush is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 3, or (at your option) +dnl any later version. +dnl +dnl GNU Rush is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Rush. If not, see <http://www.gnu.org/licenses/>. +divert(-1) +changequote([<,>]) +changecom(/*,*/) + +dnl upcase(ARGS...) +dnl Concatenate and convert ARGS to upper case. +dnl +define([<upcase>], [<translit([<$*>], [<a-z>], [<A-Z>])>]) + +dnl concat(ARGS...) +dnl Concatenate arguments, inserting ", " between each of pair of them. +dnl +define([<concat>],[<ifelse([<$#>],1,[<$1>],[<$1, concat(shift($@))>])>]) + +dnl flushleft(ARGS...) +dnl Concatenate ARGS and remove any leading whitespace +dnl +define([<flushleft>], + [<patsubst([<concat($*)>], [<^[ ]+>])>]) + +dnl chop(ARGS...) +dnl Concatenate ARGS and remove any trailing whitespace +dnl +define([<chop>], + [<patsubst([<$*>], [<[ ]+$>])>]) + +dnl escape(ARGS...) +dnl Concatenate ARGS and escape any occurrences of double-quotes with +dnl backslashes. +dnl +define([<escape>], +[<patsubst([<concat($*)>],[<[\"]>],[<\\\&>])>]) + +dnl prep(ARG) +dnl Prepare ARG for including in C strings: replace newlines with any amount +dnl of preceding and following whitespace by a single space character, remove +dnl leading whitespace, and escape double-quotes. +dnl +define([<prep>], + [<escape(flushleft(patsubst([<$1>],[<[ ]* ++[ ]*>],[< >])))>]) + +dnl SHORT_OPTS +dnl Accumulator for the 3rd argument of getopt_long +dnl +define([<SHORT_OPTS>],[<>]) + +dnl GROUP(STRING) +dnl Begin a named group of options +dnl +define([<GROUP>],[<dnl +divert(3) + { NULL, NULL, 0, N_("prep([<$1>])") }, +divert(-1)>]) + +define([<__GATHER_OPTIONS>],[< +define([<KEY>],ifelse([<$2>],,[<OPTION_>]upcase(patsubst($1,-,_)),'$2')) +ifelse([<$2>],,[< +divert(1) + KEY, +divert(-1) +>]) +define([<SELECTOR>],ifdef([<SELECTOR>],SELECTOR) case KEY:) +ifelse([<$1>],,,[< +divert(2) + { "$1", ARGTYPE, 0, KEY }, +divert(-1)>]) +dnl +define([<SHORT_OPTS>],SHORT_OPTS[<>]dnl +ifelse([<$2>],,,$2[<>]ifelse(ARGTYPE,[<no_argument>],,ARGTYPE,[<required_argument>],:,ARGTYPE,[<optional_argument>],::))) +dnl +ifelse([<$1>],,,dnl +[<define([<LONG_TAG>],ifelse(LONG_TAG,,[<--$1>],[<LONG_TAG; --$1>]))>]) +ifelse([<$2>],,,dnl +[<define([<SHORT_TAG>],ifelse(SHORT_TAG,,[<-$2>],[<SHORT_TAG; -$2>]))>]) +>]) + +dnl OPTION(long-opt, short-opt, [arg], [descr]) +dnl Introduce a command line option. Arguments: +dnl long-opt Long option. +dnl short-opt Short option (a single char) +dnl (At least one of long-opt or short-opt must be present) +dnl +dnl Optional arguments: +dnl arg Option argument. +dnl descr Option description +dnl +dnl If arg is absent, the option does not take any arguments. If arg is +dnl enclosed in square brackets, the option takes an optional argument. +dnl Otherwise, the argument is required. +dnl +dnl If descr is not given the option will not appear in the --help and +dnl --usage outputs. +dnl +define([<OPTION>],[< +pushdef([<LONG_TAG>]) +pushdef([<SHORT_TAG>]) +pushdef([<ARGNAME>],[<$3>]) +pushdef([<DOCSTRING>],[<prep([<$4>])>]) +pushdef([<ARGTYPE>],[<ifelse([<$3>],,[<no_argument>],dnl +patsubst([<$3>],[<\[.*\]>]),,[<optional_argument>],dnl +[<required_argument>])>]) +__GATHER_OPTIONS($@) +>]) + +dnl ALIAS(long-opt, short-opt) +dnl Declare aliases for the previous OPTION statement. +dnl long-opt Long option. +dnl short-opt Short option (a single char) +dnl (At least one of long-opt or short-opt must be present) +dnl An OPTION statement may be followed by any number of ALIAS statements. +dnl +define([<ALIAS>],[< +__GATHER_OPTIONS($1,$2) +>]) + +dnl BEGIN +dnl Start an action associated with the declared option. Must follow OPTION +dnl statement, with optional ALIAS statements in between. +dnl +define([<BEGIN>],[< +ifelse([<DOCSTRING>],,,[< +divert(3) + { "translit(dnl +ifelse(SHORT_TAG,,LONG_TAG,[<SHORT_TAG[<>]ifelse(LONG_TAG,,,; LONG_TAG)>]), + [<;>],[<,>])", ifelse(ARGNAME,,[<NULL, 0>], +[<ifelse(ARGTYPE,[<optional_argument>], +[<patsubst(ARGNAME,[<\[\(.*\)\]>],[<N_("\1"), 1>])>],[<N_("ARGNAME"), 0>])>]), N_("DOCSTRING") }, +divert(-1)>]) +popdef([<ARGTYPE>]) +popdef([<ARGNAME>]) +popdef([<DOCSTRING>]) +divert(4)dnl +popdef([<LONG_TAG>])dnl +popdef([<SHORT_TAG>])dnl + SELECTOR + { +>]) + +dnl END +dnl Finish the associated action +dnl +define([<END>],[< + break; + } +divert(-1) +undefine([<SELECTOR>])>]) + +dnl GETOPT(argc, argv, [default]) +dnl Emit option parsing code. Arguments: +dnl +dnl argc Name of the 1st argument to getopt_long. +dnl argv Name of the 2nd argument to getopt_long. +dnl default Code for the default branch +dnl +define([<GETOPT>],[< + { + int c; + +ifelse([<$#>],3,opterr = 0;) + while ((c = getopt_long($1, $2, "SHORT_OPTS", + long_options, NULL)) != EOF) + { + switch (c) + { + default: + ifelse([<$#>],3,$3,[<exit(1)>]); + + undivert(4) + } + } + } +>]) + +define([<STDFUNC>],[< +divert(0) +void print_help(void); +void print_usage(void); +divert(5) +const char *program_version = [<$1>]; +static char doc[] = N_("[<$3>]"); +static char args_doc[] = N_("[<$4>]"); +const char *program_bug_address = "<" PACKAGE_BUGREPORT ">"; + +#define DESCRCOLUMN 30 +#define RMARGIN 79 +#define GROUPCOLUMN 2 +#define USAGECOLUMN 13 + +static void +indent (size_t start, size_t col) +{ + for (; start < col; start++) + putchar (' '); +} + +static void +print_option_descr (const char *descr, size_t lmargin, size_t rmargin) +{ + while (*descr) + { + size_t s = 0; + size_t i; + size_t width = rmargin - lmargin; + + for (i = 0; ; i++) + { + if (descr[i] == 0 || isspace (descr[i])) + { + if (i > width) + break; + s = i; + if (descr[i] == 0) + break; + } + } + printf ("%*.*s\n", s, s, descr); + descr += s; + if (*descr) + { + indent (0, lmargin); + descr++; + } + } +} + +void +print_help(void) +{ + unsigned i; + + printf ("%s %s [%s]... %s\n", _("Usage:"), [<$2>], _("[<OPTION>]"), + gettext (args_doc)); + if (doc && doc[0]) + print_option_descr(gettext (doc), 0, RMARGIN); + putchar ('\n'); + + for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++) + { + unsigned n; + if (opthelp[i].opt) + { + n = printf (" %s", opthelp[i].opt); + if (opthelp[i].arg) + { + char *cb, *ce, *sep = ""; + if (opthelp[i].is_optional) + { + cb = "["; + ce = "]"; + } + else + cb = ce = ""; + + if (strlen (opthelp[i].opt) == 2) + { + if (!opthelp[i].is_optional) + sep = " "; + } + else + sep = "="; + n += printf ("%s%s%s%s", cb, sep, gettext (opthelp[i].arg), ce); + } + if (n >= DESCRCOLUMN) + { + putchar ('\n'); + n = 0; + } + indent (n, DESCRCOLUMN); + print_option_descr (gettext (opthelp[i].descr), DESCRCOLUMN, RMARGIN); + } + else + { + if (i) + putchar ('\n'); + indent (0, GROUPCOLUMN); + print_option_descr (gettext (opthelp[i].descr), + GROUPCOLUMN, RMARGIN); + putchar ('\n'); + } + } + + putchar ('\n'); +dnl ************************************************************************** +dnl This string cannot be split over several lines, because this would trigger +dnl a bug in GNU M4 (version 1.4.9 and 1.4.10), which would insert #line +dnl directives between the lines. +dnl ************************************************************************** + print_option_descr (_("Mandatory or optional arguments to long options are also mandatory or optional for any corresponding short options."), 0, RMARGIN); + putchar ('\n'); + printf (_("Report bugs to %s.\n"), program_bug_address); +} + +void +print_usage(void) +{ + unsigned i; + int f = 0; + unsigned n; + char buf[RMARGIN+1]; + +#define FLUSH dnl + do dnl + { dnl + buf[n] = 0; dnl + printf ("%s\n", buf); dnl + n = USAGECOLUMN; dnl + memset (buf, ' ', n); dnl + } dnl + while (0) +#define ADDC(c) dnl + do { if (n == RMARGIN) FLUSH; buf[n++] = c; } while (0) + + n = snprintf (buf, sizeof buf, "%s %s ", _("Usage:"), [<$2>]); + + /* Print a list of short options without arguments. */ + for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++) + { + if (opthelp[i].opt && opthelp[i].descr && opthelp[i].opt[1] != '-' + && opthelp[i].arg == NULL) + { + if (f == 0) + { + ADDC('['); + ADDC('-'); + f = 1; + } + ADDC(opthelp[i].opt[1]); + } + } + if (f) + ADDC(']'); + + /* Print a list of short options with arguments. */ + for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++) + { + if (opthelp[i].opt && opthelp[i].descr && opthelp[i].opt[1] != '-' + && opthelp[i].arg) + { + size_t len = 5 + + strlen (opthelp[i].arg) + + (opthelp[i].is_optional ? 2 : 1); + if (n + len > RMARGIN) FLUSH; + buf[n++] = ' '; + buf[n++] = '['; + buf[n++] = '-'; + buf[n++] = opthelp[i].opt[1]; + if (opthelp[i].is_optional) + { + buf[n++] = '['; + strcpy (&buf[n], opthelp[i].arg); + n += strlen (opthelp[i].arg); + buf[n++] = ']'; + } + else + { + buf[n++] = ' '; + strcpy (&buf[n], opthelp[i].arg); + n += strlen (opthelp[i].arg); + } + buf[n++] = ']'; + } + } + + /* Print a list of long options */ + for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++) + { + if (opthelp[i].opt && opthelp[i].descr) + { + size_t len; + const char *longopt; + + if (opthelp[i].opt[1] == '-') + longopt = opthelp[i].opt; + else if (opthelp[i].opt[2] == ',') + longopt = opthelp[i].opt + 4; + else + continue; + + len = 3 + strlen (longopt) + + (opthelp[i].arg ? 1 + strlen (opthelp[i].arg) + + (opthelp[i].is_optional ? 2 : 0) : 0); + if (n + len > RMARGIN) FLUSH; + buf[n++] = ' '; + buf[n++] = '['; + strcpy (&buf[n], longopt); + n += strlen (longopt); + if (opthelp[i].arg) + { + buf[n++] = '='; + if (opthelp[i].is_optional) + { + buf[n++] = '['; + strcpy (&buf[n], opthelp[i].arg); + n += strlen (opthelp[i].arg); + buf[n++] = ']'; + } + else + { + strcpy (&buf[n], opthelp[i].arg); + n += strlen (opthelp[i].arg); + } + } + buf[n++] = ']'; + } + } + FLUSH; + +} + +const char version_etc_copyright[] = + /* Do *not* mark this string for translation. %s is a copyright + symbol suitable for this locale, and %d is the copyright + year. */ + "Copyright %s 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff"; + +void +print_version_only(const char *program_version, FILE *stream) +{ + fprintf (stream, "%s\n", program_version); + /* TRANSLATORS: Translate "(C)" to the copyright symbol + (C-in-a-circle), if this symbol is available in the user's + locale. Otherwise, do not translate "(C)"; leave it as-is. */ + fprintf (stream, version_etc_copyright, _("(C)")); + fputc ('\n', stream); +} + +void +print_version(const char *program_version, FILE *stream) +{ + print_version_only(program_version, stream); + +dnl ************************************************************************** +dnl This string cannot be split over serveal lines, because this would trigger +dnl a bug in GNU M4 (version 1.4.9 and 1.4.10), which would insert #line +dnl directives between the lines. +dnl ************************************************************************** + fputs (_("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\n\n"), + stream); + +dnl /* TRANSLATORS: %s denotes an author name. */ +dnl fprintf (stream, _("Written by %s.\n"), "Sergey Poznyakoff"); +} + +divert(-1) +popdef([<ADDC>]) +popdef([<FLUSH>]) +>]) + +define([<OPTIONS_BEGIN>], + [<divert(-1) + define([<GETOPT_STYLE>],[<$1>]) + ifelse([<$1>],[<gnu>], + [<STDFUNC([<$2 " (" PACKAGE_NAME ") " PACKAGE_VERSION>], [<$2>], [<$3>], [<$4>])>]) +>]) + +define([<OPTIONS_END>],[< +ifelse(GETOPT_STYLE,[<gnu>],[< + GROUP([<Other options>]) + OPTION([<help>],h,,[<Give this help list>]) + BEGIN + print_help (); + exit (0); + END + OPTION([<usage>],,,[<Give a short usage message>]) + BEGIN + print_usage (); + exit (0); + END + OPTION([<version>],,,[<Print program version>]) + BEGIN + /* Give version */ + print_version(program_version, stdout); + exit (0); + END>]) +divert +/* Option codes */ +enum { + _OPTION_INIT=255, + undivert(1) + MAX_OPTION +}; +static struct option long_options[] = { + undivert(2) + {0, 0, 0, 0} +}; +static struct opthelp { + const char *opt; + const char *arg; + int is_optional; + const char *descr; +} opthelp[] = { + undivert(3) +}; +undivert(5) +>]) + +divert(0)dnl +/* -*- buffer-read-only: t -*- vi: set ro: + THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT. +*/ + diff --git a/src/update-2.0.awk b/src/update-2.0.awk index 8f74d90..2fd6657 100644 --- a/src/update-2.0.awk +++ b/src/update-2.0.awk @@ -1 +1,17 @@ +# This file is part of Wydawca +# Copyright (C) 2007, 2009 Sergey Poznyakoff +# +# Wydawca is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Wydawca is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Wydawca. If not, see <http://www.gnu.org/licenses/>. + state == 1 && NF == 1 && $1 == "end" { @@ -5,2 +21,6 @@ state == 1 && NF == 1 && $1 == "end" { } +state == 1 && $1 == "include" { + printf("m4_include(%s)\n",$2) + next +} state == 1 { print $0; next } @@ -48,3 +68,3 @@ $1 == "file-sweep-time" || $1 == "tar-program" || $1 == "admin-address" || -$1 == "umask" || $1 == "archive" { +$1 == "umask" { len = get_indent() @@ -57,2 +77,21 @@ $1 == "umask" || $1 == "archive" { +$1 == "archive" { + len = get_indent() + kw = $1 + indent(len) + printf("archive %s", $2) + if (NF > 2) { + print " {" + indent(len + 2) + printf("name \"%s\";\n", $3) + if (NF > 3) { + indent(len + 2) + printf("backup %s;\n", $4) + } + indent(len) + print "}" + } else + print ";" +} + $1 == "project-owner" || $1 == "user-data" || $1 == "verify-user" || |