ParseCmd.c revision 1ab64890
1/* $Xorg: ParseCmd.c,v 1.4 2001/02/09 02:03:35 xorgcvs Exp $ */
2
3/***********************************************************
4
5Copyright 1987, 1988, 1998  The Open Group
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall not be
24used in advertising or otherwise to promote the sale, use or other dealings
25in this Software without prior written authorization from The Open Group.
26
27
28Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
29
30                        All Rights Reserved
31
32Permission to use, copy, modify, and distribute this software and its
33documentation for any purpose and without fee is hereby granted,
34provided that the above copyright notice appear in all copies and that
35both that copyright notice and this permission notice appear in
36supporting documentation, and that the name of Digital not be
37used in advertising or publicity pertaining to distribution of the
38software without specific, written prior permission.
39
40DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
41ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
42DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
43ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
44WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
45ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46SOFTWARE.
47
48******************************************************************/
49/* $XFree86: xc/lib/X11/ParseCmd.c,v 1.5 2001/12/14 19:54:03 dawes Exp $ */
50
51/* XrmParseCommand()
52
53   Parse command line and store argument values into resource database
54
55   Allows any un-ambiguous abbreviation for an option name, but requires
56   that the table be ordered with any options that are prefixes of
57   other options appearing before the longer version in the table.
58*/
59
60#ifdef HAVE_CONFIG_H
61#include <config.h>
62#endif
63#include "Xlibint.h"
64#include <X11/Xresource.h>
65#include <stdio.h>
66
67
68static void _XReportParseError(XrmOptionDescRec *arg, const char *msg)
69{
70    (void) fprintf(stderr, "Error parsing argument \"%s\" (%s); %s\n",
71		   arg->option, arg->specifier, msg);
72    exit(1);
73}
74
75void
76XrmParseCommand(
77    XrmDatabase		*pdb,		/* data base */
78    register XrmOptionDescList options, /* pointer to table of valid options */
79    int			num_options,	/* number of options		     */
80    _Xconst char	*prefix,	/* name to prefix resources with     */
81    int			*argc,		/* address of argument count 	     */
82    char		**argv)		/* argument list (command line)	     */
83{
84    int 		foundOption;
85    char		**argsave;
86    register int	i, myargc;
87    XrmBinding		bindings[100];
88    XrmQuark		quarks[100];
89    XrmBinding		*start_bindings;
90    XrmQuark		*start_quarks;
91    char		*optP, *argP = NULL, optchar, argchar = 0;
92    int			matches;
93    enum {DontCare, Check, NotSorted, Sorted} table_is_sorted;
94    char		**argend;
95
96#define PutCommandResource(value_str)				\
97    {								\
98    XrmStringToBindingQuarkList(				\
99	options[i].specifier, start_bindings, start_quarks);    \
100    XrmQPutStringResource(pdb, bindings, quarks, value_str);    \
101    } /* PutCommandResource */
102
103    myargc = (*argc);
104    argend = argv + myargc;
105    argsave = ++argv;
106
107    /* Initialize bindings/quark list with prefix (typically app name). */
108    quarks[0] = XrmStringToName(prefix);
109    bindings[0] = XrmBindTightly;
110    start_quarks = quarks+1;
111    start_bindings = bindings+1;
112
113    table_is_sorted = (myargc > 2) ? Check : DontCare;
114    for (--myargc; myargc > 0; --myargc, ++argv) {
115	foundOption = False;
116	matches = 0;
117	for (i=0; i < num_options; ++i) {
118	    /* checking the sort order first insures we don't have to
119	       re-do the check if the arg hits on the last entry in
120	       the table.  Useful because usually '=' is the last entry
121	       and users frequently specify geometry early in the command */
122	    if (table_is_sorted == Check && i > 0 &&
123		strcmp(options[i].option, options[i-1].option) < 0) {
124		table_is_sorted = NotSorted;
125	    }
126	    for (argP = *argv, optP = options[i].option;
127		 (optchar = *optP++) &&
128		 (argchar = *argP++) &&
129		 argchar == optchar;);
130	    if (!optchar) {
131		if (!*argP ||
132		    options[i].argKind == XrmoptionStickyArg ||
133		    options[i].argKind == XrmoptionIsArg) {
134		    /* give preference to exact matches, StickyArg and IsArg */
135		    matches = 1;
136		    foundOption = i;
137		    break;
138		}
139	    }
140	    else if (!argchar) {
141		/* may be an abbreviation for this option */
142		matches++;
143		foundOption = i;
144	    }
145	    else if (table_is_sorted == Sorted && optchar > argchar) {
146		break;
147	    }
148	    if (table_is_sorted == Check && i > 0 &&
149		strcmp(options[i].option, options[i-1].option) < 0) {
150		table_is_sorted = NotSorted;
151	    }
152	}
153	if (table_is_sorted == Check && i >= (num_options-1))
154	    table_is_sorted = Sorted;
155	if (matches == 1) {
156		i = foundOption;
157		switch (options[i].argKind){
158		case XrmoptionNoArg:
159		    --(*argc);
160		    PutCommandResource(options[i].value);
161		    break;
162
163		case XrmoptionIsArg:
164		    --(*argc);
165		    PutCommandResource(*argv);
166		    break;
167
168		case XrmoptionStickyArg:
169		    --(*argc);
170		    PutCommandResource(argP);
171		    break;
172
173		case XrmoptionSepArg:
174		    if (myargc > 1) {
175			++argv; --myargc; --(*argc); --(*argc);
176			PutCommandResource(*argv);
177		    } else
178			(*argsave++) = (*argv);
179		    break;
180
181		case XrmoptionResArg:
182		    if (myargc > 1) {
183			++argv; --myargc; --(*argc); --(*argc);
184			XrmPutLineResource(pdb, *argv);
185		    } else
186			(*argsave++) = (*argv);
187		    break;
188
189		case XrmoptionSkipArg:
190		    if (myargc > 1) {
191			--myargc;
192			(*argsave++) = (*argv++);
193		    }
194		    (*argsave++) = (*argv);
195		    break;
196
197		case XrmoptionSkipLine:
198		    for (; myargc > 0; myargc--)
199			(*argsave++) = (*argv++);
200		    break;
201
202		case XrmoptionSkipNArgs:
203		    {
204			register int j = 1 + (long) options[i].value;
205
206			if (j > myargc) j = myargc;
207			for (; j > 0; j--) {
208			    (*argsave++) = (*argv++);
209			    myargc--;
210			}
211			argv--;		/* went one too far before */
212			myargc++;
213		    }
214		    break;
215
216		default:
217		    _XReportParseError (&options[i], "unknown kind");
218		    break;
219		}
220	}
221	else
222	    (*argsave++) = (*argv);  /*compress arglist*/
223    }
224
225    if (argsave < argend)
226	(*argsave)=NULL; /* put NULL terminator on compressed argv */
227}
228