~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/security/nss/cmd/cmdlib/cmdline.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * The contents of this file are subject to the Mozilla Public
 
3
 * License Version 1.1 (the "License"); you may not use this file
 
4
 * except in compliance with the License. You may obtain a copy of
 
5
 * the License at http://www.mozilla.org/MPL/
 
6
 * 
 
7
 * Software distributed under the License is distributed on an "AS
 
8
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
9
 * implied. See the License for the specific language governing
 
10
 * rights and limitations under the License.
 
11
 * 
 
12
 * The Original Code is the Netscape security libraries.
 
13
 * 
 
14
 * The Initial Developer of the Original Code is Netscape
 
15
 * Communications Corporation.  Portions created by Netscape are 
 
16
 * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
 
17
 * Rights Reserved.
 
18
 * 
 
19
 * Contributor(s):
 
20
 * 
 
21
 * Alternatively, the contents of this file may be used under the
 
22
 * terms of the GNU General Public License Version 2 or later (the
 
23
 * "GPL"), in which case the provisions of the GPL are applicable 
 
24
 * instead of those above.  If you wish to allow use of your 
 
25
 * version of this file only under the terms of the GPL and not to
 
26
 * allow others to use your version of this file under the MPL,
 
27
 * indicate your decision by deleting the provisions above and
 
28
 * replace them with the notice and other provisions required by
 
29
 * the GPL.  If you do not delete the provisions above, a recipient
 
30
 * may use your version of this file under either the MPL or the
 
31
 * GPL.
 
32
 */
 
33
 
 
34
#include <string.h>
 
35
#include <ctype.h>
 
36
 
 
37
#include "cmdutil.h"
 
38
 
 
39
static int s_indent_size = 4;
 
40
 
 
41
void
 
42
CMD_SetIndentSize(int size) 
 
43
{
 
44
    s_indent_size = size;
 
45
}
 
46
 
 
47
#if 0
 
48
static void
 
49
indent(PRFileDesc *out, int level)
 
50
{
 
51
    int i, j;
 
52
    for (i=0; i<level; i++)
 
53
        for (j=0; j<s_indent_size; j++) 
 
54
            PR_fprintf(out, " ");
 
55
}
 
56
#endif
 
57
 
 
58
struct cmdPrintStateStr {
 
59
    PRFileDesc *file;
 
60
    int width;
 
61
    int indent;
 
62
    int linepos;
 
63
};
 
64
 
 
65
static void
 
66
init_print_ps(cmdPrintState *ps, PRFileDesc *outfile, int width, int indent)
 
67
{
 
68
    ps->file = (outfile) ? outfile : PR_STDOUT;
 
69
    ps->width = (width > 0) ? width : 80;
 
70
    ps->indent = (indent > 0) ? indent : 0;
 
71
    ps->linepos = 0;
 
72
}
 
73
 
 
74
static void
 
75
print_ps_indent(cmdPrintState *ps)
 
76
{
 
77
    int j;
 
78
    if (ps->linepos != 0) {
 
79
        PR_fprintf(ps->file, "\n");
 
80
        ps->linepos = 0;
 
81
    }
 
82
    for (j=0; j<=ps->indent; j++) PR_fprintf(ps->file, " ");
 
83
    ps->linepos = ps->indent;
 
84
}
 
85
 
 
86
static void
 
87
print_ps_to_indent(cmdPrintState *ps)
 
88
{
 
89
    if (ps->linepos > ps->indent)
 
90
        PR_fprintf(ps->file, "\n");
 
91
    while (ps->linepos <= ps->indent) {
 
92
        PR_fprintf(ps->file, " ");
 
93
        ps->linepos++;
 
94
    }
 
95
}
 
96
 
 
97
static void
 
98
nprintbuf(cmdPrintState *ps, char *buf, int start, int len)
 
99
{
 
100
    int j;
 
101
    for (j=start; j<start + len; j++) {
 
102
        if (buf[j] == '\n') {
 
103
            PR_fprintf(ps->file, "\n");
 
104
            ps->linepos = 0;
 
105
            print_ps_indent(ps);
 
106
        } else {
 
107
            PR_fprintf(ps->file, "%c", buf[j]);
 
108
            ps->linepos++;
 
109
        }
 
110
    }
 
111
}
 
112
 
 
113
static void 
 
114
nprintf(cmdPrintState *ps, char *msg, ...)
 
