1a5f0fb15SPaul Saab /* 2*d713e089SXin LI * Copyright (C) 1984-2023 Mark Nudelman 3a5f0fb15SPaul Saab * 4a5f0fb15SPaul Saab * You may distribute under the terms of either the GNU General Public 5a5f0fb15SPaul Saab * License or the Less License, as specified in the README file. 6a5f0fb15SPaul Saab * 796e55cc7SXin LI * For more information, see the README file. 8a5f0fb15SPaul Saab */ 9a5f0fb15SPaul Saab 10a5f0fb15SPaul Saab 11a5f0fb15SPaul Saab /* 12a5f0fb15SPaul Saab * Process command line options. 13a5f0fb15SPaul Saab * 14a5f0fb15SPaul Saab * Each option is a single letter which controls a program variable. 15a5f0fb15SPaul Saab * The options have defaults which may be changed via 16a5f0fb15SPaul Saab * the command line option, toggled via the "-" command, 17a5f0fb15SPaul Saab * or queried via the "_" command. 18a5f0fb15SPaul Saab */ 19a5f0fb15SPaul Saab 20a5f0fb15SPaul Saab #include "less.h" 21a5f0fb15SPaul Saab #include "option.h" 22a5f0fb15SPaul Saab 23000ba3e8STim J. Robbins static struct loption *pendopt; 24a5f0fb15SPaul Saab public int plusoption = FALSE; 25a5f0fb15SPaul Saab 26*d713e089SXin LI static char *optstring(char *s, char **p_str, char *printopt, char *validchars); 27*d713e089SXin LI static int flip_triple(int val, int lc); 28a5f0fb15SPaul Saab 29a5f0fb15SPaul Saab extern int screen_trashed; 307f074f9cSXin LI extern int less_is_more; 317f074f9cSXin LI extern int quit_at_eof; 32a5f0fb15SPaul Saab extern char *every_first_cmd; 337bd2567cSXin LI extern int opt_use_backslash; 34a5f0fb15SPaul Saab 35a5f0fb15SPaul Saab /* 3633096f16SXin LI * Return a printable description of an option. 3733096f16SXin LI */ 38*d713e089SXin LI static char * opt_desc(struct loption *o) 3933096f16SXin LI { 4033096f16SXin LI static char buf[OPTNAME_MAX + 10]; 4133096f16SXin LI if (o->oletter == OLETTER_NONE) 4233096f16SXin LI SNPRINTF1(buf, sizeof(buf), "--%s", o->onames->oname); 4333096f16SXin LI else 4433096f16SXin LI SNPRINTF2(buf, sizeof(buf), "-%c (--%s)", o->oletter, o->onames->oname); 4533096f16SXin LI return (buf); 4633096f16SXin LI } 4733096f16SXin LI 4833096f16SXin LI /* 4933096f16SXin LI * Return a string suitable for printing as the "name" of an option. 5033096f16SXin LI * For example, if the option letter is 'x', just return "-x". 5133096f16SXin LI */ 52*d713e089SXin LI public char * propt(int c) 5333096f16SXin LI { 5495270f73SXin LI static char buf[MAX_PRCHAR_LEN+2]; 5533096f16SXin LI 5633096f16SXin LI sprintf(buf, "-%s", prchar(c)); 5733096f16SXin LI return (buf); 5833096f16SXin LI } 5933096f16SXin LI 6033096f16SXin LI /* 61a5f0fb15SPaul Saab * Scan an argument (either from the command line or from the 62a5f0fb15SPaul Saab * LESS environment variable) and process it. 63a5f0fb15SPaul Saab */ 64*d713e089SXin LI public void scan_option(char *s) 65a5f0fb15SPaul Saab { 661ea31627SRobert Watson struct loption *o; 671ea31627SRobert Watson int optc; 68a5f0fb15SPaul Saab char *optname; 69a5f0fb15SPaul Saab char *printopt; 70a5f0fb15SPaul Saab char *str; 71a5f0fb15SPaul Saab int set_default; 72a5f0fb15SPaul Saab int lc; 73a5f0fb15SPaul Saab int err; 74a5f0fb15SPaul Saab PARG parg; 75a5f0fb15SPaul Saab 76a5f0fb15SPaul Saab if (s == NULL) 77a5f0fb15SPaul Saab return; 78a5f0fb15SPaul Saab 79a5f0fb15SPaul Saab /* 80a5f0fb15SPaul Saab * If we have a pending option which requires an argument, 81a5f0fb15SPaul Saab * handle it now. 82a5f0fb15SPaul Saab * This happens if the previous option was, for example, "-P" 83a5f0fb15SPaul Saab * without a following string. In that case, the current 84a5f0fb15SPaul Saab * option is simply the argument for the previous option. 85a5f0fb15SPaul Saab */ 86a5f0fb15SPaul Saab if (pendopt != NULL) 87a5f0fb15SPaul Saab { 88a5f0fb15SPaul Saab switch (pendopt->otype & OTYPE) 89a5f0fb15SPaul Saab { 90a5f0fb15SPaul Saab case STRING: 91a5f0fb15SPaul Saab (*pendopt->ofunc)(INIT, s); 92a5f0fb15SPaul Saab break; 93a5f0fb15SPaul Saab case NUMBER: 9433096f16SXin LI printopt = opt_desc(pendopt); 95a5f0fb15SPaul Saab *(pendopt->ovar) = getnum(&s, printopt, (int*)NULL); 96a5f0fb15SPaul Saab break; 97a5f0fb15SPaul Saab } 98a5f0fb15SPaul Saab pendopt = NULL; 99a5f0fb15SPaul Saab return; 100a5f0fb15SPaul Saab } 101a5f0fb15SPaul Saab 102a5f0fb15SPaul Saab set_default = FALSE; 103a5f0fb15SPaul Saab optname = NULL; 104a5f0fb15SPaul Saab 105a5f0fb15SPaul Saab while (*s != '\0') 106a5f0fb15SPaul Saab { 107a5f0fb15SPaul Saab /* 108a5f0fb15SPaul Saab * Check some special cases first. 109a5f0fb15SPaul Saab */ 110a5f0fb15SPaul Saab switch (optc = *s++) 111a5f0fb15SPaul Saab { 112a5f0fb15SPaul Saab case ' ': 113a5f0fb15SPaul Saab case '\t': 114a5f0fb15SPaul Saab case END_OPTION_STRING: 115a5f0fb15SPaul Saab continue; 116a5f0fb15SPaul Saab case '-': 117a5f0fb15SPaul Saab /* 118a5f0fb15SPaul Saab * "--" indicates an option name instead of a letter. 119a5f0fb15SPaul Saab */ 120a5f0fb15SPaul Saab if (*s == '-') 121a5f0fb15SPaul Saab { 122a5f0fb15SPaul Saab optname = ++s; 123a5f0fb15SPaul Saab break; 124a5f0fb15SPaul Saab } 125a5f0fb15SPaul Saab /* 126a5f0fb15SPaul Saab * "-+" means set these options back to their defaults. 127a5f0fb15SPaul Saab * (They may have been set otherwise by previous 128a5f0fb15SPaul Saab * options.) 129a5f0fb15SPaul Saab */ 130a5f0fb15SPaul Saab set_default = (*s == '+'); 131a5f0fb15SPaul Saab if (set_default) 132a5f0fb15SPaul Saab s++; 133a5f0fb15SPaul Saab continue; 134a5f0fb15SPaul Saab case '+': 135a5f0fb15SPaul Saab /* 136a5f0fb15SPaul Saab * An option prefixed by a "+" is ungotten, so 137a5f0fb15SPaul Saab * that it is interpreted as less commands 138a5f0fb15SPaul Saab * processed at the start of the first input file. 139a5f0fb15SPaul Saab * "++" means process the commands at the start of 140a5f0fb15SPaul Saab * EVERY input file. 141a5f0fb15SPaul Saab */ 142a5f0fb15SPaul Saab plusoption = TRUE; 143000ba3e8STim J. Robbins s = optstring(s, &str, propt('+'), NULL); 1444cc5fc9aSXin LI if (s == NULL) 1454cc5fc9aSXin LI return; 146c9346414SPaul Saab if (*str == '+') 147b7780dbeSXin LI { 148b7780dbeSXin LI if (every_first_cmd != NULL) 149b7780dbeSXin LI free(every_first_cmd); 15021fa6541SXin LI every_first_cmd = save(str+1); 151b7780dbeSXin LI } else 152a15691bfSXin LI { 153c9346414SPaul Saab ungetsc(str); 1542235c7feSXin LI ungetcc_back(CHAR_END_COMMAND); 155a15691bfSXin LI } 1564cc5fc9aSXin LI free(str); 157a5f0fb15SPaul Saab continue; 158a5f0fb15SPaul Saab case '0': case '1': case '2': case '3': case '4': 159a5f0fb15SPaul Saab case '5': case '6': case '7': case '8': case '9': 160a5f0fb15SPaul Saab /* 161a5f0fb15SPaul Saab * Special "more" compatibility form "-<number>" 162a5f0fb15SPaul Saab * instead of -z<number> to set the scrolling 163a5f0fb15SPaul Saab * window size. 164a5f0fb15SPaul Saab */ 165a5f0fb15SPaul Saab s--; 166a5f0fb15SPaul Saab optc = 'z'; 167a5f0fb15SPaul Saab break; 1687f074f9cSXin LI case 'n': 1697f074f9cSXin LI if (less_is_more) 1707f074f9cSXin LI optc = 'z'; 1717f074f9cSXin LI break; 172a5f0fb15SPaul Saab } 173a5f0fb15SPaul Saab 174a5f0fb15SPaul Saab /* 175a5f0fb15SPaul Saab * Not a special case. 176a5f0fb15SPaul Saab * Look up the option letter in the option table. 177a5f0fb15SPaul Saab */ 178a5f0fb15SPaul Saab err = 0; 179a5f0fb15SPaul Saab if (optname == NULL) 180a5f0fb15SPaul Saab { 181a5f0fb15SPaul Saab printopt = propt(optc); 1826dcb072bSXin LI lc = ASCII_IS_LOWER(optc); 183a5f0fb15SPaul Saab o = findopt(optc); 184a5f0fb15SPaul Saab } else 185a5f0fb15SPaul Saab { 186a5f0fb15SPaul Saab printopt = optname; 1876dcb072bSXin LI lc = ASCII_IS_LOWER(optname[0]); 188a5f0fb15SPaul Saab o = findopt_name(&optname, NULL, &err); 189a5f0fb15SPaul Saab s = optname; 190a5f0fb15SPaul Saab optname = NULL; 191a5f0fb15SPaul Saab if (*s == '\0' || *s == ' ') 192a5f0fb15SPaul Saab { 193a5f0fb15SPaul Saab /* 194a5f0fb15SPaul Saab * The option name matches exactly. 195a5f0fb15SPaul Saab */ 196a5f0fb15SPaul Saab ; 197a5f0fb15SPaul Saab } else if (*s == '=') 198a5f0fb15SPaul Saab { 199a5f0fb15SPaul Saab /* 200a5f0fb15SPaul Saab * The option name is followed by "=value". 201a5f0fb15SPaul Saab */ 202a5f0fb15SPaul Saab if (o != NULL && 203a5f0fb15SPaul Saab (o->otype & OTYPE) != STRING && 204a5f0fb15SPaul Saab (o->otype & OTYPE) != NUMBER) 205a5f0fb15SPaul Saab { 206a5f0fb15SPaul Saab parg.p_string = printopt; 207a5f0fb15SPaul Saab error("The %s option should not be followed by =", 208a5f0fb15SPaul Saab &parg); 2094cc5fc9aSXin LI return; 210a5f0fb15SPaul Saab } 211a5f0fb15SPaul Saab s++; 212a5f0fb15SPaul Saab } else 213a5f0fb15SPaul Saab { 214a5f0fb15SPaul Saab /* 215a5f0fb15SPaul Saab * The specified name is longer than the 216a5f0fb15SPaul Saab * real option name. 217a5f0fb15SPaul Saab */ 218a5f0fb15SPaul Saab o = NULL; 219a5f0fb15SPaul Saab } 220a5f0fb15SPaul Saab } 221a5f0fb15SPaul Saab if (o == NULL) 222a5f0fb15SPaul Saab { 223a5f0fb15SPaul Saab parg.p_string = printopt; 224a5f0fb15SPaul Saab if (err == OPT_AMBIG) 225a5f0fb15SPaul Saab error("%s is an ambiguous abbreviation (\"less --help\" for help)", 226a5f0fb15SPaul Saab &parg); 227a5f0fb15SPaul Saab else 228a5f0fb15SPaul Saab error("There is no %s option (\"less --help\" for help)", 229a5f0fb15SPaul Saab &parg); 2304cc5fc9aSXin LI return; 231a5f0fb15SPaul Saab } 232a5f0fb15SPaul Saab 233a5f0fb15SPaul Saab str = NULL; 234a5f0fb15SPaul Saab switch (o->otype & OTYPE) 235a5f0fb15SPaul Saab { 236a5f0fb15SPaul Saab case BOOL: 237a5f0fb15SPaul Saab if (set_default) 238a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 239a5f0fb15SPaul Saab else 240a5f0fb15SPaul Saab *(o->ovar) = ! o->odefault; 241a5f0fb15SPaul Saab break; 242a5f0fb15SPaul Saab case TRIPLE: 243a5f0fb15SPaul Saab if (set_default) 244a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 245a5f0fb15SPaul Saab else 246a5f0fb15SPaul Saab *(o->ovar) = flip_triple(o->odefault, lc); 247a5f0fb15SPaul Saab break; 248a5f0fb15SPaul Saab case STRING: 249a5f0fb15SPaul Saab if (*s == '\0') 250a5f0fb15SPaul Saab { 251a5f0fb15SPaul Saab /* 252a5f0fb15SPaul Saab * Set pendopt and return. 253a5f0fb15SPaul Saab * We will get the string next time 254a5f0fb15SPaul Saab * scan_option is called. 255a5f0fb15SPaul Saab */ 256a5f0fb15SPaul Saab pendopt = o; 257a5f0fb15SPaul Saab return; 258a5f0fb15SPaul Saab } 259a5f0fb15SPaul Saab /* 260a5f0fb15SPaul Saab * Don't do anything here. 261a5f0fb15SPaul Saab * All processing of STRING options is done by 262a5f0fb15SPaul Saab * the handling function. 263a5f0fb15SPaul Saab */ 264000ba3e8STim J. Robbins while (*s == ' ') 265000ba3e8STim J. Robbins s++; 266000ba3e8STim J. Robbins s = optstring(s, &str, printopt, o->odesc[1]); 2674cc5fc9aSXin LI if (s == NULL) 2684cc5fc9aSXin LI return; 269a5f0fb15SPaul Saab break; 270a5f0fb15SPaul Saab case NUMBER: 271a5f0fb15SPaul Saab if (*s == '\0') 272a5f0fb15SPaul Saab { 273a5f0fb15SPaul Saab pendopt = o; 274a5f0fb15SPaul Saab return; 275a5f0fb15SPaul Saab } 276a5f0fb15SPaul Saab *(o->ovar) = getnum(&s, printopt, (int*)NULL); 277a5f0fb15SPaul Saab break; 278a5f0fb15SPaul Saab } 279a5f0fb15SPaul Saab /* 280a5f0fb15SPaul Saab * If the option has a handling function, call it. 281a5f0fb15SPaul Saab */ 282a5f0fb15SPaul Saab if (o->ofunc != NULL) 283a5f0fb15SPaul Saab (*o->ofunc)(INIT, str); 2844cc5fc9aSXin LI if (str != NULL) 2854cc5fc9aSXin LI free(str); 286a5f0fb15SPaul Saab } 287a5f0fb15SPaul Saab } 288a5f0fb15SPaul Saab 289a5f0fb15SPaul Saab /* 290a5f0fb15SPaul Saab * Toggle command line flags from within the program. 291a5f0fb15SPaul Saab * Used by the "-" and "_" commands. 292a5f0fb15SPaul Saab * how_toggle may be: 293a5f0fb15SPaul Saab * OPT_NO_TOGGLE just report the current setting, without changing it. 294a5f0fb15SPaul Saab * OPT_TOGGLE invert the current setting 295a5f0fb15SPaul Saab * OPT_UNSET set to the default value 296a5f0fb15SPaul Saab * OPT_SET set to the inverse of the default value 297a5f0fb15SPaul Saab */ 298*d713e089SXin LI public void toggle_option(struct loption *o, int lower, char *s, int how_toggle) 299a5f0fb15SPaul Saab { 3001ea31627SRobert Watson int num; 301a5f0fb15SPaul Saab int no_prompt; 302a5f0fb15SPaul Saab int err; 303a5f0fb15SPaul Saab PARG parg; 304a5f0fb15SPaul Saab 305a5f0fb15SPaul Saab no_prompt = (how_toggle & OPT_NO_PROMPT); 306a5f0fb15SPaul Saab how_toggle &= ~OPT_NO_PROMPT; 307a5f0fb15SPaul Saab 308a5f0fb15SPaul Saab if (o == NULL) 309a5f0fb15SPaul Saab { 31033096f16SXin LI error("No such option", NULL_PARG); 311a5f0fb15SPaul Saab return; 312a5f0fb15SPaul Saab } 313a5f0fb15SPaul Saab 314a5f0fb15SPaul Saab if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE)) 315a5f0fb15SPaul Saab { 31633096f16SXin LI parg.p_string = opt_desc(o); 317a5f0fb15SPaul Saab error("Cannot change the %s option", &parg); 318a5f0fb15SPaul Saab return; 319a5f0fb15SPaul Saab } 320a5f0fb15SPaul Saab 321a5f0fb15SPaul Saab if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY)) 322a5f0fb15SPaul Saab { 32333096f16SXin LI parg.p_string = opt_desc(o); 324a5f0fb15SPaul Saab error("Cannot query the %s option", &parg); 325a5f0fb15SPaul Saab return; 326a5f0fb15SPaul Saab } 327a5f0fb15SPaul Saab 328a5f0fb15SPaul Saab /* 329a5f0fb15SPaul Saab * Check for something which appears to be a do_toggle 330a5f0fb15SPaul Saab * (because the "-" command was used), but really is not. 331a5f0fb15SPaul Saab * This could be a string option with no string, or 332a5f0fb15SPaul Saab * a number option with no number. 333a5f0fb15SPaul Saab */ 334a5f0fb15SPaul Saab switch (o->otype & OTYPE) 335a5f0fb15SPaul Saab { 336a5f0fb15SPaul Saab case STRING: 337a5f0fb15SPaul Saab case NUMBER: 338a5f0fb15SPaul Saab if (how_toggle == OPT_TOGGLE && *s == '\0') 339a5f0fb15SPaul Saab how_toggle = OPT_NO_TOGGLE; 340a5f0fb15SPaul Saab break; 341a5f0fb15SPaul Saab } 342a5f0fb15SPaul Saab 343a5f0fb15SPaul Saab #if HILITE_SEARCH 344a5f0fb15SPaul Saab if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT)) 345a5f0fb15SPaul Saab repaint_hilite(0); 346a5f0fb15SPaul Saab #endif 347a5f0fb15SPaul Saab 348a5f0fb15SPaul Saab /* 349a5f0fb15SPaul Saab * Now actually toggle (change) the variable. 350a5f0fb15SPaul Saab */ 351a5f0fb15SPaul Saab if (how_toggle != OPT_NO_TOGGLE) 352a5f0fb15SPaul Saab { 353a5f0fb15SPaul Saab switch (o->otype & OTYPE) 354a5f0fb15SPaul Saab { 355a5f0fb15SPaul Saab case BOOL: 356a5f0fb15SPaul Saab /* 357a5f0fb15SPaul Saab * Boolean. 358a5f0fb15SPaul Saab */ 359a5f0fb15SPaul Saab switch (how_toggle) 360a5f0fb15SPaul Saab { 361a5f0fb15SPaul Saab case OPT_TOGGLE: 362a5f0fb15SPaul Saab *(o->ovar) = ! *(o->ovar); 363a5f0fb15SPaul Saab break; 364a5f0fb15SPaul Saab case OPT_UNSET: 365a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 366a5f0fb15SPaul Saab break; 367a5f0fb15SPaul Saab case OPT_SET: 368a5f0fb15SPaul Saab *(o->ovar) = ! o->odefault; 369a5f0fb15SPaul Saab break; 370a5f0fb15SPaul Saab } 371a5f0fb15SPaul Saab break; 372a5f0fb15SPaul Saab case TRIPLE: 373a5f0fb15SPaul Saab /* 374a5f0fb15SPaul Saab * Triple: 375a5f0fb15SPaul Saab * If user gave the lower case letter, then switch 376a5f0fb15SPaul Saab * to 1 unless already 1, in which case make it 0. 377a5f0fb15SPaul Saab * If user gave the upper case letter, then switch 378a5f0fb15SPaul Saab * to 2 unless already 2, in which case make it 0. 379a5f0fb15SPaul Saab */ 380a5f0fb15SPaul Saab switch (how_toggle) 381a5f0fb15SPaul Saab { 382a5f0fb15SPaul Saab case OPT_TOGGLE: 38333096f16SXin LI *(o->ovar) = flip_triple(*(o->ovar), lower); 384a5f0fb15SPaul Saab break; 385a5f0fb15SPaul Saab case OPT_UNSET: 386a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 387a5f0fb15SPaul Saab break; 388a5f0fb15SPaul Saab case OPT_SET: 38933096f16SXin LI *(o->ovar) = flip_triple(o->odefault, lower); 390a5f0fb15SPaul Saab break; 391a5f0fb15SPaul Saab } 392a5f0fb15SPaul Saab break; 393a5f0fb15SPaul Saab case STRING: 394a5f0fb15SPaul Saab /* 395a5f0fb15SPaul Saab * String: don't do anything here. 396a5f0fb15SPaul Saab * The handling function will do everything. 397a5f0fb15SPaul Saab */ 398a5f0fb15SPaul Saab switch (how_toggle) 399a5f0fb15SPaul Saab { 400a5f0fb15SPaul Saab case OPT_SET: 401a5f0fb15SPaul Saab case OPT_UNSET: 402a5f0fb15SPaul Saab error("Cannot use \"-+\" or \"--\" for a string option", 403a5f0fb15SPaul Saab NULL_PARG); 404a5f0fb15SPaul Saab return; 405a5f0fb15SPaul Saab } 406a5f0fb15SPaul Saab break; 407a5f0fb15SPaul Saab case NUMBER: 408a5f0fb15SPaul Saab /* 409a5f0fb15SPaul Saab * Number: set the variable to the given number. 410a5f0fb15SPaul Saab */ 411a5f0fb15SPaul Saab switch (how_toggle) 412a5f0fb15SPaul Saab { 413a5f0fb15SPaul Saab case OPT_TOGGLE: 414000ba3e8STim J. Robbins num = getnum(&s, NULL, &err); 415a5f0fb15SPaul Saab if (!err) 416a5f0fb15SPaul Saab *(o->ovar) = num; 417a5f0fb15SPaul Saab break; 418a5f0fb15SPaul Saab case OPT_UNSET: 419a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 420a5f0fb15SPaul Saab break; 421a5f0fb15SPaul Saab case OPT_SET: 422a5f0fb15SPaul Saab error("Can't use \"-!\" for a numeric option", 423a5f0fb15SPaul Saab NULL_PARG); 424a5f0fb15SPaul Saab return; 425a5f0fb15SPaul Saab } 426a5f0fb15SPaul Saab break; 427a5f0fb15SPaul Saab } 428a5f0fb15SPaul Saab } 429a5f0fb15SPaul Saab 430a5f0fb15SPaul Saab /* 431a5f0fb15SPaul Saab * Call the handling function for any special action 432a5f0fb15SPaul Saab * specific to this option. 433a5f0fb15SPaul Saab */ 434a5f0fb15SPaul Saab if (o->ofunc != NULL) 435a5f0fb15SPaul Saab (*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s); 436a5f0fb15SPaul Saab 437a5f0fb15SPaul Saab #if HILITE_SEARCH 438a5f0fb15SPaul Saab if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT)) 439a5f0fb15SPaul Saab chg_hilite(); 440a5f0fb15SPaul Saab #endif 441a5f0fb15SPaul Saab 442a5f0fb15SPaul Saab if (!no_prompt) 443a5f0fb15SPaul Saab { 444a5f0fb15SPaul Saab /* 445a5f0fb15SPaul Saab * Print a message describing the new setting. 446a5f0fb15SPaul Saab */ 447a5f0fb15SPaul Saab switch (o->otype & OTYPE) 448a5f0fb15SPaul Saab { 449a5f0fb15SPaul Saab case BOOL: 450a5f0fb15SPaul Saab case TRIPLE: 451a5f0fb15SPaul Saab /* 452a5f0fb15SPaul Saab * Print the odesc message. 453a5f0fb15SPaul Saab */ 454a5f0fb15SPaul Saab error(o->odesc[*(o->ovar)], NULL_PARG); 455a5f0fb15SPaul Saab break; 456a5f0fb15SPaul Saab case NUMBER: 457a5f0fb15SPaul Saab /* 458a5f0fb15SPaul Saab * The message is in odesc[1] and has a %d for 459a5f0fb15SPaul Saab * the value of the variable. 460a5f0fb15SPaul Saab */ 461a5f0fb15SPaul Saab parg.p_int = *(o->ovar); 462a5f0fb15SPaul Saab error(o->odesc[1], &parg); 463a5f0fb15SPaul Saab break; 464a5f0fb15SPaul Saab case STRING: 465a5f0fb15SPaul Saab /* 466a5f0fb15SPaul Saab * Message was already printed by the handling function. 467a5f0fb15SPaul Saab */ 468a5f0fb15SPaul Saab break; 469a5f0fb15SPaul Saab } 470a5f0fb15SPaul Saab } 471a5f0fb15SPaul Saab 472a5f0fb15SPaul Saab if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT)) 473a5f0fb15SPaul Saab screen_trashed = TRUE; 474a5f0fb15SPaul Saab } 475a5f0fb15SPaul Saab 476a5f0fb15SPaul Saab /* 477a5f0fb15SPaul Saab * "Toggle" a triple-valued option. 478a5f0fb15SPaul Saab */ 479*d713e089SXin LI static int flip_triple(int val, int lc) 480a5f0fb15SPaul Saab { 481a5f0fb15SPaul Saab if (lc) 482a5f0fb15SPaul Saab return ((val == OPT_ON) ? OPT_OFF : OPT_ON); 483a5f0fb15SPaul Saab else 484a5f0fb15SPaul Saab return ((val == OPT_ONPLUS) ? OPT_OFF : OPT_ONPLUS); 485a5f0fb15SPaul Saab } 486a5f0fb15SPaul Saab 487a5f0fb15SPaul Saab /* 48833096f16SXin LI * Determine if an option takes a parameter. 489a5f0fb15SPaul Saab */ 490*d713e089SXin LI public int opt_has_param(struct loption *o) 491a5f0fb15SPaul Saab { 492a5f0fb15SPaul Saab if (o == NULL) 49333096f16SXin LI return (0); 49433096f16SXin LI if (o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE)) 49533096f16SXin LI return (0); 49633096f16SXin LI return (1); 497a5f0fb15SPaul Saab } 498a5f0fb15SPaul Saab 499a5f0fb15SPaul Saab /* 500a5f0fb15SPaul Saab * Return the prompt to be used for a given option letter. 501a5f0fb15SPaul Saab * Only string and number valued options have prompts. 502a5f0fb15SPaul Saab */ 503*d713e089SXin LI public char * opt_prompt(struct loption *o) 504a5f0fb15SPaul Saab { 505a5f0fb15SPaul Saab if (o == NULL || (o->otype & (STRING|NUMBER)) == 0) 50633096f16SXin LI return ("?"); 507a5f0fb15SPaul Saab return (o->odesc[0]); 508a5f0fb15SPaul Saab } 509a5f0fb15SPaul Saab 510a5f0fb15SPaul Saab /* 5116f26c71dSXin LI * If the specified option can be toggled, return NULL. 5126f26c71dSXin LI * Otherwise return an appropriate error message. 5136f26c71dSXin LI */ 514*d713e089SXin LI public char * opt_toggle_disallowed(int c) 5156f26c71dSXin LI { 5166f26c71dSXin LI switch (c) 5176f26c71dSXin LI { 5186f26c71dSXin LI case 'o': 5196f26c71dSXin LI if (ch_getflags() & CH_CANSEEK) 5206f26c71dSXin LI return "Input is not a pipe"; 5216f26c71dSXin LI break; 5226f26c71dSXin LI } 5236f26c71dSXin LI return NULL; 5246f26c71dSXin LI } 5256f26c71dSXin LI 5266f26c71dSXin LI /* 527a5f0fb15SPaul Saab * Return whether or not there is a string option pending; 528a5f0fb15SPaul Saab * that is, if the previous option was a string-valued option letter 529a5f0fb15SPaul Saab * (like -P) without a following string. 530a5f0fb15SPaul Saab * In that case, the current option is taken to be the string for 531a5f0fb15SPaul Saab * the previous option. 532a5f0fb15SPaul Saab */ 533*d713e089SXin LI public int isoptpending(void) 534a5f0fb15SPaul Saab { 535a5f0fb15SPaul Saab return (pendopt != NULL); 536a5f0fb15SPaul Saab } 537a5f0fb15SPaul Saab 538a5f0fb15SPaul Saab /* 539a5f0fb15SPaul Saab * Print error message about missing string. 540a5f0fb15SPaul Saab */ 541*d713e089SXin LI static void nostring(char *printopt) 542a5f0fb15SPaul Saab { 543a5f0fb15SPaul Saab PARG parg; 544a5f0fb15SPaul Saab parg.p_string = printopt; 545a5f0fb15SPaul Saab error("Value is required after %s", &parg); 546a5f0fb15SPaul Saab } 547a5f0fb15SPaul Saab 548a5f0fb15SPaul Saab /* 549a5f0fb15SPaul Saab * Print error message if a STRING type option is not followed by a string. 550a5f0fb15SPaul Saab */ 551*d713e089SXin LI public void nopendopt(void) 552a5f0fb15SPaul Saab { 55333096f16SXin LI nostring(opt_desc(pendopt)); 554a5f0fb15SPaul Saab } 555a5f0fb15SPaul Saab 556a5f0fb15SPaul Saab /* 557a5f0fb15SPaul Saab * Scan to end of string or to an END_OPTION_STRING character. 558a5f0fb15SPaul Saab * In the latter case, replace the char with a null char. 559a5f0fb15SPaul Saab * Return a pointer to the remainder of the string, if any. 560a5f0fb15SPaul Saab */ 561*d713e089SXin LI static char * optstring(char *s, char **p_str, char *printopt, char *validchars) 562a5f0fb15SPaul Saab { 5631ea31627SRobert Watson char *p; 5641ea31627SRobert Watson char *out; 565a5f0fb15SPaul Saab 566a5f0fb15SPaul Saab if (*s == '\0') 567a5f0fb15SPaul Saab { 568a5f0fb15SPaul Saab nostring(printopt); 5694cc5fc9aSXin LI return (NULL); 570a5f0fb15SPaul Saab } 5714cc5fc9aSXin LI /* Alloc could be more than needed, but not worth trimming. */ 5724cc5fc9aSXin LI *p_str = (char *) ecalloc(strlen(s)+1, sizeof(char)); 5734cc5fc9aSXin LI out = *p_str; 5744cc5fc9aSXin LI 575a5f0fb15SPaul Saab for (p = s; *p != '\0'; p++) 576000ba3e8STim J. Robbins { 5777bd2567cSXin LI if (opt_use_backslash && *p == '\\' && p[1] != '\0') 5784cc5fc9aSXin LI { 5794cc5fc9aSXin LI /* Take next char literally. */ 5804cc5fc9aSXin LI ++p; 5814cc5fc9aSXin LI } else 5824cc5fc9aSXin LI { 583c9346414SPaul Saab if (*p == END_OPTION_STRING || 584c9346414SPaul Saab (validchars != NULL && strchr(validchars, *p) == NULL)) 5854cc5fc9aSXin LI /* End of option string. */ 586c9346414SPaul Saab break; 587c9346414SPaul Saab } 5884cc5fc9aSXin LI *out++ = *p; 589000ba3e8STim J. Robbins } 5904cc5fc9aSXin LI *out = '\0'; 591a5f0fb15SPaul Saab return (p); 592a5f0fb15SPaul Saab } 593a5f0fb15SPaul Saab 594a5f0fb15SPaul Saab /* 5957f074f9cSXin LI */ 596*d713e089SXin LI static int num_error(char *printopt, int *errp, int overflow) 5977f074f9cSXin LI { 5987f074f9cSXin LI PARG parg; 5997f074f9cSXin LI 6007f074f9cSXin LI if (errp != NULL) 6017f074f9cSXin LI { 6027f074f9cSXin LI *errp = TRUE; 6037f074f9cSXin LI return (-1); 6047f074f9cSXin LI } 6057f074f9cSXin LI if (printopt != NULL) 6067f074f9cSXin LI { 6077f074f9cSXin LI parg.p_string = printopt; 608*d713e089SXin LI error((overflow 609*d713e089SXin LI ? "Number too large in '%s'" 610*d713e089SXin LI : "Number is required after %s"), 611*d713e089SXin LI &parg); 6127f074f9cSXin LI } 6137f074f9cSXin LI return (-1); 6147f074f9cSXin LI } 6157f074f9cSXin LI 6167f074f9cSXin LI /* 617a5f0fb15SPaul Saab * Translate a string into a number. 618a5f0fb15SPaul Saab * Like atoi(), but takes a pointer to a char *, and updates 619a5f0fb15SPaul Saab * the char * to point after the translated number. 620a5f0fb15SPaul Saab */ 621*d713e089SXin LI public int getnum(char **sp, char *printopt, int *errp) 622a5f0fb15SPaul Saab { 6231ea31627SRobert Watson char *s; 6241ea31627SRobert Watson int n; 6251ea31627SRobert Watson int neg; 626a5f0fb15SPaul Saab 627a5f0fb15SPaul Saab s = skipsp(*sp); 628a5f0fb15SPaul Saab neg = FALSE; 629a5f0fb15SPaul Saab if (*s == '-') 630a5f0fb15SPaul Saab { 631a5f0fb15SPaul Saab neg = TRUE; 632a5f0fb15SPaul Saab s++; 633a5f0fb15SPaul Saab } 634a5f0fb15SPaul Saab if (*s < '0' || *s > '9') 635*d713e089SXin LI return (num_error(printopt, errp, FALSE)); 636a5f0fb15SPaul Saab 637*d713e089SXin LI n = lstrtoi(s, sp, 10); 638*d713e089SXin LI if (n < 0) 639*d713e089SXin LI return (num_error(printopt, errp, TRUE)); 640a5f0fb15SPaul Saab if (errp != NULL) 641a5f0fb15SPaul Saab *errp = FALSE; 642a5f0fb15SPaul Saab if (neg) 643a5f0fb15SPaul Saab n = -n; 644a5f0fb15SPaul Saab return (n); 645a5f0fb15SPaul Saab } 6467f074f9cSXin LI 6477f074f9cSXin LI /* 6487f074f9cSXin LI * Translate a string into a fraction, represented by the part of a 6497f074f9cSXin LI * number which would follow a decimal point. 6507f074f9cSXin LI * The value of the fraction is returned as parts per NUM_FRAC_DENOM. 6517f074f9cSXin LI * That is, if "n" is returned, the fraction intended is n/NUM_FRAC_DENOM. 6527f074f9cSXin LI */ 653*d713e089SXin LI public long getfraction(char **sp, char *printopt, int *errp) 6547f074f9cSXin LI { 6551ea31627SRobert Watson char *s; 6567f074f9cSXin LI long frac = 0; 6577f074f9cSXin LI int fraclen = 0; 6587f074f9cSXin LI 6597f074f9cSXin LI s = skipsp(*sp); 6607f074f9cSXin LI if (*s < '0' || *s > '9') 661*d713e089SXin LI return (num_error(printopt, errp, FALSE)); 6627f074f9cSXin LI 6637f074f9cSXin LI for ( ; *s >= '0' && *s <= '9'; s++) 6647f074f9cSXin LI { 665*d713e089SXin LI if (NUM_LOG_FRAC_DENOM <= fraclen) 666*d713e089SXin LI continue; 6677f074f9cSXin LI frac = (frac * 10) + (*s - '0'); 6687f074f9cSXin LI fraclen++; 6697f074f9cSXin LI } 6707f074f9cSXin LI while (fraclen++ < NUM_LOG_FRAC_DENOM) 6717f074f9cSXin LI frac *= 10; 6727f074f9cSXin LI *sp = s; 6737f074f9cSXin LI if (errp != NULL) 6747f074f9cSXin LI *errp = FALSE; 6757f074f9cSXin LI return (frac); 6767f074f9cSXin LI } 6777f074f9cSXin LI 6787f074f9cSXin LI 6797f074f9cSXin LI /* 6807f074f9cSXin LI * Get the value of the -e flag. 6817f074f9cSXin LI */ 682*d713e089SXin LI public int get_quit_at_eof(void) 6837f074f9cSXin LI { 6847f074f9cSXin LI if (!less_is_more) 6857f074f9cSXin LI return quit_at_eof; 6867f074f9cSXin LI /* When less_is_more is set, the -e flag semantics are different. */ 687a15691bfSXin LI return quit_at_eof ? OPT_ONPLUS : OPT_ON; 6887f074f9cSXin LI } 689