opttbl.c revision 1.3 1 1.3 tron /* $NetBSD: opttbl.c,v 1.3 2011/07/03 20:14:13 tron Exp $ */
2 1.1 tron
3 1.1 tron /*
4 1.1 tron * Copyright (C) 1984-2011 Mark Nudelman
5 1.1 tron *
6 1.1 tron * You may distribute under the terms of either the GNU General Public
7 1.1 tron * License or the Less License, as specified in the README file.
8 1.1 tron *
9 1.1 tron * For more information about less, or for information on how to
10 1.1 tron * contact the author, see the README file.
11 1.1 tron */
12 1.1 tron
13 1.1 tron
14 1.1 tron /*
15 1.1 tron * The option table.
16 1.1 tron */
17 1.1 tron
18 1.1 tron #include "less.h"
19 1.1 tron #include "option.h"
20 1.1 tron
21 1.1 tron /*
22 1.1 tron * Variables controlled by command line options.
23 1.1 tron */
24 1.1 tron public int quiet; /* Should we suppress the audible bell? */
25 1.1 tron public int how_search; /* Where should forward searches start? */
26 1.1 tron public int top_scroll; /* Repaint screen from top?
27 1.1 tron (alternative is scroll from bottom) */
28 1.1 tron public int pr_type; /* Type of prompt (short, medium, long) */
29 1.1 tron public int bs_mode; /* How to process backspaces */
30 1.1 tron public int know_dumb; /* Don't complain about dumb terminals */
31 1.1 tron public int quit_at_eof; /* Quit after hitting end of file twice */
32 1.1 tron public int quit_if_one_screen; /* Quit if EOF on first screen */
33 1.3 tron public int be_helpful; /* more(1) style -d */
34 1.1 tron public int squeeze; /* Squeeze multiple blank lines into one */
35 1.1 tron public int tabstop; /* Tab settings */
36 1.1 tron public int back_scroll; /* Repaint screen on backwards movement */
37 1.1 tron public int forw_scroll; /* Repaint screen on forward movement */
38 1.1 tron public int caseless; /* Do "caseless" searches */
39 1.1 tron public int linenums; /* Use line numbers */
40 1.1 tron public int autobuf; /* Automatically allocate buffers as needed */
41 1.1 tron public int bufspace; /* Max buffer space per file (K) */
42 1.1 tron public int ctldisp; /* Send control chars to screen untranslated */
43 1.1 tron public int force_open; /* Open the file even if not regular file */
44 1.1 tron public int swindow; /* Size of scrolling window */
45 1.1 tron public int jump_sline; /* Screen line of "jump target" */
46 1.1 tron public long jump_sline_fraction = -1;
47 1.1 tron public long shift_count_fraction = -1;
48 1.1 tron public int chopline; /* Truncate displayed lines at screen width */
49 1.1 tron public int no_init; /* Disable sending ti/te termcap strings */
50 1.1 tron public int no_keypad; /* Disable sending ks/ke termcap strings */
51 1.1 tron public int twiddle; /* Show tildes after EOF */
52 1.1 tron public int show_attn; /* Hilite first unread line */
53 1.1 tron public int shift_count; /* Number of positions to shift horizontally */
54 1.1 tron public int status_col; /* Display a status column */
55 1.1 tron public int use_lessopen; /* Use the LESSOPEN filter */
56 1.1 tron public int quit_on_intr; /* Quit on interrupt */
57 1.1 tron public int follow_mode; /* F cmd Follows file desc or file name? */
58 1.1 tron public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */
59 1.1 tron #if HILITE_SEARCH
60 1.1 tron public int hilite_search; /* Highlight matched search patterns? */
61 1.1 tron #endif
62 1.1 tron
63 1.1 tron public int less_is_more = 0; /* Make compatible with POSIX more */
64 1.1 tron
65 1.1 tron /*
66 1.1 tron * Long option names.
67 1.1 tron */
68 1.1 tron static struct optname a_optname = { "search-skip-screen", NULL };
69 1.1 tron static struct optname b_optname = { "buffers", NULL };
70 1.1 tron static struct optname B__optname = { "auto-buffers", NULL };
71 1.1 tron static struct optname c_optname = { "clear-screen", NULL };
72 1.1 tron static struct optname d_optname = { "dumb", NULL };
73 1.1 tron #if MSDOS_COMPILER
74 1.1 tron static struct optname D__optname = { "color", NULL };
75 1.1 tron #endif
76 1.1 tron static struct optname e_optname = { "quit-at-eof", NULL };
77 1.1 tron static struct optname f_optname = { "force", NULL };
78 1.1 tron static struct optname F__optname = { "quit-if-one-screen", NULL };
79 1.1 tron #if HILITE_SEARCH
80 1.1 tron static struct optname g_optname = { "hilite-search", NULL };
81 1.1 tron #endif
82 1.1 tron static struct optname h_optname = { "max-back-scroll", NULL };
83 1.1 tron static struct optname i_optname = { "ignore-case", NULL };
84 1.1 tron static struct optname j_optname = { "jump-target", NULL };
85 1.1 tron static struct optname J__optname = { "status-column", NULL };
86 1.1 tron #if USERFILE
87 1.1 tron static struct optname k_optname = { "lesskey-file", NULL };
88 1.1 tron #endif
89 1.1 tron static struct optname K__optname = { "quit-on-intr", NULL };
90 1.1 tron static struct optname L__optname = { "no-lessopen", NULL };
91 1.1 tron static struct optname m_optname = { "long-prompt", NULL };
92 1.1 tron static struct optname n_optname = { "line-numbers", NULL };
93 1.1 tron #if LOGFILE
94 1.1 tron static struct optname o_optname = { "log-file", NULL };
95 1.1 tron static struct optname O__optname = { "LOG-FILE", NULL };
96 1.1 tron #endif
97 1.1 tron static struct optname p_optname = { "pattern", NULL };
98 1.1 tron static struct optname P__optname = { "prompt", NULL };
99 1.1 tron static struct optname q2_optname = { "silent", NULL };
100 1.1 tron static struct optname q_optname = { "quiet", &q2_optname };
101 1.1 tron static struct optname r_optname = { "raw-control-chars", NULL };
102 1.1 tron static struct optname s_optname = { "squeeze-blank-lines", NULL };
103 1.1 tron static struct optname S__optname = { "chop-long-lines", NULL };
104 1.1 tron #if TAGS
105 1.1 tron static struct optname t_optname = { "tag", NULL };
106 1.1 tron static struct optname T__optname = { "tag-file", NULL };
107 1.1 tron #endif
108 1.1 tron static struct optname u_optname = { "underline-special", NULL };
109 1.1 tron static struct optname V__optname = { "version", NULL };
110 1.1 tron static struct optname w_optname = { "hilite-unread", NULL };
111 1.1 tron static struct optname x_optname = { "tabs", NULL };
112 1.1 tron static struct optname X__optname = { "no-init", NULL };
113 1.1 tron static struct optname y_optname = { "max-forw-scroll", NULL };
114 1.1 tron static struct optname z_optname = { "window", NULL };
115 1.1 tron static struct optname quote_optname = { "quotes", NULL };
116 1.1 tron static struct optname tilde_optname = { "tilde", NULL };
117 1.1 tron static struct optname query_optname = { "help", NULL };
118 1.1 tron static struct optname pound_optname = { "shift", NULL };
119 1.1 tron static struct optname keypad_optname = { "no-keypad", NULL };
120 1.1 tron static struct optname oldbot_optname = { "old-bot", NULL };
121 1.1 tron static struct optname follow_optname = { "follow-name", NULL };
122 1.1 tron
123 1.1 tron
124 1.1 tron /*
125 1.1 tron * Table of all options and their semantics.
126 1.1 tron *
127 1.1 tron * For BOOL and TRIPLE options, odesc[0], odesc[1], odesc[2] are
128 1.1 tron * the description of the option when set to 0, 1 or 2, respectively.
129 1.1 tron * For NUMBER options, odesc[0] is the prompt to use when entering
130 1.1 tron * a new value, and odesc[1] is the description, which should contain
131 1.1 tron * one %d which is replaced by the value of the number.
132 1.1 tron * For STRING options, odesc[0] is the prompt to use when entering
133 1.1 tron * a new value, and odesc[1], if not NULL, is the set of characters
134 1.1 tron * that are valid in the string.
135 1.1 tron */
136 1.1 tron static struct loption option[] =
137 1.1 tron {
138 1.1 tron { 'a', &a_optname,
139 1.1 tron TRIPLE, OPT_ONPLUS, &how_search, NULL,
140 1.1 tron {
141 1.1 tron "Search includes displayed screen",
142 1.1 tron "Search skips displayed screen",
143 1.1 tron "Search includes all of displayed screen"
144 1.1 tron }
145 1.1 tron },
146 1.1 tron
147 1.1 tron { 'b', &b_optname,
148 1.1 tron NUMBER|INIT_HANDLER, 64, &bufspace, opt_b,
149 1.1 tron {
150 1.1 tron "Max buffer space per file (K): ",
151 1.1 tron "Max buffer space per file: %dK",
152 1.1 tron NULL
153 1.1 tron }
154 1.1 tron },
155 1.1 tron { 'B', &B__optname,
156 1.1 tron BOOL, OPT_ON, &autobuf, NULL,
157 1.1 tron {
158 1.1 tron "Don't automatically allocate buffers",
159 1.1 tron "Automatically allocate buffers when needed",
160 1.1 tron NULL
161 1.1 tron }
162 1.1 tron },
163 1.1 tron { 'c', &c_optname,
164 1.1 tron TRIPLE, OPT_OFF, &top_scroll, NULL,
165 1.1 tron {
166 1.1 tron "Repaint by scrolling from bottom of screen",
167 1.1 tron "Repaint by painting from top of screen",
168 1.1 tron "Repaint by painting from top of screen"
169 1.1 tron }
170 1.1 tron },
171 1.3 tron #if 1
172 1.1 tron { 'd', &d_optname,
173 1.3 tron BOOL, OPT_OFF, &be_helpful, NULL,
174 1.3 tron { "Be less helpful in prompts",
175 1.3 tron "Be helpful in prompts",
176 1.3 tron NULL }
177 1.3 tron },
178 1.3 tron #endif
179 1.3 tron { -1, &d_optname,
180 1.1 tron BOOL|NO_TOGGLE, OPT_OFF, &know_dumb, NULL,
181 1.1 tron {
182 1.1 tron "Assume intelligent terminal",
183 1.1 tron "Assume dumb terminal",
184 1.1 tron NULL
185 1.1 tron }
186 1.1 tron },
187 1.1 tron #if MSDOS_COMPILER
188 1.1 tron { 'D', &D__optname,
189 1.1 tron STRING|REPAINT|NO_QUERY, 0, NULL, opt_D,
190 1.1 tron {
191 1.1 tron "color desc: ",
192 1.1 tron "Ddknsu0123456789.",
193 1.1 tron NULL
194 1.1 tron }
195 1.1 tron },
196 1.1 tron #endif
197 1.1 tron { 'e', &e_optname,
198 1.1 tron TRIPLE, OPT_OFF, &quit_at_eof, NULL,
199 1.1 tron {
200 1.1 tron "Don't quit at end-of-file",
201 1.1 tron "Quit at end-of-file",
202 1.1 tron "Quit immediately at end-of-file"
203 1.1 tron }
204 1.1 tron },
205 1.1 tron { 'f', &f_optname,
206 1.1 tron BOOL, OPT_OFF, &force_open, NULL,
207 1.1 tron {
208 1.1 tron "Open only regular files",
209 1.1 tron "Open even non-regular files",
210 1.1 tron NULL
211 1.1 tron }
212 1.1 tron },
213 1.1 tron { 'F', &F__optname,
214 1.1 tron BOOL, OPT_OFF, &quit_if_one_screen, NULL,
215 1.1 tron {
216 1.1 tron "Don't quit if end-of-file on first screen",
217 1.1 tron "Quit if end-of-file on first screen",
218 1.1 tron NULL
219 1.1 tron }
220 1.1 tron },
221 1.1 tron #if HILITE_SEARCH
222 1.1 tron { 'g', &g_optname,
223 1.1 tron TRIPLE|HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL,
224 1.1 tron {
225 1.1 tron "Don't highlight search matches",
226 1.1 tron "Highlight matches for previous search only",
227 1.1 tron "Highlight all matches for previous search pattern",
228 1.1 tron }
229 1.1 tron },
230 1.1 tron #endif
231 1.1 tron { 'h', &h_optname,
232 1.1 tron NUMBER, -1, &back_scroll, NULL,
233 1.1 tron {
234 1.1 tron "Backwards scroll limit: ",
235 1.1 tron "Backwards scroll limit is %d lines",
236 1.1 tron NULL
237 1.1 tron }
238 1.1 tron },
239 1.1 tron { 'i', &i_optname,
240 1.1 tron TRIPLE|HL_REPAINT, OPT_OFF, &caseless, opt_i,
241 1.1 tron {
242 1.1 tron "Case is significant in searches",
243 1.1 tron "Ignore case in searches",
244 1.1 tron "Ignore case in searches and in patterns"
245 1.1 tron }
246 1.1 tron },
247 1.1 tron { 'j', &j_optname,
248 1.1 tron STRING, 0, NULL, opt_j,
249 1.1 tron {
250 1.1 tron "Target line: ",
251 1.1 tron "0123456789.-",
252 1.1 tron NULL
253 1.1 tron }
254 1.1 tron },
255 1.1 tron { 'J', &J__optname,
256 1.1 tron BOOL|REPAINT, OPT_OFF, &status_col, NULL,
257 1.1 tron {
258 1.1 tron "Don't display a status column",
259 1.1 tron "Display a status column",
260 1.1 tron NULL
261 1.1 tron }
262 1.1 tron },
263 1.1 tron #if USERFILE
264 1.1 tron { 'k', &k_optname,
265 1.1 tron STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k,
266 1.1 tron { NULL, NULL, NULL }
267 1.1 tron },
268 1.1 tron #endif
269 1.1 tron { 'K', &K__optname,
270 1.1 tron BOOL, OPT_OFF, &quit_on_intr, NULL,
271 1.1 tron {
272 1.1 tron "Interrupt (ctrl-C) returns to prompt",
273 1.1 tron "Interrupt (ctrl-C) exits less",
274 1.1 tron NULL
275 1.1 tron }
276 1.1 tron },
277 1.1 tron { 'L', &L__optname,
278 1.1 tron BOOL, OPT_ON, &use_lessopen, NULL,
279 1.1 tron {
280 1.1 tron "Don't use the LESSOPEN filter",
281 1.1 tron "Use the LESSOPEN filter",
282 1.1 tron NULL
283 1.1 tron }
284 1.1 tron },
285 1.1 tron { 'm', &m_optname,
286 1.1 tron TRIPLE, OPT_OFF, &pr_type, NULL,
287 1.1 tron {
288 1.1 tron "Short prompt",
289 1.1 tron "Medium prompt",
290 1.1 tron "Long prompt"
291 1.1 tron }
292 1.1 tron },
293 1.1 tron { 'n', &n_optname,
294 1.1 tron TRIPLE|REPAINT, OPT_ON, &linenums, NULL,
295 1.1 tron {
296 1.1 tron "Don't use line numbers",
297 1.1 tron "Use line numbers",
298 1.1 tron "Constantly display line numbers"
299 1.1 tron }
300 1.1 tron },
301 1.1 tron #if LOGFILE
302 1.1 tron { 'o', &o_optname,
303 1.1 tron STRING, 0, NULL, opt_o,
304 1.1 tron { "log file: ", NULL, NULL }
305 1.1 tron },
306 1.1 tron { 'O', &O__optname,
307 1.1 tron STRING, 0, NULL, opt__O,
308 1.1 tron { "Log file: ", NULL, NULL }
309 1.1 tron },
310 1.1 tron #endif
311 1.1 tron { 'p', &p_optname,
312 1.1 tron STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_p,
313 1.1 tron { NULL, NULL, NULL }
314 1.1 tron },
315 1.1 tron { 'P', &P__optname,
316 1.1 tron STRING, 0, NULL, opt__P,
317 1.1 tron { "prompt: ", NULL, NULL }
318 1.1 tron },
319 1.1 tron { 'q', &q_optname,
320 1.1 tron TRIPLE, OPT_OFF, &quiet, NULL,
321 1.1 tron {
322 1.1 tron "Ring the bell for errors AND at eof/bof",
323 1.1 tron "Ring the bell for errors but not at eof/bof",
324 1.1 tron "Never ring the bell"
325 1.1 tron }
326 1.1 tron },
327 1.1 tron { 'r', &r_optname,
328 1.1 tron TRIPLE|REPAINT, OPT_OFF, &ctldisp, NULL,
329 1.1 tron {
330 1.1 tron "Display control characters as ^X",
331 1.1 tron "Display control characters directly",
332 1.1 tron "Display control characters directly, processing ANSI sequences"
333 1.1 tron }
334 1.1 tron },
335 1.1 tron { 's', &s_optname,
336 1.1 tron BOOL|REPAINT, OPT_OFF, &squeeze, NULL,
337 1.1 tron {
338 1.1 tron "Display all blank lines",
339 1.1 tron "Squeeze multiple blank lines",
340 1.1 tron NULL
341 1.1 tron }
342 1.1 tron },
343 1.1 tron { 'S', &S__optname,
344 1.1 tron BOOL|REPAINT, OPT_OFF, &chopline, NULL,
345 1.1 tron {
346 1.1 tron "Fold long lines",
347 1.1 tron "Chop long lines",
348 1.1 tron NULL
349 1.1 tron }
350 1.1 tron },
351 1.1 tron #if TAGS
352 1.1 tron { 't', &t_optname,
353 1.1 tron STRING|NO_QUERY, 0, NULL, opt_t,
354 1.1 tron { "tag: ", NULL, NULL }
355 1.1 tron },
356 1.1 tron { 'T', &T__optname,
357 1.1 tron STRING, 0, NULL, opt__T,
358 1.1 tron { "tags file: ", NULL, NULL }
359 1.1 tron },
360 1.1 tron #endif
361 1.1 tron { 'u', &u_optname,
362 1.1 tron TRIPLE|REPAINT, OPT_OFF, &bs_mode, NULL,
363 1.1 tron {
364 1.1 tron "Display underlined text in underline mode",
365 1.1 tron "Backspaces cause overstrike",
366 1.1 tron "Print backspace as ^H"
367 1.1 tron }
368 1.1 tron },
369 1.1 tron { 'V', &V__optname,
370 1.1 tron NOVAR, 0, NULL, opt__V,
371 1.1 tron { NULL, NULL, NULL }
372 1.1 tron },
373 1.1 tron { 'w', &w_optname,
374 1.1 tron TRIPLE|REPAINT, OPT_OFF, &show_attn, NULL,
375 1.1 tron {
376 1.1 tron "Don't highlight first unread line",
377 1.1 tron "Highlight first unread line after forward-screen",
378 1.1 tron "Highlight first unread line after any forward movement",
379 1.1 tron }
380 1.1 tron },
381 1.1 tron { 'x', &x_optname,
382 1.1 tron STRING|REPAINT, 0, NULL, opt_x,
383 1.1 tron {
384 1.1 tron "Tab stops: ",
385 1.1 tron "0123456789,",
386 1.1 tron NULL
387 1.1 tron }
388 1.1 tron },
389 1.1 tron { 'X', &X__optname,
390 1.1 tron BOOL|NO_TOGGLE, OPT_OFF, &no_init, NULL,
391 1.1 tron {
392 1.1 tron "Send init/deinit strings to terminal",
393 1.1 tron "Don't use init/deinit strings",
394 1.1 tron NULL
395 1.1 tron }
396 1.1 tron },
397 1.1 tron { 'y', &y_optname,
398 1.1 tron NUMBER, -1, &forw_scroll, NULL,
399 1.1 tron {
400 1.1 tron "Forward scroll limit: ",
401 1.1 tron "Forward scroll limit is %d lines",
402 1.1 tron NULL
403 1.1 tron }
404 1.1 tron },
405 1.1 tron { 'z', &z_optname,
406 1.1 tron NUMBER, -1, &swindow, NULL,
407 1.1 tron {
408 1.1 tron "Scroll window size: ",
409 1.1 tron "Scroll window size is %d lines",
410 1.1 tron NULL
411 1.1 tron }
412 1.1 tron },
413 1.1 tron { '"', "e_optname,
414 1.1 tron STRING, 0, NULL, opt_quote,
415 1.1 tron { "quotes: ", NULL, NULL }
416 1.1 tron },
417 1.1 tron { '~', &tilde_optname,
418 1.1 tron BOOL|REPAINT, OPT_ON, &twiddle, NULL,
419 1.1 tron {
420 1.1 tron "Don't show tildes after end of file",
421 1.1 tron "Show tildes after end of file",
422 1.1 tron NULL
423 1.1 tron }
424 1.1 tron },
425 1.1 tron { '?', &query_optname,
426 1.1 tron NOVAR, 0, NULL, opt_query,
427 1.1 tron { NULL, NULL, NULL }
428 1.1 tron },
429 1.1 tron { '#', £_optname,
430 1.1 tron STRING, 0, NULL, opt_shift,
431 1.1 tron {
432 1.1 tron "Horizontal shift: ",
433 1.1 tron "0123456789.",
434 1.1 tron NULL
435 1.1 tron }
436 1.1 tron },
437 1.1 tron { OLETTER_NONE, &keypad_optname,
438 1.1 tron BOOL|NO_TOGGLE, OPT_OFF, &no_keypad, NULL,
439 1.1 tron {
440 1.1 tron "Use keypad mode",
441 1.1 tron "Don't use keypad mode",
442 1.1 tron NULL
443 1.1 tron }
444 1.1 tron },
445 1.1 tron { OLETTER_NONE, &oldbot_optname,
446 1.1 tron BOOL, OPT_OFF, &oldbot, NULL,
447 1.1 tron {
448 1.1 tron "Use new bottom of screen behavior",
449 1.1 tron "Use old bottom of screen behavior",
450 1.1 tron NULL
451 1.1 tron }
452 1.1 tron },
453 1.1 tron { OLETTER_NONE, &follow_optname,
454 1.1 tron BOOL, FOLLOW_DESC, &follow_mode, NULL,
455 1.1 tron {
456 1.1 tron "F command follows file descriptor",
457 1.1 tron "F command follows file name",
458 1.1 tron NULL
459 1.1 tron }
460 1.1 tron },
461 1.1 tron { '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } }
462 1.1 tron };
463 1.1 tron
464 1.1 tron
465 1.1 tron /*
466 1.1 tron * Initialize each option to its default value.
467 1.1 tron */
468 1.1 tron public void
469 1.1 tron init_option()
470 1.1 tron {
471 1.1 tron register struct loption *o;
472 1.1 tron char *p;
473 1.1 tron
474 1.1 tron p = lgetenv("LESS_IS_MORE");
475 1.1 tron if (p != NULL && *p != '\0')
476 1.1 tron less_is_more = 1;
477 1.1 tron
478 1.1 tron for (o = option; o->oletter != '\0'; o++)
479 1.1 tron {
480 1.1 tron /*
481 1.1 tron * Set each variable to its default.
482 1.1 tron */
483 1.1 tron if (o->ovar != NULL)
484 1.1 tron *(o->ovar) = o->odefault;
485 1.1 tron if (o->otype & INIT_HANDLER)
486 1.1 tron (*(o->ofunc))(INIT, (char *) NULL);
487 1.1 tron }
488 1.1 tron }
489 1.1 tron
490 1.1 tron /*
491 1.1 tron * Find an option in the option table, given its option letter.
492 1.1 tron */
493 1.1 tron public struct loption *
494 1.1 tron findopt(c)
495 1.1 tron int c;
496 1.1 tron {
497 1.1 tron register struct loption *o;
498 1.1 tron
499 1.1 tron for (o = option; o->oletter != '\0'; o++)
500 1.1 tron {
501 1.1 tron if (o->oletter == c)
502 1.1 tron return (o);
503 1.1 tron if ((o->otype & TRIPLE) && ASCII_TO_UPPER(o->oletter) == c)
504 1.1 tron return (o);
505 1.1 tron }
506 1.1 tron return (NULL);
507 1.1 tron }
508 1.1 tron
509 1.1 tron /*
510 1.1 tron *
511 1.1 tron */
512 1.1 tron static int
513 1.1 tron is_optchar(c)
514 1.1 tron char c;
515 1.1 tron {
516 1.1 tron if (ASCII_IS_UPPER(c))
517 1.1 tron return 1;
518 1.1 tron if (ASCII_IS_LOWER(c))
519 1.1 tron return 1;
520 1.1 tron if (c == '-')
521 1.1 tron return 1;
522 1.1 tron return 0;
523 1.1 tron }
524 1.1 tron
525 1.1 tron /*
526 1.1 tron * Find an option in the option table, given its option name.
527 1.1 tron * p_optname is the (possibly partial) name to look for, and
528 1.1 tron * is updated to point after the matched name.
529 1.1 tron * p_oname if non-NULL is set to point to the full option name.
530 1.1 tron */
531 1.1 tron public struct loption *
532 1.1 tron findopt_name(p_optname, p_oname, p_err)
533 1.1 tron char **p_optname;
534 1.1 tron char **p_oname;
535 1.1 tron int *p_err;
536 1.1 tron {
537 1.1 tron char *optname = *p_optname;
538 1.1 tron register struct loption *o;
539 1.1 tron register struct optname *oname;
540 1.1 tron register int len;
541 1.1 tron int uppercase;
542 1.1 tron struct loption *maxo = NULL;
543 1.1 tron struct optname *maxoname = NULL;
544 1.1 tron int maxlen = 0;
545 1.1 tron int ambig = 0;
546 1.1 tron int exact = 0;
547 1.1 tron
548 1.1 tron /*
549 1.1 tron * Check all options.
550 1.1 tron */
551 1.1 tron for (o = option; o->oletter != '\0'; o++)
552 1.1 tron {
553 1.1 tron /*
554 1.1 tron * Check all names for this option.
555 1.1 tron */
556 1.1 tron for (oname = o->onames; oname != NULL; oname = oname->onext)
557 1.1 tron {
558 1.1 tron /*
559 1.1 tron * Try normal match first (uppercase == 0),
560 1.1 tron * then, then if it's a TRIPLE option,
561 1.1 tron * try uppercase match (uppercase == 1).
562 1.1 tron */
563 1.1 tron for (uppercase = 0; uppercase <= 1; uppercase++)
564 1.1 tron {
565 1.1 tron len = sprefix(optname, oname->oname, uppercase);
566 1.1 tron if (len <= 0 || is_optchar(optname[len]))
567 1.1 tron {
568 1.1 tron /*
569 1.1 tron * We didn't use all of the option name.
570 1.1 tron */
571 1.1 tron continue;
572 1.1 tron }
573 1.1 tron if (!exact && len == maxlen)
574 1.1 tron /*
575 1.1 tron * Already had a partial match,
576 1.1 tron * and now there's another one that
577 1.1 tron * matches the same length.
578 1.1 tron */
579 1.1 tron ambig = 1;
580 1.1 tron else if (len > maxlen)
581 1.1 tron {
582 1.1 tron /*
583 1.1 tron * Found a better match than
584 1.1 tron * the one we had.
585 1.1 tron */
586 1.1 tron maxo = o;
587 1.1 tron maxoname = oname;
588 1.1 tron maxlen = len;
589 1.1 tron ambig = 0;
590 1.1 tron exact = (len == (int)strlen(oname->oname));
591 1.1 tron }
592 1.1 tron if (!(o->otype & TRIPLE))
593 1.1 tron break;
594 1.1 tron }
595 1.1 tron }
596 1.1 tron }
597 1.1 tron if (ambig)
598 1.1 tron {
599 1.1 tron /*
600 1.1 tron * Name matched more than one option.
601 1.1 tron */
602 1.1 tron if (p_err != NULL)
603 1.1 tron *p_err = OPT_AMBIG;
604 1.1 tron return (NULL);
605 1.1 tron }
606 1.1 tron *p_optname = optname + maxlen;
607 1.1 tron if (p_oname != NULL)
608 1.1 tron *p_oname = maxoname == NULL ? NULL : maxoname->oname;
609 1.1 tron return (maxo);
610 1.1 tron }
611