115
{
 
116
    char buf[256];
 
117
    int i, len, grouplen;
 
118
    PRBool openquote, openbracket, openparen, openangle, itsaword;
 
119
    va_list args;
 
120
    va_start(args, msg);
 
121
    vsprintf(buf, msg, args);
 
122
    len = strlen(buf);
 
123
    /* print_ps_indent(ps); */
 
124
    if (len < ps->width - ps->linepos) {
 
125
        nprintbuf(ps, buf, 0, len + 1);
 
126
        return;
 
127
    }
 
128
    /* group in this order: " [ ( < word > ) ] " */
 
129
    i=0;
 
130
    openquote=openbracket=openparen=openangle=itsaword=PR_FALSE;
 
131
    while (i<len) {
 
132
        grouplen = 0;
 
133
        if (buf[i] == '\"') { openquote = PR_TRUE; grouplen = 1; }
 
134
        else if (buf[i] == '[') { openbracket = PR_TRUE; grouplen = 1; }
 
135
        else if (buf[i] == '(') { openparen = PR_TRUE; grouplen = 1; }
 
136
        else if (buf[i] == '<') { openangle = PR_TRUE; grouplen = 1; }
 
137
        else itsaword = PR_TRUE;
 
138
        while (grouplen < len && buf[i+grouplen] != '\0' &&
 
139
               ((openquote && buf[i+grouplen] != '\"') ||
 
140
                (openbracket && buf[i+grouplen] != ']') ||
 
141
                (openparen && buf[i+grouplen] != ')') ||
 
142
                (openangle && buf[i+grouplen] != '>') ||
 
143
                (itsaword && !isspace(buf[i+grouplen]))))
 
144
            grouplen++;
 
145
        grouplen++; /* grab the terminator (whitespace for word) */
 
146
        if (!itsaword && isspace(buf[i+grouplen])) grouplen++;
 
147
        if (grouplen < ps->width - ps->linepos) {
 
148
            nprintbuf(ps, buf, i, grouplen);
 
149
        } else if (grouplen < ps->width - ps->indent) {
 
150
            print_ps_indent(ps);
 
151
            nprintbuf(ps, buf, i, grouplen);
 
152
        } else {
 
153
            /* it's just too darn long.  what to do? */
 
154
        }
 
155
        i += grouplen;
 
156
        openquote=openbracket=openparen=openangle=itsaword=PR_FALSE;
 
157
    }
 
158
    va_end(args);
 
159
}
 
160
 
 
161
void 
 
162
CMD_PrintUsageString(cmdPrintState *ps, char *str)
 
163
{
 
164
    nprintf(ps, "%s", str);
 
165
}
 
166
 
 
167
/* void because it exits with Usage() if failure */
 
168
static void
 
169
command_line_okay(cmdCommand *cmd, char *progName)
 
170
{
 
171
    int i, c = -1;
 
172
    /* user asked for help.  hope somebody gives it to them. */
 
173
    if (cmd->opt[0].on) return;
 
174
    /* check that the command got all of its needed options */
 
175
    for (i=0; i<cmd->ncmd; i++) {
 
176
        if (cmd->cmd[i].on) {
 
177
            if (c > 0) {
 
178
                fprintf(stderr, 
 
179
                        "%s: only one command can be given at a time.\n",
 
180
                        progName);
 
181
                CMD_Usage(progName, cmd);
 
182
            } else {
 
183
                c = i;
 
184
            }
 
185
        }
 
186
    }
 
187
    if (cmd->cmd[c].argUse == CMDArgReq && cmd->cmd[c].arg == NULL) {
 
188
        /* where's the arg when you need it... */
 
189
        fprintf(stderr, "%s: command --%s requires an argument.\n",
 
190
                         progName, cmd->cmd[c].s);
 
191
        fprintf(stderr, "type \"%s --%s --help\" for help.\n",
 
192
                         progName, cmd->cmd[c].s);
 
193
        CMD_Usage(progName, cmd);
 
194
    }
 
195
    for (i=0; i<cmd->nopt; i++) {
 
196
        if (cmd->cmd[c].req & CMDBIT(i)) {
 
197
            /* command requires this option */
 
198
            if (!cmd->opt[i].on) {
 
199
                /* but it ain't there */
 
200
                fprintf(stderr, "%s: command --%s requires option --%s.\n",
 
201
                                 progName, cmd->cmd[c].s, cmd->opt[i].s);
 
202
            } else {
 
203
                /* okay, its there, but does it have an arg? */
 
204
                if (cmd->opt[i].argUse == CMDArgReq && !cmd->opt[i].arg) {
 
205
                    fprintf(stderr, "%s: option --%s requires an argument.\n",
 
206
                                     progName, cmd->opt[i].s);
 
207
                }
 
208
            }
 
209
        } else if (cmd->cmd[c].opt & CMDBIT(i)) {
 
210
           /* this option is optional */
 
211
            if (cmd->opt[i].on) {
 
212
                /* okay, its there, but does it have an arg? */
 
213
                if (cmd->opt[i].argUse == CMDArgReq && !cmd->opt[i].arg) {
 
214
                    fprintf(stderr, "%s: option --%s requires an argument.\n",
 
215
                                     progName, cmd->opt[i].s);
 
216
                }
 
217
            }
 
218
        } else {
 
219
           /* command knows nothing about it */
 
220
           if (cmd->opt[i].on) {
 
221
                /* so why the h--- is it on? */
 
222
                fprintf(stderr, "%s: option --%s not used with command --%s.\n",
 
223
                                 progName, cmd->opt[i].s, cmd->cmd[c].s);
 
224
           }
 
225
        }
 
226
    }
 
227
}
 
