option.c revision 240121
160786Sps/*
2240121Sdelphij * Copyright (C) 1984-2012  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 *
7240121Sdelphij * For more information, see the README file.
860786Sps */
960786Sps
1060786Sps
1160786Sps/*
1260786Sps * Process command line options.
1360786Sps *
1460786Sps * Each option is a single letter which controls a program variable.
1560786Sps * The options have defaults which may be changed via
1660786Sps * the command line option, toggled via the "-" command,
1760786Sps * or queried via the "_" command.
1860786Sps */
1960786Sps
2060786Sps#include "less.h"
2160786Sps#include "option.h"
2260786Sps
23128345Stjrstatic struct loption *pendopt;
2460786Spspublic int plusoption = FALSE;
2560786Sps
2660786Spsstatic char *optstring();
2760786Spsstatic int flip_triple();
2860786Sps
2960786Spsextern int screen_trashed;
30170256Sdelphijextern int less_is_more;
31170256Sdelphijextern int quit_at_eof;
3260786Spsextern char *every_first_cmd;
3360786Sps
34221715Sdelphij/*
35221715Sdelphij * Return a printable description of an option.
36221715Sdelphij */
37221715Sdelphij	static char *
38221715Sdelphijopt_desc(o)
39221715Sdelphij	struct loption *o;
40221715Sdelphij{
41221715Sdelphij	static char buf[OPTNAME_MAX + 10];
42221715Sdelphij	if (o->oletter == OLETTER_NONE)
43221715Sdelphij		SNPRINTF1(buf, sizeof(buf), "--%s", o->onames->oname);
44221715Sdelphij	else
45221715Sdelphij		SNPRINTF2(buf, sizeof(buf), "-%c (--%s)", o->oletter, o->onames->oname);
46221715Sdelphij	return (buf);
47221715Sdelphij}
48221715Sdelphij
49221715Sdelphij/*
50221715Sdelphij * Return a string suitable for printing as the "name" of an option.
51221715Sdelphij * For example, if the option letter is 'x', just return "-x".
52221715Sdelphij */
53221715Sdelphij	public char *
54221715Sdelphijpropt(c)
55221715Sdelphij	int c;
56221715Sdelphij{
57221715Sdelphij	static char buf[8];
58221715Sdelphij
59221715Sdelphij	sprintf(buf, "-%s", prchar(c));
60221715Sdelphij	return (buf);
61221715Sdelphij}
62221715Sdelphij
6360786Sps/*
6460786Sps * Scan an argument (either from the command line or from the
6560786Sps * LESS environment variable) and process it.
6660786Sps */
6760786Sps	public void
6860786Spsscan_option(s)
6960786Sps	char *s;
7060786Sps{
71128345Stjr	register struct loption *o;
7260786Sps	register int optc;
7360786Sps	char *optname;
7460786Sps	char *printopt;
7560786Sps	char *str;
7660786Sps	int set_default;
7760786Sps	int lc;
7860786Sps	int err;
7960786Sps	PARG parg;
8060786Sps
8160786Sps	if (s == NULL)
8260786Sps		return;
8360786Sps
8460786Sps	/*
8560786Sps	 * If we have a pending option which requires an argument,
8660786Sps	 * handle it now.
8760786Sps	 * This happens if the previous option was, for example, "-P"
8860786Sps	 * without a following string.  In that case, the current
8960786Sps	 * option is simply the argument for the previous option.
9060786Sps	 */
9160786Sps	if (pendopt != NULL)
9260786Sps	{
9360786Sps		switch (pendopt->otype & OTYPE)
9460786Sps		{
9560786Sps		case STRING:
9660786Sps			(*pendopt->ofunc)(INIT, s);
9760786Sps			break;
9860786Sps		case NUMBER:
99221715Sdelphij			printopt = opt_desc(pendopt);
10060786Sps			*(pendopt->ovar) = getnum(&s, printopt, (int*)NULL);
10160786Sps			break;
10260786Sps		}
10360786Sps		pendopt = NULL;
10460786Sps		return;
10560786Sps	}
10660786Sps
10760786Sps	set_default = FALSE;
10860786Sps	optname = NULL;
10960786Sps
11060786Sps	while (*s != '\0')
11160786Sps	{
11260786Sps		/*
11360786Sps		 * Check some special cases first.
11460786Sps		 */
11560786Sps		switch (optc = *s++)
11660786Sps		{
11760786Sps		case ' ':
11860786Sps		case '\t':
11960786Sps		case END_OPTION_STRING:
12060786Sps			continue;
12160786Sps		case '-':
12260786Sps			/*
12360786Sps			 * "--" indicates an option name instead of a letter.
12460786Sps			 */
12560786Sps			if (*s == '-')
12660786Sps			{
12760786Sps				optname = ++s;
12860786Sps				break;
12960786Sps			}
13060786Sps			/*
13160786Sps			 * "-+" means set these options back to their defaults.
13260786Sps			 * (They may have been set otherwise by previous
13360786Sps			 * options.)
13460786Sps			 */
13560786Sps			set_default = (*s == '+');
13660786Sps			if (set_default)
13760786Sps				s++;
13860786Sps			continue;
13960786Sps		case '+':
14060786Sps			/*
14160786Sps			 * An option prefixed by a "+" is ungotten, so
14260786Sps			 * that it is interpreted as less commands
14360786Sps			 * processed at the start of the first input file.
14460786Sps			 * "++" means process the commands at the start of
14560786Sps			 * EVERY input file.
14660786Sps			 */
14760786Sps			plusoption = TRUE;
148128345Stjr			s = optstring(s, &str, propt('+'), NULL);
14989019Sps			if (*str == '+')
15089019Sps				every_first_cmd = save(++str);
15160786Sps			else
15289019Sps				ungetsc(str);
15360786Sps			continue;
15460786Sps		case '0':  case '1':  case '2':  case '3':  case '4':
15560786Sps		case '5':  case '6':  case '7':  case '8':  case '9':
15660786Sps			/*
15760786Sps			 * Special "more" compatibility form "-<number>"
15860786Sps			 * instead of -z<number> to set the scrolling
15960786Sps			 * window size.
16060786Sps			 */
16160786Sps			s--;
16260786Sps			optc = 'z';
16360786Sps			break;
164170256Sdelphij		case 'n':
165170256Sdelphij			if (less_is_more)
166170256Sdelphij				optc = 'z';
167170256Sdelphij			break;
16860786Sps		}
16960786Sps
17060786Sps		/*
17160786Sps		 * Not a special case.
17260786Sps		 * Look up the option letter in the option table.
17360786Sps		 */
17460786Sps		err = 0;
17560786Sps		if (optname == NULL)
17660786Sps		{
17760786Sps			printopt = propt(optc);
178161475Sdelphij			lc = ASCII_IS_LOWER(optc);
17960786Sps			o = findopt(optc);
18060786Sps		} else
18160786Sps		{
18260786Sps			printopt = optname;
183161475Sdelphij			lc = ASCII_IS_LOWER(optname[0]);
18460786Sps			o = findopt_name(&optname, NULL, &err);
18560786Sps			s = optname;
18660786Sps			optname = NULL;
18760786Sps			if (*s == '\0' || *s == ' ')
18860786Sps			{
18960786Sps				/*
19060786Sps				 * The option name matches exactly.
19160786Sps				 */
19260786Sps				;
19360786Sps			} else if (*s == '=')
19460786Sps			{
19560786Sps				/*
19660786Sps				 * The option name is followed by "=value".
19760786Sps				 */
19860786Sps				if (o != NULL &&
19960786Sps				    (o->otype & OTYPE) != STRING &&
20060786Sps				    (o->otype & OTYPE) != NUMBER)
20160786Sps				{
20260786Sps					parg.p_string = printopt;
20360786Sps					error("The %s option should not be followed by =",
20460786Sps						&parg);
20560786Sps					quit(QUIT_ERROR);
20660786Sps				}
20760786Sps				s++;
20860786Sps			} else
20960786Sps			{
21060786Sps				/*
21160786Sps				 * The specified name is longer than the
21260786Sps				 * real option name.
21360786Sps				 */
21460786Sps				o = NULL;
21560786Sps			}
21660786Sps		}
21760786Sps		if (o == NULL)
21860786Sps		{
21960786Sps			parg.p_string = printopt;
22060786Sps			if (err == OPT_AMBIG)
22160786Sps				error("%s is an ambiguous abbreviation (\"less --help\" for help)",
22260786Sps					&parg);
22360786Sps			else
22460786Sps				error("There is no %s option (\"less --help\" for help)",
22560786Sps					&parg);
22660786Sps			quit(QUIT_ERROR);
22760786Sps		}
22860786Sps
22960786Sps		str = NULL;
23060786Sps		switch (o->otype & OTYPE)
23160786Sps		{
23260786Sps		case BOOL:
23360786Sps			if (set_default)
23460786Sps				*(o->ovar) = o->odefault;
23560786Sps			else
23660786Sps				*(o->ovar) = ! o->odefault;
23760786Sps			break;
23860786Sps		case TRIPLE:
23960786Sps			if (set_default)
24060786Sps				*(o->ovar) = o->odefault;
24160786Sps			else
24260786Sps				*(o->ovar) = flip_triple(o->odefault, lc);
24360786Sps			break;
24460786Sps		case STRING:
24560786Sps			if (*s == '\0')
24660786Sps			{
24760786Sps				/*
24860786Sps				 * Set pendopt and return.
24960786Sps				 * We will get the string next time
25060786Sps				 * scan_option is called.
25160786Sps				 */
25260786Sps				pendopt = o;
25360786Sps				return;
25460786Sps			}
25560786Sps			/*
25660786Sps			 * Don't do anything here.
25760786Sps			 * All processing of STRING options is done by
25860786Sps			 * the handling function.
25960786Sps			 */
260128345Stjr			while (*s == ' ')
261128345Stjr				s++;
262128345Stjr			s = optstring(s, &str, printopt, o->odesc[1]);
26360786Sps			break;
26460786Sps		case NUMBER:
26560786Sps			if (*s == '\0')
26660786Sps			{
26760786Sps				pendopt = o;
26860786Sps				return;
26960786Sps			}
27060786Sps			*(o->ovar) = getnum(&s, printopt, (int*)NULL);
27160786Sps			break;
27260786Sps		}
27360786Sps		/*
27460786Sps		 * If the option has a handling function, call it.
27560786Sps		 */
27660786Sps		if (o->ofunc != NULL)
27760786Sps			(*o->ofunc)(INIT, str);
27860786Sps	}
27960786Sps}
28060786Sps
28160786Sps/*
28260786Sps * Toggle command line flags from within the program.
28360786Sps * Used by the "-" and "_" commands.
28460786Sps * how_toggle may be:
28560786Sps *	OPT_NO_TOGGLE	just report the current setting, without changing it.
28660786Sps *	OPT_TOGGLE	invert the current setting
28760786Sps *	OPT_UNSET	set to the default value
28860786Sps *	OPT_SET		set to the inverse of the default value
28960786Sps */
29060786Sps	public void
291221715Sdelphijtoggle_option(o, lower, s, how_toggle)
292221715Sdelphij	struct loption *o;
293221715Sdelphij	int lower;
29460786Sps	char *s;
29560786Sps	int how_toggle;
29660786Sps{
29760786Sps	register int num;
29860786Sps	int no_prompt;
29960786Sps	int err;
30060786Sps	PARG parg;
30160786Sps
30260786Sps	no_prompt = (how_toggle & OPT_NO_PROMPT);
30360786Sps	how_toggle &= ~OPT_NO_PROMPT;
30460786Sps
30560786Sps	if (o == NULL)
30660786Sps	{
307221715Sdelphij		error("No such option", NULL_PARG);
30860786Sps		return;
30960786Sps	}
31060786Sps
31160786Sps	if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE))
31260786Sps	{
313221715Sdelphij		parg.p_string = opt_desc(o);
31460786Sps		error("Cannot change the %s option", &parg);
31560786Sps		return;
316221715Sdelphij	}
31760786Sps
31860786Sps	if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY))
31960786Sps	{
320221715Sdelphij		parg.p_string = opt_desc(o);
32160786Sps		error("Cannot query the %s option", &parg);
32260786Sps		return;
32360786Sps	}
32460786Sps
32560786Sps	/*
32660786Sps	 * Check for something which appears to be a do_toggle
32760786Sps	 * (because the "-" command was used), but really is not.
32860786Sps	 * This could be a string option with no string, or
32960786Sps	 * a number option with no number.
33060786Sps	 */
33160786Sps	switch (o->otype & OTYPE)
33260786Sps	{
33360786Sps	case STRING:
33460786Sps	case NUMBER:
33560786Sps		if (how_toggle == OPT_TOGGLE && *s == '\0')
33660786Sps			how_toggle = OPT_NO_TOGGLE;
33760786Sps		break;
33860786Sps	}
33960786Sps
34060786Sps#if HILITE_SEARCH
34160786Sps	if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
34260786Sps		repaint_hilite(0);
34360786Sps#endif
34460786Sps
34560786Sps	/*
34660786Sps	 * Now actually toggle (change) the variable.
34760786Sps	 */
34860786Sps	if (how_toggle != OPT_NO_TOGGLE)
34960786Sps	{
35060786Sps		switch (o->otype & OTYPE)
35160786Sps		{
35260786Sps		case BOOL:
35360786Sps			/*
35460786Sps			 * Boolean.
35560786Sps			 */
35660786Sps			switch (how_toggle)
35760786Sps			{
35860786Sps			case OPT_TOGGLE:
35960786Sps				*(o->ovar) = ! *(o->ovar);
36060786Sps				break;
36160786Sps			case OPT_UNSET:
36260786Sps				*(o->ovar) = o->odefault;
36360786Sps				break;
36460786Sps			case OPT_SET:
36560786Sps				*(o->ovar) = ! o->odefault;
36660786Sps				break;
36760786Sps			}
36860786Sps			break;
36960786Sps		case TRIPLE:
37060786Sps			/*
37160786Sps			 * Triple:
37260786Sps			 *	If user gave the lower case letter, then switch
37360786Sps			 *	to 1 unless already 1, in which case make it 0.
37460786Sps			 *	If user gave the upper case letter, then switch
37560786Sps			 *	to 2 unless already 2, in which case make it 0.
37660786Sps			 */
37760786Sps			switch (how_toggle)
37860786Sps			{
37960786Sps			case OPT_TOGGLE:
380221715Sdelphij				*(o->ovar) = flip_triple(*(o->ovar), lower);
38160786Sps				break;
38260786Sps			case OPT_UNSET:
38360786Sps				*(o->ovar) = o->odefault;
38460786Sps				break;
38560786Sps			case OPT_SET:
386221715Sdelphij				*(o->ovar) = flip_triple(o->odefault, lower);
38760786Sps				break;
38860786Sps			}
38960786Sps			break;
39060786Sps		case STRING:
39160786Sps			/*
39260786Sps			 * String: don't do anything here.
39360786Sps			 *	The handling function will do everything.
39460786Sps			 */
39560786Sps			switch (how_toggle)
39660786Sps			{
39760786Sps			case OPT_SET:
39860786Sps			case OPT_UNSET:
39960786Sps				error("Cannot use \"-+\" or \"--\" for a string option",
40060786Sps					NULL_PARG);
40160786Sps				return;
40260786Sps			}
40360786Sps			break;
40460786Sps		case NUMBER:
40560786Sps			/*
40660786Sps			 * Number: set the variable to the given number.
40760786Sps			 */
40860786Sps			switch (how_toggle)
40960786Sps			{
41060786Sps			case OPT_TOGGLE:
411128345Stjr				num = getnum(&s, NULL, &err);
41260786Sps				if (!err)
41360786Sps					*(o->ovar) = num;
41460786Sps				break;
41560786Sps			case OPT_UNSET:
41660786Sps				*(o->ovar) = o->odefault;
41760786Sps				break;
41860786Sps			case OPT_SET:
41960786Sps				error("Can't use \"-!\" for a numeric option",
42060786Sps					NULL_PARG);
42160786Sps				return;
42260786Sps			}
42360786Sps			break;
42460786Sps		}
42560786Sps	}
42660786Sps
42760786Sps	/*
42860786Sps	 * Call the handling function for any special action
42960786Sps	 * specific to this option.
43060786Sps	 */
43160786Sps	if (o->ofunc != NULL)
43260786Sps		(*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s);
43360786Sps
43460786Sps#if HILITE_SEARCH
43560786Sps	if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
43660786Sps		chg_hilite();
43760786Sps#endif
43860786Sps
43960786Sps	if (!no_prompt)
44060786Sps	{
44160786Sps		/*
44260786Sps		 * Print a message describing the new setting.
44360786Sps		 */
44460786Sps		switch (o->otype & OTYPE)
44560786Sps		{
44660786Sps		case BOOL:
44760786Sps		case TRIPLE:
44860786Sps			/*
44960786Sps			 * Print the odesc message.
45060786Sps			 */
45160786Sps			error(o->odesc[*(o->ovar)], NULL_PARG);
45260786Sps			break;
45360786Sps		case NUMBER:
45460786Sps			/*
45560786Sps			 * The message is in odesc[1] and has a %d for
45660786Sps			 * the value of the variable.
45760786Sps			 */
45860786Sps			parg.p_int = *(o->ovar);
45960786Sps			error(o->odesc[1], &parg);
46060786Sps			break;
46160786Sps		case STRING:
46260786Sps			/*
46360786Sps			 * Message was already printed by the handling function.
46460786Sps			 */
46560786Sps			break;
46660786Sps		}
46760786Sps	}
46860786Sps
46960786Sps	if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT))
47060786Sps		screen_trashed = TRUE;
47160786Sps}
47260786Sps
47360786Sps/*
47460786Sps * "Toggle" a triple-valued option.
47560786Sps */
47660786Sps	static int
47760786Spsflip_triple(val, lc)
47860786Sps	int val;
47960786Sps	int lc;
48060786Sps{
48160786Sps	if (lc)
48260786Sps		return ((val == OPT_ON) ? OPT_OFF : OPT_ON);
48360786Sps	else
48460786Sps		return ((val == OPT_ONPLUS) ? OPT_OFF : OPT_ONPLUS);
48560786Sps}
48660786Sps
48760786Sps/*
488221715Sdelphij * Determine if an option takes a parameter.
48960786Sps */
49060786Sps	public int
491221715Sdelphijopt_has_param(o)
492221715Sdelphij	struct loption *o;
49360786Sps{
49460786Sps	if (o == NULL)
495221715Sdelphij		return (0);
496221715Sdelphij	if (o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE))
497221715Sdelphij		return (0);
498221715Sdelphij	return (1);
49960786Sps}
50060786Sps
50160786Sps/*
50260786Sps * Return the prompt to be used for a given option letter.
50360786Sps * Only string and number valued options have prompts.
50460786Sps */
50560786Sps	public char *
506221715Sdelphijopt_prompt(o)
507221715Sdelphij	struct loption *o;
50860786Sps{
50960786Sps	if (o == NULL || (o->otype & (STRING|NUMBER)) == 0)
510221715Sdelphij		return ("?");
51160786Sps	return (o->odesc[0]);
51260786Sps}
51360786Sps
51460786Sps/*
51560786Sps * Return whether or not there is a string option pending;
51660786Sps * that is, if the previous option was a string-valued option letter
51760786Sps * (like -P) without a following string.
51860786Sps * In that case, the current option is taken to be the string for
51960786Sps * the previous option.
52060786Sps */
52160786Sps	public int
52260786Spsisoptpending()
52360786Sps{
52460786Sps	return (pendopt != NULL);
52560786Sps}
52660786Sps
52760786Sps/*
52860786Sps * Print error message about missing string.
52960786Sps */
53060786Sps	static void
53160786Spsnostring(printopt)
53260786Sps	char *printopt;
53360786Sps{
53460786Sps	PARG parg;
53560786Sps	parg.p_string = printopt;
53660786Sps	error("Value is required after %s", &parg);
53760786Sps}
53860786Sps
53960786Sps/*
54060786Sps * Print error message if a STRING type option is not followed by a string.
54160786Sps */
54260786Sps	public void
54360786Spsnopendopt()
54460786Sps{
545221715Sdelphij	nostring(opt_desc(pendopt));
54660786Sps}
54760786Sps
54860786Sps/*
54960786Sps * Scan to end of string or to an END_OPTION_STRING character.
55060786Sps * In the latter case, replace the char with a null char.
55160786Sps * Return a pointer to the remainder of the string, if any.
55260786Sps */
55360786Sps	static char *
554128345Stjroptstring(s, p_str, printopt, validchars)
55560786Sps	char *s;
556128345Stjr	char **p_str;
55760786Sps	char *printopt;
55889019Sps	char *validchars;
55960786Sps{
56060786Sps	register char *p;
56160786Sps
56260786Sps	if (*s == '\0')
56360786Sps	{
56460786Sps		nostring(printopt);
56560786Sps		quit(QUIT_ERROR);
56660786Sps	}
567128345Stjr	*p_str = s;
56860786Sps	for (p = s;  *p != '\0';  p++)
569128345Stjr	{
57089019Sps		if (*p == END_OPTION_STRING ||
57189019Sps		    (validchars != NULL && strchr(validchars, *p) == NULL))
57260786Sps		{
57389019Sps			switch (*p)
57489019Sps			{
57589019Sps			case END_OPTION_STRING:
57689019Sps			case ' ':  case '\t':  case '-':
577128345Stjr				/* Replace the char with a null to terminate string. */
578128345Stjr				*p++ = '\0';
57989019Sps				break;
58089019Sps			default:
581128345Stjr				/* Cannot replace char; make a copy of the string. */
582128345Stjr				*p_str = (char *) ecalloc(p-s+1, sizeof(char));
583128345Stjr				strncpy(*p_str, s, p-s);
584128345Stjr				(*p_str)[p-s] = '\0';
58589019Sps				break;
58689019Sps			}
587128345Stjr			break;
58860786Sps		}
589128345Stjr	}
59060786Sps	return (p);
59160786Sps}
59260786Sps
59360786Sps/*
594170256Sdelphij */
595170256Sdelphij	static int
596170256Sdelphijnum_error(printopt, errp)
597170256Sdelphij	char *printopt;
598170256Sdelphij	int *errp;
599170256Sdelphij{
600170256Sdelphij	PARG parg;
601170256Sdelphij
602170256Sdelphij	if (errp != NULL)
603170256Sdelphij	{
604170256Sdelphij		*errp = TRUE;
605170256Sdelphij		return (-1);
606170256Sdelphij	}
607170256Sdelphij	if (printopt != NULL)
608170256Sdelphij	{
609170256Sdelphij		parg.p_string = printopt;
610170256Sdelphij		error("Number is required after %s", &parg);
611170256Sdelphij	}
612170256Sdelphij	quit(QUIT_ERROR);
613170256Sdelphij	/* NOTREACHED */
614170256Sdelphij	return (-1);
615170256Sdelphij}
616170256Sdelphij
617170256Sdelphij/*
61860786Sps * Translate a string into a number.
61960786Sps * Like atoi(), but takes a pointer to a char *, and updates
62060786Sps * the char * to point after the translated number.
62160786Sps */
62260786Sps	public int
62360786Spsgetnum(sp, printopt, errp)
62460786Sps	char **sp;
62560786Sps	char *printopt;
62660786Sps	int *errp;
62760786Sps{
62860786Sps	register char *s;
62960786Sps	register int n;
63060786Sps	register int neg;
63160786Sps
63260786Sps	s = skipsp(*sp);
63360786Sps	neg = FALSE;
63460786Sps	if (*s == '-')
63560786Sps	{
63660786Sps		neg = TRUE;
63760786Sps		s++;
63860786Sps	}
63960786Sps	if (*s < '0' || *s > '9')
640170256Sdelphij		return (num_error(printopt, errp));
64160786Sps
64260786Sps	n = 0;
64360786Sps	while (*s >= '0' && *s <= '9')
64460786Sps		n = 10 * n + *s++ - '0';
64560786Sps	*sp = s;
64660786Sps	if (errp != NULL)
64760786Sps		*errp = FALSE;
64860786Sps	if (neg)
64960786Sps		n = -n;
65060786Sps	return (n);
65160786Sps}
652170256Sdelphij
653170256Sdelphij/*
654170256Sdelphij * Translate a string into a fraction, represented by the part of a
655170256Sdelphij * number which would follow a decimal point.
656170256Sdelphij * The value of the fraction is returned as parts per NUM_FRAC_DENOM.
657170256Sdelphij * That is, if "n" is returned, the fraction intended is n/NUM_FRAC_DENOM.
658170256Sdelphij */
659170256Sdelphij	public long
660170256Sdelphijgetfraction(sp, printopt, errp)
661170256Sdelphij	char **sp;
662170256Sdelphij	char *printopt;
663170256Sdelphij	int *errp;
664170256Sdelphij{
665170256Sdelphij	register char *s;
666170256Sdelphij	long frac = 0;
667170256Sdelphij	int fraclen = 0;
668170256Sdelphij
669170256Sdelphij	s = skipsp(*sp);
670170256Sdelphij	if (*s < '0' || *s > '9')
671170256Sdelphij		return (num_error(printopt, errp));
672170256Sdelphij
673170256Sdelphij	for ( ;  *s >= '0' && *s <= '9';  s++)
674170256Sdelphij	{
675170256Sdelphij		frac = (frac * 10) + (*s - '0');
676170256Sdelphij		fraclen++;
677170256Sdelphij	}
678170256Sdelphij	if (fraclen > NUM_LOG_FRAC_DENOM)
679170256Sdelphij		while (fraclen-- > NUM_LOG_FRAC_DENOM)
680170256Sdelphij			frac /= 10;
681170256Sdelphij	else
682170256Sdelphij		while (fraclen++ < NUM_LOG_FRAC_DENOM)
683170256Sdelphij			frac *= 10;
684170256Sdelphij	*sp = s;
685170256Sdelphij	if (errp != NULL)
686170256Sdelphij		*errp = FALSE;
687170256Sdelphij	return (frac);
688170256Sdelphij}
689170256Sdelphij
690170256Sdelphij
691170256Sdelphij/*
692170256Sdelphij * Get the value of the -e flag.
693170256Sdelphij */
694170256Sdelphij	public int
695170256Sdelphijget_quit_at_eof()
696170256Sdelphij{
697170256Sdelphij	if (!less_is_more)
698170256Sdelphij		return quit_at_eof;
699170256Sdelphij	/* When less_is_more is set, the -e flag semantics are different. */
700170256Sdelphij	return quit_at_eof ? OPT_ON : OPT_ONPLUS;
701170256Sdelphij}
702