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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (hide annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (7 years, 7 months ago) by dashley
File MIME type: text/plain
File size: 12075 byte(s)
License and property (keyword) changes.
1 dashley 69 /* $Header$ */
2 dashley 25
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 dashley 69 /* End of tkargv.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25