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