public inbox for util-linux@vger.kernel.org
 help / color / mirror / Atom feed
From: Sami Kerola <kerolasa@iki.fi>
To: util-linux@vger.kernel.org
Cc: kerolasa@iki.fi
Subject: [PATCH 02/17] setterm: use getopt_long_only() for option parsing
Date: Sun, 18 May 2014 15:05:26 +0100	[thread overview]
Message-ID: <1400421941-14244-3-git-send-email-kerolasa@iki.fi> (raw)
In-Reply-To: <1400421941-14244-1-git-send-email-kerolasa@iki.fi>

The getopt_long_only() has advantage of allowing one and two hyphen
versions of options, for example -help and --help.  Secondly the getopt
function family from libc can ensure some options requiring arguments,
while other are optional, and some should not accept argument at all.
That makes option parsing more robust.

Unfortunately retiring the old option parsing makes this change greater
than preferred.  Assuming not mistakes happen the new code works
functionally exactly as the old did.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
 term-utils/setterm.c | 916 ++++++++++++++++++++++++---------------------------
 1 file changed, 426 insertions(+), 490 deletions(-)

diff --git a/term-utils/setterm.c b/term-utils/setterm.c
index e6385ac..25baff7 100644
--- a/term-utils/setterm.c
+++ b/term-utils/setterm.c
@@ -95,6 +95,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -217,7 +218,7 @@ int opt_tb_array[TABS_MAX + 1];	/* Array for tab list */
 int opt_msglevel_num;
 int opt_ps_mode, opt_pd_min;	/* powersave mode/powerdown time */
 
-char opt_sn_name[PATH_MAX + 1] = "screen.dump";
+char opt_sn_name[PATH_MAX] = "screen.dump";
 
 static void screendump(int vcnum, FILE *F);
 
@@ -226,416 +227,231 @@ static void screendump(int vcnum, FILE *F);
  * Note that it is an error for a given option to be invoked more than once.
  */
 