228
 
 
229
static char *
 
230
get_arg(char *curopt, char **nextopt, int argc, int *index)
 
231
{
 
232
    char *str;
 
233
    if (curopt) {
 
234
        str = curopt;
 
235
    } else {
 
236
        if (*index + 1 >= argc) return NULL;
 
237
        /* not really an argument but another flag */
 
238
        if (nextopt[*index+1][0] == '-') return NULL;
 
239
        str = nextopt[++(*index)];
 
240
    }
 
241
    /* parse the option */
 
242
    return strdup(str);
 
243
}
 
244
 
 
245
int
 
246
CMD_ParseCommandLine(int argc, char **argv, char *progName, cmdCommand *cmd)
 
247
{
 
248
    int i, j, k;
 
249
    int cmdToRun = -1;
 
250
    char *flag;
 
251
    i=1;
 
252
    if (argc <= 1) return -2; /* gross hack for cmdless things like atob */
 
253
    do {
 
254
        flag = argv[i];
 
255
        if (strlen(flag) < 2) /* huh? */
 
256
            return -1;
 
257
        if (flag[0] != '-')
 
258
            return -1;
 
259
        /* ignore everything after lone "--" (app-specific weirdness there) */
 
260
        if (strcmp(flag, "--") == 0)
 
261
            return cmdToRun;
 
262
        /* single hyphen means short alias (single-char) */
 
263
        if (flag[1] != '-') {
 
264
            j=1;
 
265
            /* collect a set of opts, ex. -abc */
 
266
            while (flag[j] != '\0') {
 
267
                PRBool found = PR_FALSE;
 
268
                /* walk the command set looking for match */
 
269
                for (k=0; k<cmd->ncmd; k++) {
 
270
                    if (flag[j] == cmd->cmd[k].c) {
 
271
                        /* done - only take one command at a time */
 
272
                        if (j > 1) return -1;
 
273
                        cmd->cmd[k].on = found = PR_TRUE;
 
274
                        cmdToRun = k;
 
275
                        if (cmd->cmd[k].argUse != CMDNoArg)
 
276
                            cmd->cmd[k].arg = get_arg(NULL, argv, argc, &i);
 
277
                        goto next_flag;
 
278
                    }
 
279
                }
 
280
                /* wasn't found in commands, try options */
 
281
                for (k=0; k<cmd->nopt; k++) {
 
282
                    if (flag[j] == cmd->opt[k].c) {
 
283
                        /* collect this option and keep going */
 
284
                        cmd->opt[k].on = found = PR_TRUE;
 
285
                        if (flag[j+1] == '\0') {
 
286
                            if (cmd->opt[k].argUse != CMDNoArg)
 
287
                                cmd->opt[k].arg = get_arg(NULL, argv, argc, &i);
 
288
                            goto next_flag;
 
289
                        }
 
290
                    }
 
291
                }
 
292
                j++;
 
293
                if (!found) return -1;
 
294
            }
 
295
        } else { /* long alias, ex. --list */
 
296
            char *fl = NULL, *arg = NULL;
 
297
            PRBool hyphened = PR_FALSE;
 
298
            fl = &flag[2];
 
299
            arg = strchr(fl, '=');
 
300
            if (arg) {
 
301
                *arg++ = '\0';
 
302
            } else {
 
303
                arg = strchr(fl, '-');
 
304
                if (arg) {
 
305
                    hyphened = PR_TRUE; /* watch this, see below */
 
306
                    *arg++ = '\0';
 
307
                }
 
308
            }
 
309
            for (k=0; k<cmd->ncmd; k++) {
 
310
                if (strcmp(fl, cmd->cmd[k].s) == 0) {
 
311
                    cmd->cmd[k].on = PR_TRUE;
 
312
                    cmdToRun = k;
 
313
                    if (cmd->cmd[k].argUse != CMDNoArg || hyphened) {
 
314
                        cmd->cmd[k].arg = get_arg(arg, argv, argc, &i);
 
315
                    }
 
316
                    if (arg) arg[-1] = '=';
 
317
                    goto next_flag;
 
318
                }
 
319
            }
 
320
            for (k=0; k<cmd->nopt; k++) {
 
321
                if (strcmp(fl, cmd->opt[k].s) == 0) {
 
322
                    cmd->opt[k].on = PR_TRUE;
 
323
                    if (cmd->opt[k].argUse != CMDNoArg || hyphened) {
 
324
                        cmd->opt[k].arg = get_arg(arg, argv, argc, &i);
 
325
                    }
 
326
                    if (arg) arg[-1] = '=';
 
327
                    goto next_flag;
 
328
                }
 
329
            }
 
330
            return -1;
 
331
        }
 
332
next_flag:
 
333
        i++;
 
334
    } while (i < argc);
 
335
    command_line_okay(cmd, progName);
 
336
    return cmdToRun;
 
337
}
 
