=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/less/option.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- src/usr.bin/less/option.c 1996/09/21 05:39:43 1.1.1.1 +++ src/usr.bin/less/option.c 2003/04/13 18:21:21 1.1.1.2 @@ -1,27 +1,11 @@ /* - * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman - * All rights reserved. + * Copyright (C) 1984-2002 Mark Nudelman * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice in the documentation and/or other materials provided with - * the distribution. + * You may distribute under the terms of either the GNU General Public + * License or the Less License, as specified in the README file. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * For more information about less, or for information on how to + * contact the author, see the README file. */ @@ -37,7 +21,7 @@ #include "less.h" #include "option.h" -static struct option *pendopt; +static struct loption *pendopt; public int plusoption = FALSE; static char *propt(); @@ -55,36 +39,51 @@ scan_option(s) char *s; { - register struct option *o; - register int c; + register struct loption *o; + register int optc; + char *optname; + char *printopt; char *str; int set_default; + int lc; + int err; PARG parg; if (s == NULL) return; /* - * If we have a pending string-valued option, handle it now. + * If we have a pending option which requires an argument, + * handle it now. * This happens if the previous option was, for example, "-P" * without a following string. In that case, the current - * option is simply the string for the previous option. + * option is simply the argument for the previous option. */ if (pendopt != NULL) { - (*pendopt->ofunc)(INIT, s); + switch (pendopt->otype & OTYPE) + { + case STRING: + (*pendopt->ofunc)(INIT, s); + break; + case NUMBER: + printopt = propt(pendopt->oletter); + *(pendopt->ovar) = getnum(&s, printopt, (int*)NULL); + break; + } pendopt = NULL; return; } set_default = FALSE; + optname = NULL; while (*s != '\0') { /* * Check some special cases first. */ - switch (c = *s++) + switch (optc = *s++) { case ' ': case '\t': @@ -92,11 +91,20 @@ continue; case '-': /* + * "--" indicates an option name instead of a letter. + */ + if (*s == '-') + { + optname = ++s; + break; + } + /* * "-+" means set these options back to their defaults. * (They may have been set otherwise by previous * options.) */ - if (set_default = (*s == '+')) + set_default = (*s == '+'); + if (set_default) s++; continue; case '+': @@ -108,11 +116,11 @@ * EVERY input file. */ plusoption = TRUE; - if (*s == '+') - every_first_cmd = save(++s); + s = optstring(s, &str, propt('+'), NULL); + if (*str == '+') + every_first_cmd = save(++str); else - ungetsc(s); - s = optstring(s, c); + ungetsc(str); continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -122,7 +130,7 @@ * window size. */ s--; - c = 'z'; + optc = 'z'; break; } @@ -130,20 +138,62 @@ * Not a special case. * Look up the option letter in the option table. */ - o = findopt(c); + err = 0; + if (optname == NULL) + { + printopt = propt(optc); + lc = SIMPLE_IS_LOWER(optc); + o = findopt(optc); + } else + { + printopt = optname; + lc = SIMPLE_IS_LOWER(optname[0]); + o = findopt_name(&optname, NULL, &err); + s = optname; + optname = NULL; + if (*s == '\0' || *s == ' ') + { + /* + * The option name matches exactly. + */ + ; + } else if (*s == '=') + { + /* + * The option name is followed by "=value". + */ + if (o != NULL && + (o->otype & OTYPE) != STRING && + (o->otype & OTYPE) != NUMBER) + { + parg.p_string = printopt; + error("The %s option should not be followed by =", + &parg); + quit(QUIT_ERROR); + } + s++; + } else + { + /* + * The specified name is longer than the + * real option name. + */ + o = NULL; + } + } if (o == NULL) { - parg.p_string = propt(c); -#if MSOFTC || OS2 - error("There is no %s flag (\"less -?\" for help)", - &parg); -#else - error("There is no %s flag (\"less -\\?\" for help)", - &parg); -#endif + parg.p_string = printopt; + if (err == OPT_AMBIG) + error("%s is an ambiguous abbreviation (\"less --help\" for help)", + &parg); + else + error("There is no %s option (\"less --help\" for help)", + &parg); quit(QUIT_ERROR); } + str = NULL; switch (o->otype & OTYPE) { case BOOL: @@ -156,8 +206,7 @@ if (set_default) *(o->ovar) = o->odefault; else - *(o->ovar) = flip_triple(o->odefault, - (o->oletter == c)); + *(o->ovar) = flip_triple(o->odefault, lc); break; case STRING: if (*s == '\0') @@ -175,11 +224,17 @@ * All processing of STRING options is done by * the handling function. */ - str = s; - s = optstring(s, c); + while (*s == ' ') + s++; + s = optstring(s, &str, printopt, o->odesc[1]); break; case NUMBER: - *(o->ovar) = getnum(&s, c, (int*)NULL); + if (*s == '\0') + { + pendopt = o; + return; + } + *(o->ovar) = getnum(&s, printopt, (int*)NULL); break; } /* @@ -205,11 +260,15 @@ char *s; int how_toggle; { - register struct option *o; + register struct loption *o; register int num; + int no_prompt; int err; PARG parg; + no_prompt = (how_toggle & OPT_NO_PROMPT); + how_toggle &= ~OPT_NO_PROMPT; + /* * Look up the option letter in the option table. */ @@ -217,21 +276,21 @@ if (o == NULL) { parg.p_string = propt(c); - error("There is no %s flag", &parg); + error("There is no %s option", &parg); return; } if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE)) { parg.p_string = propt(c); - error("Cannot change the %s flag", &parg); + error("Cannot change the %s option", &parg); return; } if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY)) { parg.p_string = propt(c); - error("Cannot query the %s flag", &parg); + error("Cannot query the %s option", &parg); return; } @@ -291,14 +350,14 @@ { case OPT_TOGGLE: *(o->ovar) = flip_triple(*(o->ovar), - o->oletter == c); + islower(c)); break; case OPT_UNSET: *(o->ovar) = o->odefault; break; case OPT_SET: *(o->ovar) = flip_triple(o->odefault, - o->oletter == c); + islower(c)); break; } break; @@ -311,7 +370,7 @@ { case OPT_SET: case OPT_UNSET: - error("Can't use \"-+\" or \"--\" for a string flag", + error("Cannot use \"-+\" or \"--\" for a string option", NULL_PARG); return; } @@ -323,7 +382,7 @@ switch (how_toggle) { case OPT_TOGGLE: - num = getnum(&s, '\0', &err); + num = getnum(&s, NULL, &err); if (!err) *(o->ovar) = num; break; @@ -331,7 +390,7 @@ *(o->ovar) = o->odefault; break; case OPT_SET: - error("Can't use \"--\" for a numeric flag", + error("Can't use \"-!\" for a numeric option", NULL_PARG); return; } @@ -351,31 +410,34 @@ chg_hilite(); #endif - /* - * Print a message describing the new setting. - */ - switch (o->otype & OTYPE) + if (!no_prompt) { - case BOOL: - case TRIPLE: /* - * Print the odesc message. + * Print a message describing the new setting. */ - error(o->odesc[*(o->ovar)], NULL_PARG); - break; - case NUMBER: - /* - * The message is in odesc[1] and has a %d for - * the value of the variable. - */ - parg.p_int = *(o->ovar); - error(o->odesc[1], &parg); - break; - case STRING: - /* - * Message was already printed by the handling function. - */ - break; + switch (o->otype & OTYPE) + { + case BOOL: + case TRIPLE: + /* + * Print the odesc message. + */ + error(o->odesc[*(o->ovar)], NULL_PARG); + break; + case NUMBER: + /* + * The message is in odesc[1] and has a %d for + * the value of the variable. + */ + parg.p_int = *(o->ovar); + error(o->odesc[1], &parg); + break; + case STRING: + /* + * Message was already printed by the handling function. + */ + break; + } } if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT)) @@ -418,7 +480,7 @@ single_char_option(c) int c; { - register struct option *o; + register struct loption *o; o = findopt(c); if (o == NULL) @@ -434,7 +496,7 @@ opt_prompt(c) int c; { - register struct option *o; + register struct loption *o; o = findopt(c); if (o == NULL || (o->otype & (STRING|NUMBER)) == 0) @@ -459,12 +521,12 @@ * Print error message about missing string. */ static void -nostring(c) - int c; +nostring(printopt) + char *printopt; { PARG parg; - parg.p_string = propt(c); - error("String is required after %s", &parg); + parg.p_string = printopt; + error("Value is required after %s", &parg); } /* @@ -473,7 +535,7 @@ public void nopendopt() { - nostring(pendopt->oletter); + nostring(propt(pendopt->oletter)); } /* @@ -482,23 +544,42 @@ * Return a pointer to the remainder of the string, if any. */ static char * -optstring(s, c) +optstring(s, p_str, printopt, validchars) char *s; - int c; + char **p_str; + char *printopt; + char *validchars; { register char *p; if (*s == '\0') { - nostring(c); + nostring(printopt); quit(QUIT_ERROR); } + *p_str = s; for (p = s; *p != '\0'; p++) - if (*p == END_OPTION_STRING) + { + if (*p == END_OPTION_STRING || + (validchars != NULL && strchr(validchars, *p) == NULL)) { - *p = '\0'; - return (p+1); + switch (*p) + { + case END_OPTION_STRING: + case ' ': case '\t': case '-': + /* Replace the char with a null to terminate string. */ + *p++ = '\0'; + break; + default: + /* Cannot replace char; make a copy of the string. */ + *p_str = (char *) ecalloc(p-s+1, sizeof(char)); + strncpy(*p_str, s, p-s); + (*p_str)[p-s] = '\0'; + break; + } + break; } + } return (p); } @@ -508,9 +589,9 @@ * the char * to point after the translated number. */ public int -getnum(sp, c, errp) +getnum(sp, printopt, errp) char **sp; - int c; + char *printopt; int *errp; { register char *s; @@ -532,8 +613,11 @@ *errp = TRUE; return (-1); } - parg.p_string = propt(c); - error("Number is required after %s", &parg); + if (printopt != NULL) + { + parg.p_string = printopt; + error("Number is required after %s", &parg); + } quit(QUIT_ERROR); }