1a5f0fb15SPaul Saab /* 2*33096f16SXin LI * Copyright (C) 1984-2011 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 * 7a5f0fb15SPaul Saab * For more information about less, or for information on how to 8a5f0fb15SPaul Saab * contact the author, see the README file. 9a5f0fb15SPaul Saab */ 10a5f0fb15SPaul Saab 11a5f0fb15SPaul Saab 12a5f0fb15SPaul Saab /* 13a5f0fb15SPaul Saab * Process command line options. 14a5f0fb15SPaul Saab * 15a5f0fb15SPaul Saab * Each option is a single letter which controls a program variable. 16a5f0fb15SPaul Saab * The options have defaults which may be changed via 17a5f0fb15SPaul Saab * the command line option, toggled via the "-" command, 18a5f0fb15SPaul Saab * or queried via the "_" command. 19a5f0fb15SPaul Saab */ 20a5f0fb15SPaul Saab 21a5f0fb15SPaul Saab #include "less.h" 22a5f0fb15SPaul Saab #include "option.h" 23a5f0fb15SPaul Saab 24000ba3e8STim J. Robbins static struct loption *pendopt; 25a5f0fb15SPaul Saab public int plusoption = FALSE; 26a5f0fb15SPaul Saab 27a5f0fb15SPaul Saab static char *optstring(); 28a5f0fb15SPaul Saab static int flip_triple(); 29a5f0fb15SPaul Saab 30a5f0fb15SPaul Saab extern int screen_trashed; 317f074f9cSXin LI extern int less_is_more; 327f074f9cSXin LI extern int quit_at_eof; 33a5f0fb15SPaul Saab extern char *every_first_cmd; 34a5f0fb15SPaul Saab 35a5f0fb15SPaul Saab /* 36*33096f16SXin LI * Return a printable description of an option. 37*33096f16SXin LI */ 38*33096f16SXin LI static char * 39*33096f16SXin LI opt_desc(o) 40*33096f16SXin LI struct loption *o; 41*33096f16SXin LI { 42*33096f16SXin LI static char buf[OPTNAME_MAX + 10]; 43*33096f16SXin LI if (o->oletter == OLETTER_NONE) 44*33096f16SXin LI SNPRINTF1(buf, sizeof(buf), "--%s", o->onames->oname); 45*33096f16SXin LI else 46*33096f16SXin LI SNPRINTF2(buf, sizeof(buf), "-%c (--%s)", o->oletter, o->onames->oname); 47*33096f16SXin LI return (buf); 48*33096f16SXin LI } 49*33096f16SXin LI 50*33096f16SXin LI /* 51*33096f16SXin LI * Return a string suitable for printing as the "name" of an option. 52*33096f16SXin LI * For example, if the option letter is 'x', just return "-x". 53*33096f16SXin LI */ 54*33096f16SXin LI public char * 55*33096f16SXin LI propt(c) 56*33096f16SXin LI int c; 57*33096f16SXin LI { 58*33096f16SXin LI static char buf[8]; 59*33096f16SXin LI 60*33096f16SXin LI sprintf(buf, "-%s", prchar(c)); 61*33096f16SXin LI return (buf); 62*33096f16SXin LI } 63*33096f16SXin LI 64*33096f16SXin LI /* 65a5f0fb15SPaul Saab * Scan an argument (either from the command line or from the 66a5f0fb15SPaul Saab * LESS environment variable) and process it. 67a5f0fb15SPaul Saab */ 68a5f0fb15SPaul Saab public void 69a5f0fb15SPaul Saab scan_option(s) 70a5f0fb15SPaul Saab char *s; 71a5f0fb15SPaul Saab { 72000ba3e8STim J. Robbins register struct loption *o; 73a5f0fb15SPaul Saab register int optc; 74a5f0fb15SPaul Saab char *optname; 75a5f0fb15SPaul Saab char *printopt; 76a5f0fb15SPaul Saab char *str; 77a5f0fb15SPaul Saab int set_default; 78a5f0fb15SPaul Saab int lc; 79a5f0fb15SPaul Saab int err; 80a5f0fb15SPaul Saab PARG parg; 81a5f0fb15SPaul Saab 82a5f0fb15SPaul Saab if (s == NULL) 83a5f0fb15SPaul Saab return; 84a5f0fb15SPaul Saab 85a5f0fb15SPaul Saab /* 86a5f0fb15SPaul Saab * If we have a pending option which requires an argument, 87a5f0fb15SPaul Saab * handle it now. 88a5f0fb15SPaul Saab * This happens if the previous option was, for example, "-P" 89a5f0fb15SPaul Saab * without a following string. In that case, the current 90a5f0fb15SPaul Saab * option is simply the argument for the previous option. 91a5f0fb15SPaul Saab */ 92a5f0fb15SPaul Saab if (pendopt != NULL) 93a5f0fb15SPaul Saab { 94a5f0fb15SPaul Saab switch (pendopt->otype & OTYPE) 95a5f0fb15SPaul Saab { 96a5f0fb15SPaul Saab case STRING: 97a5f0fb15SPaul Saab (*pendopt->ofunc)(INIT, s); 98a5f0fb15SPaul Saab break; 99a5f0fb15SPaul Saab case NUMBER: 100*33096f16SXin LI printopt = opt_desc(pendopt); 101a5f0fb15SPaul Saab *(pendopt->ovar) = getnum(&s, printopt, (int*)NULL); 102a5f0fb15SPaul Saab break; 103a5f0fb15SPaul Saab } 104a5f0fb15SPaul Saab pendopt = NULL; 105a5f0fb15SPaul Saab return; 106a5f0fb15SPaul Saab } 107a5f0fb15SPaul Saab 108a5f0fb15SPaul Saab set_default = FALSE; 109a5f0fb15SPaul Saab optname = NULL; 110a5f0fb15SPaul Saab 111a5f0fb15SPaul Saab while (*s != '\0') 112a5f0fb15SPaul Saab { 113a5f0fb15SPaul Saab /* 114a5f0fb15SPaul Saab * Check some special cases first. 115a5f0fb15SPaul Saab */ 116a5f0fb15SPaul Saab switch (optc = *s++) 117a5f0fb15SPaul Saab { 118a5f0fb15SPaul Saab case ' ': 119a5f0fb15SPaul Saab case '\t': 120a5f0fb15SPaul Saab case END_OPTION_STRING: 121a5f0fb15SPaul Saab continue; 122a5f0fb15SPaul Saab case '-': 123a5f0fb15SPaul Saab /* 124a5f0fb15SPaul Saab * "--" indicates an option name instead of a letter. 125a5f0fb15SPaul Saab */ 126a5f0fb15SPaul Saab if (*s == '-') 127a5f0fb15SPaul Saab { 128a5f0fb15SPaul Saab optname = ++s; 129a5f0fb15SPaul Saab break; 130a5f0fb15SPaul Saab } 131a5f0fb15SPaul Saab /* 132a5f0fb15SPaul Saab * "-+" means set these options back to their defaults. 133a5f0fb15SPaul Saab * (They may have been set otherwise by previous 134a5f0fb15SPaul Saab * options.) 135a5f0fb15SPaul Saab */ 136a5f0fb15SPaul Saab set_default = (*s == '+'); 137a5f0fb15SPaul Saab if (set_default) 138a5f0fb15SPaul Saab s++; 139a5f0fb15SPaul Saab continue; 140a5f0fb15SPaul Saab case '+': 141a5f0fb15SPaul Saab /* 142a5f0fb15SPaul Saab * An option prefixed by a "+" is ungotten, so 143a5f0fb15SPaul Saab * that it is interpreted as less commands 144a5f0fb15SPaul Saab * processed at the start of the first input file. 145a5f0fb15SPaul Saab * "++" means process the commands at the start of 146a5f0fb15SPaul Saab * EVERY input file. 147a5f0fb15SPaul Saab */ 148a5f0fb15SPaul Saab plusoption = TRUE; 149000ba3e8STim J. Robbins s = optstring(s, &str, propt('+'), NULL); 150c9346414SPaul Saab if (*str == '+') 151c9346414SPaul Saab every_first_cmd = save(++str); 152a5f0fb15SPaul Saab else 153c9346414SPaul Saab ungetsc(str); 154a5f0fb15SPaul Saab continue; 155a5f0fb15SPaul Saab case '0': case '1': case '2': case '3': case '4': 156a5f0fb15SPaul Saab case '5': case '6': case '7': case '8': case '9': 157a5f0fb15SPaul Saab /* 158a5f0fb15SPaul Saab * Special "more" compatibility form "-<number>" 159a5f0fb15SPaul Saab * instead of -z<number> to set the scrolling 160a5f0fb15SPaul Saab * window size. 161a5f0fb15SPaul Saab */ 162a5f0fb15SPaul Saab s--; 163a5f0fb15SPaul Saab optc = 'z'; 164a5f0fb15SPaul Saab break; 1657f074f9cSXin LI case 'n': 1667f074f9cSXin LI if (less_is_more) 1677f074f9cSXin LI optc = 'z'; 1687f074f9cSXin LI break; 169a5f0fb15SPaul Saab } 170a5f0fb15SPaul Saab 171a5f0fb15SPaul Saab /* 172a5f0fb15SPaul Saab * Not a special case. 173a5f0fb15SPaul Saab * Look up the option letter in the option table. 174a5f0fb15SPaul Saab */ 175a5f0fb15SPaul Saab err = 0; 176a5f0fb15SPaul Saab if (optname == NULL) 177a5f0fb15SPaul Saab { 178a5f0fb15SPaul Saab printopt = propt(optc); 1796dcb072bSXin LI lc = ASCII_IS_LOWER(optc); 180a5f0fb15SPaul Saab o = findopt(optc); 181a5f0fb15SPaul Saab } else 182a5f0fb15SPaul Saab { 183a5f0fb15SPaul Saab printopt = optname; 1846dcb072bSXin LI lc = ASCII_IS_LOWER(optname[0]); 185a5f0fb15SPaul Saab o = findopt_name(&optname, NULL, &err); 186a5f0fb15SPaul Saab s = optname; 187a5f0fb15SPaul Saab optname = NULL; 188a5f0fb15SPaul Saab if (*s == '\0' || *s == ' ') 189a5f0fb15SPaul Saab { 190a5f0fb15SPaul Saab /* 191a5f0fb15SPaul Saab * The option name matches exactly. 192a5f0fb15SPaul Saab */ 193a5f0fb15SPaul Saab ; 194a5f0fb15SPaul Saab } else if (*s == '=') 195a5f0fb15SPaul Saab { 196a5f0fb15SPaul Saab /* 197a5f0fb15SPaul Saab * The option name is followed by "=value". 198a5f0fb15SPaul Saab */ 199a5f0fb15SPaul Saab if (o != NULL && 200a5f0fb15SPaul Saab (o->otype & OTYPE) != STRING && 201a5f0fb15SPaul Saab (o->otype & OTYPE) != NUMBER) 202a5f0fb15SPaul Saab { 203a5f0fb15SPaul Saab parg.p_string = printopt; 204a5f0fb15SPaul Saab error("The %s option should not be followed by =", 205a5f0fb15SPaul Saab &parg); 206a5f0fb15SPaul Saab quit(QUIT_ERROR); 207a5f0fb15SPaul Saab } 208a5f0fb15SPaul Saab s++; 209a5f0fb15SPaul Saab } else 210a5f0fb15SPaul Saab { 211a5f0fb15SPaul Saab /* 212a5f0fb15SPaul Saab * The specified name is longer than the 213a5f0fb15SPaul Saab * real option name. 214a5f0fb15SPaul Saab */ 215a5f0fb15SPaul Saab o = NULL; 216a5f0fb15SPaul Saab } 217a5f0fb15SPaul Saab } 218a5f0fb15SPaul Saab if (o == NULL) 219a5f0fb15SPaul Saab { 220a5f0fb15SPaul Saab parg.p_string = printopt; 221a5f0fb15SPaul Saab if (err == OPT_AMBIG) 222a5f0fb15SPaul Saab error("%s is an ambiguous abbreviation (\"less --help\" for help)", 223a5f0fb15SPaul Saab &parg); 224a5f0fb15SPaul Saab else 225a5f0fb15SPaul Saab error("There is no %s option (\"less --help\" for help)", 226a5f0fb15SPaul Saab &parg); 227a5f0fb15SPaul Saab quit(QUIT_ERROR); 228a5f0fb15SPaul Saab } 229a5f0fb15SPaul Saab 230a5f0fb15SPaul Saab str = NULL; 231a5f0fb15SPaul Saab switch (o->otype & OTYPE) 232a5f0fb15SPaul Saab { 233a5f0fb15SPaul Saab case BOOL: 234a5f0fb15SPaul Saab if (set_default) 235a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 236a5f0fb15SPaul Saab else 237a5f0fb15SPaul Saab *(o->ovar) = ! o->odefault; 238a5f0fb15SPaul Saab break; 239a5f0fb15SPaul Saab case TRIPLE: 240a5f0fb15SPaul Saab if (set_default) 241a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 242a5f0fb15SPaul Saab else 243a5f0fb15SPaul Saab *(o->ovar) = flip_triple(o->odefault, lc); 244a5f0fb15SPaul Saab break; 245a5f0fb15SPaul Saab case STRING: 246a5f0fb15SPaul Saab if (*s == '\0') 247a5f0fb15SPaul Saab { 248a5f0fb15SPaul Saab /* 249a5f0fb15SPaul Saab * Set pendopt and return. 250a5f0fb15SPaul Saab * We will get the string next time 251a5f0fb15SPaul Saab * scan_option is called. 252a5f0fb15SPaul Saab */ 253a5f0fb15SPaul Saab pendopt = o; 254a5f0fb15SPaul Saab return; 255a5f0fb15SPaul Saab } 256a5f0fb15SPaul Saab /* 257a5f0fb15SPaul Saab * Don't do anything here. 258a5f0fb15SPaul Saab * All processing of STRING options is done by 259a5f0fb15SPaul Saab * the handling function. 260a5f0fb15SPaul Saab */ 261000ba3e8STim J. Robbins while (*s == ' ') 262000ba3e8STim J. Robbins s++; 263000ba3e8STim J. Robbins s = optstring(s, &str, printopt, o->odesc[1]); 264a5f0fb15SPaul Saab break; 265a5f0fb15SPaul Saab case NUMBER: 266a5f0fb15SPaul Saab if (*s == '\0') 267a5f0fb15SPaul Saab { 268a5f0fb15SPaul Saab pendopt = o; 269a5f0fb15SPaul Saab return; 270a5f0fb15SPaul Saab } 271a5f0fb15SPaul Saab *(o->ovar) = getnum(&s, printopt, (int*)NULL); 272a5f0fb15SPaul Saab break; 273a5f0fb15SPaul Saab } 274a5f0fb15SPaul Saab /* 275a5f0fb15SPaul Saab * If the option has a handling function, call it. 276a5f0fb15SPaul Saab */ 277a5f0fb15SPaul Saab if (o->ofunc != NULL) 278a5f0fb15SPaul Saab (*o->ofunc)(INIT, str); 279a5f0fb15SPaul Saab } 280a5f0fb15SPaul Saab } 281a5f0fb15SPaul Saab 282a5f0fb15SPaul Saab /* 283a5f0fb15SPaul Saab * Toggle command line flags from within the program. 284a5f0fb15SPaul Saab * Used by the "-" and "_" commands. 285a5f0fb15SPaul Saab * how_toggle may be: 286a5f0fb15SPaul Saab * OPT_NO_TOGGLE just report the current setting, without changing it. 287a5f0fb15SPaul Saab * OPT_TOGGLE invert the current setting 288a5f0fb15SPaul Saab * OPT_UNSET set to the default value 289a5f0fb15SPaul Saab * OPT_SET set to the inverse of the default value 290a5f0fb15SPaul Saab */ 291a5f0fb15SPaul Saab public void 292*33096f16SXin LI toggle_option(o, lower, s, how_toggle) 293*33096f16SXin LI struct loption *o; 294*33096f16SXin LI int lower; 295a5f0fb15SPaul Saab char *s; 296a5f0fb15SPaul Saab int how_toggle; 297a5f0fb15SPaul Saab { 298a5f0fb15SPaul Saab register int num; 299a5f0fb15SPaul Saab int no_prompt; 300a5f0fb15SPaul Saab int err; 301a5f0fb15SPaul Saab PARG parg; 302a5f0fb15SPaul Saab 303a5f0fb15SPaul Saab no_prompt = (how_toggle & OPT_NO_PROMPT); 304a5f0fb15SPaul Saab how_toggle &= ~OPT_NO_PROMPT; 305a5f0fb15SPaul Saab 306a5f0fb15SPaul Saab if (o == NULL) 307a5f0fb15SPaul Saab { 308*33096f16SXin LI error("No such option", NULL_PARG); 309a5f0fb15SPaul Saab return; 310a5f0fb15SPaul Saab } 311a5f0fb15SPaul Saab 312a5f0fb15SPaul Saab if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE)) 313a5f0fb15SPaul Saab { 314*33096f16SXin LI parg.p_string = opt_desc(o); 315a5f0fb15SPaul Saab error("Cannot change the %s option", &parg); 316a5f0fb15SPaul Saab return; 317a5f0fb15SPaul Saab } 318a5f0fb15SPaul Saab 319a5f0fb15SPaul Saab if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY)) 320a5f0fb15SPaul Saab { 321*33096f16SXin LI parg.p_string = opt_desc(o); 322a5f0fb15SPaul Saab error("Cannot query the %s option", &parg); 323a5f0fb15SPaul Saab return; 324a5f0fb15SPaul Saab } 325a5f0fb15SPaul Saab 326a5f0fb15SPaul Saab /* 327a5f0fb15SPaul Saab * Check for something which appears to be a do_toggle 328a5f0fb15SPaul Saab * (because the "-" command was used), but really is not. 329a5f0fb15SPaul Saab * This could be a string option with no string, or 330a5f0fb15SPaul Saab * a number option with no number. 331a5f0fb15SPaul Saab */ 332a5f0fb15SPaul Saab switch (o->otype & OTYPE) 333a5f0fb15SPaul Saab { 334a5f0fb15SPaul Saab case STRING: 335a5f0fb15SPaul Saab case NUMBER: 336a5f0fb15SPaul Saab if (how_toggle == OPT_TOGGLE && *s == '\0') 337a5f0fb15SPaul Saab how_toggle = OPT_NO_TOGGLE; 338a5f0fb15SPaul Saab break; 339a5f0fb15SPaul Saab } 340a5f0fb15SPaul Saab 341a5f0fb15SPaul Saab #if HILITE_SEARCH 342a5f0fb15SPaul Saab if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT)) 343a5f0fb15SPaul Saab repaint_hilite(0); 344a5f0fb15SPaul Saab #endif 345a5f0fb15SPaul Saab 346a5f0fb15SPaul Saab /* 347a5f0fb15SPaul Saab * Now actually toggle (change) the variable. 348a5f0fb15SPaul Saab */ 349a5f0fb15SPaul Saab if (how_toggle != OPT_NO_TOGGLE) 350a5f0fb15SPaul Saab { 351a5f0fb15SPaul Saab switch (o->otype & OTYPE) 352a5f0fb15SPaul Saab { 353a5f0fb15SPaul Saab case BOOL: 354a5f0fb15SPaul Saab /* 355a5f0fb15SPaul Saab * Boolean. 356a5f0fb15SPaul Saab */ 357a5f0fb15SPaul Saab switch (how_toggle) 358a5f0fb15SPaul Saab { 359a5f0fb15SPaul Saab case OPT_TOGGLE: 360a5f0fb15SPaul Saab *(o->ovar) = ! *(o->ovar); 361a5f0fb15SPaul Saab break; 362a5f0fb15SPaul Saab case OPT_UNSET: 363a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 364a5f0fb15SPaul Saab break; 365a5f0fb15SPaul Saab case OPT_SET: 366a5f0fb15SPaul Saab *(o->ovar) = ! o->odefault; 367a5f0fb15SPaul Saab break; 368a5f0fb15SPaul Saab } 369a5f0fb15SPaul Saab break; 370a5f0fb15SPaul Saab case TRIPLE: 371a5f0fb15SPaul Saab /* 372a5f0fb15SPaul Saab * Triple: 373a5f0fb15SPaul Saab * If user gave the lower case letter, then switch 374a5f0fb15SPaul Saab * to 1 unless already 1, in which case make it 0. 375a5f0fb15SPaul Saab * If user gave the upper case letter, then switch 376a5f0fb15SPaul Saab * to 2 unless already 2, in which case make it 0. 377a5f0fb15SPaul Saab */ 378a5f0fb15SPaul Saab switch (how_toggle) 379a5f0fb15SPaul Saab { 380a5f0fb15SPaul Saab case OPT_TOGGLE: 381*33096f16SXin LI *(o->ovar) = flip_triple(*(o->ovar), lower); 382a5f0fb15SPaul Saab break; 383a5f0fb15SPaul Saab case OPT_UNSET: 384a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 385a5f0fb15SPaul Saab break; 386a5f0fb15SPaul Saab case OPT_SET: 387*33096f16SXin LI *(o->ovar) = flip_triple(o->odefault, lower); 388a5f0fb15SPaul Saab break; 389a5f0fb15SPaul Saab } 390a5f0fb15SPaul Saab break; 391a5f0fb15SPaul Saab case STRING: 392a5f0fb15SPaul Saab /* 393a5f0fb15SPaul Saab * String: don't do anything here. 394a5f0fb15SPaul Saab * The handling function will do everything. 395a5f0fb15SPaul Saab */ 396a5f0fb15SPaul Saab switch (how_toggle) 397a5f0fb15SPaul Saab { 398a5f0fb15SPaul Saab case OPT_SET: 399a5f0fb15SPaul Saab case OPT_UNSET: 400a5f0fb15SPaul Saab error("Cannot use \"-+\" or \"--\" for a string option", 401a5f0fb15SPaul Saab NULL_PARG); 402a5f0fb15SPaul Saab return; 403a5f0fb15SPaul Saab } 404a5f0fb15SPaul Saab break; 405a5f0fb15SPaul Saab case NUMBER: 406a5f0fb15SPaul Saab /* 407a5f0fb15SPaul Saab * Number: set the variable to the given number. 408a5f0fb15SPaul Saab */ 409a5f0fb15SPaul Saab switch (how_toggle) 410a5f0fb15SPaul Saab { 411a5f0fb15SPaul Saab case OPT_TOGGLE: 412000ba3e8STim J. Robbins num = getnum(&s, NULL, &err); 413a5f0fb15SPaul Saab if (!err) 414a5f0fb15SPaul Saab *(o->ovar) = num; 415a5f0fb15SPaul Saab break; 416a5f0fb15SPaul Saab case OPT_UNSET: 417a5f0fb15SPaul Saab *(o->ovar) = o->odefault; 418a5f0fb15SPaul Saab break; 419a5f0fb15SPaul Saab case OPT_SET: 420a5f0fb15SPaul Saab error("Can't use \"-!\" for a numeric option", 421a5f0fb15SPaul Saab NULL_PARG); 422a5f0fb15SPaul Saab return; 423a5f0fb15SPaul Saab } 424a5f0fb15SPaul Saab break; 425a5f0fb15SPaul Saab } 426a5f0fb15SPaul Saab } 427a5f0fb15SPaul Saab 428a5f0fb15SPaul Saab /* 429a5f0fb15SPaul Saab * Call the handling function for any special action 430a5f0fb15SPaul Saab * specific to this option. 431a5f0fb15SPaul Saab */ 432a5f0fb15SPaul Saab if (o->ofunc != NULL) 433a5f0fb15SPaul Saab (*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s); 434a5f0fb15SPaul Saab 435a5f0fb15SPaul Saab #if HILITE_SEARCH 436a5f0fb15SPaul Saab if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT)) 437a5f0fb15SPaul Saab chg_hilite(); 438a5f0fb15SPaul Saab #endif 439a5f0fb15SPaul Saab 440a5f0fb15SPaul Saab if (!no_prompt) 441a5f0fb15SPaul Saab { 442a5f0fb15SPaul Saab /* 443a5f0fb15SPaul Saab * Print a message describing the new setting. 444a5f0fb15SPaul Saab */ 445a5f0fb15SPaul Saab switch (o->otype & OTYPE) 446a5f0fb15SPaul Saab { 447a5f0fb15SPaul Saab case BOOL: 448a5f0fb15SPaul Saab case TRIPLE: 449a5f0fb15SPaul Saab /* 450a5f0fb15SPaul Saab * Print the odesc message. 451a5f0fb15SPaul Saab */ 452a5f0fb15SPaul Saab error(o->odesc[*(o->ovar)], NULL_PARG); 453a5f0fb15SPaul Saab break; 454a5f0fb15SPaul Saab case NUMBER: 455a5f0fb15SPaul Saab /* 456a5f0fb15SPaul Saab * The message is in odesc[1] and has a %d for 457a5f0fb15SPaul Saab * the value of the variable. 458a5f0fb15SPaul Saab */ 459a5f0fb15SPaul Saab parg.p_int = *(o->ovar); 460a5f0fb15SPaul Saab error(o->odesc[1], &parg); 461a5f0fb15SPaul Saab break; 462a5f0fb15SPaul Saab case STRING: 463a5f0fb15SPaul Saab /* 464a5f0fb15SPaul Saab * Message was already printed by the handling function. 465a5f0fb15SPaul Saab */ 466a5f0fb15SPaul Saab break; 467a5f0fb15SPaul Saab } 468a5f0fb15SPaul Saab } 469a5f0fb15SPaul Saab 470a5f0fb15SPaul Saab if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT)) 471a5f0fb15SPaul Saab screen_trashed = TRUE; 472a5f0fb15SPaul Saab } 473a5f0fb15SPaul Saab 474a5f0fb15SPaul Saab /* 475a5f0fb15SPaul Saab * "Toggle" a triple-valued option. 476a5f0fb15SPaul Saab */ 477a5f0fb15SPaul Saab static int 478a5f0fb15SPaul Saab flip_triple(val, lc) 479a5f0fb15SPaul Saab int val; 480a5f0fb15SPaul Saab int lc; 481a5f0fb15SPaul Saab { 482a5f0fb15SPaul Saab if (lc) 483a5f0fb15SPaul Saab return ((val == OPT_ON) ? OPT_OFF : OPT_ON); 484a5f0fb15SPaul Saab else 485a5f0fb15SPaul Saab return ((val == OPT_ONPLUS) ? OPT_OFF : OPT_ONPLUS); 486a5f0fb15SPaul Saab } 487a5f0fb15SPaul Saab 488a5f0fb15SPaul Saab /* 489*33096f16SXin LI * Determine if an option takes a parameter. 490a5f0fb15SPaul Saab */ 491a5f0fb15SPaul Saab public int 492*33096f16SXin LI opt_has_param(o) 493*33096f16SXin LI struct loption *o; 494a5f0fb15SPaul Saab { 495a5f0fb15SPaul Saab if (o == NULL) 496*33096f16SXin LI return (0); 497*33096f16SXin LI if (o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE)) 498*33096f16SXin LI return (0); 499*33096f16SXin LI return (1); 500a5f0fb15SPaul Saab } 501a5f0fb15SPaul Saab 502a5f0fb15SPaul Saab /* 503a5f0fb15SPaul Saab * Return the prompt to be used for a given option letter. 504a5f0fb15SPaul Saab * Only string and number valued options have prompts. 505a5f0fb15SPaul Saab */ 506a5f0fb15SPaul Saab public char * 507*33096f16SXin LI opt_prompt(o) 508*33096f16SXin LI struct loption *o; 509a5f0fb15SPaul Saab { 510a5f0fb15SPaul Saab if (o == NULL || (o->otype & (STRING|NUMBER)) == 0) 511*33096f16SXin LI return ("?"); 512a5f0fb15SPaul Saab return (o->odesc[0]); 513a5f0fb15SPaul Saab } 514a5f0fb15SPaul Saab 515a5f0fb15SPaul Saab /* 516a5f0fb15SPaul Saab * Return whether or not there is a string option pending; 517a5f0fb15SPaul Saab * that is, if the previous option was a string-valued option letter 518a5f0fb15SPaul Saab * (like -P) without a following string. 519a5f0fb15SPaul Saab * In that case, the current option is taken to be the string for 520a5f0fb15SPaul Saab * the previous option. 521a5f0fb15SPaul Saab */ 522a5f0fb15SPaul Saab public int 523a5f0fb15SPaul Saab isoptpending() 524a5f0fb15SPaul Saab { 525a5f0fb15SPaul Saab return (pendopt != NULL); 526a5f0fb15SPaul Saab } 527a5f0fb15SPaul Saab 528a5f0fb15SPaul Saab /* 529a5f0fb15SPaul Saab * Print error message about missing string. 530a5f0fb15SPaul Saab */ 531a5f0fb15SPaul Saab static void 532a5f0fb15SPaul Saab nostring(printopt) 533a5f0fb15SPaul Saab char *printopt; 534a5f0fb15SPaul Saab { 535a5f0fb15SPaul Saab PARG parg; 536a5f0fb15SPaul Saab parg.p_string = printopt; 537a5f0fb15SPaul Saab error("Value is required after %s", &parg); 538a5f0fb15SPaul Saab } 539a5f0fb15SPaul Saab 540a5f0fb15SPaul Saab /* 541a5f0fb15SPaul Saab * Print error message if a STRING type option is not followed by a string. 542a5f0fb15SPaul Saab */ 543a5f0fb15SPaul Saab public void 544a5f0fb15SPaul Saab nopendopt() 545a5f0fb15SPaul Saab { 546*33096f16SXin LI nostring(opt_desc(pendopt)); 547a5f0fb15SPaul Saab } 548a5f0fb15SPaul Saab 549a5f0fb15SPaul Saab /* 550a5f0fb15SPaul Saab * Scan to end of string or to an END_OPTION_STRING character. 551a5f0fb15SPaul Saab * In the latter case, replace the char with a null char. 552a5f0fb15SPaul Saab * Return a pointer to the remainder of the string, if any. 553a5f0fb15SPaul Saab */ 554a5f0fb15SPaul Saab static char * 555000ba3e8STim J. Robbins optstring(s, p_str, printopt, validchars) 556a5f0fb15SPaul Saab char *s; 557000ba3e8STim J. Robbins char **p_str; 558a5f0fb15SPaul Saab char *printopt; 559c9346414SPaul Saab char *validchars; 560a5f0fb15SPaul Saab { 561a5f0fb15SPaul Saab register char *p; 562a5f0fb15SPaul Saab 563a5f0fb15SPaul Saab if (*s == '\0') 564a5f0fb15SPaul Saab { 565a5f0fb15SPaul Saab nostring(printopt); 566a5f0fb15SPaul Saab quit(QUIT_ERROR); 567a5f0fb15SPaul Saab } 568000ba3e8STim J. Robbins *p_str = s; 569a5f0fb15SPaul Saab for (p = s; *p != '\0'; p++) 570000ba3e8STim J. Robbins { 571c9346414SPaul Saab if (*p == END_OPTION_STRING || 572c9346414SPaul Saab (validchars != NULL && strchr(validchars, *p) == NULL)) 573a5f0fb15SPaul Saab { 574c9346414SPaul Saab switch (*p) 575c9346414SPaul Saab { 576c9346414SPaul Saab case END_OPTION_STRING: 577c9346414SPaul Saab case ' ': case '\t': case '-': 578000ba3e8STim J. Robbins /* Replace the char with a null to terminate string. */ 579000ba3e8STim J. Robbins *p++ = '\0'; 580c9346414SPaul Saab break; 581c9346414SPaul Saab default: 582000ba3e8STim J. Robbins /* Cannot replace char; make a copy of the string. */ 583000ba3e8STim J. Robbins *p_str = (char *) ecalloc(p-s+1, sizeof(char)); 584000ba3e8STim J. Robbins strncpy(*p_str, s, p-s); 585000ba3e8STim J. Robbins (*p_str)[p-s] = '\0'; 586c9346414SPaul Saab break; 587c9346414SPaul Saab } 588000ba3e8STim J. Robbins break; 589000ba3e8STim J. Robbins } 590a5f0fb15SPaul Saab } 591a5f0fb15SPaul Saab return (p); 592a5f0fb15SPaul Saab } 593a5f0fb15SPaul Saab 594a5f0fb15SPaul Saab /* 5957f074f9cSXin LI */ 5967f074f9cSXin LI static int 5977f074f9cSXin LI num_error(printopt, errp) 5987f074f9cSXin LI char *printopt; 5997f074f9cSXin LI int *errp; 6007f074f9cSXin LI { 6017f074f9cSXin LI PARG parg; 6027f074f9cSXin LI 6037f074f9cSXin LI if (errp != NULL) 6047f074f9cSXin LI { 6057f074f9cSXin LI *errp = TRUE; 6067f074f9cSXin LI return (-1); 6077f074f9cSXin LI } 6087f074f9cSXin LI if (printopt != NULL) 6097f074f9cSXin LI { 6107f074f9cSXin LI parg.p_string = printopt; 6117f074f9cSXin LI error("Number is required after %s", &parg); 6127f074f9cSXin LI } 6137f074f9cSXin LI quit(QUIT_ERROR); 6147f074f9cSXin LI /* NOTREACHED */ 6157f074f9cSXin LI return (-1); 6167f074f9cSXin LI } 6177f074f9cSXin LI 6187f074f9cSXin LI /* 619a5f0fb15SPaul Saab * Translate a string into a number. 620a5f0fb15SPaul Saab * Like atoi(), but takes a pointer to a char *, and updates 621a5f0fb15SPaul Saab * the char * to point after the translated number. 622a5f0fb15SPaul Saab */ 623a5f0fb15SPaul Saab public int 624a5f0fb15SPaul Saab getnum(sp, printopt, errp) 625a5f0fb15SPaul Saab char **sp; 626a5f0fb15SPaul Saab char *printopt; 627a5f0fb15SPaul Saab int *errp; 628a5f0fb15SPaul Saab { 629a5f0fb15SPaul Saab register char *s; 630a5f0fb15SPaul Saab register int n; 631a5f0fb15SPaul Saab register int neg; 632a5f0fb15SPaul Saab 633a5f0fb15SPaul Saab s = skipsp(*sp); 634a5f0fb15SPaul Saab neg = FALSE; 635a5f0fb15SPaul Saab if (*s == '-') 636a5f0fb15SPaul Saab { 637a5f0fb15SPaul Saab neg = TRUE; 638a5f0fb15SPaul Saab s++; 639a5f0fb15SPaul Saab } 640a5f0fb15SPaul Saab if (*s < '0' || *s > '9') 6417f074f9cSXin LI return (num_error(printopt, errp)); 642a5f0fb15SPaul Saab 643a5f0fb15SPaul Saab n = 0; 644a5f0fb15SPaul Saab while (*s >= '0' && *s <= '9') 645a5f0fb15SPaul Saab n = 10 * n + *s++ - '0'; 646a5f0fb15SPaul Saab *sp = s; 647a5f0fb15SPaul Saab if (errp != NULL) 648a5f0fb15SPaul Saab *errp = FALSE; 649a5f0fb15SPaul Saab if (neg) 650a5f0fb15SPaul Saab n = -n; 651a5f0fb15SPaul Saab return (n); 652a5f0fb15SPaul Saab } 6537f074f9cSXin LI 6547f074f9cSXin LI /* 6557f074f9cSXin LI * Translate a string into a fraction, represented by the part of a 6567f074f9cSXin LI * number which would follow a decimal point. 6577f074f9cSXin LI * The value of the fraction is returned as parts per NUM_FRAC_DENOM. 6587f074f9cSXin LI * That is, if "n" is returned, the fraction intended is n/NUM_FRAC_DENOM. 6597f074f9cSXin LI */ 6607f074f9cSXin LI public long 6617f074f9cSXin LI getfraction(sp, printopt, errp) 6627f074f9cSXin LI char **sp; 6637f074f9cSXin LI char *printopt; 6647f074f9cSXin LI int *errp; 6657f074f9cSXin LI { 6667f074f9cSXin LI register char *s; 6677f074f9cSXin LI long frac = 0; 6687f074f9cSXin LI int fraclen = 0; 6697f074f9cSXin LI 6707f074f9cSXin LI s = skipsp(*sp); 6717f074f9cSXin LI if (*s < '0' || *s > '9') 6727f074f9cSXin LI return (num_error(printopt, errp)); 6737f074f9cSXin LI 6747f074f9cSXin LI for ( ; *s >= '0' && *s <= '9'; s++) 6757f074f9cSXin LI { 6767f074f9cSXin LI frac = (frac * 10) + (*s - '0'); 6777f074f9cSXin LI fraclen++; 6787f074f9cSXin LI } 6797f074f9cSXin LI if (fraclen > NUM_LOG_FRAC_DENOM) 6807f074f9cSXin LI while (fraclen-- > NUM_LOG_FRAC_DENOM) 6817f074f9cSXin LI frac /= 10; 6827f074f9cSXin LI else 6837f074f9cSXin LI while (fraclen++ < NUM_LOG_FRAC_DENOM) 6847f074f9cSXin LI frac *= 10; 6857f074f9cSXin LI *sp = s; 6867f074f9cSXin LI if (errp != NULL) 6877f074f9cSXin LI *errp = FALSE; 6887f074f9cSXin LI return (frac); 6897f074f9cSXin LI } 6907f074f9cSXin LI 6917f074f9cSXin LI 6927f074f9cSXin LI /* 6937f074f9cSXin LI * Get the value of the -e flag. 6947f074f9cSXin LI */ 6957f074f9cSXin LI public int 6967f074f9cSXin LI get_quit_at_eof() 6977f074f9cSXin LI { 6987f074f9cSXin LI if (!less_is_more) 6997f074f9cSXin LI return quit_at_eof; 7007f074f9cSXin LI /* When less_is_more is set, the -e flag semantics are different. */ 7017f074f9cSXin LI return quit_at_eof ? OPT_ON : OPT_ONPLUS; 7027f074f9cSXin LI } 703