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