338
 
 
339
void
 
340
CMD_LongUsage(char *progName, cmdCommand *cmd, cmdUsageCallback usage)
 
341
{
 
342
    int i, j;
 
343
    PRBool oneCommand = PR_FALSE;
 
344
    cmdPrintState ps;
 
345
    init_print_ps(&ps, PR_STDERR, 80, 0);
 
346
    nprintf(&ps, "\n%s:   ", progName);
 
347
    /* prints app-specific header */
 
348
    ps.indent = strlen(progName) + 4;
 
349
    usage(&ps, 0, PR_FALSE, PR_TRUE, PR_FALSE);
 
350
    for (i=0; i<cmd->ncmd; i++) if (cmd->cmd[i].on) oneCommand = PR_TRUE;
 
351
    for (i=0; i<cmd->ncmd; i++) {
 
352
        if ((oneCommand  && cmd->cmd[i].on) || !oneCommand) {
 
353
            ps.indent = 0;
 
354
            print_ps_indent(&ps);
 
355
            if (cmd->cmd[i].c != 0) {
 
356
                nprintf(&ps, "-%c, ", cmd->cmd[i].c);
 
357
                nprintf(&ps, "--%-16s ", cmd->cmd[i].s);
 
358
            } else {
 
359
                nprintf(&ps, "--%-20s ", cmd->cmd[i].s);
 
360
            }
 
361
            ps.indent += 20;
 
362
            usage(&ps, i, PR_TRUE, PR_FALSE, PR_FALSE);
 
363
            for (j=0; j<cmd->nopt; j++) {
 
364
                if (cmd->cmd[i].req & CMDBIT(j)) {
 
365
                    ps.indent = 0;
 
366
                    print_ps_indent(&ps);
 
367
                    nprintf(&ps, "%3s* ", "");
 
368
                    if (cmd->opt[j].c != 0) {
 
369
                        nprintf(&ps, "-%c, ", cmd->opt[j].c);
 
370
                        nprintf(&ps, "--%-16s  ", cmd->opt[j].s);
 
371
                    } else {
 
372
                        nprintf(&ps, "--%-20s  ", cmd->opt[j].s);
 
373
                    }
 
374
                    ps.indent += 29;
 
375
                    usage(&ps, j, PR_FALSE, PR_FALSE, PR_FALSE);
 
376
                }
 
377
            }
 
378
            for (j=0; j<cmd->nopt; j++) {
 
379
                if (cmd->cmd[i].opt & CMDBIT(j)) {
 
380
                    ps.indent = 0;
 
381
                    print_ps_indent(&ps);
 
382
                    nprintf(&ps, "%5s", "");
 
383
                    if (cmd->opt[j].c != 0) {
 
384
                        nprintf(&ps, "-%c, ", cmd->opt[j].c);
 
385
                        nprintf(&ps, "--%-16s  ", cmd->opt[j].s);
 
386
                    } else {
 
387
                        nprintf(&ps, "--%-20s  ", cmd->opt[j].s);
 
388
                    }
 
389
                    ps.indent += 29;
 
390
                    usage(&ps, j, PR_FALSE, PR_FALSE, PR_FALSE);
 
391
                }
 
392
            }
 
393
        }
 
394
        nprintf(&ps, "\n");
 
395
    }
 
396
    ps.indent = 0;
 
397
    nprintf(&ps, "\n* - required flag for command\n\n");
 
398
    /* prints app-specific footer */
 
399
    usage(&ps, 0, PR_FALSE, PR_FALSE, PR_TRUE);
 
400
    /*nprintf(&ps, "\n\n");*/
 
401
    exit(1);
 
402
}
 
