OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkArgv.c] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkArgv.c --
3
 *
4
 *      This file contains a procedure that handles table-based
5
 *      argv-argc parsing.
6
 *
7
 * Copyright (c) 1990-1994 The Regents of the University of California.
8
 * Copyright (c) 1994 Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * RCS: @(#) $Id: tkArgv.c,v 1.1.1.1 2002-01-16 10:25:50 markom Exp $
14
 */
15
 
16
#include "tkPort.h"
17
#include "tk.h"
18
 
19
/*
20
 * Default table of argument descriptors.  These are normally available
21
 * in every application.
22
 */
23
 
24
static Tk_ArgvInfo defaultTable[] = {
25
    {"-help",   TK_ARGV_HELP,   (char *) NULL,  (char *) NULL,
26
        "Print summary of command-line options and abort"},
27
    {"-version",        TK_ARGV_VERSION,        (char *) NULL,  (char *) NULL,
28
        "Print version number 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 interp->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
            case TK_ARGV_VERSION:
297
                Tcl_AppendResult(interp, "Tk version ", TK_VERSION, "-foundry-971110",
298
                        (char *) NULL);
299
                return TCL_ERROR;
300
            default:
301
                sprintf(interp->result, "bad argument type %d in Tk_ArgvInfo",
302
                        infoPtr->type);
303
                return TCL_ERROR;
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
 *      Interp->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[30];
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.