option.c revision 238730
1168404Spjd/* 2168404Spjd * Copyright (C) 1984-2012 Mark Nudelman 3168404Spjd * 4168404Spjd * You may distribute under the terms of either the GNU General Public 5168404Spjd * License or the Less License, as specified in the README file. 6168404Spjd * 7168404Spjd * For more information, see the README file. 8168404Spjd */ 9168404Spjd 10168404Spjd 11168404Spjd/* 12168404Spjd * Process command line options. 13168404Spjd * 14168404Spjd * Each option is a single letter which controls a program variable. 15168404Spjd * The options have defaults which may be changed via 16168404Spjd * the command line option, toggled via the "-" command, 17168404Spjd * or queried via the "_" command. 18168404Spjd */ 19168404Spjd 20168404Spjd#include "less.h" 21168404Spjd#include "option.h" 22168404Spjd 23219089Spjdstatic struct loption *pendopt; 24227497Smmpublic int plusoption = FALSE; 25236155Smm 26236145Smmstatic char *optstring(); 27236155Smmstatic int flip_triple(); 28254758Sdelphij 29168404Spjdextern int screen_trashed; 30168404Spjdextern int less_is_more; 31168404Spjdextern int quit_at_eof; 32168404Spjdextern char *every_first_cmd; 33168404Spjd 34168404Spjd/* 35168404Spjd * Return a printable description of an option. 36168404Spjd */ 37168404Spjd static char * 38168404Spjdopt_desc(o) 39168404Spjd struct loption *o; 40168404Spjd{ 41168404Spjd static char buf[OPTNAME_MAX + 10]; 42168404Spjd if (o->oletter == OLETTER_NONE) 43168404Spjd SNPRINTF1(buf, sizeof(buf), "--%s", o->onames->oname); 44168404Spjd else 45168404Spjd SNPRINTF2(buf, sizeof(buf), "-%c (--%s)", o->oletter, o->onames->oname); 46168404Spjd return (buf); 47185029Spjd} 48185029Spjd 49168404Spjd/* 50236155Smm * Return a string suitable for printing as the "name" of an option. 51168404Spjd * For example, if the option letter is 'x', just return "-x". 52168404Spjd */ 53168404Spjd public char * 54168404Spjdpropt(c) 55168404Spjd int c; 56168404Spjd{ 57185029Spjd static char buf[8]; 58236884Smm 59168404Spjd sprintf(buf, "-%s", prchar(c)); 60219089Spjd return (buf); 61219089Spjd} 62168404Spjd 63168404Spjd/* 64168404Spjd * Scan an argument (either from the command line or from the 65168404Spjd * LESS environment variable) and process it. 66168404Spjd */ 67224171Sgibbs public void 68168404Spjdscan_option(s) 69168404Spjd char *s; 70168404Spjd{ 71168404Spjd register struct loption *o; 72168404Spjd register int optc; 73168404Spjd char *optname; 74168404Spjd char *printopt; 75168404Spjd char *str; 76236155Smm int set_default; 77168404Spjd int lc; 78228103Smm int err; 79228103Smm PARG parg; 80168404Spjd 81168404Spjd if (s == NULL) 82168404Spjd return; 83219089Spjd 84168404Spjd /* 85168404Spjd * If we have a pending option which requires an argument, 86168404Spjd * handle it now. 87168404Spjd * This happens if the previous option was, for example, "-P" 88168404Spjd * without a following string. In that case, the current 89168404Spjd * option is simply the argument for the previous option. 90168404Spjd */ 91168404Spjd if (pendopt != NULL) 92168404Spjd { 93168404Spjd switch (pendopt->otype & OTYPE) 94168404Spjd { 95168404Spjd case STRING: 96168404Spjd (*pendopt->ofunc)(INIT, s); 97168404Spjd break; 98168404Spjd case NUMBER: 99168404Spjd printopt = opt_desc(pendopt); 100168404Spjd *(pendopt->ovar) = getnum(&s, printopt, (int*)NULL); 101185029Spjd break; 102185029Spjd } 103168404Spjd pendopt = NULL; 104168404Spjd return; 105168404Spjd } 106168404Spjd 107168404Spjd set_default = FALSE; 108168404Spjd optname = NULL; 109168404Spjd 110168404Spjd while (*s != '\0') 111168404Spjd { 112168404Spjd /* 113168404Spjd * Check some special cases first. 114185029Spjd */ 115168404Spjd switch (optc = *s++) 116168404Spjd { 117168404Spjd case ' ': 118168404Spjd case '\t': 119168404Spjd case END_OPTION_STRING: 120168404Spjd continue; 121168404Spjd case '-': 122168404Spjd /* 123168404Spjd * "--" indicates an option name instead of a letter. 124168404Spjd */ 125168404Spjd if (*s == '-') 126168404Spjd { 127224171Sgibbs optname = ++s; 128168404Spjd break; 129168404Spjd } 130168404Spjd /* 131168404Spjd * "-+" means set these options back to their defaults. 132168404Spjd * (They may have been set otherwise by previous 133168404Spjd * options.) 134168404Spjd */ 135168404Spjd set_default = (*s == '+'); 136168404Spjd if (set_default) 137219089Spjd s++; 138228103Smm continue; 139236155Smm case '+': 140236155Smm /* 141168404Spjd * An option prefixed by a "+" is ungotten, so 142168404Spjd * that it is interpreted as less commands 143168404Spjd * processed at the start of the first input file. 144168404Spjd * "++" means process the commands at the start of 145168404Spjd * EVERY input file. 146168404Spjd */ 147168404Spjd plusoption = TRUE; 148168404Spjd s = optstring(s, &str, propt('+'), NULL); 149168404Spjd if (*str == '+') 150168404Spjd every_first_cmd = save(++str); 151168404Spjd else 152168404Spjd ungetsc(str); 153168404Spjd continue; 154168404Spjd case '0': case '1': case '2': case '3': case '4': 155168404Spjd case '5': case '6': case '7': case '8': case '9': 156168404Spjd /* 157168404Spjd * Special "more" compatibility form "-<number>" 158168404Spjd * instead of -z<number> to set the scrolling 159168404Spjd * window size. 160168404Spjd */ 161168404Spjd s--; 162168404Spjd optc = 'z'; 163168404Spjd break; 164168404Spjd case 'n': 165168404Spjd if (less_is_more) 166224171Sgibbs optc = 'z'; 167224171Sgibbs break; 168168404Spjd } 169168404Spjd 170168404Spjd /* 171168404Spjd * Not a special case. 172168404Spjd * Look up the option letter in the option table. 173168404Spjd */ 174168404Spjd err = 0; 175236155Smm if (optname == NULL) 176168404Spjd { 177168404Spjd printopt = propt(optc); 178168404Spjd lc = ASCII_IS_LOWER(optc); 179168404Spjd o = findopt(optc); 180219089Spjd } else 181168404Spjd { 182168404Spjd printopt = optname; 183168404Spjd lc = ASCII_IS_LOWER(optname[0]); 184168404Spjd o = findopt_name(&optname, NULL, &err); 185168404Spjd s = optname; 186168404Spjd optname = NULL; 187228103Smm if (*s == '\0' || *s == ' ') 188168404Spjd { 189168404Spjd /* 190168404Spjd * The option name matches exactly. 191168404Spjd */ 192168404Spjd ; 193168404Spjd } else if (*s == '=') 194168404Spjd { 195168404Spjd /* 196248571Smm * The option name is followed by "=value". 197185029Spjd */ 198248571Smm if (o != NULL && 199219089Spjd (o->otype & OTYPE) != STRING && 200219089Spjd (o->otype & OTYPE) != NUMBER) 201168404Spjd { 202168404Spjd parg.p_string = printopt; 203168404Spjd error("The %s option should not be followed by =", 204168404Spjd &parg); 205168404Spjd quit(QUIT_ERROR); 206168404Spjd } 207168404Spjd s++; 208185029Spjd } else 209168404Spjd { 210219089Spjd /* 211168404Spjd * The specified name is longer than the 212236884Smm * real option name. 213185029Spjd */ 214185029Spjd o = NULL; 215168404Spjd } 216168404Spjd } 217168404Spjd if (o == NULL) 218168404Spjd { 219168404Spjd parg.p_string = printopt; 220168404Spjd if (err == OPT_AMBIG) 221168404Spjd error("%s is an ambiguous abbreviation (\"less --help\" for help)", 222185029Spjd &parg); 223168404Spjd else 224168404Spjd error("There is no %s option (\"less --help\" for help)", 225219089Spjd &parg); 226185029Spjd quit(QUIT_ERROR); 227219089Spjd } 228219089Spjd 229185029Spjd str = NULL; 230219089Spjd switch (o->otype & OTYPE) 231219089Spjd { 232219089Spjd case BOOL: 233168404Spjd if (set_default) 234219089Spjd *(o->ovar) = o->odefault; 235168404Spjd else 236224171Sgibbs *(o->ovar) = ! o->odefault; 237224171Sgibbs break; 238168404Spjd case TRIPLE: 239236960Smm if (set_default) 240219089Spjd *(o->ovar) = o->odefault; 241168404Spjd else 242168404Spjd *(o->ovar) = flip_triple(o->odefault, lc); 243168404Spjd break; 244228020Smm case STRING: 245168404Spjd if (*s == '\0') 246168404Spjd { 247185029Spjd /* 248168404Spjd * Set pendopt and return. 249185029Spjd * We will get the string next time 250236155Smm * scan_option is called. 251236155Smm */ 252168404Spjd pendopt = o; 253168404Spjd return; 254168404Spjd } 255219089Spjd /* 256219089Spjd * Don't do anything here. 257168404Spjd * All processing of STRING options is done by 258228020Smm * the handling function. 259185029Spjd */ 260168404Spjd while (*s == ' ') 261185029Spjd s++; 262168404Spjd s = optstring(s, &str, printopt, o->odesc[1]); 263168404Spjd break; 264168404Spjd case NUMBER: 265219089Spjd if (*s == '\0') 266219089Spjd { 267219089Spjd pendopt = o; 268219089Spjd return; 269228103Smm } 270228103Smm *(o->ovar) = getnum(&s, printopt, (int*)NULL); 271168404Spjd break; 272168404Spjd } 273168404Spjd /* 274168404Spjd * If the option has a handling function, call it. 275168404Spjd */ 276168404Spjd if (o->ofunc != NULL) 277168404Spjd (*o->ofunc)(INIT, str); 278168404Spjd } 279168404Spjd} 280168404Spjd 281185029Spjd/* 282185029Spjd * Toggle command line flags from within the program. 283168404Spjd * Used by the "-" and "_" commands. 284168404Spjd * how_toggle may be: 285168404Spjd * OPT_NO_TOGGLE just report the current setting, without changing it. 286219089Spjd * OPT_TOGGLE invert the current setting 287168404Spjd * OPT_UNSET set to the default value 288185029Spjd * OPT_SET set to the inverse of the default value 289185029Spjd */ 290185029Spjd public void 291219089Spjdtoggle_option(o, lower, s, how_toggle) 292185029Spjd struct loption *o; 293168404Spjd int lower; 294168404Spjd char *s; 295168404Spjd int how_toggle; 296168404Spjd{ 297168404Spjd register int num; 298185029Spjd int no_prompt; 299168404Spjd int err; 300168404Spjd PARG parg; 301168404Spjd 302168404Spjd no_prompt = (how_toggle & OPT_NO_PROMPT); 303168404Spjd how_toggle &= ~OPT_NO_PROMPT; 304168404Spjd 305168404Spjd if (o == NULL) 306168404Spjd { 307168404Spjd error("No such option", NULL_PARG); 308168404Spjd return; 309168404Spjd } 310168404Spjd 311168404Spjd if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE)) 312168404Spjd { 313168404Spjd parg.p_string = opt_desc(o); 314168404Spjd error("Cannot change the %s option", &parg); 315168404Spjd return; 316168404Spjd } 317168404Spjd 318168404Spjd if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY)) 319168404Spjd { 320168404Spjd parg.p_string = opt_desc(o); 321168404Spjd error("Cannot query the %s option", &parg); 322168404Spjd return; 323168404Spjd } 324168404Spjd 325168404Spjd /* 326168404Spjd * Check for something which appears to be a do_toggle 327168404Spjd * (because the "-" command was used), but really is not. 328168404Spjd * This could be a string option with no string, or 329168404Spjd * a number option with no number. 330168404Spjd */ 331168404Spjd switch (o->otype & OTYPE) 332185029Spjd { 333185029Spjd case STRING: 334168404Spjd case NUMBER: 335168404Spjd if (how_toggle == OPT_TOGGLE && *s == '\0') 336168404Spjd how_toggle = OPT_NO_TOGGLE; 337168404Spjd break; 338219089Spjd } 339185029Spjd 340168404Spjd#if HILITE_SEARCH 341168404Spjd if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT)) 342185029Spjd repaint_hilite(0); 343185029Spjd#endif 344236884Smm 345236884Smm /* 346236884Smm * Now actually toggle (change) the variable. 347236884Smm */ 348236884Smm if (how_toggle != OPT_NO_TOGGLE) 349243014Smm { 350168404Spjd switch (o->otype & OTYPE) 351168404Spjd { 352168404Spjd case BOOL: 353168404Spjd /* 354168404Spjd * Boolean. 355168404Spjd */ 356168404Spjd switch (how_toggle) 357168404Spjd { 358168404Spjd case OPT_TOGGLE: 359168404Spjd *(o->ovar) = ! *(o->ovar); 360168404Spjd break; 361168404Spjd case OPT_UNSET: 362168404Spjd *(o->ovar) = o->odefault; 363168404Spjd break; 364185029Spjd case OPT_SET: 365185029Spjd *(o->ovar) = ! o->odefault; 366168404Spjd break; 367168404Spjd } 368168404Spjd break; 369168404Spjd case TRIPLE: 370168404Spjd /* 371168404Spjd * Triple: 372168404Spjd * If user gave the lower case letter, then switch 373168404Spjd * to 1 unless already 1, in which case make it 0. 374168404Spjd * If user gave the upper case letter, then switch 375168404Spjd * to 2 unless already 2, in which case make it 0. 376168404Spjd */ 377168404Spjd switch (how_toggle) 378168404Spjd { 379185029Spjd case OPT_TOGGLE: 380185029Spjd *(o->ovar) = flip_triple(*(o->ovar), lower); 381185029Spjd break; 382185029Spjd case OPT_UNSET: 383185029Spjd *(o->ovar) = o->odefault; 384185029Spjd break; 385185029Spjd case OPT_SET: 386219089Spjd *(o->ovar) = flip_triple(o->odefault, lower); 387185029Spjd break; 388185029Spjd } 389168404Spjd break; 390168404Spjd case STRING: 391168404Spjd /* 392168404Spjd * String: don't do anything here. 393238926Smm * The handling function will do everything. 394238926Smm */ 395238926Smm switch (how_toggle) 396238926Smm { 397238926Smm case OPT_SET: 398238926Smm case OPT_UNSET: 399238926Smm error("Cannot use \"-+\" or \"--\" for a string option", 400238926Smm NULL_PARG); 401238926Smm return; 402238926Smm } 403238926Smm break; 404238926Smm case NUMBER: 405168404Spjd /* 406185029Spjd * Number: set the variable to the given number. 407185029Spjd */ 408185029Spjd switch (how_toggle) 409185029Spjd { 410185029Spjd case OPT_TOGGLE: 411185029Spjd num = getnum(&s, NULL, &err); 412185029Spjd if (!err) 413185029Spjd *(o->ovar) = num; 414185029Spjd break; 415185029Spjd case OPT_UNSET: 416185029Spjd *(o->ovar) = o->odefault; 417185029Spjd break; 418185029Spjd case OPT_SET: 419185029Spjd error("Can't use \"-!\" for a numeric option", 420185029Spjd NULL_PARG); 421185029Spjd return; 422185029Spjd } 423185029Spjd break; 424185029Spjd } 425185029Spjd } 426185029Spjd 427185029Spjd /* 428238926Smm * Call the handling function for any special action 429238926Smm * specific to this option. 430236884Smm */ 431236884Smm if (o->ofunc != NULL) 432185029Spjd (*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s); 433185029Spjd 434185029Spjd#if HILITE_SEARCH 435185029Spjd if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT)) 436238926Smm chg_hilite(); 437238926Smm#endif 438238926Smm 439238926Smm if (!no_prompt) 440238926Smm { 441238926Smm /* 442238926Smm * Print a message describing the new setting. 443238926Smm */ 444238926Smm switch (o->otype & OTYPE) 445238926Smm { 446238926Smm case BOOL: 447238926Smm case TRIPLE: 448238926Smm /* 449238926Smm * Print the odesc message. 450238926Smm */ 451238926Smm error(o->odesc[*(o->ovar)], NULL_PARG); 452236884Smm break; 453236884Smm case NUMBER: 454236884Smm /* 455236884Smm * The message is in odesc[1] and has a %d for 456185029Spjd * the value of the variable. 457209962Smm */ 458209962Smm parg.p_int = *(o->ovar); 459209962Smm error(o->odesc[1], &parg); 460209962Smm break; 461185029Spjd case STRING: 462185029Spjd /* 463185029Spjd * Message was already printed by the handling function. 464185029Spjd */ 465185029Spjd break; 466185029Spjd } 467185029Spjd } 468185029Spjd 469185029Spjd if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT)) 470185029Spjd screen_trashed = TRUE; 471185029Spjd} 472185029Spjd 473185029Spjd/* 474185029Spjd * "Toggle" a triple-valued option. 475185029Spjd */ 476185029Spjd static int 477185029Spjdflip_triple(val, lc) 478185029Spjd int val; 479185029Spjd int lc; 480185029Spjd{ 481168404Spjd if (lc) 482168404Spjd return ((val == OPT_ON) ? OPT_OFF : OPT_ON); 483168404Spjd else 484168404Spjd return ((val == OPT_ONPLUS) ? OPT_OFF : OPT_ONPLUS); 485168404Spjd} 486168404Spjd 487168404Spjd/* 488168404Spjd * Determine if an option takes a parameter. 489168404Spjd */ 490168404Spjd public int 491168404Spjdopt_has_param(o) 492168404Spjd struct loption *o; 493168404Spjd{ 494168404Spjd if (o == NULL) 495168404Spjd return (0); 496168404Spjd if (o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE)) 497168404Spjd return (0); 498168404Spjd return (1); 499168404Spjd} 500168404Spjd 501168404Spjd/* 502168404Spjd * Return the prompt to be used for a given option letter. 503168404Spjd * Only string and number valued options have prompts. 504168404Spjd */ 505168404Spjd public char * 506168404Spjdopt_prompt(o) 507168404Spjd struct loption *o; 508168404Spjd{ 509168404Spjd if (o == NULL || (o->otype & (STRING|NUMBER)) == 0) 510168404Spjd return ("?"); 511168404Spjd return (o->odesc[0]); 512168404Spjd} 513168404Spjd 514168404Spjd/* 515168404Spjd * Return whether or not there is a string option pending; 516168404Spjd * that is, if the previous option was a string-valued option letter 517168404Spjd * (like -P) without a following string. 518168404Spjd * In that case, the current option is taken to be the string for 519168404Spjd * the previous option. 520168404Spjd */ 521168404Spjd public int 522168404Spjdisoptpending() 523168404Spjd{ 524168404Spjd return (pendopt != NULL); 525168404Spjd} 526168404Spjd 527168404Spjd/* 528168404Spjd * Print error message about missing string. 529168404Spjd */ 530168404Spjd static void 531168404Spjdnostring(printopt) 532168404Spjd char *printopt; 533168404Spjd{ 534168404Spjd PARG parg; 535168404Spjd parg.p_string = printopt; 536168404Spjd error("Value is required after %s", &parg); 537168404Spjd} 538168404Spjd 539168404Spjd/* 540168404Spjd * Print error message if a STRING type option is not followed by a string. 541168404Spjd */ 542168404Spjd public void 543168404Spjdnopendopt() 544168404Spjd{ 545168404Spjd nostring(opt_desc(pendopt)); 546168404Spjd} 547168404Spjd 548185029Spjd/* 549185029Spjd * Scan to end of string or to an END_OPTION_STRING character. 550168404Spjd * In the latter case, replace the char with a null char. 551168404Spjd * Return a pointer to the remainder of the string, if any. 552168404Spjd */ 553168404Spjd static char * 554168404Spjdoptstring(s, p_str, printopt, validchars) 555168404Spjd char *s; 556168404Spjd char **p_str; 557168404Spjd char *printopt; 558168404Spjd char *validchars; 559168404Spjd{ 560168404Spjd register char *p; 561168404Spjd 562168404Spjd if (*s == '\0') 563168404Spjd { 564185029Spjd nostring(printopt); 565185029Spjd quit(QUIT_ERROR); 566185029Spjd } 567168404Spjd *p_str = s; 568185029Spjd for (p = s; *p != '\0'; p++) 569185029Spjd { 570185029Spjd if (*p == END_OPTION_STRING || 571185029Spjd (validchars != NULL && strchr(validchars, *p) == NULL)) 572185029Spjd { 573185029Spjd switch (*p) 574185029Spjd { 575185029Spjd case END_OPTION_STRING: 576168404Spjd case ' ': case '\t': case '-': 577168404Spjd /* Replace the char with a null to terminate string. */ 578168404Spjd *p++ = '\0'; 579168404Spjd break; 580168404Spjd default: 581168404Spjd /* Cannot replace char; make a copy of the string. */ 582168404Spjd *p_str = (char *) ecalloc(p-s+1, sizeof(char)); 583168404Spjd strncpy(*p_str, s, p-s); 584168404Spjd (*p_str)[p-s] = '\0'; 585168404Spjd break; 586168404Spjd } 587168404Spjd break; 588219089Spjd } 589168404Spjd } 590219089Spjd return (p); 591219089Spjd} 592168404Spjd 593168404Spjd/* 594168404Spjd */ 595168404Spjd static int 596168404Spjdnum_error(printopt, errp) 597185029Spjd char *printopt; 598168404Spjd int *errp; 599168404Spjd{ 600168404Spjd PARG parg; 601168404Spjd 602168404Spjd if (errp != NULL) 603168404Spjd { 604168404Spjd *errp = TRUE; 605168404Spjd return (-1); 606168404Spjd } 607168404Spjd if (printopt != NULL) 608168404Spjd { 609168404Spjd parg.p_string = printopt; 610168404Spjd error("Number is required after %s", &parg); 611168404Spjd } 612168404Spjd quit(QUIT_ERROR); 613168404Spjd /* NOTREACHED */ 614168404Spjd return (-1); 615168404Spjd} 616168404Spjd 617168404Spjd/* 618185029Spjd * Translate a string into a number. 619185029Spjd * Like atoi(), but takes a pointer to a char *, and updates 620185029Spjd * the char * to point after the translated number. 621168404Spjd */ 622168404Spjd public int 623168404Spjdgetnum(sp, printopt, errp) 624168404Spjd char **sp; 625168404Spjd char *printopt; 626168404Spjd int *errp; 627224171Sgibbs{ 628224171Sgibbs register char *s; 629224171Sgibbs register int n; 630224171Sgibbs register int neg; 631224171Sgibbs 632224171Sgibbs s = skipsp(*sp); 633224171Sgibbs neg = FALSE; 634224171Sgibbs if (*s == '-') 635224171Sgibbs { 636224171Sgibbs neg = TRUE; 637224171Sgibbs s++; 638224171Sgibbs } 639224171Sgibbs if (*s < '0' || *s > '9') 640224171Sgibbs return (num_error(printopt, errp)); 641224171Sgibbs 642224171Sgibbs n = 0; 643224171Sgibbs while (*s >= '0' && *s <= '9') 644224171Sgibbs n = 10 * n + *s++ - '0'; 645224171Sgibbs *sp = s; 646224171Sgibbs if (errp != NULL) 647224171Sgibbs *errp = FALSE; 648224171Sgibbs if (neg) 649224171Sgibbs n = -n; 650224171Sgibbs return (n); 651224171Sgibbs} 652224171Sgibbs 653224171Sgibbs/* 654224171Sgibbs * Translate a string into a fraction, represented by the part of a 655224171Sgibbs * number which would follow a decimal point. 656224171Sgibbs * The value of the fraction is returned as parts per NUM_FRAC_DENOM. 657224171Sgibbs * That is, if "n" is returned, the fraction intended is n/NUM_FRAC_DENOM. 658224171Sgibbs */ 659224171Sgibbs public long 660224171Sgibbsgetfraction(sp, printopt, errp) 661224171Sgibbs char **sp; 662224171Sgibbs char *printopt; 663224171Sgibbs int *errp; 664224171Sgibbs{ 665224171Sgibbs register char *s; 666224171Sgibbs long frac = 0; 667224171Sgibbs int fraclen = 0; 668224171Sgibbs 669224171Sgibbs s = skipsp(*sp); 670224171Sgibbs if (*s < '0' || *s > '9') 671224171Sgibbs return (num_error(printopt, errp)); 672224171Sgibbs 673224171Sgibbs for ( ; *s >= '0' && *s <= '9'; s++) 674224171Sgibbs { 675224171Sgibbs frac = (frac * 10) + (*s - '0'); 676224171Sgibbs fraclen++; 677224171Sgibbs } 678224171Sgibbs if (fraclen > NUM_LOG_FRAC_DENOM) 679224171Sgibbs while (fraclen-- > NUM_LOG_FRAC_DENOM) 680224171Sgibbs frac /= 10; 681224171Sgibbs else 682224171Sgibbs while (fraclen++ < NUM_LOG_FRAC_DENOM) 683224171Sgibbs frac *= 10; 684224171Sgibbs *sp = s; 685224171Sgibbs if (errp != NULL) 686224171Sgibbs *errp = FALSE; 687224171Sgibbs return (frac); 688224171Sgibbs} 689224171Sgibbs 690224171Sgibbs 691224171Sgibbs/* 692224171Sgibbs * Get the value of the -e flag. 693224171Sgibbs */ 694224171Sgibbs public int 695224171Sgibbsget_quit_at_eof() 696224171Sgibbs{ 697224171Sgibbs if (!less_is_more) 698224171Sgibbs return quit_at_eof; 699224171Sgibbs /* When less_is_more is set, the -e flag semantics are different. */ 700224171Sgibbs return quit_at_eof ? OPT_ON : OPT_ONPLUS; 701224171Sgibbs} 702224171Sgibbs