xref: /freebsd/contrib/less/option.c (revision c9346414d95d69f958210e825deb3b086dac3529)
1a5f0fb15SPaul Saab /*
2a5f0fb15SPaul Saab  * Copyright (C) 1984-2000  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 
24a5f0fb15SPaul Saab static struct option *pendopt;
25a5f0fb15SPaul Saab public int plusoption = FALSE;
26a5f0fb15SPaul Saab 
27a5f0fb15SPaul Saab static char *propt();
28a5f0fb15SPaul Saab static char *optstring();
29a5f0fb15SPaul Saab static int flip_triple();
30a5f0fb15SPaul Saab 
31a5f0fb15SPaul Saab extern int screen_trashed;
32a5f0fb15SPaul Saab extern char *every_first_cmd;
33a5f0fb15SPaul Saab 
34a5f0fb15SPaul Saab /*
35a5f0fb15SPaul Saab  * Scan an argument (either from the command line or from the
36a5f0fb15SPaul Saab  * LESS environment variable) and process it.
37a5f0fb15SPaul Saab  */
38a5f0fb15SPaul Saab 	public void
39a5f0fb15SPaul Saab scan_option(s)
40a5f0fb15SPaul Saab 	char *s;
41a5f0fb15SPaul Saab {
42a5f0fb15SPaul Saab 	register struct option *o;
43a5f0fb15SPaul Saab 	register int optc;
44a5f0fb15SPaul Saab 	char *optname;
45a5f0fb15SPaul Saab 	char *printopt;
46a5f0fb15SPaul Saab 	char *str;
47a5f0fb15SPaul Saab 	int set_default;
48a5f0fb15SPaul Saab 	int lc;
49a5f0fb15SPaul Saab 	int err;
50a5f0fb15SPaul Saab 	PARG parg;
51a5f0fb15SPaul Saab 
52a5f0fb15SPaul Saab 	if (s == NULL)
53a5f0fb15SPaul Saab 		return;
54a5f0fb15SPaul Saab 
55a5f0fb15SPaul Saab 	/*
56a5f0fb15SPaul Saab 	 * If we have a pending option which requires an argument,
57a5f0fb15SPaul Saab 	 * handle it now.
58a5f0fb15SPaul Saab 	 * This happens if the previous option was, for example, "-P"
59a5f0fb15SPaul Saab 	 * without a following string.  In that case, the current
60a5f0fb15SPaul Saab 	 * option is simply the argument for the previous option.
61a5f0fb15SPaul Saab 	 */
62a5f0fb15SPaul Saab 	if (pendopt != NULL)
63a5f0fb15SPaul Saab 	{
64a5f0fb15SPaul Saab 		switch (pendopt->otype & OTYPE)
65a5f0fb15SPaul Saab 		{
66a5f0fb15SPaul Saab 		case STRING:
67a5f0fb15SPaul Saab 			(*pendopt->ofunc)(INIT, s);
68a5f0fb15SPaul Saab 			break;
69a5f0fb15SPaul Saab 		case NUMBER:
70a5f0fb15SPaul Saab 			printopt = propt(pendopt->oletter);
71a5f0fb15SPaul Saab 			*(pendopt->ovar) = getnum(&s, printopt, (int*)NULL);
72a5f0fb15SPaul Saab 			break;
73a5f0fb15SPaul Saab 		}
74a5f0fb15SPaul Saab 		pendopt = NULL;
75a5f0fb15SPaul Saab 		return;
76a5f0fb15SPaul Saab 	}
77a5f0fb15SPaul Saab 
78a5f0fb15SPaul Saab 	set_default = FALSE;
79a5f0fb15SPaul Saab 	optname = NULL;
80a5f0fb15SPaul Saab 
81a5f0fb15SPaul Saab 	while (*s != '\0')
82a5f0fb15SPaul Saab 	{
83a5f0fb15SPaul Saab 		/*
84a5f0fb15SPaul Saab 		 * Check some special cases first.
85a5f0fb15SPaul Saab 		 */
86a5f0fb15SPaul Saab 		switch (optc = *s++)
87a5f0fb15SPaul Saab 		{
88a5f0fb15SPaul Saab 		case ' ':
89a5f0fb15SPaul Saab 		case '\t':
90a5f0fb15SPaul Saab 		case END_OPTION_STRING:
91a5f0fb15SPaul Saab 			continue;
92a5f0fb15SPaul Saab 		case '-':
93a5f0fb15SPaul Saab 			/*
94a5f0fb15SPaul Saab 			 * "--" indicates an option name instead of a letter.
95a5f0fb15SPaul Saab 			 */
96a5f0fb15SPaul Saab 			if (*s == '-')
97a5f0fb15SPaul Saab 			{
98a5f0fb15SPaul Saab 				optname = ++s;
99a5f0fb15SPaul Saab 				break;
100a5f0fb15SPaul Saab 			}
101a5f0fb15SPaul Saab 			/*
102a5f0fb15SPaul Saab 			 * "-+" means set these options back to their defaults.
103a5f0fb15SPaul Saab 			 * (They may have been set otherwise by previous
104a5f0fb15SPaul Saab 			 * options.)
105a5f0fb15SPaul Saab 			 */
106a5f0fb15SPaul Saab 			set_default = (*s == '+');
107a5f0fb15SPaul Saab 			if (set_default)
108a5f0fb15SPaul Saab 				s++;
109a5f0fb15SPaul Saab 			continue;
110a5f0fb15SPaul Saab 		case '+':
111a5f0fb15SPaul Saab 			/*
112a5f0fb15SPaul Saab 			 * An option prefixed by a "+" is ungotten, so
113a5f0fb15SPaul Saab 			 * that it is interpreted as less commands
114a5f0fb15SPaul Saab 			 * processed at the start of the first input file.
115a5f0fb15SPaul Saab 			 * "++" means process the commands at the start of
116a5f0fb15SPaul Saab 			 * EVERY input file.
117a5f0fb15SPaul Saab 			 */
118a5f0fb15SPaul Saab 			plusoption = TRUE;
119c9346414SPaul Saab 			str = s;
120c9346414SPaul Saab 			s = optstring(s, propt('+'), NULL);
121c9346414SPaul Saab 			if (*str == '+')
122c9346414SPaul Saab 				every_first_cmd = save(++str);
123a5f0fb15SPaul Saab 			else
124c9346414SPaul Saab 				ungetsc(str);
125a5f0fb15SPaul Saab 			continue;
126a5f0fb15SPaul Saab 		case '0':  case '1':  case '2':  case '3':  case '4':
127a5f0fb15SPaul Saab 		case '5':  case '6':  case '7':  case '8':  case '9':
128a5f0fb15SPaul Saab 			/*
129a5f0fb15SPaul Saab 			 * Special "more" compatibility form "-<number>"
130a5f0fb15SPaul Saab 			 * instead of -z<number> to set the scrolling
131a5f0fb15SPaul Saab 			 * window size.
132a5f0fb15SPaul Saab 			 */
133a5f0fb15SPaul Saab 			s--;
134a5f0fb15SPaul Saab 			optc = 'z';
135a5f0fb15SPaul Saab 			break;
136a5f0fb15SPaul Saab 		}
137a5f0fb15SPaul Saab 
138a5f0fb15SPaul Saab 		/*
139a5f0fb15SPaul Saab 		 * Not a special case.
140a5f0fb15SPaul Saab 		 * Look up the option letter in the option table.
141a5f0fb15SPaul Saab 		 */
142a5f0fb15SPaul Saab 		err = 0;
143a5f0fb15SPaul Saab 		if (optname == NULL)
144a5f0fb15SPaul Saab 		{
145a5f0fb15SPaul Saab 			printopt = propt(optc);
146a5f0fb15SPaul Saab 			lc = SIMPLE_IS_LOWER(optc);
147a5f0fb15SPaul Saab 			o = findopt(optc);
148a5f0fb15SPaul Saab 		} else
149a5f0fb15SPaul Saab 		{
150a5f0fb15SPaul Saab 			printopt = optname;
151a5f0fb15SPaul Saab 			lc = SIMPLE_IS_LOWER(optname[0]);
152a5f0fb15SPaul Saab 			o = findopt_name(&optname, NULL, &err);
153a5f0fb15SPaul Saab 			s = optname;
154a5f0fb15SPaul Saab 			optname = NULL;
155a5f0fb15SPaul Saab 			if (*s == '\0' || *s == ' ')
156a5f0fb15SPaul Saab 			{
157a5f0fb15SPaul Saab 				/*
158a5f0fb15SPaul Saab 				 * The option name matches exactly.
159a5f0fb15SPaul Saab 				 */
160a5f0fb15SPaul Saab 				;
161a5f0fb15SPaul Saab 			} else if (*s == '=')
162a5f0fb15SPaul Saab 			{
163a5f0fb15SPaul Saab 				/*
164a5f0fb15SPaul Saab 				 * The option name is followed by "=value".
165a5f0fb15SPaul Saab 				 */
166a5f0fb15SPaul Saab 				if (o != NULL &&
167a5f0fb15SPaul Saab 				    (o->otype & OTYPE) != STRING &&
168a5f0fb15SPaul Saab 				    (o->otype & OTYPE) != NUMBER)
169a5f0fb15SPaul Saab 				{
170a5f0fb15SPaul Saab 					parg.p_string = printopt;
171a5f0fb15SPaul Saab 					error("The %s option should not be followed by =",
172a5f0fb15SPaul Saab 						&parg);
173a5f0fb15SPaul Saab 					quit(QUIT_ERROR);
174a5f0fb15SPaul Saab 				}
175a5f0fb15SPaul Saab 				s++;
176a5f0fb15SPaul Saab 			} else
177a5f0fb15SPaul Saab 			{
178a5f0fb15SPaul Saab 				/*
179a5f0fb15SPaul Saab 				 * The specified name is longer than the
180a5f0fb15SPaul Saab 				 * real option name.
181a5f0fb15SPaul Saab 				 */
182a5f0fb15SPaul Saab 				o = NULL;
183a5f0fb15SPaul Saab 			}
184a5f0fb15SPaul Saab 		}
185a5f0fb15SPaul Saab 		if (o == NULL)
186a5f0fb15SPaul Saab 		{
187a5f0fb15SPaul Saab 			parg.p_string = printopt;
188a5f0fb15SPaul Saab 			if (err == OPT_AMBIG)
189a5f0fb15SPaul Saab 				error("%s is an ambiguous abbreviation (\"less --help\" for help)",
190a5f0fb15SPaul Saab 					&parg);
191a5f0fb15SPaul Saab 			else
192a5f0fb15SPaul Saab 				error("There is no %s option (\"less --help\" for help)",
193a5f0fb15SPaul Saab 					&parg);
194a5f0fb15SPaul Saab 			quit(QUIT_ERROR);
195a5f0fb15SPaul Saab 		}
196a5f0fb15SPaul Saab 
197a5f0fb15SPaul Saab 		str = NULL;
198a5f0fb15SPaul Saab 		switch (o->otype & OTYPE)
199a5f0fb15SPaul Saab 		{
200a5f0fb15SPaul Saab 		case BOOL:
201a5f0fb15SPaul Saab 			if (set_default)
202a5f0fb15SPaul Saab 				*(o->ovar) = o->odefault;
203a5f0fb15SPaul Saab 			else
204a5f0fb15SPaul Saab 				*(o->ovar) = ! o->odefault;
205a5f0fb15SPaul Saab 			break;
206a5f0fb15SPaul Saab 		case TRIPLE:
207a5f0fb15SPaul Saab 			if (set_default)
208a5f0fb15SPaul Saab 				*(o->ovar) = o->odefault;
209a5f0fb15SPaul Saab 			else
210a5f0fb15SPaul Saab 				*(o->ovar) = flip_triple(o->odefault, lc);
211a5f0fb15SPaul Saab 			break;
212a5f0fb15SPaul Saab 		case STRING:
213a5f0fb15SPaul Saab 			if (*s == '\0')
214a5f0fb15SPaul Saab 			{
215a5f0fb15SPaul Saab 				/*
216a5f0fb15SPaul Saab 				 * Set pendopt and return.
217a5f0fb15SPaul Saab 				 * We will get the string next time
218a5f0fb15SPaul Saab 				 * scan_option is called.
219a5f0fb15SPaul Saab 				 */
220a5f0fb15SPaul Saab 				pendopt = o;
221a5f0fb15SPaul Saab 				return;
222a5f0fb15SPaul Saab 			}
223a5f0fb15SPaul Saab 			/*
224a5f0fb15SPaul Saab 			 * Don't do anything here.
225a5f0fb15SPaul Saab 			 * All processing of STRING options is done by
226a5f0fb15SPaul Saab 			 * the handling function.
227a5f0fb15SPaul Saab 			 */
228a5f0fb15SPaul Saab 			str = s;
229c9346414SPaul Saab 			s = optstring(s, printopt, o->odesc[1]);
230a5f0fb15SPaul Saab 			break;
231a5f0fb15SPaul Saab 		case NUMBER:
232a5f0fb15SPaul Saab 			if (*s == '\0')
233a5f0fb15SPaul Saab 			{
234a5f0fb15SPaul Saab 				pendopt = o;
235a5f0fb15SPaul Saab 				return;
236a5f0fb15SPaul Saab 			}
237a5f0fb15SPaul Saab 			*(o->ovar) = getnum(&s, printopt, (int*)NULL);
238a5f0fb15SPaul Saab 			break;
239a5f0fb15SPaul Saab 		}
240a5f0fb15SPaul Saab 		/*
241a5f0fb15SPaul Saab 		 * If the option has a handling function, call it.
242a5f0fb15SPaul Saab 		 */
243a5f0fb15SPaul Saab 		if (o->ofunc != NULL)
244a5f0fb15SPaul Saab 			(*o->ofunc)(INIT, str);
245a5f0fb15SPaul Saab 	}
246a5f0fb15SPaul Saab }
247a5f0fb15SPaul Saab 
248a5f0fb15SPaul Saab /*
249a5f0fb15SPaul Saab  * Toggle command line flags from within the program.
250a5f0fb15SPaul Saab  * Used by the "-" and "_" commands.
251a5f0fb15SPaul Saab  * how_toggle may be:
252a5f0fb15SPaul Saab  *	OPT_NO_TOGGLE	just report the current setting, without changing it.
253a5f0fb15SPaul Saab  *	OPT_TOGGLE	invert the current setting
254a5f0fb15SPaul Saab  *	OPT_UNSET	set to the default value
255a5f0fb15SPaul Saab  *	OPT_SET		set to the inverse of the default value
256a5f0fb15SPaul Saab  */
257a5f0fb15SPaul Saab 	public void
258a5f0fb15SPaul Saab toggle_option(c, s, how_toggle)
259a5f0fb15SPaul Saab 	int c;
260a5f0fb15SPaul Saab 	char *s;
261a5f0fb15SPaul Saab 	int how_toggle;
262a5f0fb15SPaul Saab {
263a5f0fb15SPaul Saab 	register struct option *o;
264a5f0fb15SPaul Saab 	register int num;
265a5f0fb15SPaul Saab 	int no_prompt;
266a5f0fb15SPaul Saab 	int err;
267a5f0fb15SPaul Saab 	PARG parg;
268a5f0fb15SPaul Saab 
269a5f0fb15SPaul Saab 	no_prompt = (how_toggle & OPT_NO_PROMPT);
270a5f0fb15SPaul Saab 	how_toggle &= ~OPT_NO_PROMPT;
271a5f0fb15SPaul Saab 
272a5f0fb15SPaul Saab 	/*
273a5f0fb15SPaul Saab 	 * Look up the option letter in the option table.
274a5f0fb15SPaul Saab 	 */
275a5f0fb15SPaul Saab 	o = findopt(c);
276a5f0fb15SPaul Saab 	if (o == NULL)
277a5f0fb15SPaul Saab 	{
278a5f0fb15SPaul Saab 		parg.p_string = propt(c);
279a5f0fb15SPaul Saab 		error("There is no %s option", &parg);
280a5f0fb15SPaul Saab 		return;
281a5f0fb15SPaul Saab 	}
282a5f0fb15SPaul Saab 
283a5f0fb15SPaul Saab 	if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE))
284a5f0fb15SPaul Saab 	{
285a5f0fb15SPaul Saab 		parg.p_string = propt(c);
286a5f0fb15SPaul Saab 		error("Cannot change the %s option", &parg);
287a5f0fb15SPaul Saab 		return;
288a5f0fb15SPaul Saab 	}
289a5f0fb15SPaul Saab 
290a5f0fb15SPaul Saab 	if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY))
291a5f0fb15SPaul Saab 	{
292a5f0fb15SPaul Saab 		parg.p_string = propt(c);
293a5f0fb15SPaul Saab 		error("Cannot query the %s option", &parg);
294a5f0fb15SPaul Saab 		return;
295a5f0fb15SPaul Saab 	}
296a5f0fb15SPaul Saab 
297a5f0fb15SPaul Saab 	/*
298a5f0fb15SPaul Saab 	 * Check for something which appears to be a do_toggle
299a5f0fb15SPaul Saab 	 * (because the "-" command was used), but really is not.
300a5f0fb15SPaul Saab 	 * This could be a string option with no string, or
301a5f0fb15SPaul Saab 	 * a number option with no number.
302a5f0fb15SPaul Saab 	 */
303a5f0fb15SPaul Saab 	switch (o->otype & OTYPE)
304a5f0fb15SPaul Saab 	{
305a5f0fb15SPaul Saab 	case STRING:
306a5f0fb15SPaul Saab 	case NUMBER:
307a5f0fb15SPaul Saab 		if (how_toggle == OPT_TOGGLE && *s == '\0')
308a5f0fb15SPaul Saab 			how_toggle = OPT_NO_TOGGLE;
309a5f0fb15SPaul Saab 		break;
310a5f0fb15SPaul Saab 	}
311a5f0fb15SPaul Saab 
312a5f0fb15SPaul Saab #if HILITE_SEARCH
313a5f0fb15SPaul Saab 	if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
314a5f0fb15SPaul Saab 		repaint_hilite(0);
315a5f0fb15SPaul Saab #endif
316a5f0fb15SPaul Saab 
317a5f0fb15SPaul Saab 	/*
318a5f0fb15SPaul Saab 	 * Now actually toggle (change) the variable.
319a5f0fb15SPaul Saab 	 */
320a5f0fb15SPaul Saab 	if (how_toggle != OPT_NO_TOGGLE)
321a5f0fb15SPaul Saab 	{
322a5f0fb15SPaul Saab 		switch (o->otype & OTYPE)
323a5f0fb15SPaul Saab 		{
324a5f0fb15SPaul Saab 		case BOOL:
325a5f0fb15SPaul Saab 			/*
326a5f0fb15SPaul Saab 			 * Boolean.
327a5f0fb15SPaul Saab 			 */
328a5f0fb15SPaul Saab 			switch (how_toggle)
329a5f0fb15SPaul Saab 			{
330a5f0fb15SPaul Saab 			case OPT_TOGGLE:
331a5f0fb15SPaul Saab 				*(o->ovar) = ! *(o->ovar);
332a5f0fb15SPaul Saab 				break;
333a5f0fb15SPaul Saab 			case OPT_UNSET:
334a5f0fb15SPaul Saab 				*(o->ovar) = o->odefault;
335a5f0fb15SPaul Saab 				break;
336a5f0fb15SPaul Saab 			case OPT_SET:
337a5f0fb15SPaul Saab 				*(o->ovar) = ! o->odefault;
338a5f0fb15SPaul Saab 				break;
339a5f0fb15SPaul Saab 			}
340a5f0fb15SPaul Saab 			break;
341a5f0fb15SPaul Saab 		case TRIPLE:
342a5f0fb15SPaul Saab 			/*
343a5f0fb15SPaul Saab 			 * Triple:
344a5f0fb15SPaul Saab 			 *	If user gave the lower case letter, then switch
345a5f0fb15SPaul Saab 			 *	to 1 unless already 1, in which case make it 0.
346a5f0fb15SPaul Saab 			 *	If user gave the upper case letter, then switch
347a5f0fb15SPaul Saab 			 *	to 2 unless already 2, in which case make it 0.
348a5f0fb15SPaul Saab 			 */
349a5f0fb15SPaul Saab 			switch (how_toggle)
350a5f0fb15SPaul Saab 			{
351a5f0fb15SPaul Saab 			case OPT_TOGGLE:
352a5f0fb15SPaul Saab 				*(o->ovar) = flip_triple(*(o->ovar),
353a5f0fb15SPaul Saab 						islower(c));
354a5f0fb15SPaul Saab 				break;
355a5f0fb15SPaul Saab 			case OPT_UNSET:
356a5f0fb15SPaul Saab 				*(o->ovar) = o->odefault;
357a5f0fb15SPaul Saab 				break;
358a5f0fb15SPaul Saab 			case OPT_SET:
359a5f0fb15SPaul Saab 				*(o->ovar) = flip_triple(o->odefault,
360a5f0fb15SPaul Saab 						islower(c));
361a5f0fb15SPaul Saab 				break;
362a5f0fb15SPaul Saab 			}
363a5f0fb15SPaul Saab 			break;
364a5f0fb15SPaul Saab 		case STRING:
365a5f0fb15SPaul Saab 			/*
366a5f0fb15SPaul Saab 			 * String: don't do anything here.
367a5f0fb15SPaul Saab 			 *	The handling function will do everything.
368a5f0fb15SPaul Saab 			 */
369a5f0fb15SPaul Saab 			switch (how_toggle)
370a5f0fb15SPaul Saab 			{
371a5f0fb15SPaul Saab 			case OPT_SET:
372a5f0fb15SPaul Saab 			case OPT_UNSET:
373a5f0fb15SPaul Saab 				error("Cannot use \"-+\" or \"--\" for a string option",
374a5f0fb15SPaul Saab 					NULL_PARG);
375a5f0fb15SPaul Saab 				return;
376a5f0fb15SPaul Saab 			}
377a5f0fb15SPaul Saab 			break;
378a5f0fb15SPaul Saab 		case NUMBER:
379a5f0fb15SPaul Saab 			/*
380a5f0fb15SPaul Saab 			 * Number: set the variable to the given number.
381a5f0fb15SPaul Saab 			 */
382a5f0fb15SPaul Saab 			switch (how_toggle)
383a5f0fb15SPaul Saab 			{
384a5f0fb15SPaul Saab 			case OPT_TOGGLE:
385a5f0fb15SPaul Saab 				num = getnum(&s, '\0', &err);
386a5f0fb15SPaul Saab 				if (!err)
387a5f0fb15SPaul Saab 					*(o->ovar) = num;
388a5f0fb15SPaul Saab 				break;
389a5f0fb15SPaul Saab 			case OPT_UNSET:
390a5f0fb15SPaul Saab 				*(o->ovar) = o->odefault;
391a5f0fb15SPaul Saab 				break;
392a5f0fb15SPaul Saab 			case OPT_SET:
393a5f0fb15SPaul Saab 				error("Can't use \"-!\" for a numeric option",
394a5f0fb15SPaul Saab 					NULL_PARG);
395a5f0fb15SPaul Saab 				return;
396a5f0fb15SPaul Saab 			}
397a5f0fb15SPaul Saab 			break;
398a5f0fb15SPaul Saab 		}
399a5f0fb15SPaul Saab 	}
400a5f0fb15SPaul Saab 
401a5f0fb15SPaul Saab 	/*
402a5f0fb15SPaul Saab 	 * Call the handling function for any special action
403a5f0fb15SPaul Saab 	 * specific to this option.
404a5f0fb15SPaul Saab 	 */
405a5f0fb15SPaul Saab 	if (o->ofunc != NULL)
406a5f0fb15SPaul Saab 		(*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s);
407a5f0fb15SPaul Saab 
408a5f0fb15SPaul Saab #if HILITE_SEARCH
409a5f0fb15SPaul Saab 	if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
410a5f0fb15SPaul Saab 		chg_hilite();
411a5f0fb15SPaul Saab #endif
412a5f0fb15SPaul Saab 
413a5f0fb15SPaul Saab 	if (!no_prompt)
414a5f0fb15SPaul Saab 	{
415a5f0fb15SPaul Saab 		/*
416a5f0fb15SPaul Saab 		 * Print a message describing the new setting.
417a5f0fb15SPaul Saab 		 */
418a5f0fb15SPaul Saab 		switch (o->otype & OTYPE)
419a5f0fb15SPaul Saab 		{
420a5f0fb15SPaul Saab 		case BOOL:
421a5f0fb15SPaul Saab 		case TRIPLE:
422a5f0fb15SPaul Saab 			/*
423a5f0fb15SPaul Saab 			 * Print the odesc message.
424a5f0fb15SPaul Saab 			 */
425a5f0fb15SPaul Saab 			error(o->odesc[*(o->ovar)], NULL_PARG);
426a5f0fb15SPaul Saab 			break;
427a5f0fb15SPaul Saab 		case NUMBER:
428a5f0fb15SPaul Saab 			/*
429a5f0fb15SPaul Saab 			 * The message is in odesc[1] and has a %d for
430a5f0fb15SPaul Saab 			 * the value of the variable.
431a5f0fb15SPaul Saab 			 */
432a5f0fb15SPaul Saab 			parg.p_int = *(o->ovar);
433a5f0fb15SPaul Saab 			error(o->odesc[1], &parg);
434a5f0fb15SPaul Saab 			break;
435a5f0fb15SPaul Saab 		case STRING:
436a5f0fb15SPaul Saab 			/*
437a5f0fb15SPaul Saab 			 * Message was already printed by the handling function.
438a5f0fb15SPaul Saab 			 */
439a5f0fb15SPaul Saab 			break;
440a5f0fb15SPaul Saab 		}
441a5f0fb15SPaul Saab 	}
442a5f0fb15SPaul Saab 
443a5f0fb15SPaul Saab 	if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT))
444a5f0fb15SPaul Saab 		screen_trashed = TRUE;
445a5f0fb15SPaul Saab }
446a5f0fb15SPaul Saab 
447a5f0fb15SPaul Saab /*
448a5f0fb15SPaul Saab  * "Toggle" a triple-valued option.
449a5f0fb15SPaul Saab  */
450a5f0fb15SPaul Saab 	static int
451a5f0fb15SPaul Saab flip_triple(val, lc)
452a5f0fb15SPaul Saab 	int val;
453a5f0fb15SPaul Saab 	int lc;
454a5f0fb15SPaul Saab {
455a5f0fb15SPaul Saab 	if (lc)
456a5f0fb15SPaul Saab 		return ((val == OPT_ON) ? OPT_OFF : OPT_ON);
457a5f0fb15SPaul Saab 	else
458a5f0fb15SPaul Saab 		return ((val == OPT_ONPLUS) ? OPT_OFF : OPT_ONPLUS);
459a5f0fb15SPaul Saab }
460a5f0fb15SPaul Saab 
461a5f0fb15SPaul Saab /*
462a5f0fb15SPaul Saab  * Return a string suitable for printing as the "name" of an option.
463a5f0fb15SPaul Saab  * For example, if the option letter is 'x', just return "-x".
464a5f0fb15SPaul Saab  */
465a5f0fb15SPaul Saab 	static char *
466a5f0fb15SPaul Saab propt(c)
467a5f0fb15SPaul Saab 	int c;
468a5f0fb15SPaul Saab {
469a5f0fb15SPaul Saab 	static char buf[8];
470a5f0fb15SPaul Saab 
471a5f0fb15SPaul Saab 	sprintf(buf, "-%s", prchar(c));
472a5f0fb15SPaul Saab 	return (buf);
473a5f0fb15SPaul Saab }
474a5f0fb15SPaul Saab 
475a5f0fb15SPaul Saab /*
476a5f0fb15SPaul Saab  * Determine if an option is a single character option (BOOL or TRIPLE),
477a5f0fb15SPaul Saab  * or if it a multi-character option (NUMBER).
478a5f0fb15SPaul Saab  */
479a5f0fb15SPaul Saab 	public int
480a5f0fb15SPaul Saab single_char_option(c)
481a5f0fb15SPaul Saab 	int c;
482a5f0fb15SPaul Saab {
483a5f0fb15SPaul Saab 	register struct option *o;
484a5f0fb15SPaul Saab 
485a5f0fb15SPaul Saab 	o = findopt(c);
486a5f0fb15SPaul Saab 	if (o == NULL)
487a5f0fb15SPaul Saab 		return (TRUE);
488a5f0fb15SPaul Saab 	return ((o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE)) != 0);
489a5f0fb15SPaul Saab }
490a5f0fb15SPaul Saab 
491a5f0fb15SPaul Saab /*
492a5f0fb15SPaul Saab  * Return the prompt to be used for a given option letter.
493a5f0fb15SPaul Saab  * Only string and number valued options have prompts.
494a5f0fb15SPaul Saab  */
495a5f0fb15SPaul Saab 	public char *
496a5f0fb15SPaul Saab opt_prompt(c)
497a5f0fb15SPaul Saab 	int c;
498a5f0fb15SPaul Saab {
499a5f0fb15SPaul Saab 	register struct option *o;
500a5f0fb15SPaul Saab 
501a5f0fb15SPaul Saab 	o = findopt(c);
502a5f0fb15SPaul Saab 	if (o == NULL || (o->otype & (STRING|NUMBER)) == 0)
503a5f0fb15SPaul Saab 		return (NULL);
504a5f0fb15SPaul Saab 	return (o->odesc[0]);
505a5f0fb15SPaul Saab }
506a5f0fb15SPaul Saab 
507a5f0fb15SPaul Saab /*
508a5f0fb15SPaul Saab  * Return whether or not there is a string option pending;
509a5f0fb15SPaul Saab  * that is, if the previous option was a string-valued option letter
510a5f0fb15SPaul Saab  * (like -P) without a following string.
511a5f0fb15SPaul Saab  * In that case, the current option is taken to be the string for
512a5f0fb15SPaul Saab  * the previous option.
513a5f0fb15SPaul Saab  */
514a5f0fb15SPaul Saab 	public int
515a5f0fb15SPaul Saab isoptpending()
516a5f0fb15SPaul Saab {
517a5f0fb15SPaul Saab 	return (pendopt != NULL);
518a5f0fb15SPaul Saab }
519a5f0fb15SPaul Saab 
520a5f0fb15SPaul Saab /*
521a5f0fb15SPaul Saab  * Print error message about missing string.
522a5f0fb15SPaul Saab  */
523a5f0fb15SPaul Saab 	static void
524a5f0fb15SPaul Saab nostring(printopt)
525a5f0fb15SPaul Saab 	char *printopt;
526a5f0fb15SPaul Saab {
527a5f0fb15SPaul Saab 	PARG parg;
528a5f0fb15SPaul Saab 	parg.p_string = printopt;
529a5f0fb15SPaul Saab 	error("Value is required after %s", &parg);
530a5f0fb15SPaul Saab }
531a5f0fb15SPaul Saab 
532a5f0fb15SPaul Saab /*
533a5f0fb15SPaul Saab  * Print error message if a STRING type option is not followed by a string.
534a5f0fb15SPaul Saab  */
535a5f0fb15SPaul Saab 	public void
536a5f0fb15SPaul Saab nopendopt()
537a5f0fb15SPaul Saab {
538a5f0fb15SPaul Saab 	nostring(propt(pendopt->oletter));
539a5f0fb15SPaul Saab }
540a5f0fb15SPaul Saab 
541a5f0fb15SPaul Saab /*
542a5f0fb15SPaul Saab  * Scan to end of string or to an END_OPTION_STRING character.
543a5f0fb15SPaul Saab  * In the latter case, replace the char with a null char.
544a5f0fb15SPaul Saab  * Return a pointer to the remainder of the string, if any.
545a5f0fb15SPaul Saab  */
546a5f0fb15SPaul Saab 	static char *
547c9346414SPaul Saab optstring(s, printopt, validchars)
548a5f0fb15SPaul Saab 	char *s;
549a5f0fb15SPaul Saab 	char *printopt;
550c9346414SPaul Saab 	char *validchars;
551a5f0fb15SPaul Saab {
552a5f0fb15SPaul Saab 	register char *p;
553c9346414SPaul Saab 	PARG parg;
554a5f0fb15SPaul Saab 
555a5f0fb15SPaul Saab 	if (*s == '\0')
556a5f0fb15SPaul Saab 	{
557a5f0fb15SPaul Saab 		nostring(printopt);
558a5f0fb15SPaul Saab 		quit(QUIT_ERROR);
559a5f0fb15SPaul Saab 	}
560a5f0fb15SPaul Saab 	for (p = s;  *p != '\0';  p++)
561c9346414SPaul Saab 		if (*p == END_OPTION_STRING ||
562c9346414SPaul Saab 		    (validchars != NULL && strchr(validchars, *p) == NULL))
563a5f0fb15SPaul Saab 		{
564c9346414SPaul Saab 			switch (*p)
565c9346414SPaul Saab 			{
566c9346414SPaul Saab 			case END_OPTION_STRING:
567c9346414SPaul Saab 			case ' ':  case '\t':  case '-':
568c9346414SPaul Saab 				break;
569c9346414SPaul Saab 			default:
570c9346414SPaul Saab 				parg.p_string = p;
571c9346414SPaul Saab 				error("Option string needs delimiter before %s", &parg);
572c9346414SPaul Saab 				break;
573c9346414SPaul Saab 			}
574a5f0fb15SPaul Saab 			*p = '\0';
575a5f0fb15SPaul Saab 			return (p+1);
576a5f0fb15SPaul Saab 		}
577a5f0fb15SPaul Saab 	return (p);
578a5f0fb15SPaul Saab }
579a5f0fb15SPaul Saab 
580a5f0fb15SPaul Saab /*
581a5f0fb15SPaul Saab  * Translate a string into a number.
582a5f0fb15SPaul Saab  * Like atoi(), but takes a pointer to a char *, and updates
583a5f0fb15SPaul Saab  * the char * to point after the translated number.
584a5f0fb15SPaul Saab  */
585a5f0fb15SPaul Saab 	public int
586a5f0fb15SPaul Saab getnum(sp, printopt, errp)
587a5f0fb15SPaul Saab 	char **sp;
588a5f0fb15SPaul Saab 	char *printopt;
589a5f0fb15SPaul Saab 	int *errp;
590a5f0fb15SPaul Saab {
591a5f0fb15SPaul Saab 	register char *s;
592a5f0fb15SPaul Saab 	register int n;
593a5f0fb15SPaul Saab 	register int neg;
594a5f0fb15SPaul Saab 	PARG parg;
595a5f0fb15SPaul Saab 
596a5f0fb15SPaul Saab 	s = skipsp(*sp);
597a5f0fb15SPaul Saab 	neg = FALSE;
598a5f0fb15SPaul Saab 	if (*s == '-')
599a5f0fb15SPaul Saab 	{
600a5f0fb15SPaul Saab 		neg = TRUE;
601a5f0fb15SPaul Saab 		s++;
602a5f0fb15SPaul Saab 	}
603a5f0fb15SPaul Saab 	if (*s < '0' || *s > '9')
604a5f0fb15SPaul Saab 	{
605a5f0fb15SPaul Saab 		if (errp != NULL)
606a5f0fb15SPaul Saab 		{
607a5f0fb15SPaul Saab 			*errp = TRUE;
608a5f0fb15SPaul Saab 			return (-1);
609a5f0fb15SPaul Saab 		}
610a5f0fb15SPaul Saab 		parg.p_string = printopt;
611a5f0fb15SPaul Saab 		error("Number is required after %s", &parg);
612a5f0fb15SPaul Saab 		quit(QUIT_ERROR);
613a5f0fb15SPaul Saab 	}
614a5f0fb15SPaul Saab 
615a5f0fb15SPaul Saab 	n = 0;
616a5f0fb15SPaul Saab 	while (*s >= '0' && *s <= '9')
617a5f0fb15SPaul Saab 		n = 10 * n + *s++ - '0';
618a5f0fb15SPaul Saab 	*sp = s;
619a5f0fb15SPaul Saab 	if (errp != NULL)
620a5f0fb15SPaul Saab 		*errp = FALSE;
621a5f0fb15SPaul Saab 	if (neg)
622a5f0fb15SPaul Saab 		n = -n;
623a5f0fb15SPaul Saab 	return (n);
624a5f0fb15SPaul Saab }
625