option.c revision 170256
160786Sps/*
2170256Sdelphij * Copyright (C) 1984-2007  Mark Nudelman
360786Sps *
460786Sps * You may distribute under the terms of either the GNU General Public
560786Sps * License or the Less License, as specified in the README file.
660786Sps *
760786Sps * For more information about less, or for information on how to
860786Sps * contact the author, see the README file.
960786Sps */
1060786Sps
1160786Sps
1260786Sps/*
1360786Sps * Process command line options.
1460786Sps *
1560786Sps * Each option is a single letter which controls a program variable.
1660786Sps * The options have defaults which may be changed via
1760786Sps * the command line option, toggled via the "-" command,
1860786Sps * or queried via the "_" command.
1960786Sps */
2060786Sps
2160786Sps#include "less.h"
2260786Sps#include "option.h"
2360786Sps
24128345Stjrstatic struct loption *pendopt;
2560786Spspublic int plusoption = FALSE;
2660786Sps
2760786Spsstatic char *propt();
2860786Spsstatic char *optstring();
2960786Spsstatic int flip_triple();
3060786Sps
3160786Spsextern int screen_trashed;
32170256Sdelphijextern int less_is_more;
33170256Sdelphijextern int quit_at_eof;
3460786Spsextern char *every_first_cmd;
3560786Sps
3660786Sps/*
3760786Sps * Scan an argument (either from the command line or from the
3860786Sps * LESS environment variable) and process it.
3960786Sps */
4060786Sps	public void
4160786Spsscan_option(s)
4260786Sps	char *s;
4360786Sps{
44128345Stjr	register struct loption *o;
4560786Sps	register int optc;
4660786Sps	char *optname;
4760786Sps	char *printopt;
4860786Sps	char *str;
4960786Sps	int set_default;
5060786Sps	int lc;
5160786Sps	int err;
5260786Sps	PARG parg;
5360786Sps
5460786Sps	if (s == NULL)
5560786Sps		return;
5660786Sps
5760786Sps	/*
5860786Sps	 * If we have a pending option which requires an argument,
5960786Sps	 * handle it now.
6060786Sps	 * This happens if the previous option was, for example, "-P"
6160786Sps	 * without a following string.  In that case, the current
6260786Sps	 * option is simply the argument for the previous option.
6360786Sps	 */
6460786Sps	if (pendopt != NULL)
6560786Sps	{
6660786Sps		switch (pendopt->otype & OTYPE)
6760786Sps		{
6860786Sps		case STRING:
6960786Sps			(*pendopt->ofunc)(INIT, s);
7060786Sps			break;
7160786Sps		case NUMBER:
7260786Sps			printopt = propt(pendopt->oletter);
7360786Sps			*(pendopt->ovar) = getnum(&s, printopt, (int*)NULL);
7460786Sps			break;
7560786Sps		}
7660786Sps		pendopt = NULL;
7760786Sps		return;
7860786Sps	}
7960786Sps
8060786Sps	set_default = FALSE;
8160786Sps	optname = NULL;
8260786Sps
8360786Sps	while (*s != '\0')
8460786Sps	{
8560786Sps		/*
8660786Sps		 * Check some special cases first.
8760786Sps		 */
8860786Sps		switch (optc = *s++)
8960786Sps		{
9060786Sps		case ' ':
9160786Sps		case '\t':
9260786Sps		case END_OPTION_STRING:
9360786Sps			continue;
9460786Sps		case '-':
9560786Sps			/*
9660786Sps			 * "--" indicates an option name instead of a letter.
9760786Sps			 */
9860786Sps			if (*s == '-')
9960786Sps			{
10060786Sps				optname = ++s;
10160786Sps				break;
10260786Sps			}
10360786Sps			/*
10460786Sps			 * "-+" means set these options back to their defaults.
10560786Sps			 * (They may have been set otherwise by previous
10660786Sps			 * options.)
10760786Sps			 */
10860786Sps			set_default = (*s == '+');
10960786Sps			if (set_default)
11060786Sps				s++;
11160786Sps			continue;
11260786Sps		case '+':
11360786Sps			/*
11460786Sps			 * An option prefixed by a "+" is ungotten, so
11560786Sps			 * that it is interpreted as less commands
11660786Sps			 * processed at the start of the first input file.
11760786Sps			 * "++" means process the commands at the start of
11860786Sps			 * EVERY input file.
11960786Sps			 */
12060786Sps			plusoption = TRUE;
121128345Stjr			s = optstring(s, &str, propt('+'), NULL);
12289019Sps			if (*str == '+')
12389019Sps				every_first_cmd = save(++str);
12460786Sps			else
12589019Sps				ungetsc(str);
12660786Sps			continue;
12760786Sps		case '0':  case '1':  case '2':  case '3':  case '4':
12860786Sps		case '5':  case '6':  case '7':  case '8':  case '9':
12960786Sps			/*
13060786Sps			 * Special "more" compatibility form "-<number>"
13160786Sps			 * instead of -z<number> to set the scrolling
13260786Sps			 * window size.
13360786Sps			 */
13460786Sps			s--;
13560786Sps			optc = 'z';
13660786Sps			break;
137170256Sdelphij		case 'n':
138170256Sdelphij			if (less_is_more)
139170256Sdelphij				optc = 'z';
140170256Sdelphij			break;
14160786Sps		}
14260786Sps
14360786Sps		/*
14460786Sps		 * Not a special case.
14560786Sps		 * Look up the option letter in the option table.
14660786Sps		 */
14760786Sps		err = 0;
14860786Sps		if (optname == NULL)
14960786Sps		{
15060786Sps			printopt = propt(optc);
151161475Sdelphij			lc = ASCII_IS_LOWER(optc);
15260786Sps			o = findopt(optc);
15360786Sps		} else
15460786Sps		{
15560786Sps			printopt = optname;
156161475Sdelphij			lc = ASCII_IS_LOWER(optname[0]);
15760786Sps			o = findopt_name(&optname, NULL, &err);
15860786Sps			s = optname;
15960786Sps			optname = NULL;
16060786Sps			if (*s == '\0' || *s == ' ')
16160786Sps			{
16260786Sps				/*
16360786Sps				 * The option name matches exactly.
16460786Sps				 */
16560786Sps				;
16660786Sps			} else if (*s == '=')
16760786Sps			{
16860786Sps				/*
16960786Sps				 * The option name is followed by "=value".
17060786Sps				 */
17160786Sps				if (o != NULL &&
17260786Sps				    (o->otype & OTYPE) != STRING &&
17360786Sps				    (o->otype & OTYPE) != NUMBER)
17460786Sps				{
17560786Sps					parg.p_string = printopt;
17660786Sps					error("The %s option should not be followed by =",
17760786Sps						&parg);
17860786Sps					quit(QUIT_ERROR);
17960786Sps				}
18060786Sps				s++;
18160786Sps			} else
18260786Sps			{
18360786Sps				/*
18460786Sps				 * The specified name is longer than the
18560786Sps				 * real option name.
18660786Sps				 */
18760786Sps				o = NULL;
18860786Sps			}
18960786Sps		}
19060786Sps		if (o == NULL)
19160786Sps		{
19260786Sps			parg.p_string = printopt;
19360786Sps			if (err == OPT_AMBIG)
19460786Sps				error("%s is an ambiguous abbreviation (\"less --help\" for help)",
19560786Sps					&parg);
19660786Sps			else
19760786Sps				error("There is no %s option (\"less --help\" for help)",
19860786Sps					&parg);
19960786Sps			quit(QUIT_ERROR);
20060786Sps		}
20160786Sps
20260786Sps		str = NULL;
20360786Sps		switch (o->otype & OTYPE)
20460786Sps		{
20560786Sps		case BOOL:
20660786Sps			if (set_default)
20760786Sps				*(o->ovar) = o->odefault;
20860786Sps			else
20960786Sps				*(o->ovar) = ! o->odefault;
21060786Sps			break;
21160786Sps		case TRIPLE:
21260786Sps			if (set_default)
21360786Sps				*(o->ovar) = o->odefault;
21460786Sps			else
21560786Sps				*(o->ovar) = flip_triple(o->odefault, lc);
21660786Sps			break;
21760786Sps		case STRING:
21860786Sps			if (*s == '\0')
21960786Sps			{
22060786Sps				/*
22160786Sps				 * Set pendopt and return.
22260786Sps				 * We will get the string next time
22360786Sps				 * scan_option is called.
22460786Sps				 */
22560786Sps				pendopt = o;
22660786Sps				return;
22760786Sps			}
22860786Sps			/*
22960786Sps			 * Don't do anything here.
23060786Sps			 * All processing of STRING options is done by
23160786Sps			 * the handling function.
23260786Sps			 */
233128345Stjr			while (*s == ' ')
234128345Stjr				s++;
235128345Stjr			s = optstring(s, &str, printopt, o->odesc[1]);
23660786Sps			break;
23760786Sps		case NUMBER:
23860786Sps			if (*s == '\0')
23960786Sps			{
24060786Sps				pendopt = o;
24160786Sps				return;
24260786Sps			}
24360786Sps			*(o->ovar) = getnum(&s, printopt, (int*)NULL);
24460786Sps			break;
24560786Sps		}
24660786Sps		/*
24760786Sps		 * If the option has a handling function, call it.
24860786Sps		 */
24960786Sps		if (o->ofunc != NULL)
25060786Sps			(*o->ofunc)(INIT, str);
25160786Sps	}
25260786Sps}
25360786Sps
25460786Sps/*
25560786Sps * Toggle command line flags from within the program.
25660786Sps * Used by the "-" and "_" commands.
25760786Sps * how_toggle may be:
25860786Sps *	OPT_NO_TOGGLE	just report the current setting, without changing it.
25960786Sps *	OPT_TOGGLE	invert the current setting
26060786Sps *	OPT_UNSET	set to the default value
26160786Sps *	OPT_SET		set to the inverse of the default value
26260786Sps */
26360786Sps	public void
26460786Spstoggle_option(c, s, how_toggle)
26560786Sps	int c;
26660786Sps	char *s;
26760786Sps	int how_toggle;
26860786Sps{
269128345Stjr	register struct loption *o;
27060786Sps	register int num;
27160786Sps	int no_prompt;
27260786Sps	int err;
27360786Sps	PARG parg;
27460786Sps
27560786Sps	no_prompt = (how_toggle & OPT_NO_PROMPT);
27660786Sps	how_toggle &= ~OPT_NO_PROMPT;
27760786Sps
27860786Sps	/*
27960786Sps	 * Look up the option letter in the option table.
28060786Sps	 */
28160786Sps	o = findopt(c);
28260786Sps	if (o == NULL)
28360786Sps	{
28460786Sps		parg.p_string = propt(c);
28560786Sps		error("There is no %s option", &parg);
28660786Sps		return;
28760786Sps	}
28860786Sps
28960786Sps	if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE))
29060786Sps	{
29160786Sps		parg.p_string = propt(c);
29260786Sps		error("Cannot change the %s option", &parg);
29360786Sps		return;
29460786Sps	}
29560786Sps
29660786Sps	if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY))
29760786Sps	{
29860786Sps		parg.p_string = propt(c);
29960786Sps		error("Cannot query the %s option", &parg);
30060786Sps		return;
30160786Sps	}
30260786Sps
30360786Sps	/*
30460786Sps	 * Check for something which appears to be a do_toggle
30560786Sps	 * (because the "-" command was used), but really is not.
30660786Sps	 * This could be a string option with no string, or
30760786Sps	 * a number option with no number.
30860786Sps	 */
30960786Sps	switch (o->otype & OTYPE)
31060786Sps	{
31160786Sps	case STRING:
31260786Sps	case NUMBER:
31360786Sps		if (how_toggle == OPT_TOGGLE && *s == '\0')
31460786Sps			how_toggle = OPT_NO_TOGGLE;
31560786Sps		break;
31660786Sps	}
31760786Sps
31860786Sps#if HILITE_SEARCH
31960786Sps	if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
32060786Sps		repaint_hilite(0);
32160786Sps#endif
32260786Sps
32360786Sps	/*
32460786Sps	 * Now actually toggle (change) the variable.
32560786Sps	 */
32660786Sps	if (how_toggle != OPT_NO_TOGGLE)
32760786Sps	{
32860786Sps		switch (o->otype & OTYPE)
32960786Sps		{
33060786Sps		case BOOL:
33160786Sps			/*
33260786Sps			 * Boolean.
33360786Sps			 */
33460786Sps			switch (how_toggle)
33560786Sps			{
33660786Sps			case OPT_TOGGLE:
33760786Sps				*(o->ovar) = ! *(o->ovar);
33860786Sps				break;
33960786Sps			case OPT_UNSET:
34060786Sps				*(o->ovar) = o->odefault;
34160786Sps				break;
34260786Sps			case OPT_SET:
34360786Sps				*(o->ovar) = ! o->odefault;
34460786Sps				break;
34560786Sps			}
34660786Sps			break;
34760786Sps		case TRIPLE:
34860786Sps			/*
34960786Sps			 * Triple:
35060786Sps			 *	If user gave the lower case letter, then switch
35160786Sps			 *	to 1 unless already 1, in which case make it 0.
35260786Sps			 *	If user gave the upper case letter, then switch
35360786Sps			 *	to 2 unless already 2, in which case make it 0.
35460786Sps			 */
35560786Sps			switch (how_toggle)
35660786Sps			{
35760786Sps			case OPT_TOGGLE:
35860786Sps				*(o->ovar) = flip_triple(*(o->ovar),
359161475Sdelphij						ASCII_IS_LOWER(c));
36060786Sps				break;
36160786Sps			case OPT_UNSET:
36260786Sps				*(o->ovar) = o->odefault;
36360786Sps				break;
36460786Sps			case OPT_SET:
36560786Sps				*(o->ovar) = flip_triple(o->odefault,
366161475Sdelphij						ASCII_IS_LOWER(c));
36760786Sps				break;
36860786Sps			}
36960786Sps			break;
37060786Sps		case STRING:
37160786Sps			/*
37260786Sps			 * String: don't do anything here.
37360786Sps			 *	The handling function will do everything.
37460786Sps			 */
37560786Sps			switch (how_toggle)
37660786Sps			{
37760786Sps			case OPT_SET:
37860786Sps			case OPT_UNSET:
37960786Sps				error("Cannot use \"-+\" or \"--\" for a string option",
38060786Sps					NULL_PARG);
38160786Sps				return;
38260786Sps			}
38360786Sps			break;
38460786Sps		case NUMBER:
38560786Sps			/*
38660786Sps			 * Number: set the variable to the given number.
38760786Sps			 */
38860786Sps			switch (how_toggle)
38960786Sps			{
39060786Sps			case OPT_TOGGLE:
391128345Stjr				num = getnum(&s, NULL, &err);
39260786Sps				if (!err)
39360786Sps					*(o->ovar) = num;
39460786Sps				break;
39560786Sps			case OPT_UNSET:
39660786Sps				*(o->ovar) = o->odefault;
39760786Sps				break;
39860786Sps			case OPT_SET:
39960786Sps				error("Can't use \"-!\" for a numeric option",
40060786Sps					NULL_PARG);
40160786Sps				return;
40260786Sps			}
40360786Sps			break;
40460786Sps		}
40560786Sps	}
40660786Sps
40760786Sps	/*
40860786Sps	 * Call the handling function for any special action
40960786Sps	 * specific to this option.
41060786Sps	 */
41160786Sps	if (o->ofunc != NULL)
41260786Sps		(*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s);
41360786Sps
41460786Sps#if HILITE_SEARCH
41560786Sps	if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
41660786Sps		chg_hilite();
41760786Sps#endif
41860786Sps
41960786Sps	if (!no_prompt)
42060786Sps	{
42160786Sps		/*
42260786Sps		 * Print a message describing the new setting.
42360786Sps		 */
42460786Sps		switch (o->otype & OTYPE)
42560786Sps		{
42660786Sps		case BOOL:
42760786Sps		case TRIPLE:
42860786Sps			/*
42960786Sps			 * Print the odesc message.
43060786Sps			 */
43160786Sps			error(o->odesc[*(o->ovar)], NULL_PARG);
43260786Sps			break;
43360786Sps		case NUMBER:
43460786Sps			/*
43560786Sps			 * The message is in odesc[1] and has a %d for
43660786Sps			 * the value of the variable.
43760786Sps			 */
43860786Sps			parg.p_int = *(o->ovar);
43960786Sps			error(o->odesc[1], &parg);
44060786Sps			break;
44160786Sps		case STRING:
44260786Sps			/*
44360786Sps			 * Message was already printed by the handling function.
44460786Sps			 */
44560786Sps			break;
44660786Sps		}
44760786Sps	}
44860786Sps
44960786Sps	if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT))
45060786Sps		screen_trashed = TRUE;
45160786Sps}
45260786Sps
45360786Sps/*
45460786Sps * "Toggle" a triple-valued option.
45560786Sps */
45660786Sps	static int
45760786Spsflip_triple(val, lc)
45860786Sps	int val;
45960786Sps	int lc;
46060786Sps{
46160786Sps	if (lc)
46260786Sps		return ((val == OPT_ON) ? OPT_OFF : OPT_ON);
46360786Sps	else
46460786Sps		return ((val == OPT_ONPLUS) ? OPT_OFF : OPT_ONPLUS);
46560786Sps}
46660786Sps
46760786Sps/*
46860786Sps * Return a string suitable for printing as the "name" of an option.
46960786Sps * For example, if the option letter is 'x', just return "-x".
47060786Sps */
47160786Sps	static char *
47260786Spspropt(c)
47360786Sps	int c;
47460786Sps{
47560786Sps	static char buf[8];
47660786Sps
47760786Sps	sprintf(buf, "-%s", prchar(c));
47860786Sps	return (buf);
47960786Sps}
48060786Sps
48160786Sps/*
48260786Sps * Determine if an option is a single character option (BOOL or TRIPLE),
48360786Sps * or if it a multi-character option (NUMBER).
48460786Sps */
48560786Sps	public int
48660786Spssingle_char_option(c)
48760786Sps	int c;
48860786Sps{
489128345Stjr	register struct loption *o;
49060786Sps
49160786Sps	o = findopt(c);
49260786Sps	if (o == NULL)
49360786Sps		return (TRUE);
49460786Sps	return ((o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE)) != 0);
49560786Sps}
49660786Sps
49760786Sps/*
49860786Sps * Return the prompt to be used for a given option letter.
49960786Sps * Only string and number valued options have prompts.
50060786Sps */
50160786Sps	public char *
50260786Spsopt_prompt(c)
50360786Sps	int c;
50460786Sps{
505128345Stjr	register struct loption *o;
50660786Sps
50760786Sps	o = findopt(c);
50860786Sps	if (o == NULL || (o->otype & (STRING|NUMBER)) == 0)
50960786Sps		return (NULL);
51060786Sps	return (o->odesc[0]);
51160786Sps}
51260786Sps
51360786Sps/*
51460786Sps * Return whether or not there is a string option pending;
51560786Sps * that is, if the previous option was a string-valued option letter
51660786Sps * (like -P) without a following string.
51760786Sps * In that case, the current option is taken to be the string for
51860786Sps * the previous option.
51960786Sps */
52060786Sps	public int
52160786Spsisoptpending()
52260786Sps{
52360786Sps	return (pendopt != NULL);
52460786Sps}
52560786Sps
52660786Sps/*
52760786Sps * Print error message about missing string.
52860786Sps */
52960786Sps	static void
53060786Spsnostring(printopt)
53160786Sps	char *printopt;
53260786Sps{
53360786Sps	PARG parg;
53460786Sps	parg.p_string = printopt;
53560786Sps	error("Value is required after %s", &parg);
53660786Sps}
53760786Sps
53860786Sps/*
53960786Sps * Print error message if a STRING type option is not followed by a string.
54060786Sps */
54160786Sps	public void
54260786Spsnopendopt()
54360786Sps{
54460786Sps	nostring(propt(pendopt->oletter));
54560786Sps}
54660786Sps
54760786Sps/*
54860786Sps * Scan to end of string or to an END_OPTION_STRING character.
54960786Sps * In the latter case, replace the char with a null char.
55060786Sps * Return a pointer to the remainder of the string, if any.
55160786Sps */
55260786Sps	static char *
553128345Stjroptstring(s, p_str, printopt, validchars)
55460786Sps	char *s;
555128345Stjr	char **p_str;
55660786Sps	char *printopt;
55789019Sps	char *validchars;
55860786Sps{
55960786Sps	register char *p;
56060786Sps
56160786Sps	if (*s == '\0')
56260786Sps	{
56360786Sps		nostring(printopt);
56460786Sps		quit(QUIT_ERROR);
56560786Sps	}
566128345Stjr	*p_str = s;
56760786Sps	for (p = s;  *p != '\0';  p++)
568128345Stjr	{
56989019Sps		if (*p == END_OPTION_STRING ||
57089019Sps		    (validchars != NULL && strchr(validchars, *p) == NULL))
57160786Sps		{
57289019Sps			switch (*p)
57389019Sps			{
57489019Sps			case END_OPTION_STRING:
57589019Sps			case ' ':  case '\t':  case '-':
576128345Stjr				/* Replace the char with a null to terminate string. */
577128345Stjr				*p++ = '\0';
57889019Sps				break;
57989019Sps			default:
580128345Stjr				/* Cannot replace char; make a copy of the string. */
581128345Stjr				*p_str = (char *) ecalloc(p-s+1, sizeof(char));
582128345Stjr				strncpy(*p_str, s, p-s);
583128345Stjr				(*p_str)[p-s] = '\0';
58489019Sps				break;
58589019Sps			}
586128345Stjr			break;
58760786Sps		}
588128345Stjr	}
58960786Sps	return (p);
59060786Sps}
59160786Sps
59260786Sps/*
593170256Sdelphij */
594170256Sdelphij	static int
595170256Sdelphijnum_error(printopt, errp)
596170256Sdelphij	char *printopt;
597170256Sdelphij	int *errp;
598170256Sdelphij{
599170256Sdelphij	PARG parg;
600170256Sdelphij
601170256Sdelphij	if (errp != NULL)
602170256Sdelphij	{
603170256Sdelphij		*errp = TRUE;
604170256Sdelphij		return (-1);
605170256Sdelphij	}
606170256Sdelphij	if (printopt != NULL)
607170256Sdelphij	{
608170256Sdelphij		parg.p_string = printopt;
609170256Sdelphij		error("Number is required after %s", &parg);
610170256Sdelphij	}
611170256Sdelphij	quit(QUIT_ERROR);
612170256Sdelphij	/* NOTREACHED */
613170256Sdelphij	return (-1);
614170256Sdelphij}
615170256Sdelphij
616170256Sdelphij/*
61760786Sps * Translate a string into a number.
61860786Sps * Like atoi(), but takes a pointer to a char *, and updates
61960786Sps * the char * to point after the translated number.
62060786Sps */
62160786Sps	public int
62260786Spsgetnum(sp, printopt, errp)
62360786Sps	char **sp;
62460786Sps	char *printopt;
62560786Sps	int *errp;
62660786Sps{
62760786Sps	register char *s;
62860786Sps	register int n;
62960786Sps	register int neg;
63060786Sps
63160786Sps	s = skipsp(*sp);
63260786Sps	neg = FALSE;
63360786Sps	if (*s == '-')
63460786Sps	{
63560786Sps		neg = TRUE;
63660786Sps		s++;
63760786Sps	}
63860786Sps	if (*s < '0' || *s > '9')
639170256Sdelphij		return (num_error(printopt, errp));
64060786Sps
64160786Sps	n = 0;
64260786Sps	while (*s >= '0' && *s <= '9')
64360786Sps		n = 10 * n + *s++ - '0';
64460786Sps	*sp = s;
64560786Sps	if (errp != NULL)
64660786Sps		*errp = FALSE;
64760786Sps	if (neg)
64860786Sps		n = -n;
64960786Sps	return (n);
65060786Sps}
651170256Sdelphij
652170256Sdelphij/*
653170256Sdelphij * Translate a string into a fraction, represented by the part of a
654170256Sdelphij * number which would follow a decimal point.
655170256Sdelphij * The value of the fraction is returned as parts per NUM_FRAC_DENOM.
656170256Sdelphij * That is, if "n" is returned, the fraction intended is n/NUM_FRAC_DENOM.
657170256Sdelphij */
658170256Sdelphij	public long
659170256Sdelphijgetfraction(sp, printopt, errp)
660170256Sdelphij	char **sp;
661170256Sdelphij	char *printopt;
662170256Sdelphij	int *errp;
663170256Sdelphij{
664170256Sdelphij	register char *s;
665170256Sdelphij	long frac = 0;
666170256Sdelphij	int fraclen = 0;
667170256Sdelphij
668170256Sdelphij	s = skipsp(*sp);
669170256Sdelphij	if (*s < '0' || *s > '9')
670170256Sdelphij		return (num_error(printopt, errp));
671170256Sdelphij
672170256Sdelphij	for ( ;  *s >= '0' && *s <= '9';  s++)
673170256Sdelphij	{
674170256Sdelphij		frac = (frac * 10) + (*s - '0');
675170256Sdelphij		fraclen++;
676170256Sdelphij	}
677170256Sdelphij	if (fraclen > NUM_LOG_FRAC_DENOM)
678170256Sdelphij		while (fraclen-- > NUM_LOG_FRAC_DENOM)
679170256Sdelphij			frac /= 10;
680170256Sdelphij	else
681170256Sdelphij		while (fraclen++ < NUM_LOG_FRAC_DENOM)
682170256Sdelphij			frac *= 10;
683170256Sdelphij	*sp = s;
684170256Sdelphij	if (errp != NULL)
685170256Sdelphij		*errp = FALSE;
686170256Sdelphij	return (frac);
687170256Sdelphij}
688170256Sdelphij
689170256Sdelphij
690170256Sdelphij/*
691170256Sdelphij * Get the value of the -e flag.
692170256Sdelphij */
693170256Sdelphij	public int
694170256Sdelphijget_quit_at_eof()
695170256Sdelphij{
696170256Sdelphij	if (!less_is_more)
697170256Sdelphij		return quit_at_eof;
698170256Sdelphij	/* When less_is_more is set, the -e flag semantics are different. */
699170256Sdelphij	return quit_at_eof ? OPT_ON : OPT_ONPLUS;
700170256Sdelphij}
701