403
 
 
404
void
 
405
CMD_Usage(char *progName, cmdCommand *cmd)
 
406
{
 
407
    int i, j, inc;
 
408
    PRBool first;
 
409
    cmdPrintState ps;
 
410
    init_print_ps(&ps, PR_STDERR, 80, 0);
 
411
    nprintf(&ps, "%s", progName);
 
412
    ps.indent = strlen(progName) + 1;
 
413
    print_ps_to_indent(&ps);
 
414
    for (i=0; i<cmd->ncmd; i++) {
 
415
        if (cmd->cmd[i].c != 0) {
 
416
            nprintf(&ps, "-%c", cmd->cmd[i].c);
 
417
            inc = 4;
 
418
        } else {
 
419
            nprintf(&ps, "--%s", cmd->cmd[i].s);
 
420
            inc = 4 + strlen(cmd->cmd[i].s);
 
421
        }
 
422
        first = PR_TRUE;
 
423
        ps.indent += inc;
 
424
        print_ps_to_indent(&ps);
 
425
        for (j=0; j<cmd->nopt; j++) {
 
426
            if (cmd->cmd[i].req & CMDBIT(j)) {
 
427
                if (cmd->opt[j].c != 0 && cmd->opt[j].argUse == CMDNoArg) {
 
428
                    if (first) {
 
429
                        nprintf(&ps, "-");
 
430
                        first = !first;
 
431
                    }
 
432
                    nprintf(&ps, "%c", cmd->opt[j].c);
 
433
                }
 
434
            }
 
435
        }
 
436
        for (j=0; j<cmd->nopt; j++) {
 
437
            if (cmd->cmd[i].req & CMDBIT(j)) {
 
438
                if (cmd->opt[j].c != 0)
 
439
                    nprintf(&ps, "-%c ", cmd->opt[j].c);
 
440
                else
 
441
                    nprintf(&ps, "--%s ", cmd->opt[j].s);
 
442
                if (cmd->opt[j].argUse != CMDNoArg)
 
443
                    nprintf(&ps, "%s ", cmd->opt[j].s);
 
444
            }
 
445
        }
 
446
        first = PR_TRUE;
 
447
        for (j=0; j<cmd->nopt; j++) {
 
448
            if (cmd->cmd[i].opt & CMDBIT(j)) {
 
449
                if (cmd->opt[j].c != 0 && cmd->opt[j].argUse == CMDNoArg) {
 
450
                    if (first) {
 
451
                        nprintf(&ps, "[-");
 
452
                        first = !first;
 
453
                    }
 
454
                    nprintf(&ps, "%c", cmd->opt[j].c);
 
455
                }
 
456
            }
 
457
        }
 
458
        if (!first) nprintf(&ps, "] ");
 
459
        for (j=0; j<cmd->nopt; j++) {
 
460
            if (cmd->cmd[i].opt & CMDBIT(j) && 
 
461
                 cmd->opt[j].argUse != CMDNoArg) {
 
462
                if (cmd->opt[j].c != 0)
 
463
                    nprintf(&ps, "[-%c %s] ", cmd->opt[j].c, cmd->opt[j].s);
 
464
                else
 
465
                    nprintf(&ps, "[--%s %s] ", cmd->opt[j].s, cmd->opt[j].s);
 
466
            }
 
467
        }
 
468
        ps.indent -= inc;
 
469
        print_ps_indent(&ps);
 
470
    }
 
471
    ps.indent = 0;
 
472
    nprintf(&ps, "\n");
 
473
    exit(1);
 
474
}