/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkargv.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkargv.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 71 - (show annotations) (download)
Sat Nov 5 11:07:06 2016 UTC (7 years, 11 months ago) by dashley
File MIME type: text/plain
File size: 11634 byte(s)
Set EOL properties appropriately to facilitate simultaneous Linux and Windows development.
1 /* $Header$ */
2
3 /*
4 * tkArgv.c --
5 *
6 * This file contains a procedure that handles table-based
7 * argv-argc parsing.
8 *
9 * Copyright (c) 1990-1994 The Regents of the University of California.
10 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
11 *
12 * See the file "license.terms" for information on usage and redistribution
13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 *
15 * RCS: @(#) $Id: tkargv.c,v 1.1.1.1 2001/06/13 04:53:35 dtashley Exp $
16 */
17
18 #include "tkPort.h"
19 #include "tk.h"
20
21 /*
22 * Default table of argument descriptors. These are normally available
23 * in every application.
24 */
25
26 static Tk_ArgvInfo defaultTable[] = {
27 {"-help", TK_ARGV_HELP, (char *) NULL, (char *) NULL,
28 "Print summary of command-line options and abort"},
29 {NULL, TK_ARGV_END, (char *) NULL, (char *) NULL,
30 (char *) NULL}
31 };
32
33 /*
34 * Forward declarations for procedures defined in this file:
35 */
36
37 static void PrintUsage _ANSI_ARGS_((Tcl_Interp *interp,
38 Tk_ArgvInfo *argTable, int flags));
39
40 /*
41 *----------------------------------------------------------------------
42 *
43 * Tk_ParseArgv --
44 *
45 * Process an argv array according to a table of expected
46 * command-line options. See the manual page for more details.
47 *
48 * Results:
49 * The return value is a standard Tcl return value. If an
50 * error occurs then an error message is left in the interp's result.
51 * Under normal conditions, both *argcPtr and *argv are modified
52 * to return the arguments that couldn't be processed here (they
53 * didn't match the option table, or followed an TK_ARGV_REST
54 * argument).
55 *
56 * Side effects:
57 * Variables may be modified, resources may be entered for tkwin,
58 * or procedures may be called. It all depends on the arguments
59 * and their entries in argTable. See the user documentation
60 * for details.
61 *
62 *----------------------------------------------------------------------
63 */
64
65 int
66 Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags)
67 Tcl_Interp *interp; /* Place to store error message. */
68 Tk_Window tkwin; /* Window to use for setting Tk options.
69 * NULL means ignore Tk option specs. */
70 int *argcPtr; /* Number of arguments in argv. Modified
71 * to hold # args left in argv at end. */
72 char **argv; /* Array of arguments. Modified to hold
73 * those that couldn't be processed here. */
74 Tk_ArgvInfo *argTable; /* Array of option descriptions */
75 int flags; /* Or'ed combination of various flag bits,
76 * such as TK_ARGV_NO_DEFAULTS. */
77 {
78 register Tk_ArgvInfo *infoPtr;
79 /* Pointer to the current entry in the
80 * table of argument descriptions. */
81 Tk_ArgvInfo *matchPtr; /* Descriptor that matches current argument. */
82 char *curArg; /* Current argument */
83 register char c; /* Second character of current arg (used for
84 * quick check for matching; use 2nd char.
85 * because first char. will almost always
86 * be '-'). */
87 int srcIndex; /* Location from which to read next argument
88 * from argv. */
89 int dstIndex; /* Index into argv to which next unused
90 * argument should be copied (never greater
91 * than srcIndex). */
92 int argc; /* # arguments in argv still to process. */
93 size_t length; /* Number of characters in current argument. */
94 int i;
95
96 if (flags & TK_ARGV_DONT_SKIP_FIRST_ARG) {
97 srcIndex = dstIndex = 0;
98 argc = *argcPtr;
99 } else {
100 srcIndex = dstIndex = 1;
101 argc = *argcPtr-1;
102 }
103
104 while (argc > 0) {
105 curArg = argv[srcIndex];
106 srcIndex++;
107 argc--;
108 length = strlen(curArg);
109 if (length > 0) {
110 c = curArg[1];
111 } else {
112 c = 0;
113 }
114
115 /*
116 * Loop throught the argument descriptors searching for one with
117 * the matching key string. If found, leave a pointer to it in
118 * matchPtr.
119 */
120
121 matchPtr = NULL;
122 for (i = 0; i < 2; i++) {
123 if (i == 0) {
124 infoPtr = argTable;
125 } else {
126 infoPtr = defaultTable;
127 }
128 for (; (infoPtr != NULL) && (infoPtr->type != TK_ARGV_END);
129 infoPtr++) {
130 if (infoPtr->key == NULL) {
131 continue;
132 }
133 if ((infoPtr->key[1] != c)
134 || (strncmp(infoPtr->key, curArg, length) != 0)) {
135 continue;
136 }
137 if ((tkwin == NULL)
138 && ((infoPtr->type == TK_ARGV_CONST_OPTION)
139 || (infoPtr->type == TK_ARGV_OPTION_VALUE)
140 || (infoPtr->type == TK_ARGV_OPTION_NAME_VALUE))) {
141 continue;
142 }
143 if (infoPtr->key[length] == 0) {
144 matchPtr = infoPtr;
145 goto gotMatch;
146 }
147 if (flags & TK_ARGV_NO_ABBREV) {
148 continue;
149 }
150 if (matchPtr != NULL) {
151 Tcl_AppendResult(interp, "ambiguous option \"", curArg,
152 "\"", (char *) NULL);
153 return TCL_ERROR;
154 }
155 matchPtr = infoPtr;
156 }
157 }
158 if (matchPtr == NULL) {
159
160 /*
161 * Unrecognized argument. Just copy it down, unless the caller
162 * prefers an error to be registered.
163 */
164
165 if (flags & TK_ARGV_NO_LEFTOVERS) {
166 Tcl_AppendResult(interp, "unrecognized argument \"",
167 curArg, "\"", (char *) NULL);
168 return TCL_ERROR;
169 }
170 argv[dstIndex] = curArg;
171 dstIndex++;
172 continue;
173 }
174
175 /*
176 * Take the appropriate action based on the option type
177 */
178
179 gotMatch:
180 infoPtr = matchPtr;
181 switch (infoPtr->type) {
182 case TK_ARGV_CONSTANT:
183 *((int *) infoPtr->dst) = (int) infoPtr->src;
184 break;
185 case TK_ARGV_INT:
186 if (argc == 0) {
187 goto missingArg;
188 } else {
189 char *endPtr;
190
191 *((int *) infoPtr->dst) =
192 strtol(argv[srcIndex], &endPtr, 0);
193 if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
194 Tcl_AppendResult(interp, "expected integer argument ",
195 "for \"", infoPtr->key, "\" but got \"",
196 argv[srcIndex], "\"", (char *) NULL);
197 return TCL_ERROR;
198 }
199 srcIndex++;
200 argc--;
201 }
202 break;
203 case TK_ARGV_STRING:
204 if (argc == 0) {
205 goto missingArg;
206 } else {
207 *((char **)infoPtr->dst) = argv[srcIndex];
208 srcIndex++;
209 argc--;
210 }
211 break;
212 case TK_ARGV_UID:
213 if (argc == 0) {
214 goto missingArg;
215 } else {
216 *((Tk_Uid *)infoPtr->dst) = Tk_GetUid(argv[srcIndex]);
217 srcIndex++;
218 argc--;
219 }
220 break;
221 case TK_ARGV_REST:
222 *((int *) infoPtr->dst) = dstIndex;
223 goto argsDone;
224 case TK_ARGV_FLOAT:
225 if (argc == 0) {
226 goto missingArg;
227 } else {
228 char *endPtr;
229
230 *((double *) infoPtr->dst) =
231 strtod(argv[srcIndex], &endPtr);
232 if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
233 Tcl_AppendResult(interp, "expected floating-point ",
234 "argument for \"", infoPtr->key,
235 "\" but got \"", argv[srcIndex], "\"",
236 (char *) NULL);
237 return TCL_ERROR;
238 }
239 srcIndex++;
240 argc--;
241 }
242 break;
243 case TK_ARGV_FUNC: {
244 typedef int (ArgvFunc)_ANSI_ARGS_((char *, char *, char *));
245 ArgvFunc *handlerProc;
246
247 handlerProc = (ArgvFunc *) infoPtr->src;
248 if ((*handlerProc)(infoPtr->dst, infoPtr->key,
249 argv[srcIndex])) {
250 srcIndex += 1;
251 argc -= 1;
252 }
253 break;
254 }
255 case TK_ARGV_GENFUNC: {
256 typedef int (ArgvGenFunc)_ANSI_ARGS_((char *, Tcl_Interp *,
257 char *, int, char **));
258 ArgvGenFunc *handlerProc;
259
260 handlerProc = (ArgvGenFunc *) infoPtr->src;
261 argc = (*handlerProc)(infoPtr->dst, interp, infoPtr->key,
262 argc, argv+srcIndex);
263 if (argc < 0) {
264 return TCL_ERROR;
265 }
266 break;
267 }
268 case TK_ARGV_HELP:
269 PrintUsage (interp, argTable, flags);
270 return TCL_ERROR;
271 case TK_ARGV_CONST_OPTION:
272 Tk_AddOption(tkwin, infoPtr->dst, infoPtr->src,
273 TK_INTERACTIVE_PRIO);
274 break;
275 case TK_ARGV_OPTION_VALUE:
276 if (argc < 1) {
277 goto missingArg;
278 }
279 Tk_AddOption(tkwin, infoPtr->dst, argv[srcIndex],
280 TK_INTERACTIVE_PRIO);
281 srcIndex++;
282 argc--;
283 break;
284 case TK_ARGV_OPTION_NAME_VALUE:
285 if (argc < 2) {
286 Tcl_AppendResult(interp, "\"", curArg,
287 "\" option requires two following arguments",
288 (char *) NULL);
289 return TCL_ERROR;
290 }
291 Tk_AddOption(tkwin, argv[srcIndex], argv[srcIndex+1],
292 TK_INTERACTIVE_PRIO);
293 srcIndex += 2;
294 argc -= 2;
295 break;
296 default: {
297 char buf[64 + TCL_INTEGER_SPACE];
298
299 sprintf(buf, "bad argument type %d in Tk_ArgvInfo",
300 infoPtr->type);
301 Tcl_SetResult(interp, buf, TCL_VOLATILE);
302 return TCL_ERROR;
303 }
304 }
305 }
306
307 /*
308 * If we broke out of the loop because of an OPT_REST argument,
309 * copy the remaining arguments down.
310 */
311
312 argsDone:
313 while (argc) {
314 argv[dstIndex] = argv[srcIndex];
315 srcIndex++;
316 dstIndex++;
317 argc--;
318 }
319 argv[dstIndex] = (char *) NULL;
320 *argcPtr = dstIndex;
321 return TCL_OK;
322
323 missingArg:
324 Tcl_AppendResult(interp, "\"", curArg,
325 "\" option requires an additional argument", (char *) NULL);
326 return TCL_ERROR;
327 }
328
329 /*
330 *----------------------------------------------------------------------
331 *
332 * PrintUsage --
333 *
334 * Generate a help string describing command-line options.
335 *
336 * Results:
337 * The interp's result will be modified to hold a help string
338 * describing all the options in argTable, plus all those
339 * in the default table unless TK_ARGV_NO_DEFAULTS is
340 * specified in flags.
341 *
342 * Side effects:
343 * None.
344 *
345 *----------------------------------------------------------------------
346 */
347
348 static void
349 PrintUsage(interp, argTable, flags)
350 Tcl_Interp *interp; /* Place information in this interp's
351 * result area. */
352 Tk_ArgvInfo *argTable; /* Array of command-specific argument
353 * descriptions. */
354 int flags; /* If the TK_ARGV_NO_DEFAULTS bit is set
355 * in this word, then don't generate
356 * information for default options. */
357 {
358 register Tk_ArgvInfo *infoPtr;
359 int width, i, numSpaces;
360 #define NUM_SPACES 20
361 static char spaces[] = " ";
362 char tmp[TCL_DOUBLE_SPACE];
363
364 /*
365 * First, compute the width of the widest option key, so that we
366 * can make everything line up.
367 */
368
369 width = 4;
370 for (i = 0; i < 2; i++) {
371 for (infoPtr = i ? defaultTable : argTable;
372 infoPtr->type != TK_ARGV_END; infoPtr++) {
373 int length;
374 if (infoPtr->key == NULL) {
375 continue;
376 }
377 length = strlen(infoPtr->key);
378 if (length > width) {
379 width = length;
380 }
381 }
382 }
383
384 Tcl_AppendResult(interp, "Command-specific options:", (char *) NULL);
385 for (i = 0; ; i++) {
386 for (infoPtr = i ? defaultTable : argTable;
387 infoPtr->type != TK_ARGV_END; infoPtr++) {
388 if ((infoPtr->type == TK_ARGV_HELP) && (infoPtr->key == NULL)) {
389 Tcl_AppendResult(interp, "\n", infoPtr->help, (char *) NULL);
390 continue;
391 }
392 Tcl_AppendResult(interp, "\n ", infoPtr->key, ":", (char *) NULL);
393 numSpaces = width + 1 - strlen(infoPtr->key);
394 while (numSpaces > 0) {
395 if (numSpaces >= NUM_SPACES) {
396 Tcl_AppendResult(interp, spaces, (char *) NULL);
397 } else {
398 Tcl_AppendResult(interp, spaces+NUM_SPACES-numSpaces,
399 (char *) NULL);
400 }
401 numSpaces -= NUM_SPACES;
402 }
403 Tcl_AppendResult(interp, infoPtr->help, (char *) NULL);
404 switch (infoPtr->type) {
405 case TK_ARGV_INT: {
406 sprintf(tmp, "%d", *((int *) infoPtr->dst));
407 Tcl_AppendResult(interp, "\n\t\tDefault value: ",
408 tmp, (char *) NULL);
409 break;
410 }
411 case TK_ARGV_FLOAT: {
412 sprintf(tmp, "%g", *((double *) infoPtr->dst));
413 Tcl_AppendResult(interp, "\n\t\tDefault value: ",
414 tmp, (char *) NULL);
415 break;
416 }
417 case TK_ARGV_STRING: {
418 char *string;
419
420 string = *((char **) infoPtr->dst);
421 if (string != NULL) {
422 Tcl_AppendResult(interp, "\n\t\tDefault value: \"",
423 string, "\"", (char *) NULL);
424 }
425 break;
426 }
427 default: {
428 break;
429 }
430 }
431 }
432
433 if ((flags & TK_ARGV_NO_DEFAULTS) || (i > 0)) {
434 break;
435 }
436 Tcl_AppendResult(interp, "\nGeneric options for all commands:",
437 (char *) NULL);
438 }
439 }
440
441 /* End of tkargv.c */

Properties

Name Value
svn:eol-style native
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25