-static void
-parse_term(int argc, char **argv, int *option, char **ttyname, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Term flag to set. */
-	/* ttyname: Terminal name to set. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a -term specification. */
-
-	if (argc != 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1)
-		*ttyname = argv[0];
-}
-
-static void
-parse_none(int argc, char **argv __attribute__ ((__unused__)), int *option, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Term flag to set. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a parameterless specification. */
-
-	if (argc != 0 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-}
-
-static void
-parse_switch(int argc, char **argv, int *option, int *opt_on, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Option flag to set. */
-	/* opt_on: Boolean option switch to set or reset. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a boolean (on/off) specification. */
-
-	if (argc > 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1) {
-		if (strcmp(argv[0], "on") == 0)
-			*opt_on = TRUE;
-		else if (strcmp(argv[0], "off") == 0)
-			*opt_on = FALSE;
-		else
-			*bad_arg = TRUE;
-	} else {
-		*opt_on = TRUE;
-	}
+static int parse_switch(const char *arg, const char *t, const char *f)
+{
+	if (strcmp(arg, t) == 0)
+		return 1;
+	else if (strcmp(arg, f) == 0)
+		return 0;
+	errx(EXIT_FAILURE, _("argument error: %s"), arg);
 }
 
-static void
-par_color(int argc, char **argv, int *option, int *opt_color, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Color flag to set. */
-	/* opt_color: Color to set. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a -foreground or -background specification. */
-
-	if (argc != 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1) {
-		if (strcmp(argv[0], "black") == 0)
-			*opt_color = BLACK;
-		else if (strcmp(argv[0], "red") == 0)
-			*opt_color = RED;
-		else if (strcmp(argv[0], "green") == 0)
-			*opt_color = GREEN;
-		else if (strcmp(argv[0], "yellow") == 0)
-			*opt_color = YELLOW;
-		else if (strcmp(argv[0], "blue") == 0)
-			*opt_color = BLUE;
-		else if (strcmp(argv[0], "magenta") == 0)
-			*opt_color = MAGENTA;
-		else if (strcmp(argv[0], "cyan") == 0)
-			*opt_color = CYAN;
-		else if (strcmp(argv[0], "white") == 0)
-			*opt_color = WHITE;
-		else if (strcmp(argv[0], "default") == 0)
-			*opt_color = DEFAULT;
-		else if (isdigit(argv[0][0]))
-			*opt_color = atoi(argv[0]);
-		else
-			*bad_arg = TRUE;
-
-		if(*opt_color < BLACK || DEFAULT < *opt_color || *opt_color == GREY)
-			*bad_arg = TRUE;
+static int parse_febg_color(const char *arg)
+{
+	if (strcmp(arg, "black") == 0)
+		return BLACK;
+	else if (strcmp(arg, "red") == 0)
+		return RED;
+	else if (strcmp(arg, "green") == 0)
+		return GREEN;
+	else if (strcmp(arg, "yellow") == 0)
+		return YELLOW;
+	else if (strcmp(arg, "blue") == 0)
+		return BLUE;
+	else if (strcmp(arg, "magenta") == 0)
+		return MAGENTA;
+	else if (strcmp(arg, "cyan") == 0)
+		return CYAN;
+	else if (strcmp(arg, "white") == 0)
+		return WHITE;
+	else if (strcmp(arg, "default") == 0)
+		return DEFAULT;
+	else if (isdigit(arg[0])) {
+		int color;
+
+		color = atoi(arg);
+		if (color < BLACK || DEFAULT < color || color == GREY)
+			errx(EXIT_FAILURE, _("argument error: %s"), arg);
+		return color;
 	}
+	errx(EXIT_FAILURE, _("argument error: %s"), arg);
 }
 
-static void
-par_color2(int argc, char **argv, int *option, int *opt_color, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Color flag to set. */
-	/* opt_color: Color to set. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a -ulcolor or -hbcolor specification. */
-
-	if (!argc || argc > 2 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	*opt_color = 0;
-	if (argc == 2) {
-		if (strcmp(argv[0], "bright") == 0)
-			*opt_color = GREY;
-		else {
-			*bad_arg = TRUE;
-			return;
-		}
-	}
-	if (argc) {
-		if (strcmp(argv[argc-1], "black") == 0) {
-			if(*opt_color)
-				*bad_arg = TRUE;
-			else
-				*opt_color = BLACK;
-		} else if (strcmp(argv[argc-1], "grey") == 0) {
-			if(*opt_color)
-				*bad_arg = TRUE;
-			else
-				*opt_color = GREY;
-		} else if (strcmp(argv[argc-1], "red") == 0)
-			*opt_color |= RED;
-		else if (strcmp(argv[argc-1], "green") == 0)
-			*opt_color |= GREEN;
-		else if (strcmp(argv[argc-1], "yellow") == 0)
-			*opt_color |= YELLOW;
-		else if (strcmp(argv[argc-1], "blue") == 0)
-			*opt_color |= BLUE;
-		else if (strcmp(argv[argc-1], "magenta") == 0)
-			*opt_color |= MAGENTA;
-		else if (strcmp(argv[argc-1], "cyan") == 0)
-			*opt_color |= CYAN;
-		else if (strcmp(argv[argc-1], "white") == 0)
-			*opt_color |= WHITE;
-		else if (isdigit(argv[argc-1][0]))
-			*opt_color = atoi(argv[argc-1]);
-		else
-			*bad_arg = TRUE;
-		if(*opt_color < BLACK || DEFAULT < *opt_color )
-			*bad_arg = TRUE;
-	}
+static int parse_ulhb_color(char **argv, int *optind)
+{
+	char *color_name;
+	int bright = 0;
+	int color = -1;
+
+	if (argv[*optind] && strcmp(argv[*optind - 1], "bright") == 0) {
+		bright = 1;
+		color_name = argv[*optind];
+		(*optind)++;
+	} else
+		color_name = argv[*optind - 1];
+
+	if (strcmp(color_name, "black") == 0)
+		color = BLACK;
+	else if (strcmp(color_name, "grey") == 0)
+		color = GREY;
+	else if (strcmp(color_name, "red") == 0)
+		color = RED;
+	else if (strcmp(color_name, "green") == 0)
+		color = GREEN;
+	else if (strcmp(color_name, "yellow") == 0)
+		color = YELLOW;
+	else if (strcmp(color_name, "blue") == 0)
+		color = BLUE;
+	else if (strcmp(color_name, "magenta") == 0)
+		color = MAGENTA;
+	else if (strcmp(color_name, "cyan") == 0)
+		color = CYAN;
+	else if (strcmp(color_name, "white") == 0)
+		color = WHITE;
+	else if (isdigit(color_name[0]))
+		color = atoi(color_name);
+
+	if (color < BLACK || DEFAULT < color)
+		errx(EXIT_FAILURE, _("argument error: %s"), color_name);
+	if (bright && (color == BLACK || color == GREY))
+		errx(EXIT_FAILURE, _("argument error: bright %s is not supported"), color_name);
+
+	return color;
 }
 
-static void
-parse_clear(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* opt_all: Clear all switch to set or reset. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a -clear specification. */
-
-	if (argc > 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1) {
-		if (strcmp(argv[0], "all") == 0)
-			*opt_all = TRUE;
-		else if (strcmp(argv[0], "rest") == 0)
-			*opt_all = FALSE;
-		else
-			*bad_arg = TRUE;
-	} else {
-		*opt_all = TRUE;
+static char *find_optional_arg(char **argv, char *optarg, int *optind)
+{
+	char *arg;
+	if (optarg)
+		return optarg;
+	else {
+		arg = argv[*optind];
+		if (!arg || arg[0] == '-')
+			return NULL;
 	}
+	(*optind)++;
+	return arg;
 }
 
-static void
-parse_blank(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* opt_all: Clear all switch to set or reset. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a -blank specification. */
-
-	if (argc > 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1) {
-		if (!strcmp(argv[0], "force"))
-			*opt_all = BLANKSCREEN;
-		else if (!strcmp(argv[0], "poke"))
-			*opt_all = UNBLANKSCREEN;
-		else {
-			*opt_all = atoi(argv[0]);
-			if (*opt_all < 0 || BLANK_MAX < *opt_all)
-				*bad_arg = TRUE;
-		}
-	} else {
-		*opt_all = BLANKEDSCREEN;
+static int parse_blank(char **argv, char *optarg, int *optind)
+{
+	char *arg;
+
+	arg = find_optional_arg(argv, optarg, optind);
+	if (!arg)
+		return BLANKEDSCREEN;
+	if (!strcmp(arg, "force"))
+		return BLANKSCREEN;
+	else if (!strcmp(arg, "poke"))
+		return UNBLANKSCREEN;
+	else {
+		int ret = -1;
+
+		if (isdigit(arg[0]))
+			ret = atoi(arg);
+		if (ret < 0 || BLANK_MAX < ret)
+			errx(EXIT_FAILURE, _("argument error: %s"), arg);
+		return ret;
 	}
+	/* should be impossible to reach */
+	abort();
 }
 
-static void
-parse_powersave(int argc, char **argv, int *option, int *opt_mode, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: powersave flag to set. */
-	/* opt_mode: Powersaving mode, defined in vesa_blank.c */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a -powersave mode specification. */
-
-	if (argc > 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1) {
-		if (strcmp(argv[0], "on") == 0)
-			*opt_mode = VESA_BLANK_MODE_SUSPENDV;
-		else if (strcmp(argv[0], "vsync") == 0)
-			*opt_mode = VESA_BLANK_MODE_SUSPENDV;
-		else if (strcmp(argv[0], "hsync") == 0)
-			*opt_mode = VESA_BLANK_MODE_SUSPENDH;
-		else if (strcmp(argv[0], "powerdown") == 0)
-			*opt_mode = VESA_BLANK_MODE_POWERDOWN;
-		else if (strcmp(argv[0], "off") == 0)
-			*opt_mode = VESA_BLANK_MODE_OFF;
-		else
-			*bad_arg = TRUE;
-	} else {
-		*opt_mode = VESA_BLANK_MODE_OFF;
-	}
+static int parse_powersave(const char *arg)
+{
+	if (strcmp(arg, "on") == 0)
+		return VESA_BLANK_MODE_SUSPENDV;
+	else if (strcmp(arg, "vsync") == 0)
+		return VESA_BLANK_MODE_SUSPENDV;
+	else if (strcmp(arg, "hsync") == 0)
+		return VESA_BLANK_MODE_SUSPENDH;
+	else if (strcmp(arg, "powerdown") == 0)
+		return VESA_BLANK_MODE_POWERDOWN;
+	else if (strcmp(arg, "off") == 0)
+		return VESA_BLANK_MODE_OFF;
+	errx(EXIT_FAILURE, _("argument error: %s"), arg);
 }
 
-static void
-parse_msglevel(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* opt_all: Clear all switch to set or reset. */
-	/* bad_arg: Set to true if an error is detected. */
-
-	if (argc > 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1) {
-		*opt_all = atoi(argv[0]);
-		if (*opt_all < CONSOLE_LEVEL_MIN || CONSOLE_LEVEL_MAX <  *opt_all)
-			*bad_arg = TRUE;
-	} else {
-		*opt_all = -1;
-	}
-}
+static int parse_msglevel(const char *arg)
+{
+	int ret = CONSOLE_LEVEL_MIN - 1;
 
-static void
-parse_snap(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* opt_all: Clear all switch to set or reset. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a -dump or -append specification. */
-
-	if (argc > 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1) {
-		*opt_all = atoi(argv[0]);
-		if ((*opt_all <= 0))
-			*bad_arg = TRUE;
-	} else {
-		*opt_all = 0;
-	}
+	if (isdigit(arg[0]))
+		ret = atoi(arg);
+	if (ret < CONSOLE_LEVEL_MIN || CONSOLE_LEVEL_MAX < ret)
+		errx(EXIT_FAILURE, _("argument error: %s"), arg);
+	return ret;
 }
 
-static void
-parse_snapfile(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* opt_all: Clear all switch to set or reset. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a -file specification. */
-
-	if (argc != 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	memset(opt_all, 0, PATH_MAX + 1);
-	if (argc == 1)
-		strncpy((char *)opt_all, argv[0], PATH_MAX);
+static int parse_snap(char **argv, char *optarg, int *optind)
+{
+	int ret = 0;
+	char *arg;
+
+	arg = find_optional_arg(argv, optarg, optind);
+	if (!arg)
+		return 0;
+	if (isdigit(arg[0]))
+		ret = atoi(arg);
+	if (ret < 1)
+		errx(EXIT_FAILURE, _("argument error: %s"), arg);
+	return ret;
 }
 
-static void
-parse_tabs(int argc, char **argv, int *option, int *tab_array, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* tab_array: Array of tabs */
-	/* bad_arg: Set to true if an error is detected. */
-
-	if (*option || TABS_MAX < argc)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	tab_array[argc] = -1;
-	while(argc--) {
-		tab_array[argc] = atoi(argv[argc]);
-		if (tab_array[argc] < 1 || TABS_MAX < tab_array[argc]) {
-			*bad_arg = TRUE;
-			return;
-		}
-	}
-}
+static void parse_tabs(char **argv, char *optarg, int *optind, int *tab_array)
+{
+	int i = 0;
 
-static void
-parse_clrtabs(int argc, char **argv, int *option, int *tab_array, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* tab_array: Array of tabs */
-	/* bad_arg: Set to true if an error is detected. */
-
-	if (*option || TABS_MAX < argc)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if(argc == 0) {
-		tab_array[0] = -1;
-		return;
+	if (optarg) {
+		tab_array[i] = atoi(optarg);
+		i++;
 	}
-	tab_array[argc] = -1;
-	while(argc--) {
-		tab_array[argc] = atoi(argv[argc]);
-		if(tab_array[argc] < 1 || TABS_MAX < tab_array[argc]) {
-			*bad_arg = TRUE;
-			return;
-		}
+	while (argv[*optind]) {
+		if (TABS_MAX < i)
+			errx(EXIT_FAILURE, _("too many tabs"));
+		if (argv[*optind][0] == '-')
+			break;
+		if (isdigit(argv[*optind][0]))
+			tab_array[i] = atoi(argv[*optind]);
+		else
+			break;
+		(*optind)++;
+		i++;
 	}
+	tab_array[i] = -1;
 }
 
-static void
-parse_regtabs(int argc, char **argv, int *option, int *opt_len, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* opt_len: Regular tab length. */
-	/* bad_arg: Set to true if an error is detected. */
-
-	if (*option || argc > 1)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if(argc == 0) {
-		*opt_len = DEFAULT_TAB_LEN;
-		return;
-	}
-	*opt_len = atoi(argv[0]);
-	if(*opt_len < 1 || TABS_MAX < *opt_len) {
-		*bad_arg = TRUE;
-		return;
-	}
+static int parse_regtabs(char **argv, char *optarg, int *optind)
+{
+	int ret;
+	char *arg;
+
+	arg = find_optional_arg(argv, optarg, optind);
+	if (!arg)
+		return DEFAULT_TAB_LEN;
+	ret = atoi(arg);
+	if (ret < 1 || TABS_MAX < ret)
+		errx(EXIT_FAILURE, _("argument error: %s"), arg);
+	return ret;
 }
 
-
-static void
-parse_blength(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* opt_all */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse  -blength specification. */
-
-	if (argc > 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1) {
-		*opt_all = atoi(argv[0]);
-		if (BLENGTH_MAX < *opt_all)
-			*bad_arg = TRUE;
-	} else {
-		*opt_all = 0;
-	}
+static int parse_blength(char **argv, char *optarg, int *optind)
+{
+	int ret = -1;
+	char *arg;
+
+	arg = find_optional_arg(argv, optarg, optind);
+	if (!arg)
+		return 0;
+	if (isdigit(arg[0]))
+		ret = atoi(arg);
+	if (ret < 0 || BLENGTH_MAX < ret)
+		errx(EXIT_FAILURE, _("argument error: %s"), arg);
+	return ret;
 }
 
-static void
-parse_bfreq(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* option: Clear flag to set. */
-	/* opt_all */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse  -bfreq specification. */
-
-	if (argc > 1 || *option)
-		*bad_arg = TRUE;
-	*option = TRUE;
-	if (argc == 1) {
-		*opt_all = atoi(argv[0]);
-	} else {
-		*opt_all = 0;
-	}
+static int parse_bfreq(char **argv, char *optarg, int *optind)
+{
+	char *arg;
+
+	arg = find_optional_arg(argv, optarg, optind);
+	if (!arg)
+		return 0;
+	if (isdigit(arg[0]))
+		return atoi(arg);
+	return 0;
 }
 
-
 static void
 show_tabs(void) {
 	int i, co = tigetnum("cols");
@@ -696,7 +512,7 @@ usage(FILE *out) {
 	fputs(_(" -append <1-NR_CONSOLES>\n"), out);
 	fputs(_(" -file dumpfilename\n"), out);
 	fputs(_(" -msg <on|off>\n"), out);
-	fputs(_(" -msglevel <0-8>\n"), out);
+	fputs(_(" -msglevel <0-8>\n"), out);	/* FIXME: klogctl console_log range is 1-8 */
 	fputs(_(" -powersave <on|vsync|hsync|powerdown|off>\n"), out);
 	fputs(_(" -powerdown <0-60>\n"), out);
 	fputs(_(" -blength <0-2000>\n"), out);
@@ -709,91 +525,234 @@ usage(FILE *out) {
 	exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
 }
 
-#define STRCMP(str1,str2) strncmp(str1,str2,strlen(str1))
+static void set_opt_flag(int *opt)
+{
+	if (*opt)
+		errx(EXIT_FAILURE, "duplicate use of an option");
+	*opt = 1;
+}
 
-static void
-parse_option(char *option, int argc, char **argv, int *bad_arg) {
-	/* option: Option with leading '-' removed. */
-	/* argc: Number of arguments for this option. */
-	/* argv: Arguments for this option. */
-	/* bad_arg: Set to true if an error is detected. */
-
-/* Parse a single specification. */
-
-	if (STRCMP(option, "term") == 0)
-		parse_term(argc, argv, &opt_term, &opt_te_terminal_name, bad_arg);
-	else if (STRCMP(option, "reset") == 0)
-		parse_none(argc, argv, &opt_reset, bad_arg);
-	else if (STRCMP(option, "initialize") == 0)
-		parse_none(argc, argv, &opt_initialize, bad_arg);
-	else if (STRCMP(option, "cursor") == 0)
-		parse_switch(argc, argv, &opt_cursor, &opt_cu_on, bad_arg);
-	else if (STRCMP(option, "repeat") == 0)
-		parse_switch(argc, argv, &opt_repeat, &opt_rep_on, bad_arg);
-	else if (STRCMP(option, "appcursorkeys") == 0)
-		parse_switch(argc, argv, &opt_appcursorkeys, &opt_appck_on, bad_arg);
-	else if (STRCMP(option, "linewrap") == 0)
-		parse_switch(argc, argv, &opt_linewrap, &opt_li_on, bad_arg);
-	else if (STRCMP(option, "default") == 0)
-		parse_none(argc, argv, &opt_default, bad_arg);
-	else if (STRCMP(option, "foreground") == 0)
-		par_color(argc, argv, &opt_foreground, &opt_fo_color, bad_arg);
-	else if (STRCMP(option, "background") == 0)
-		par_color(argc, argv, &opt_background, &opt_ba_color, bad_arg);
-	else if (STRCMP(option, "ulcolor") == 0)
-		par_color2(argc, argv, &opt_ulcolor, &opt_ul_color, bad_arg);
-	else if (STRCMP(option, "hbcolor") == 0)
-		par_color2(argc, argv, &opt_hbcolor, &opt_hb_color, bad_arg);
-	else if (STRCMP(option, "inversescreen") == 0)
-		parse_switch(argc, argv, &opt_inversescreen, &opt_invsc_on, bad_arg);
-	else if (STRCMP(option, "bold") == 0)
-		parse_switch(argc, argv, &opt_bold, &opt_bo_on, bad_arg);
-	else if (STRCMP(option, "half-bright") == 0)
-		parse_switch(argc, argv, &opt_halfbright, &opt_hb_on, bad_arg);
-	else if (STRCMP(option, "blink") == 0)
-		parse_switch(argc, argv, &opt_blink, &opt_bl_on, bad_arg);
-	else if (STRCMP(option, "reverse") == 0)
-		parse_switch(argc, argv, &opt_reverse, &opt_re_on, bad_arg);
-	else if (STRCMP(option, "underline") == 0)
-		parse_switch(argc, argv, &opt_underline, &opt_un_on, bad_arg);
-	else if (STRCMP(option, "store") == 0)
-		parse_none(argc, argv, &opt_store, bad_arg);
-	else if (STRCMP(option, "clear") == 0)
-		parse_clear(argc, argv, &opt_clear, &opt_cl_all, bad_arg);
-	else if (STRCMP(option, "tabs") == 0)
-		parse_tabs(argc, argv, &opt_tabs, opt_tb_array, bad_arg);
-	else if (STRCMP(option, "clrtabs") == 0)
-		parse_clrtabs(argc, argv, &opt_clrtabs, opt_tb_array, bad_arg);
-	else if (STRCMP(option, "regtabs") == 0)
-		parse_regtabs(argc, argv, &opt_regtabs, &opt_rt_len, bad_arg);
-	else if (STRCMP(option, "blank") == 0)
-		parse_blank(argc, argv, &opt_blank, &opt_bl_min, bad_arg);
-	else if (STRCMP(option, "dump") == 0)
-		parse_snap(argc, argv, &opt_snap, &opt_sn_num, bad_arg);
-	else if (STRCMP(option, "append") == 0)
-		parse_snap(argc, argv, &opt_append, &opt_sn_num, bad_arg);
-	else if (STRCMP(option, "file") == 0)
-		parse_snapfile(argc, argv, &opt_snapfile, (int *)opt_sn_name, bad_arg);
-	else if (STRCMP(option, "msg") == 0)
-		parse_switch(argc, argv, &opt_msg, &opt_msg_on, bad_arg);
-	else if (STRCMP(option, "msglevel") == 0)
-		parse_msglevel(argc, argv, &opt_msglevel, &opt_msglevel_num, bad_arg);
-	else if (STRCMP(option, "powersave") == 0)
-		parse_powersave(argc, argv, &opt_powersave, &opt_ps_mode, bad_arg);
-	else if (STRCMP(option, "powerdown") == 0)
-		parse_blank(argc, argv, &opt_powerdown, &opt_pd_min, bad_arg);
-	else if (STRCMP(option, "blength") == 0)
-		parse_blength(argc, argv, &opt_blength, &opt_blength_l, bad_arg);
-	else if (STRCMP(option, "bfreq") == 0)
-		parse_bfreq(argc, argv, &opt_bfreq, &opt_bfreq_f, bad_arg);
-	else if (STRCMP(option, "version") == 0) {
-		printf(_("%s from %s\n"), program_invocation_short_name,
-					  PACKAGE_STRING);
-		exit(EXIT_SUCCESS);
-	} else if (STRCMP(option, "help") == 0)
-		usage(stdout);
-	else
-		*bad_arg = TRUE;
+static void parse_option(int argc, char **argv)
+{
+	int c;
+	enum {
+		OPT_TERM = CHAR_MAX + 1,
+		OPT_RESET,
+		OPT_INITIALIZE,
+		OPT_CURSOR,
+		OPT_REPEAT,
+		OPT_APPCURSORKEYS,
+		OPT_LINEWRAP,
+		OPT_DEFAULT,
+		OPT_FOREGROUND,
+		OPT_BACKGROUND,
+		OPT_ULCOLOR,
+		OPT_HBCOLOR,
+		OPT_INVERSESCREEN,
+		OPT_BOLD,
+		OPT_HALF_BRIGHT,
+		OPT_BLINK,
+		OPT_REVERSE,
+		OPT_UNDERLINE,
+		OPT_STORE,
+		OPT_CLEAR,
+		OPT_TABS,
+		OPT_CLRTABS,
+		OPT_REGTABS,
+		OPT_BLANK,
+		OPT_DUMP,
+		OPT_APPEND,
+		OPT_FILE,
+		OPT_MSG,
+		OPT_MSGLEVEL,
+		OPT_POWERSAVE,
+		OPT_POWERDOWN,
+		OPT_BLENGTH,
+		OPT_BFREQ,
+		OPT_VERSION,
+		OPT_HELP
+	};
+	static const struct option longopts[] = {
+		{"term", required_argument, NULL, OPT_TERM},
+		{"reset", no_argument, NULL, OPT_RESET},
+		{"initialize", no_argument, NULL, OPT_INITIALIZE},
+		{"cursor", required_argument, NULL, OPT_CURSOR},
+		{"repeat", required_argument, NULL, OPT_REPEAT},
+		{"appcursorkeys", required_argument, NULL, OPT_APPCURSORKEYS},
+		{"linewrap", required_argument, NULL, OPT_LINEWRAP},
+		{"default", no_argument, NULL, OPT_DEFAULT},
+		{"foreground", required_argument, NULL, OPT_FOREGROUND},
+		{"background", required_argument, NULL, OPT_BACKGROUND},
+		{"ulcolor", required_argument, NULL, OPT_ULCOLOR},
+		{"ulcolor", required_argument, NULL, OPT_ULCOLOR},
+		{"hbcolor", required_argument, NULL, OPT_HBCOLOR},
+		{"hbcolor", required_argument, NULL, OPT_HBCOLOR},
+		{"inversescreen", required_argument, NULL, OPT_INVERSESCREEN},
+		{"bold", required_argument, NULL, OPT_BOLD},
+		{"half-bright", required_argument, NULL, OPT_HALF_BRIGHT},
+		{"blink", required_argument, NULL, OPT_BLINK},
+		{"reverse", required_argument, NULL, OPT_REVERSE},
+		{"underline", required_argument, NULL, OPT_UNDERLINE},
+		{"store", no_argument, NULL, OPT_STORE},
+		{"clear", required_argument, NULL, OPT_CLEAR},
+		{"tabs", optional_argument, NULL, OPT_TABS},
+		{"clrtabs", optional_argument, NULL, OPT_CLRTABS},
+		{"regtabs", optional_argument, NULL, OPT_REGTABS},
+		{"blank", optional_argument, NULL, OPT_BLANK},
+		{"dump", optional_argument, NULL, OPT_DUMP},
+		{"append", required_argument, NULL, OPT_APPEND},
+		{"file", required_argument, NULL, OPT_FILE},
+		{"msg", required_argument, NULL, OPT_MSG},
+		{"msglevel", required_argument, NULL, OPT_MSGLEVEL},
+		{"powersave", required_argument, NULL, OPT_POWERSAVE},
+		{"powerdown", optional_argument, NULL, OPT_POWERDOWN},
+		{"blength", optional_argument, NULL, OPT_BLENGTH},
+		{"bfreq", optional_argument, NULL, OPT_BFREQ},
+		{"version", no_argument, NULL, OPT_VERSION},
+		{"help", no_argument, NULL, OPT_HELP},
+		{NULL, 0, NULL, 0}
+	};
+
+	while ((c = getopt_long_only(argc, argv, "", longopts, NULL)) != -1) {
+		switch (c) {
+		case OPT_TERM:
+			set_opt_flag(&opt_term);
+			opt_te_terminal_name = optarg;
+			break;
+		case OPT_RESET:
+			set_opt_flag(&opt_reset);
+			break;
+		case OPT_INITIALIZE:
+			set_opt_flag(&opt_initialize);
+			break;
+		case OPT_CURSOR:
+			set_opt_flag(&opt_cursor);
+			opt_cu_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_REPEAT:
+			set_opt_flag(&opt_repeat);
+			opt_rep_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_APPCURSORKEYS:
+			set_opt_flag(&opt_appcursorkeys);
+			opt_appck_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_LINEWRAP:
+			set_opt_flag(&opt_linewrap);
+			opt_li_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_DEFAULT:
+			set_opt_flag(&opt_default);
+			break;
+		case OPT_FOREGROUND:
+			set_opt_flag(&opt_foreground);
+			opt_fo_color = parse_febg_color(optarg);
+			break;
+		case OPT_BACKGROUND:
+			set_opt_flag(&opt_background);
+			opt_ba_color = parse_febg_color(optarg);
+			break;
+		case OPT_ULCOLOR:
+			set_opt_flag(&opt_ulcolor);
+			opt_ul_color = parse_ulhb_color(argv, &optind);
+			break;
+		case OPT_HBCOLOR:
+			set_opt_flag(&opt_hbcolor);
+			opt_hb_color = parse_ulhb_color(argv, &optind);
+			break;
+		case OPT_INVERSESCREEN:
+			set_opt_flag(&opt_inversescreen);
+			opt_invsc_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_BOLD:
+			set_opt_flag(&opt_bold);
+			opt_bo_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_HALF_BRIGHT:
+			set_opt_flag(&opt_halfbright);
+			opt_hb_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_BLINK:
+			set_opt_flag(&opt_blink);
+			opt_bl_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_REVERSE:
+			set_opt_flag(&opt_reverse);
+			opt_re_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_UNDERLINE:
+			set_opt_flag(&opt_underline);
+			opt_un_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_STORE:
+			set_opt_flag(&opt_store);
+			break;
+		case OPT_CLEAR:
+			set_opt_flag(&opt_clear);
+			opt_cl_all = parse_switch(optarg, "all", "reset");
+			break;
+		case OPT_TABS:
+			set_opt_flag(&opt_tabs);
+			parse_tabs(argv, optarg, &optind, opt_tb_array);
+			break;
+		case OPT_CLRTABS:
+			set_opt_flag(&opt_clrtabs);
+			parse_tabs(argv, optarg, &optind, opt_tb_array);
+			break;
+		case OPT_REGTABS:
+			set_opt_flag(&opt_regtabs);
+			opt_rt_len = parse_regtabs(argv, optarg, &optind);
+			break;
+		case OPT_BLANK:
+			set_opt_flag(&opt_blank);
+			opt_bl_min = parse_blank(argv, optarg, &optind);
+			break;
+		case OPT_DUMP:
+			set_opt_flag(&opt_snap);
+			opt_sn_num = parse_snap(argv, optarg, &optind);
+			break;
+		case OPT_APPEND:
+			set_opt_flag(&opt_append);
+			opt_sn_num = parse_snap(argv, optarg, &optind);
+			break;
+		case OPT_FILE:
+			set_opt_flag(&opt_snapfile);
+			strncpy(opt_sn_name, optarg, PATH_MAX);	/* FIXME: should use xstrncpy() */
+			opt_sn_name[PATH_MAX - 1] = 0;
+			break;
+		case OPT_MSG:
+			set_opt_flag(&opt_msg);
+			opt_msg_on = parse_switch(optarg, "on", "off");
+			break;
+		case OPT_MSGLEVEL:
+			set_opt_flag(&opt_msglevel);
+			opt_msglevel_num = parse_msglevel(optarg);
+			break;
+		case OPT_POWERSAVE:
+			set_opt_flag(&opt_powersave);
+			opt_ps_mode = parse_powersave(optarg);
+			break;
+		case OPT_POWERDOWN:
+			set_opt_flag(&opt_powerdown);
+			opt_pd_min = parse_blank(argv, optarg, &optind);
+			break;
+		case OPT_BLENGTH:
+			set_opt_flag(&opt_blength);
+			opt_blength_l = parse_blength(argv, optarg, &optind);
+			break;
+		case OPT_BFREQ:
+			set_opt_flag(&opt_bfreq);
+			opt_bfreq_f = parse_bfreq(argv, optarg, &optind);
+			break;
+		case OPT_VERSION:
+			printf(UTIL_LINUX_VERSION);
+			exit(EXIT_SUCCESS);
+		case OPT_HELP:
+			usage(stdout);
+		default:
+			usage(stderr);
+		}
+	}
 }
 
 /* End of command line parsing routines. */
@@ -1153,8 +1112,6 @@ error:
 
 int
 main(int argc, char **argv) {
-	int bad_arg = FALSE;		/* Set if error in arguments. */
-	int arg, modifier;
 	char *term;			/* Terminal type. */
 	int vcterm;			/* Set if terminal is a virtual console. */
 	int errret;
@@ -1165,31 +1122,10 @@ main(int argc, char **argv) {
 	atexit(close_stdout);
 
 	if (argc < 2)
-		bad_arg = TRUE;
+		usage(stderr);
 
 	/* Parse arguments. */
-
-	for (arg = 1; arg < argc;) {
-		if (*argv[arg] == '-') {
-
-			/* Parse a single option. */
-
-			for (modifier = arg + 1; modifier < argc; modifier++) {
-				if (*argv[modifier] == '-') break;
-			}
-			parse_option(argv[arg] + 1, modifier - arg - 1,
-				     &argv[arg + 1], &bad_arg);
-			arg = modifier;
-		} else {
-			bad_arg = TRUE;
-			arg++;
-		}
-	}
-
-	/* Display syntax message if error in arguments. */
-
-	if (bad_arg)
-		usage(stderr);
+	parse_option(argc, argv);
 
 	/* Find out terminal name. */
 
-- 
1.9.2


  parent reply	other threads:[~2014-05-18 14:05 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-18 14:05 [PATCH 00/17] pull: almost complete setterm refactoring Sami Kerola
2014-05-18 14:05 ` [PATCH 01/17] setterm: clean up includes Sami Kerola
2014-05-18 14:05 ` Sami Kerola [this message]
2014-05-19  9:29   ` [PATCH 02/17] setterm: use getopt_long_only() for option parsing Karel Zak
2014-05-18 14:05 ` [PATCH 03/17] setterm: use string utils to numeric parsing Sami Kerola
2014-05-19  9:24   ` Karel Zak
2014-05-18 14:05 ` [PATCH 04/17] setterm: move show_tabs() and screendump() functions Sami Kerola
2014-05-18 14:05 ` [PATCH 05/17] setterm: remove usage comment segment Sami Kerola
2014-05-18 14:05 ` [PATCH 06/17] setterm: add option control structure Sami Kerola
2014-05-19  9:38   ` Karel Zak
2014-05-19  9:48   ` Karel Zak
2014-05-18 14:05 ` [PATCH 07/17] setterm: add init_terminal() to make main() shorter Sami Kerola
2014-05-18 14:05 ` [PATCH 08/17] setterm: clean up screendump() Sami Kerola
2014-05-18 14:05 ` [PATCH 09/17] setterm: remove devfs and /dev/vcsa0 support Sami Kerola
2014-05-19  9:52   ` Karel Zak
2014-05-18 14:05 ` [PATCH 10/17] setterm: make -msglevel 0 to work as is did earlier Sami Kerola
2014-05-18 14:05 ` [PATCH 11/17] setterm: correct usage() bright color argument Sami Kerola
2014-05-19  9:57   ` Karel Zak
2014-05-18 14:05 ` [PATCH 12/17] setterm: improve perform_sequence() coding style Sami Kerola
2014-05-18 14:05 ` [PATCH 13/17] setterm: tell user when options does not effect Sami Kerola
2014-05-19 10:02   ` Karel Zak
2014-05-18 14:05 ` [PATCH 14/17] setterm: improve error messages Sami Kerola
2014-05-18 14:05 ` [PATCH 15/17] setterm: various visual terminal effects are not console specific Sami Kerola
2014-05-18 14:05 ` [PATCH 16/17] setterm: mark some options to be exclusive with each other Sami Kerola
2014-05-18 14:05 ` [PATCH 17/17] setterm: add set_blanking() action Sami Kerola
2014-05-19 21:51 ` [PATCH 00/17] pull: almost complete setterm refactoring Sami Kerola
2014-05-20  8:11   ` Benno Schulenberg
2014-05-20 10:02     ` Karel Zak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1400421941-14244-3-git-send-email-kerolasa@iki.fi \
    --to=kerolasa@iki.fi \
    --cc=util-linux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox