diff options
author | pgen <p.gen.progs@gmail.com> | 2018-09-30 00:15:19 +0200 |
---|---|---|
committer | pgen <p.gen.progs@gmail.com> | 2018-10-01 19:36:56 +0200 |
commit | 1851c8c98f42dbfd89da5c05c34d5f49674b15ad (patch) | |
tree | 4d704f0532532341bd8cfca05d95dc09bdce3358 | |
parent | feac7702627f023d0b6c9e0f47b1aabe05d6e24d (diff) |
Create getopt.[ch]
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | Makefile.in | 6 | ||||
-rw-r--r-- | getopt.c | 205 | ||||
-rw-r--r-- | getopt.h | 31 | ||||
-rw-r--r-- | smenu.c | 503 |
5 files changed, 467 insertions, 280 deletions
diff --git a/Makefile.am b/Makefile.am index 2b90458..cebe16b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ bin_PROGRAMS = smenu smenu_SOURCES = smenu.c smenu.h ptrlist.c ptrlist.h xmalloc.c xmalloc.h \ index.c index.h utf8.c utf8.h fgetc.c fgetc.h \ - utils.c utils.h + utils.c utils.h getopt.c getopt.h dist_man_MANS = smenu.1 EXTRA_DIST = smenu.spec.in smenu.spec ChangeLog build.sh version \ COPYRIGHT LICENSE.rst README.rst examples build-aux tests diff --git a/Makefile.in b/Makefile.in index 58c6eef..6e9b41d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -103,7 +103,8 @@ CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) am_smenu_OBJECTS = smenu.$(OBJEXT) ptrlist.$(OBJEXT) xmalloc.$(OBJEXT) \ - index.$(OBJEXT) utf8.$(OBJEXT) fgetc.$(OBJEXT) utils.$(OBJEXT) + index.$(OBJEXT) utf8.$(OBJEXT) fgetc.$(OBJEXT) utils.$(OBJEXT) \ + getopt.$(OBJEXT) smenu_OBJECTS = $(am_smenu_OBJECTS) smenu_LDADD = $(LDADD) AM_V_P = $(am__v_P_@AM_V@) @@ -308,7 +309,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ smenu_SOURCES = smenu.c smenu.h ptrlist.c ptrlist.h xmalloc.c xmalloc.h \ index.c index.h utf8.c utf8.h fgetc.c fgetc.h \ - utils.c utils.h + utils.c utils.h getopt.c getopt.h dist_man_MANS = smenu.1 EXTRA_DIST = smenu.spec.in smenu.spec ChangeLog build.sh version \ @@ -424,6 +425,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fgetc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/index.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptrlist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smenu.Po@am__quote@ diff --git a/getopt.c b/getopt.c new file mode 100644 index 0000000..6966f80 --- /dev/null +++ b/getopt.c @@ -0,0 +1,205 @@ +/* egetopt.c -- Extended 'getopt'. + * + * A while back, a public-domain version of getopt() was posted to the + * net. A bit later, a gentleman by the name of Keith Bostic made some + * enhancements and reposted it. + * + * In recent weeks (i.e., early-to-mid 1988) there's been some + * heated discussion in comp.lang.c about the merits and drawbacks + * of getopt(), especially with regard to its handling of '?'. + * + * In light of this, I have taken Mr. Bostic's public-domain getopt() + * and have made some changes that I hope will be considered to be + * improvements. I call this routine 'egetopt' ("Extended getopt"). + * The default behavior of this routine is the same as that of getopt(), + * but it has some optional features that make it more useful. These + * options are controlled by the settings of some global variables. + * By not setting any of these extra global variables, you will have + * the same functionality as getopt(), which should satisfy those + * purists who believe getopt() is perfect and can never be improved. + * If, on the other hand, you are someone who isn't satisfied with the + * status quo, egetopt() may very well give you the added capabilities + * you want. + * + * Look at the enclosed README file for a description of egetopt()'s + * new features. + * + * The code was originally posted to the net as getopt.c by ... + * + * Keith Bostic + * ARPA: keith@seismo + * UUCP: seismo!keith + * + * Current version: added enhancements and comments, reformatted code. + * + * Lloyd Zusman + * Master Byte Software + * Los Gatos, California + * Internet: ljz@fx.com + * UUCP: ...!ames!fxgrp!ljz + * + * May, 1988 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include "getopt.h" + +/* Here are all the pertinent global variables. */ +/* """""""""""""""""""""""""""""""""""""""""""" */ +int opterr = 1; /* if true, output error message */ +int optind = 1; /* index into parent argv vector */ +int optopt; /* character checked for validity */ +int optbad = BADCH; /* character returned on error */ +int optchar = 0; /* character that begins returned option */ +int optneed = NEEDSEP; /* flag for mandatory argument */ +int optmaybe = MAYBESEP; /* flag for optional argument */ +int opterrfd = ERRFD; /* file descriptor for error text */ +char * optarg = NULL; /* argument associated with option */ +char * optstart = START; /* list of characters that start options */ + +/* Here it is: */ +/* """"""""""" */ +int +egetopt(int nargc, char ** nargv, char * ostr) +{ + static char * place = EMSG; /* option letter processing */ + register char * oli; /* option letter list index */ + register char * osi = NULL; /* option start list index */ + + if (nargv == (char **)NULL) + return (EOF); + + if (nargc <= optind || nargv[optind] == NULL) + return (EOF); + + if (place == NULL) + place = EMSG; + + /* Update scanning pointer. */ + /* """""""""""""""""""""""" */ + if (*place == '\0') + { + place = nargv[optind]; + if (place == NULL) + return (EOF); + else if (*place == '\0') + return (EOF); + + osi = strchr(optstart, *place); + if (osi != NULL) + optchar = (int)*osi; + + if (optind >= nargc || osi == NULL || *++place == '\0') + return (EOF); + + /* Two adjacent, identical flag characters were found. */ + /* This takes care of "--", for example. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ + if (*place == place[-1]) + { + ++optind; + return (EOF); + } + } + + /* If the option is a separator or the option isn't in the list, */ + /* we've got an error. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + optopt = (int)*place++; + oli = strchr(ostr, optopt); + if (optopt == optneed || optopt == (int)optmaybe || oli == NULL) + { + /* If we're at the end of the current argument, bump the */ + /* argument index. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ + if (*place == '\0') + ++optind; + + TELL("Illegal option -- "); /* bye bye */ + } + + /* If there is no argument indicator, then we don't even try to */ + /* return an argument. */ + /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + ++oli; + if (*oli == '\0' || (*oli != (char)optneed && *oli != (char)optmaybe)) + { + /* If we're at the end of the current argument, bump the */ + /* argument index. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ + if (*place == '\0') + ++optind; + + optarg = NULL; + } + /* If we're here, there's an argument indicator. It's handled */ + /* differently depending on whether it's a mandatory or an */ + /* optional argument. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + else + { + /* If there's no white space, use the rest of the */ + /* string as the argument. In this case, it doesn't */ + /* matter if the argument is mandatory or optional. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""" */ + if (*place != '\0') + optarg = place; + + /* If we're here, there's whitespace after the option. */ + /* */ + /* Is it a mandatory argument? If so, return the */ + /* next command-line argument if there is one. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ + else if (*oli == (char)optneed) + { + /* If we're at the end of the argument list, there */ + /* isn't an argument and hence we have an error. */ + /* Otherwise, make 'optarg' point to the argument. */ + /* """"""""""""""""""""""""""""""""""""""""""""""" */ + if (nargc <= ++optind) + { + place = EMSG; + TELL("Option requires an argument -- "); + } + else + optarg = nargv[optind]; + } + /* If we're here it must have been an optional argument. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ + else + { + if (nargc <= ++optind) + { + place = EMSG; + optarg = NULL; + } + else + { + optarg = nargv[optind]; + if (optarg == NULL) + place = EMSG; + + /* If the next item begins with a flag */ + /* character, we treat it like a new */ + /* argument. This is accomplished by */ + /* decrementing 'optind' and returning */ + /* a null argument. */ + /* """"""""""""""""""""""""""""""""""" */ + else if (strchr(optstart, *optarg) != NULL) + { + --optind; + optarg = NULL; + } + } + } + place = EMSG; + ++optind; + } + + /* Return option letter. */ + /* """"""""""""""""""""" */ + return (optopt); +} diff --git a/getopt.h b/getopt.h new file mode 100644 index 0000000..4e40721 --- /dev/null +++ b/getopt.h @@ -0,0 +1,31 @@ +#ifndef GETOPT_H +#define GETOPT_H + +/* None of these constants are referenced in the executable portion of */ +/* the code ... their sole purpose is to initialize global variables. */ +/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ +#define BADCH (int)'@' +#define NEEDSEP (int)':' +#define MAYBESEP (int)'%' +#define ERRFD 2 +#define EMSG "" +#define START "-" + +/* Conditionally print out an error message and return (depends on the */ +/* setting of 'opterr' and 'opterrfd'). Note that this version of */ +/* TELL() doesn't require the existence of stdio.h. */ +/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ +#define TELL(S) \ + { \ + ssize_t dummy_rc; \ + if (opterr && opterrfd >= 0) \ + { \ + char option = (char)optopt; \ + dummy_rc = write(opterrfd, (S), strlen(S)); \ + dummy_rc = write(opterrfd, &option, 1); \ + dummy_rc = write(opterrfd, "\n", 1); \ + } \ + return (optbad); \ + } + +#endif @@ -44,6 +44,7 @@ #include "utf8.h" #include "fgetc.h" #include "utils.h" +#include "getopt.h" #include "smenu.h" /* **************** */ @@ -51,13 +52,18 @@ /* **************** */ extern ll_t * tst_search_list; +extern char * optarg; +extern char * opterr; +extern int optind; +extern int optopt; +extern int optbad; +extern int opterrfd; /* **************** */ /* Global variables */ /* **************** */ word_t * word_a; /* Array containing words data (size: count) */ -long dummy_rc; /* temporary variable to silence the compiler */ long count = 0; /* number of words read from stdin */ long current; /* index the current selection under the cursor) */ long new_current; /* final current position, (used in search function) */ @@ -3868,236 +3874,6 @@ sig_handler(int s) } } -/* egetopt.c -- Extended 'getopt'. - * - * A while back, a public-domain version of getopt() was posted to the - * net. A bit later, a gentleman by the name of Keith Bostic made some - * enhancements and reposted it. - * - * In recent weeks (i.e., early-to-mid 1988) there's been some - * heated discussion in comp.lang.c about the merits and drawbacks - * of getopt(), especially with regard to its handling of '?'. - * - * In light of this, I have taken Mr. Bostic's public-domain getopt() - * and have made some changes that I hope will be considered to be - * improvements. I call this routine 'egetopt' ("Extended getopt"). - * The default behavior of this routine is the same as that of getopt(), - * but it has some optional features that make it more useful. These - * options are controlled by the settings of some global variables. - * By not setting any of these extra global variables, you will have - * the same functionality as getopt(), which should satisfy those - * purists who believe getopt() is perfect and can never be improved. - * If, on the other hand, you are someone who isn't satisfied with the - * status quo, egetopt() may very well give you the added capabilities - * you want. - * - * Look at the enclosed README file for a description of egetopt()'s - * new features. - * - * The code was originally posted to the net as getopt.c by ... - * - * Keith Bostic - * ARPA: keith@seismo - * UUCP: seismo!keith - * - * Current version: added enhancements and comments, reformatted code. - * - * Lloyd Zusman - * Master Byte Software - * Los Gatos, California - * Internet: ljz@fx.com - * UUCP: ...!ames!fxgrp!ljz - * - * May, 1988 - */ - -/* None of these constants are referenced in the executable portion of */ -/* the code ... their sole purpose is to initialize global variables. */ -/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ -#define BADCH (int)'@' -#define NEEDSEP (int)':' -#define MAYBESEP (int)'%' -#define ERRFD 2 -#define EMSG "" -#define START "-" - -/* Here are all the pertinent global variables. */ -/* """""""""""""""""""""""""""""""""""""""""""" */ -int opterr = 1; /* if true, output error message */ -int optind = 1; /* index into parent argv vector */ -int optopt; /* character checked for validity */ -int optbad = BADCH; /* character returned on error */ -int optchar = 0; /* character that begins returned option */ -int optneed = NEEDSEP; /* flag for mandatory argument */ -int optmaybe = MAYBESEP; /* flag for optional argument */ -int opterrfd = ERRFD; /* file descriptor for error text */ -char * optarg = NULL; /* argument associated with option */ -char * optstart = START; /* list of characters that start options */ - -/* Macros. */ -/* """"""" */ - -/* Conditionally print out an error message and return (depends on the */ -/* setting of 'opterr' and 'opterrfd'). Note that this version of */ -/* TELL() doesn't require the existence of stdio.h. */ -/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ -#define TELL(S) \ - { \ - if (opterr && opterrfd >= 0) \ - { \ - char option = (char)optopt; \ - dummy_rc = write(opterrfd, (S), strlen(S)); \ - dummy_rc = write(opterrfd, &option, 1); \ - dummy_rc = write(opterrfd, "\n", 1); \ - } \ - short_usage(); \ - return (optbad); \ - } - -/* Here it is: */ -/* """"""""""" */ -int -egetopt(int nargc, char ** nargv, char * ostr) -{ - static char * place = EMSG; /* option letter processing */ - register char * oli; /* option letter list index */ - register char * osi = NULL; /* option start list index */ - - if (nargv == (char **)NULL) - return (EOF); - - if (nargc <= optind || nargv[optind] == NULL) - return (EOF); - - if (place == NULL) - place = EMSG; - - /* Update scanning pointer. */ - /* """""""""""""""""""""""" */ - if (*place == '\0') - { - place = nargv[optind]; - if (place == NULL) - return (EOF); - else if (*place == '\0') - return (EOF); - - osi = strchr(optstart, *place); - if (osi != NULL) - optchar = (int)*osi; - - if (optind >= nargc || osi == NULL || *++place == '\0') - return (EOF); - - /* Two adjacent, identical flag characters were found. */ - /* This takes care of "--", for example. */ - /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ - if (*place == place[-1]) - { - ++optind; - return (EOF); - } - } - - /* If the option is a separator or the option isn't in the list, */ - /* we've got an error. */ - /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ - optopt = (int)*place++; - oli = strchr(ostr, optopt); - if (optopt == optneed || optopt == (int)optmaybe || oli == NULL) - { - /* If we're at the end of the current argument, bump the */ - /* argument index. */ - /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ - if (*place == '\0') - ++optind; - - TELL("Illegal option -- "); /* bye bye */ - } - - /* If there is no argument indicator, then we don't even try to */ - /* return an argument. */ - /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ - ++oli; - if (*oli == '\0' || (*oli != (char)optneed && *oli != (char)optmaybe)) - { - /* If we're at the end of the current argument, bump the */ - /* argument index. */ - /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ - if (*place == '\0') - ++optind; - - optarg = NULL; - } - /* If we're here, there's an argument indicator. It's handled */ - /* differently depending on whether it's a mandatory or an */ - /* optional argument. */ - /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ - else - { - /* If there's no white space, use the rest of the */ - /* string as the argument. In this case, it doesn't */ - /* matter if the argument is mandatory or optional. */ - /* """"""""""""""""""""""""""""""""""""""""""""""""" */ - if (*place != '\0') - optarg = place; - - /* If we're here, there's whitespace after the option. */ - /* */ - /* Is it a mandatory argument? If so, return the */ - /* next command-line argument if there is one. */ - /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ - else if (*oli == (char)optneed) - { - /* If we're at the end of the argument list, there */ - /* isn't an argument and hence we have an error. */ - /* Otherwise, make 'optarg' point to the argument. */ - /* """"""""""""""""""""""""""""""""""""""""""""""" */ - if (nargc <= ++optind) - { - place = EMSG; - TELL("Option requires an argument -- "); - } - else - optarg = nargv[optind]; - } - /* If we're here it must have been an optional argument. */ - /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ - else - { - if (nargc <= ++optind) - { - place = EMSG; - optarg = NULL; - } - else - { - optarg = nargv[optind]; - if (optarg == NULL) - place = EMSG; - - /* If the next item begins with a flag */ - /* character, we treat it like a new */ - /* argument. This is accomplished by */ - /* decrementing 'optind' and returning */ - /* a null argument. */ - /* """"""""""""""""""""""""""""""""""" */ - else if (strchr(optstart, *optarg) != NULL) - { - --optind; - optarg = NULL; - } - } - } - place = EMSG; - ++optind; - } - - /* Return option letter. */ - /* """"""""""""""""""""" */ - return (optopt); -} - /* =========================================================== */ /* Helper function to compare to delimiters for use by ll_find */ /* =========================================================== */ @@ -4864,14 +4640,20 @@ main(int argc, char * argv[]) if (optarg && *optarg != '-') custom_ini_file = xstrdup(optarg); else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'n': if (optarg && *optarg != '-') win.asked_max_lines = abs(atoi(optarg)); else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'd': @@ -4889,17 +4671,26 @@ main(int argc, char * argv[]) utf8_interpret(pre_selection_index, &langinfo); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 't': if (optarg != NULL) { if (sscanf(optarg, "%ld", &(win.max_cols)) != 1) + { TELL("Argument must be numeric -- "); + short_usage(); + } if (win.max_cols < 1) + { TELL("Argument must be at least 1 -- "); + short_usage(); + } } win.tab_mode = 1; @@ -4982,6 +4773,7 @@ main(int argc, char * argv[]) free(gutter); TELL("A multi columns gutter is not allowed -- "); + short_usage(); } offset += mblen; @@ -5006,7 +4798,10 @@ main(int argc, char * argv[]) utf8_interpret(message, &langinfo); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'r': @@ -5031,7 +4826,10 @@ main(int argc, char * argv[]) include_pattern = concat(include_pattern, "|(", optarg, ")", NULL); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'e': @@ -5048,7 +4846,10 @@ main(int argc, char * argv[]) exclude_pattern = concat(exclude_pattern, "|(", optarg, ")", NULL); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'C': @@ -5060,7 +4861,10 @@ main(int argc, char * argv[]) ll_append(cols_selector_list, xstrdup(optarg)); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'R': @@ -5073,7 +4877,10 @@ main(int argc, char * argv[]) win.max_cols = 0; } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'S': @@ -5091,7 +4898,10 @@ main(int argc, char * argv[]) ll_append(sed_list, sed_node); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'I': @@ -5109,7 +4919,10 @@ main(int argc, char * argv[]) ll_append(include_sed_list, sed_node); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'E': @@ -5127,7 +4940,10 @@ main(int argc, char * argv[]) ll_append(exclude_sed_list, sed_node); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case '1': @@ -5148,7 +4964,10 @@ main(int argc, char * argv[]) while (argv[optind] && *argv[optind] != '-') { if (count > 2) + { TELL("Too many arguments -- "); + short_usage(); + } /* Colors must respect the format: <fg color>/<bg color> */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ @@ -5165,14 +4984,20 @@ main(int argc, char * argv[]) win.special_attr[opt - '1'].italic = attr.italic; } else + { TELL("Bad optional color settings -- "); + short_usage(); + } optind++; count++; } } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'a': @@ -5211,56 +5036,60 @@ main(int argc, char * argv[]) int * flag; char * prefix; int prefix_len; - } attr_infos[] = { - { &win.exclude_attr, "The exclude attribute is already set -- ", - &exc_attr_set, "e:", 2 }, - { &win.include_attr, "The include attribute is already set -- ", - &inc_attr_set, "i:", 2 }, - { &win.cursor_attr, "The cursor attribute is already set -- ", - &cur_attr_set, "c:", 2 }, - { &win.bar_attr, "The scroll bar attribute is already set -- ", - &bar_attr_set, "b:", 2 }, - { &win.shift_attr, "The shift attribute is already set -- ", - &shift_attr_set, "s:", 2 }, - { &win.tag_attr, "The tag attribute is already set -- ", - &tag_attr_set, "t:", 2 }, - { &win.cursor_on_tag_attr, - "The cursor on tagged word attribute is already set -- ", - &cursor_on_tag_attr_set, "ct:", 3 }, - { &win.search_field_attr, - "The search field attribute is already set -- ", &sf_attr_set, - "sf:", 3 }, - { &win.search_text_attr, - "The search text attribute is already set -- ", &st_attr_set, - "st:", 3 }, - { &win.search_err_field_attr, - "The search with error field attribute is already set -- ", - &sf_attr_set, "sfe:", 4 }, - { &win.search_err_text_attr, - "The search text with error attribute is already set -- ", - &st_attr_set, "ste:", 4 }, - { &win.match_field_attr, - "The matching word field attribute is already set -- ", - &mf_attr_set, "mf:", 3 }, - { &win.match_text_attr, - "The matching word text attribute is already set -- ", - &mt_attr_set, "mt:", 3 }, - { &win.match_err_field_attr, - "The matching word with error field attribute is already set -- ", - &mf_attr_set, "mfe:", 4 }, - { &win.match_err_text_attr, - "The matching word with error text attribute is already set -- ", - &mt_attr_set, "mte:", 4 }, - { &win.daccess_attr, - "The direct access tag attribute is already set -- ", - &daccess_attr_set, "da:", 3 }, - { NULL, NULL, NULL, NULL, 0 } - }; + } attr_infos[] = + { { &win.exclude_attr, "The exclude attribute is already set -- ", + &exc_attr_set, "e:", 2 }, + { &win.include_attr, "The include attribute is already set -- ", + &inc_attr_set, "i:", 2 }, + { &win.cursor_attr, "The cursor attribute is already set -- ", + &cur_attr_set, "c:", 2 }, + { &win.bar_attr, "The scroll bar attribute is already set -- ", + &bar_attr_set, "b:", 2 }, + { &win.shift_attr, "The shift attribute is already set -- ", + &shift_attr_set, "s:", 2 }, + { &win.tag_attr, "The tag attribute is already set -- ", + &tag_attr_set, "t:", 2 }, + { &win.cursor_on_tag_attr, + "The cursor on tagged word attribute is already set -- ", + &cursor_on_tag_attr_set, "ct:", 3 }, + { &win.search_field_attr, + "The search field attribute is already set -- ", &sf_attr_set, + "sf:", 3 }, + { &win.search_text_attr, + "The search text attribute is already set -- ", &st_attr_set, + "st:", 3 }, + { &win.search_err_field_attr, + "The search with error field attribute is already set -- ", + &sf_attr_set, "sfe:", 4 }, + { &win.search_err_text_attr, + "The search text with error attribute is already set -- ", + &st_attr_set, "ste:", 4 }, + { &win.match_field_attr, + "The matching word field attribute is already set -- ", + &mf_attr_set, "mf:", 3 }, + { &win.match_text_attr, + "The matching word text attribute is already set -- ", + &mt_attr_set, "mt:", 3 }, + { &win.match_err_field_attr, + "The matching word with error field attribute is already set " + "-- ", + &mf_attr_set, "mfe:", 4 }, + { &win.match_err_text_attr, + "The matching word with error text attribute is already set " + "-- ", + &mt_attr_set, "mte:", 4 }, + { &win.daccess_attr, + "The direct access tag attribute is already set -- ", + &daccess_attr_set, "da:", 3 }, + { NULL, NULL, NULL, NULL, 0 } }; optind--; if (*argv[optind] == '-') + { TELL("A blank is required before the first sub-option -- "); + short_usage(); + } /* Parse the arguments arguments */ /* """"""""""""""""""""""""""""" */ @@ -5269,7 +5098,10 @@ main(int argc, char * argv[]) attr = init_attr; if (strlen(argv[optind]) < 3) + { TELL("Empty attribute value -- "); + short_usage(); + } i = 0; while (attr_infos[i].flag != NULL) @@ -5279,7 +5111,10 @@ main(int argc, char * argv[]) == 0) { if (*attr_infos[i].flag) + { TELL(attr_infos[i].msg); + short_usage(); + } attr_to_set = attr_infos[i].attr; *attr_infos[i].flag = 1; @@ -5290,7 +5125,10 @@ main(int argc, char * argv[]) i++; } if (attr_infos[i].flag == NULL) + { TELL("Bad attribute prefix -- "); + short_usage(); + } /* Attributes must respect the format: */ /* <fg color>/<bg color>,<styles> */ @@ -5308,13 +5146,19 @@ main(int argc, char * argv[]) attr_to_set->italic = attr.italic; } else + { TELL("Bad attribute settings -- "); + short_usage(); + } optind++; } } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'X': @@ -5336,10 +5180,16 @@ main(int argc, char * argv[]) optind++; } else + { TELL("Missing timeout word -- "); + short_usage(); + } } else + { TELL("Invalid timeout type -- "); + short_usage(); + } if (argv[optind] && *argv[optind] != '-') { @@ -5349,10 +5199,16 @@ main(int argc, char * argv[]) timeout.remain = timeout.initial_value; } else + { TELL("Invalid timeout delay -- "); + short_usage(); + } } else + { TELL("Missing timeout delay -- "); + short_usage(); + } optind++; } @@ -5369,7 +5225,10 @@ main(int argc, char * argv[]) utf8_interpret(first_word_pattern, &langinfo); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'Z': @@ -5379,7 +5238,10 @@ main(int argc, char * argv[]) utf8_interpret(last_word_pattern, &langinfo); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'W': @@ -5389,7 +5251,10 @@ main(int argc, char * argv[]) utf8_interpret(iws, &langinfo); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'L': @@ -5399,7 +5264,10 @@ main(int argc, char * argv[]) utf8_interpret(ils, &langinfo); } else + { TELL("Option requires an argument -- "); + short_usage(); + } break; case 'P': @@ -5429,12 +5297,18 @@ main(int argc, char * argv[]) optind--; if (*argv[optind] == '-') + { TELL("A blank is required before the first sub-option -- "); + short_usage(); + } while (argv[optind] && *argv[optind] != '-') { if (argv[optind][1] != ':') + { TELL("Bad format -- "); + short_usage(); + } switch (*(argv[optind])) { @@ -5445,15 +5319,21 @@ main(int argc, char * argv[]) utf8_interpret(daccess.left, &langinfo); if (utf8_strlen(daccess.left) != 1) + { TELL("Too many characters after l: -- "); + short_usage(); + } n = wcswidth((w = utf8_strtowcs(daccess.left)), 1); free(w); if (n > 1) + { TELL( "A multi columns character is not allowed " "after l: -- "); + short_usage(); + } break; case 'r': /* right char */ @@ -5463,15 +5343,21 @@ main(int argc, char * argv[]) utf8_interpret(daccess.right, &langinfo); if (utf8_strlen(daccess.right) != 1) + { TELL("Too many characters after r: -- "); + short_u |