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