options-table.c revision 1.32
1/* $OpenBSD: options-table.c,v 1.32 2013/01/17 00:11:22 nicm Exp $ */
2
3/*
4 * Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <string.h>
22#include <paths.h>
23
24#include "tmux.h"
25
26/*
27 * This file has a tables with all the server, session and window
28 * options. These tables are the master copy of the options with their real
29 * (user-visible) types, range limits and default values. At start these are
30 * copied into the runtime global options trees (which only has number and
31 * string types). These tables are then used to loop up the real type when
32 * the user sets an option or its value needs to be shown.
33 */
34
35/* Choice option type lists. */
36const char *options_table_mode_keys_list[] = {
37	"emacs", "vi", NULL
38};
39const char *options_table_mode_mouse_list[] = {
40	"off", "on", "copy-mode", NULL
41};
42const char *options_table_clock_mode_style_list[] = {
43	"12", "24", NULL
44};
45const char *options_table_status_keys_list[] = {
46	"emacs", "vi", NULL
47};
48const char *options_table_status_justify_list[] = {
49	"left", "centre", "right", NULL
50};
51const char *options_table_status_position_list[] = {
52	"top", "bottom", NULL
53};
54const char *options_table_bell_action_list[] = {
55	"none", "any", "current", NULL
56};
57
58/* Server options. */
59const struct options_table_entry server_options_table[] = {
60	{ .name = "buffer-limit",
61	  .type = OPTIONS_TABLE_NUMBER,
62	  .minimum = 1,
63	  .maximum = INT_MAX,
64	  .default_num = 20
65	},
66
67	{ .name = "escape-time",
68	  .type = OPTIONS_TABLE_NUMBER,
69	  .minimum = 0,
70	  .maximum = INT_MAX,
71	  .default_num = 500
72	},
73
74	{ .name = "exit-unattached",
75	  .type = OPTIONS_TABLE_FLAG,
76	  .default_num = 0
77	},
78
79	{ .name = "quiet",
80	  .type = OPTIONS_TABLE_FLAG,
81	  .default_num = 0 /* overridden in main() */
82	},
83
84	{ .name = "set-clipboard",
85	  .type = OPTIONS_TABLE_FLAG,
86	  .default_num = 1
87	},
88
89	{ .name = NULL }
90};
91
92/* Session options. */
93const struct options_table_entry session_options_table[] = {
94	{ .name = "assume-paste-time",
95	  .type = OPTIONS_TABLE_NUMBER,
96	  .minimum = 0,
97	  .maximum = INT_MAX,
98	  .default_num = 1,
99	},
100
101	{ .name = "base-index",
102	  .type = OPTIONS_TABLE_NUMBER,
103	  .minimum = 0,
104	  .maximum = INT_MAX,
105	  .default_num = 0
106	},
107
108	{ .name = "bell-action",
109	  .type = OPTIONS_TABLE_CHOICE,
110	  .choices = options_table_bell_action_list,
111	  .default_num = BELL_ANY
112	},
113
114	{ .name = "bell-on-alert",
115	  .type = OPTIONS_TABLE_FLAG,
116	  .default_num = 0
117	},
118
119	{ .name = "default-command",
120	  .type = OPTIONS_TABLE_STRING,
121	  .default_str = ""
122	},
123
124	{ .name = "default-path",
125	  .type = OPTIONS_TABLE_STRING,
126	  .default_str = ""
127	},
128
129	{ .name = "default-shell",
130	  .type = OPTIONS_TABLE_STRING,
131	  .default_str = _PATH_BSHELL
132	},
133
134	{ .name = "default-terminal",
135	  .type = OPTIONS_TABLE_STRING,
136	  .default_str = "screen"
137	},
138
139	{ .name = "destroy-unattached",
140	  .type = OPTIONS_TABLE_FLAG,
141	  .default_num = 0
142	},
143
144	{ .name = "detach-on-destroy",
145	  .type = OPTIONS_TABLE_FLAG,
146	  .default_num = 1
147	},
148
149	{ .name = "display-panes-active-colour",
150	  .type = OPTIONS_TABLE_COLOUR,
151	  .default_num = 1
152	},
153
154	{ .name = "display-panes-colour",
155	  .type = OPTIONS_TABLE_COLOUR,
156	  .default_num = 4
157	},
158
159	{ .name = "display-panes-time",
160	  .type = OPTIONS_TABLE_NUMBER,
161	  .minimum = 1,
162	  .maximum = INT_MAX,
163	  .default_num = 1000
164	},
165
166	{ .name = "display-time",
167	  .type = OPTIONS_TABLE_NUMBER,
168	  .minimum = 1,
169	  .maximum = INT_MAX,
170	  .default_num = 750
171	},
172
173	{ .name = "history-limit",
174	  .type = OPTIONS_TABLE_NUMBER,
175	  .minimum = 0,
176	  .maximum = INT_MAX,
177	  .default_num = 2000
178	},
179
180	{ .name = "lock-after-time",
181	  .type = OPTIONS_TABLE_NUMBER,
182	  .minimum = 0,
183	  .maximum = INT_MAX,
184	  .default_num = 0
185	},
186
187	{ .name = "lock-command",
188	  .type = OPTIONS_TABLE_STRING,
189	  .default_str = "lock -np"
190	},
191
192	{ .name = "lock-server",
193	  .type = OPTIONS_TABLE_FLAG,
194	  .default_num = 1
195	},
196
197	{ .name = "message-attr",
198	  .type = OPTIONS_TABLE_ATTRIBUTES,
199	  .default_num = 0
200	},
201
202	{ .name = "message-bg",
203	  .type = OPTIONS_TABLE_COLOUR,
204	  .default_num = 3
205	},
206
207	{ .name = "message-command-attr",
208	  .type = OPTIONS_TABLE_ATTRIBUTES,
209	  .default_num = 0
210	},
211
212	{ .name = "message-command-bg",
213	  .type = OPTIONS_TABLE_COLOUR,
214	  .default_num = 0
215	},
216
217	{ .name = "message-command-fg",
218	  .type = OPTIONS_TABLE_COLOUR,
219	  .default_num = 3
220	},
221
222	{ .name = "message-fg",
223	  .type = OPTIONS_TABLE_COLOUR,
224	  .default_num = 0
225	},
226
227	{ .name = "message-limit",
228	  .type = OPTIONS_TABLE_NUMBER,
229	  .minimum = 0,
230	  .maximum = INT_MAX,
231	  .default_num = 20
232	},
233
234	{ .name = "mouse-resize-pane",
235	  .type = OPTIONS_TABLE_FLAG,
236	  .default_num = 0
237	},
238
239	{ .name = "mouse-select-pane",
240	  .type = OPTIONS_TABLE_FLAG,
241	  .default_num = 0
242	},
243
244	{ .name = "mouse-select-window",
245	  .type = OPTIONS_TABLE_FLAG,
246	  .default_num = 0
247	},
248
249	{ .name = "mouse-utf8",
250	  .type = OPTIONS_TABLE_FLAG,
251	  .default_num = 0
252	},
253
254	{ .name = "pane-active-border-bg",
255	  .type = OPTIONS_TABLE_COLOUR,
256	  .default_num = 8
257	},
258
259	{ .name = "pane-active-border-fg",
260	  .type = OPTIONS_TABLE_COLOUR,
261	  .default_num = 2
262	},
263
264	{ .name = "pane-border-bg",
265	  .type = OPTIONS_TABLE_COLOUR,
266	  .default_num = 8
267	},
268
269	{ .name = "pane-border-fg",
270	  .type = OPTIONS_TABLE_COLOUR,
271	  .default_num = 8
272	},
273
274	{ .name = "prefix",
275	  .type = OPTIONS_TABLE_KEY,
276	  .default_num = '\002',
277	},
278
279	{ .name = "prefix2",
280	  .type = OPTIONS_TABLE_KEY,
281	  .default_num = KEYC_NONE,
282	},
283
284	{ .name = "renumber-windows",
285	  .type = OPTIONS_TABLE_FLAG,
286	  .default_num = 0
287	},
288
289	{ .name = "repeat-time",
290	  .type = OPTIONS_TABLE_NUMBER,
291	  .minimum = 0,
292	  .maximum = SHRT_MAX,
293	  .default_num = 500
294	},
295
296	{ .name = "set-remain-on-exit",
297	  .type = OPTIONS_TABLE_FLAG,
298	  .default_num = 0
299	},
300
301	{ .name = "set-titles",
302	  .type = OPTIONS_TABLE_FLAG,
303	  .default_num = 0
304	},
305
306	{ .name = "set-titles-string",
307	  .type = OPTIONS_TABLE_STRING,
308	  .default_str = "#S:#I:#W - \"#T\""
309	},
310
311	{ .name = "status",
312	  .type = OPTIONS_TABLE_FLAG,
313	  .default_num = 1
314	},
315
316	{ .name = "status-attr",
317	  .type = OPTIONS_TABLE_ATTRIBUTES,
318	  .default_num = 0
319	},
320
321	{ .name = "status-bg",
322	  .type = OPTIONS_TABLE_COLOUR,
323	  .default_num = 2
324	},
325
326	{ .name = "status-fg",
327	  .type = OPTIONS_TABLE_COLOUR,
328	  .default_num = 0
329	},
330
331	{ .name = "status-interval",
332	  .type = OPTIONS_TABLE_NUMBER,
333	  .minimum = 0,
334	  .maximum = INT_MAX,
335	  .default_num = 15
336	},
337
338	{ .name = "status-justify",
339	  .type = OPTIONS_TABLE_CHOICE,
340	  .choices = options_table_status_justify_list,
341	  .default_num = 0
342	},
343
344	{ .name = "status-keys",
345	  .type = OPTIONS_TABLE_CHOICE,
346	  .choices = options_table_status_keys_list,
347	  .default_num = MODEKEY_EMACS
348	},
349
350	{ .name = "status-left",
351	  .type = OPTIONS_TABLE_STRING,
352	  .default_str = "[#S]"
353	},
354
355	{ .name = "status-left-attr",
356	  .type = OPTIONS_TABLE_ATTRIBUTES,
357	  .default_num = 0
358	},
359
360	{ .name = "status-left-bg",
361	  .type = OPTIONS_TABLE_COLOUR,
362	  .default_num = 8
363	},
364
365	{ .name = "status-left-fg",
366	  .type = OPTIONS_TABLE_COLOUR,
367	  .default_num = 8
368	},
369
370	{ .name = "status-left-length",
371	  .type = OPTIONS_TABLE_NUMBER,
372	  .minimum = 0,
373	  .maximum = SHRT_MAX,
374	  .default_num = 10
375	},
376
377	{ .name = "status-position",
378	  .type = OPTIONS_TABLE_CHOICE,
379	  .choices = options_table_status_position_list,
380	  .default_num = 1
381	},
382
383	{ .name = "status-right",
384	  .type = OPTIONS_TABLE_STRING,
385	  .default_str = "\"#22T\" %H:%M %d-%b-%y"
386	},
387
388	{ .name = "status-right-attr",
389	  .type = OPTIONS_TABLE_ATTRIBUTES,
390	  .default_num = 0
391	},
392
393	{ .name = "status-right-bg",
394	  .type = OPTIONS_TABLE_COLOUR,
395	  .default_num = 8
396	},
397
398	{ .name = "status-right-fg",
399	  .type = OPTIONS_TABLE_COLOUR,
400	  .default_num = 8
401	},
402
403	{ .name = "status-right-length",
404	  .type = OPTIONS_TABLE_NUMBER,
405	  .minimum = 0,
406	  .maximum = SHRT_MAX,
407	  .default_num = 40
408	},
409
410	{ .name = "status-utf8",
411	  .type = OPTIONS_TABLE_FLAG,
412	  .default_num = 0 /* overridden in main() */
413	},
414
415	{ .name = "terminal-overrides",
416	  .type = OPTIONS_TABLE_STRING,
417	  .default_str = "*88col*:colors=88,*256col*:colors=256"
418	                 ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
419	                 ":Cc=\\E]12;%p1%s\\007:Cr=\\E]112\\007"
420			 ":Cs=\\E[%p1%d q:Csr=\\E[2 q,screen*:XT"
421	},
422
423	{ .name = "update-environment",
424	  .type = OPTIONS_TABLE_STRING,
425	  .default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID "
426	                 "SSH_CONNECTION WINDOWID XAUTHORITY"
427
428	},
429
430	{ .name = "visual-activity",
431	  .type = OPTIONS_TABLE_FLAG,
432	  .default_num = 0
433	},
434
435	{ .name = "visual-bell",
436	  .type = OPTIONS_TABLE_FLAG,
437	  .default_num = 0
438	},
439
440	{ .name = "visual-content",
441	  .type = OPTIONS_TABLE_FLAG,
442	  .default_num = 0
443	},
444
445	{ .name = "visual-silence",
446	  .type = OPTIONS_TABLE_FLAG,
447	  .default_num = 0
448	},
449
450	{ .name = "word-separators",
451	  .type = OPTIONS_TABLE_STRING,
452	  .default_str = " -_@"
453	},
454
455	{ .name = NULL }
456};
457
458/* Window options. */
459const struct options_table_entry window_options_table[] = {
460	{ .name = "aggressive-resize",
461	  .type = OPTIONS_TABLE_FLAG,
462	  .default_num = 0
463	},
464
465	{ .name = "allow-rename",
466	  .type = OPTIONS_TABLE_FLAG,
467	  .default_num = 1
468	},
469
470	{ .name = "alternate-screen",
471	  .type = OPTIONS_TABLE_FLAG,
472	  .default_num = 1
473	},
474
475	{ .name = "automatic-rename",
476	  .type = OPTIONS_TABLE_FLAG,
477	  .default_num = 1
478	},
479
480
481	{ .name = "c0-change-trigger",
482	  .type = OPTIONS_TABLE_NUMBER,
483	  .default_num = 250,
484	  .minimum = 0,
485	  .maximum = USHRT_MAX
486	},
487
488	{ .name = "c0-change-interval",
489	  .type = OPTIONS_TABLE_NUMBER,
490	  .default_num = 100,
491	  .minimum = 1,
492	  .maximum = USHRT_MAX
493	},
494
495	{ .name = "clock-mode-colour",
496	  .type = OPTIONS_TABLE_COLOUR,
497	  .default_num = 4
498	},
499
500	{ .name = "clock-mode-style",
501	  .type = OPTIONS_TABLE_CHOICE,
502	  .choices = options_table_clock_mode_style_list,
503	  .default_num = 1
504	},
505
506	{ .name = "force-height",
507	  .type = OPTIONS_TABLE_NUMBER,
508	  .minimum = 0,
509	  .maximum = INT_MAX,
510	  .default_num = 0
511	},
512
513	{ .name = "force-width",
514	  .type = OPTIONS_TABLE_NUMBER,
515	  .minimum = 0,
516	  .maximum = INT_MAX,
517	  .default_num = 0
518	},
519
520	{ .name = "main-pane-height",
521	  .type = OPTIONS_TABLE_NUMBER,
522	  .minimum = 1,
523	  .maximum = INT_MAX,
524	  .default_num = 24
525	},
526
527	{ .name = "main-pane-width",
528	  .type = OPTIONS_TABLE_NUMBER,
529	  .minimum = 1,
530	  .maximum = INT_MAX,
531	  .default_num = 80
532	},
533
534	{ .name = "mode-attr",
535	  .type = OPTIONS_TABLE_ATTRIBUTES,
536	  .default_num = 0
537	},
538
539	{ .name = "mode-bg",
540	  .type = OPTIONS_TABLE_COLOUR,
541	  .default_num = 3
542	},
543
544	{ .name = "mode-fg",
545	  .type = OPTIONS_TABLE_COLOUR,
546	  .default_num = 0
547	},
548
549	{ .name = "mode-keys",
550	  .type = OPTIONS_TABLE_CHOICE,
551	  .choices = options_table_mode_keys_list,
552	  .default_num = MODEKEY_EMACS
553	},
554
555	{ .name = "mode-mouse",
556	  .type = OPTIONS_TABLE_CHOICE,
557	  .choices = options_table_mode_mouse_list,
558	  .default_num = 0
559	},
560
561	{ .name = "monitor-activity",
562	  .type = OPTIONS_TABLE_FLAG,
563	  .default_num = 0
564	},
565
566	{ .name = "monitor-content",
567	  .type = OPTIONS_TABLE_STRING,
568	  .default_str = ""
569	},
570
571	{ .name = "monitor-silence",
572	  .type = OPTIONS_TABLE_NUMBER,
573	  .minimum = 0,
574	  .maximum = INT_MAX,
575	  .default_num = 0
576	},
577
578	{ .name = "other-pane-height",
579	  .type = OPTIONS_TABLE_NUMBER,
580	  .minimum = 0,
581	  .maximum = INT_MAX,
582	  .default_num = 0
583	},
584
585	{ .name = "other-pane-width",
586	  .type = OPTIONS_TABLE_NUMBER,
587	  .minimum = 0,
588	  .maximum = INT_MAX,
589	  .default_num = 0
590	},
591
592	{ .name = "pane-base-index",
593	  .type = OPTIONS_TABLE_NUMBER,
594	  .minimum = 0,
595	  .maximum = USHRT_MAX,
596	  .default_num = 0
597	},
598
599	{ .name = "remain-on-exit",
600	  .type = OPTIONS_TABLE_FLAG,
601	  .default_num = 0
602	},
603
604	{ .name = "synchronize-panes",
605	  .type = OPTIONS_TABLE_FLAG,
606	  .default_num = 0
607	},
608
609	{ .name = "utf8",
610	  .type = OPTIONS_TABLE_FLAG,
611	  .default_num = 0 /* overridden in main() */
612	},
613
614	{ .name = "window-status-activity-attr",
615	  .type = OPTIONS_TABLE_ATTRIBUTES,
616	  .default_num = GRID_ATTR_REVERSE
617	},
618
619	{ .name = "window-status-activity-bg",
620	  .type = OPTIONS_TABLE_COLOUR,
621	  .default_num = 8
622	},
623
624	{ .name = "window-status-activity-fg",
625	  .type = OPTIONS_TABLE_COLOUR,
626	  .default_num = 8
627	},
628
629	{ .name = "window-status-bell-attr",
630	  .type = OPTIONS_TABLE_ATTRIBUTES,
631	  .default_num = GRID_ATTR_REVERSE
632	},
633
634	{ .name = "window-status-bell-bg",
635	  .type = OPTIONS_TABLE_COLOUR,
636	  .default_num = 8
637	},
638
639	{ .name = "window-status-bell-fg",
640	  .type = OPTIONS_TABLE_COLOUR,
641	  .default_num = 8
642	},
643
644	{ .name = "window-status-content-attr",
645	  .type = OPTIONS_TABLE_ATTRIBUTES,
646	  .default_num = GRID_ATTR_REVERSE
647	},
648
649	{ .name = "window-status-content-bg",
650	  .type = OPTIONS_TABLE_COLOUR,
651	  .default_num = 8
652	},
653
654	{ .name = "window-status-content-fg",
655	  .type = OPTIONS_TABLE_COLOUR,
656	  .default_num = 8
657	},
658
659	{ .name = "window-status-attr",
660	  .type = OPTIONS_TABLE_ATTRIBUTES,
661	  .default_num = 0
662	},
663
664	{ .name = "window-status-bg",
665	  .type = OPTIONS_TABLE_COLOUR,
666	  .default_num = 8
667	},
668
669	{ .name = "window-status-current-attr",
670	  .type = OPTIONS_TABLE_ATTRIBUTES,
671	  .default_num = 0
672	},
673
674	{ .name = "window-status-current-bg",
675	  .type = OPTIONS_TABLE_COLOUR,
676	  .default_num = 8
677	},
678
679	{ .name = "window-status-current-fg",
680	  .type = OPTIONS_TABLE_COLOUR,
681	  .default_num = 8
682	},
683
684	{ .name = "window-status-current-format",
685	  .type = OPTIONS_TABLE_STRING,
686	  .default_str = "#I:#W#F"
687	},
688
689	{ .name = "window-status-last-attr",
690	  .type = OPTIONS_TABLE_ATTRIBUTES,
691	  .default_num = 0
692	},
693
694	{ .name = "window-status-last-bg",
695	  .type = OPTIONS_TABLE_COLOUR,
696	  .default_num = 8
697	},
698
699	{ .name = "window-status-last-fg",
700	  .type = OPTIONS_TABLE_COLOUR,
701	  .default_num = 8
702	},
703
704	{ .name = "window-status-fg",
705	  .type = OPTIONS_TABLE_COLOUR,
706	  .default_num = 8
707	},
708
709	{ .name = "window-status-format",
710	  .type = OPTIONS_TABLE_STRING,
711	  .default_str = "#I:#W#F"
712	},
713
714	{ .name = "window-status-separator",
715	  .type = OPTIONS_TABLE_STRING,
716	  .default_str = " "
717	},
718
719	{ .name = "wrap-search",
720	  .type = OPTIONS_TABLE_FLAG,
721	  .default_num = 1
722	},
723
724	{ .name = "xterm-keys",
725	  .type = OPTIONS_TABLE_FLAG,
726	  .default_num = 0
727	},
728
729	{ .name = NULL }
730};
731
732/* Populate an options tree from a table. */
733void
734options_table_populate_tree(
735    const struct options_table_entry *table, struct options *oo)
736{
737	const struct options_table_entry	*oe;
738
739	for (oe = table; oe->name != NULL; oe++) {
740		if (oe->default_str != NULL)
741			options_set_string(oo, oe->name, "%s", oe->default_str);
742		else
743			options_set_number(oo, oe->name, oe->default_num);
744	}
745}
746
747/* Print an option using its type from the table. */
748const char *
749options_table_print_entry(
750    const struct options_table_entry *oe, struct options_entry *o)
751{
752	static char	 out[BUFSIZ];
753	const char	*s;
754
755	*out = '\0';
756	switch (oe->type) {
757	case OPTIONS_TABLE_STRING:
758		xsnprintf(out, sizeof out, "\"%s\"", o->str);
759		break;
760	case OPTIONS_TABLE_NUMBER:
761		xsnprintf(out, sizeof out, "%lld", o->num);
762		break;
763	case OPTIONS_TABLE_KEY:
764		xsnprintf(out, sizeof out, "%s", key_string_lookup_key(o->num));
765		break;
766	case OPTIONS_TABLE_COLOUR:
767		s = colour_tostring(o->num);
768		xsnprintf(out, sizeof out, "%s", s);
769		break;
770	case OPTIONS_TABLE_ATTRIBUTES:
771		s = attributes_tostring(o->num);
772		xsnprintf(out, sizeof out, "%s", s);
773		break;
774	case OPTIONS_TABLE_FLAG:
775		if (o->num)
776			strlcpy(out, "on", sizeof out);
777		else
778			strlcpy(out, "off", sizeof out);
779		break;
780	case OPTIONS_TABLE_CHOICE:
781		s = oe->choices[o->num];
782		xsnprintf(out, sizeof out, "%s", s);
783		break;
784	}
785	return (out);
786}
787
788/* Find an option. */
789int
790options_table_find(
791    const char *optstr, const struct options_table_entry **table,
792    const struct options_table_entry **oe)
793{
794	static const struct options_table_entry	*tables[] = {
795		server_options_table,
796		window_options_table,
797		session_options_table
798	};
799	const struct options_table_entry	*oe_loop;
800	u_int					 i;
801
802	for (i = 0; i < nitems(tables); i++) {
803		for (oe_loop = tables[i]; oe_loop->name != NULL; oe_loop++) {
804			if (strncmp(oe_loop->name, optstr, strlen(optstr)) != 0)
805				continue;
806
807			/* If already found, ambiguous. */
808			if (*oe != NULL)
809				return (-1);
810			*oe = oe_loop;
811			*table = tables[i];
812
813			/* Bail now if an exact match. */
814			if (strcmp((*oe)->name, optstr) == 0)
815				break;
816		}
817	}
818	return (0);
819}
820