The code ignored the last argument provided on the command line;

It did not support the recommended '--version' and '--help' from GNU which
are often handy;

It used an unusual syntax to specify the parser, now it can also use more
usual "-parser=name" and "-parser name", the old syntax is still supported
to avoid breaking compatibility;

When a problem is found with an argument, the program stops instead of
printing an error message and continuing;

There's been updates on the exit codes in case of problem because it is an
information that could be useful for people calling the program from a
script;

Took the opportunity to provide more information in the man page and to
get it cross-checked against the program's option list during "make check".

Signed-off-by: Christophe CURIS <christophe.cu...@free.fr>
---
 doc/Makefile.am  |   8 +++-
 doc/wmmenugen.1  |  89 +++++++++++++++++++++++++++++++++++++-----
 util/wmmenugen.c | 117 ++++++++++++++++++++++++++++++++++++++++---------------
 3 files changed, 172 insertions(+), 42 deletions(-)

diff --git a/doc/Makefile.am b/doc/Makefile.am
index 26187f5..500e33a 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -49,7 +49,7 @@ am__v_CHKOPTS_0 = @echo "  CHK      $@" ;
 am__v_CHKOPTS_1 =
 
 check-local: wmaker-args WPrefs-args wmagnify-args geticonset-args 
getstyle-args seticons-args setstyle-args \
-       wdread-args wdwrite-args wmgenmenu-args wmsetbg-args wxcopy-args 
wxpaste-args
+       wdread-args wdwrite-args wmgenmenu-args wmmenugen-args wmsetbg-args 
wxcopy-args wxpaste-args
 
 wmaker-args:
        $(AM_V_CHKOPTS)$(top_srcdir)/script/check-cmdline-options-doc.sh \
@@ -91,6 +91,10 @@ wmgenmenu-args:
        $(AM_V_CHKOPTS)$(top_srcdir)/script/check-cmdline-options-doc.sh \
                --program "$(top_builddir)/util/wmgenmenu" --man-page 
"$(top_srcdir)/doc/wmgenmenu.1"
 
+wmmenugen-args:
+       $(AM_V_CHKOPTS)$(top_srcdir)/script/check-cmdline-options-doc.sh \
+               --program "$(top_builddir)/util/wmmenugen" --man-page 
"$(top_srcdir)/doc/wmmenugen.1"
+
 wmsetbg-args:
        $(AM_V_CHKOPTS)$(top_srcdir)/script/check-cmdline-options-doc.sh \
                --program "$(top_builddir)/util/wmsetbg" --man-page "wmsetbg.1"
@@ -104,4 +108,4 @@ wxpaste-args:
                --program "$(top_builddir)/util/wxpaste" --man-page 
"$(top_srcdir)/doc/wxpaste.1"
 
 .PHONY: wmaker-args WPrefs-args wmagnify-args geticonset-args getstyle-args 
seticons-args setstyle-args \
-       wdread-args wdwrite-args wmgenmenu-args wmsetbg-args wxcopy-args 
wxpaste-args
+       wdread-args wdwrite-args wmgenmenu-args wmmenugen-args wmsetbg-args 
wxcopy-args wxpaste-args
diff --git a/doc/wmmenugen.1 b/doc/wmmenugen.1
index 4a9f588..1617648 100644
--- a/doc/wmmenugen.1
+++ b/doc/wmmenugen.1
@@ -1,22 +1,93 @@
-.TH "wmmenugen" "1" "15 August 2011"
+.TH "wmmenugen" "1" "16 May 2015"
 .SH "NAME"
 \fBwmmenugen\fR \- Window Maker PropList menu generator
 .PP
 .SH "SYNOPSIS"
-.B wmmenugen \fI\-parser:<parser> fspec \fR[ fpsec ... \fR]
-\fR[\fI\-parser:<parser> fspec \fR[ fpsec ... \fR] ... \fR]
-.PP
+.B wmmenugen
+.RI [ options ...]
+.BI \-parser= <name>
+.IR fspec " [" fspec "...]"
+.BI \fR[\fP\-parser= <name>
+.IR fspec " [" fspec "...]...]"
 .SH "DESCRIPTION"
-\fBwmmenugen \fR\- Window Maker PropList menu generator
-.PP
+.B wmmenugen
+generates a menu in the
+.I PropList
+format for Window Maker from the input file
+.IR fspec .
+In the case where
+.I fspec
+is a directory instead of a file, then
+.B wmmenugen
+will read all the files present in the hierarchy of this directory.
 .SH "OPTIONS"
 .TP
+.BR \-\-help ", " \-h
+print a help message with the list of options
+.TP
 .B \-parser
-\fRspecify the parser. Known parsers are xdg and wmconfig.
+specify the format of the file to be parsed
+.TP
+.B \-\-version
+print the version of Window Maker from which the program comes
+.SH "PARSERS"
+.B wmmenugen
+supports these file formats for input files:
+.TP
+.I wmconfig
+the format of the menu generation tool for X of the same name
 .TP
-.B \-fspec
-\fRspecify the file.
+.I xdg
+the format of the menu specification as defined by the
+.I FreeDesktop
+standard, currently at version 1.1
+.SH "RETURN VALUE"
+The exit status from the
+.B wmmenugen
+command provides information for the caller:
+.TP
+.B 0
+when the
+.I PropList
+menu was successfully generated on
+.IR stdout .
+.TP
+.B 1
+when a
+.I fspec
+caused a problem (non readable file, ...)
+.TP
+.B 2
+the arguments of the command line where not recognised
+.TP
+.B 3
+the program met an unexpected menu structure;
+you probably want to look at the section
+.B BUGS
+below.
+.SH "BUGS"
+If you get the exit status
+.B 3
+with the unclear error message about
+.IR "unprocessed levels on the stack" ,
+you encountered a limitation of
+.BR wmmenugen .
+It would be a good idea to prepare an archive with the files incriminated and 
submit them to the
+mailing list (wmaker-dev@lists.windowmaker.org) with you command line, so the 
team can work on
+improving the behaviour of the program on this case.
+.SH "SEE ALSO"
+.BR wmgenmenu (1),
+the tool to generate a default menu
+.PP
+the
+.I Wmconfig
+program can be found at:
+<http://www.arrishq.net/index.html>
 .PP
+the
+.I xdg
+specification can be found at:
+<http://standards.freedesktop.org/menu-spec/menu-spec-1.1.html>
 .SH "AUTHOR"
 wmmenugen is a part of Window Maker. It was written by Tamas TEVESZ.
 .PP
diff --git a/util/wmmenugen.c b/util/wmmenugen.c
index 0c55d51..5839189 100644
--- a/util/wmmenugen.c
+++ b/util/wmmenugen.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <strings.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include "wmmenugen.h"
 
@@ -54,6 +55,35 @@ static const char *prog_name;
 WMTreeNode *menu;
 char *env_lang, *env_ctry, *env_enc, *env_mod;
 
+static void print_help(void)
+{
+       printf("Usage: %s -parser:<parser> fspec [fspec...]\n", prog_name);
+       puts("Dynamically generate a menu in Property List format for Window 
Maker");
+       puts("");
+       puts("  -h, --help\t\tdisplay this help and exit");
+       puts("  -parser=<name>\tspecify the format of the input, see below");
+       puts("  --version\t\toutput version information and exit");
+       puts("");
+       puts("fspec: the file to be converted or the directory containing all 
the menu files");
+       puts("");
+       puts("Known parsers:");
+       puts("  xdg\t\tDesktop Entry from FreeDesktop standard");
+       puts("  wmconfig\tfrom the menu generation tool by the same name");
+}
+
+#ifdef DEBUG
+static const char *get_parser_name(void)
+{
+       if (parse == &parse_xdg)
+               return "xdg";
+       if (parse == &parse_wmconfig)
+               return "wmconfig";
+
+       /* This case is not supposed to happen, but if it does it means that 
someone to update this list */
+       return "<unknown>";
+}
+#endif
+
 int main(int argc, char **argv)
 {
        struct stat st;
@@ -76,45 +106,69 @@ int main(int argc, char **argv)
        parse_locale(NULL, &env_lang, &env_ctry, &env_enc, &env_mod);
        terminal = find_terminal_emulator();
 
-       if (argc < 3) {
-               fprintf(stderr, "Usage: %s -parser:<parser> fspec [fpsec...] "
-                       "[-parser:<parser> fspec [fpsec...]...]\n", prog_name);
-               fputs(  "Known parsers: xdg wmconfig\n", stderr);
-               return 1;
-       }
-
-       for (i = 1; i < argc; i++)
+       for (i = 1; i <= argc; i++)
        {
-               if (strncmp(argv[i], "-parser:", 8) == 0) {
-                       if (strcmp(argv[i] + 8, "xdg") == 0) {
-#if DEBUG
-                               fputs("Using parser \"xdg\"\n", stderr);
-#endif
+               if (strncmp(argv[i], "-parser", 7) == 0 &&
+                   (argv[i][7] == '=' ||
+                    argv[i][7] == ':' || /* for legacy compatibility */
+                    argv[i][7] == '\0')) {
+                       const char *name;
+
+                       if (argv[i][7] == '\0') {
+                               if (++i > argc) {
+                                       fprintf(stderr, "%s: Missing parser 
name after \"-parser\"\n", prog_name);
+                                       return 2;
+                               }
+                               name = argv[i];
+                       } else {
+                               name = argv[i] + 8;
+                       }
+
+                       if (strcmp(name, "xdg") == 0) {
                                parse = &parse_xdg;
-                       } else if (strcmp(argv[i] + 8, "wmconfig") == 0) {
-#if DEBUG
-                               fputs("Using parser \"wmconfig\"\n", stderr);
-#endif
+                       } else if (strcmp(name, "wmconfig") == 0) {
                                parse = &parse_wmconfig;
                                validateFilename = &wmconfig_validate_file;
                        } else {
-                               fprintf(stderr, "%s: Unknown parser \"%s\"\n", 
prog_name, argv[i] + 8);
+                               fprintf(stderr, "%s: Unknown parser \"%s\"\n", 
prog_name, name);
+                               return 2;
                        }
                        continue;
                }
 
-               if (parse) {
-                       if (stat(argv[i], &st) == -1) {
-                               fprintf(stderr, "%s: unable to stat \"%s\"\n", 
prog_name, argv[i]);
-                       } else if (S_ISREG(st.st_mode)) {
-                               parse(argv[i], addWMMenuEntryCallback);
-                       } else if (S_ISDIR(st.st_mode)) {
-                               nftw(argv[i], dirParseFunc, 16, FTW_PHYS);
-                       } else {
-                               fprintf(stderr, "%s: \"%s\" is not a file or 
directory\n", prog_name, argv[i]);
-                       }
-               } else {
+               if (strcmp(argv[i], "--version") == 0) {
+                       printf("%s (Window Maker %s)\n", prog_name, VERSION);
+                       return 0;
+               }
+
+               if (strcmp(argv[i], "-h") == 0 ||
+                   strcmp(argv[i], "-help") == 0 ||
+                   strcmp(argv[i], "--help") == 0) {
+                       print_help();
+                       return 0;
+               }
+
+               if (parse == NULL) {
                        fprintf(stderr, "%s: argument \"%s\" with no valid 
parser\n", prog_name, argv[i]);
+                       return 2;
+               }
+
+#if DEBUG
+               fprintf(stderr, "%s: Using parser \"%s\" to process \"%s\"\n",
+                       prog_name, get_parser_name(), argv[i]);
+#endif
+
+               if (stat(argv[i], &st) == -1) {
+                       fprintf(stderr, "%s: unable to stat \"%s\", %s\n",
+                               prog_name, argv[i], strerror(errno));
+                       return 1;
+               } else if (S_ISREG(st.st_mode)) {
+                       parse(argv[i], addWMMenuEntryCallback);
+               } else if (S_ISDIR(st.st_mode)) {
+                       nftw(argv[i], dirParseFunc, 16, FTW_PHYS);
+               } else {
+                       fprintf(stderr, "%s: \"%s\" is not a file or 
directory\n", prog_name, argv[i]);
+                       return 1;
                }
        }
 
@@ -129,16 +183,17 @@ int main(int argc, char **argv)
        i = WMGetArrayItemCount(plMenuNodes);
        if (i > 2) { /* more than one submenu unprocessed is almost certainly 
an error */
                fprintf(stderr, "%s: unprocessed levels on the stack. 
fishy.\n", prog_name);
-               return 1;
+               return 3;
        } else if (i > 1 ) { /* possibly the top-level attachment is not yet 
done */
                WMPropList *first, *next;
+
                next = WMPopFromArray(plMenuNodes);
                first = WMPopFromArray(plMenuNodes);
                WMAddToPLArray(first, next);
                WMAddToArray(plMenuNodes, first);
        }
 
-       printf("%s\n", WMGetPropListDescription((WMPropList 
*)WMGetFromArray(plMenuNodes, 0), True));
+       puts(WMGetPropListDescription((WMPropList *)WMGetFromArray(plMenuNodes, 
0), True));
 
        return 0;
 }
-- 
2.1.4


-- 
To unsubscribe, send mail to wmaker-dev-unsubscr...@lists.windowmaker.org.

Reply via email to