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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [redboot/] [v2_0/] [src/] [parse.c] - Blame information for rev 1773

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

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      parse.c
4
//
5
//      RedBoot command line parsing routine
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    gthomas
44
// Contributors: gthomas
45
// Date:         2000-07-14
46
// Purpose:      
47
// Description:  
48
//              
49
// This code is part of RedBoot (tm).
50
//
51
//####DESCRIPTIONEND####
52
//
53
//==========================================================================
54
 
55
#include <redboot.h>
56
#include <cyg/hal/hal_arch.h>
57
#include <cyg/hal/hal_intr.h>
58
#include <cyg/hal/hal_cache.h>
59
#include CYGHWR_MEMORY_LAYOUT_H
60
#include <cyg/hal/hal_tables.h>
61
 
62
// Define table boundaries
63
extern struct cmd __RedBoot_CMD_TAB__[], __RedBoot_CMD_TAB_END__;
64
 
65
//
66
// Scan through an input line and break it into "arguments".  These
67
// are space delimited strings.  Return a structure which points to
68
// the strings, similar to a Unix program. Multiple commands in the line
69
// are separated by ; similar to sh. If we find a semi we stop processing the 
70
// line, terminate the current command with a null and return the start 
71
// of the next command in *line. parse() can then be called again to 
72
// process the next command on the line.
73
// Note: original input is destroyed by replacing the delimiters with 
74
// null ('\0') characters for ease of use.
75
//
76
struct cmd *
77
parse(char **line, int *argc, char **argv)
78
{
79
    char *cp = *line;
80
    char *pp;
81
    int indx = 0;
82
    int semi = 0;
83
 
84
    while (*cp) {
85
        // Skip leading spaces
86
        while (*cp && *cp == ' ') cp++;
87
        if (!*cp) {
88
            break;  // Line ended with a string of spaces
89
        }
90
        if (*cp == ';') {
91
            *cp = '\0';
92
            semi=1;
93
            break;
94
        }
95
        if (indx < MAX_ARGV) {
96
            argv[indx++] = cp;
97
        } else {
98
            diag_printf("Too many arguments - stopped at: '%s'\n", cp);
99
        }
100
        while (*cp) {
101
            if (*cp == ' ') {
102
                *cp++ = '\0';
103
                break;
104
            } else if (*cp == ';') {
105
                break;
106
            } else if (*cp == '"') {
107
                // Swallow quote, scan till following one
108
                if (argv[indx-1] == cp) {
109
                    argv[indx-1] = ++cp;
110
                }
111
                pp = cp;
112
                while (*cp && *cp != '"') {
113
                    if (*cp == '\\') {
114
                        // Skip over escape - allows for escaped '"'
115
                        cp++;
116
                    }
117
                    // Move string to swallow escapes
118
                    *pp++ = *cp++;
119
                }
120
                if (!*cp) {
121
                    diag_printf("Unbalanced string!\n");
122
                } else {
123
                    if (pp != cp) *pp = '\0';
124
                    *cp++ = '\0';
125
                    break;
126
                }
127
            } else {
128
                cp++;
129
            }
130
        }
131
    }
132
    if (semi) {
133
        *line = cp + 1;
134
    } else {
135
        *line = cp;
136
    }
137
    *argc = indx;
138
    return cmd_search(__RedBoot_CMD_TAB__, &__RedBoot_CMD_TAB_END__, argv[0]);
139
}
140
 
141
//
142
// Search through a list of commands
143
//
144
struct cmd *
145
cmd_search(struct cmd *tab, struct cmd *tabend, char *arg)
146
{
147
    int cmd_len;
148
    struct cmd *cmd, *cmd2;
149
    // Search command table
150
    cmd_len = strlen(arg);
151
    cmd = tab;
152
    while (cmd != tabend) {
153
        if (strncasecmp(arg, cmd->str, cmd_len) == 0) {
154
            if (strlen(cmd->str) > cmd_len) {
155
                // Check for ambiguous commands here
156
                // Note: If there are commands which are not length-unique
157
                // then this check will be invalid.  E.g. "du" and "dump"
158
                bool first = true;
159
                cmd2 = tab;
160
                while (cmd2 != tabend) {
161
                    if ((cmd != cmd2) &&
162
                        (strncasecmp(arg, cmd2->str, cmd_len) == 0)) {
163
                        if (first) {
164
                            diag_printf("Ambiguous command '%s', choices are: %s",
165
                                        arg, cmd->str);
166
                            first = false;
167
                        }
168
                        diag_printf(" %s", cmd2->str);
169
                    }
170
                    cmd2++;
171
                }
172
                if (!first) {
173
                    // At least one ambiguity found - fail the lookup
174
                    diag_printf("\n");
175
                    return (struct cmd *)0;
176
                }
177
            }
178
            return cmd;
179
        }
180
        cmd++;
181
    }
182
    return (struct cmd *)0;
183
}
184
 
185
void
186
cmd_usage(struct cmd *tab, struct cmd *tabend, char *prefix)
187
{
188
    struct cmd *cmd;
189
 
190
    diag_printf("Usage:\n");
191
    for (cmd = tab;  cmd != tabend;  cmd++) {
192
        diag_printf("  %s%s %s\n", prefix, cmd->str, cmd->usage);
193
    }
194
}
195
 
196
// Option processing
197
 
198
// Initialize option table entry (required because these entries
199
// may have dynamic contents, thus cannot be statically initialized)
200
//
201
void
202
init_opts(struct option_info *opts, char flag, bool takes_arg,
203
          int arg_type, void **arg, bool *arg_set, char *name)
204
{
205
    opts->flag = flag;
206
    opts->takes_arg = takes_arg;
207
    opts->arg_type = arg_type,
208
    opts->arg = arg;
209
    opts->arg_set = arg_set;
210
    opts->name = name;
211
}
212
 
213
//
214
// Scan command line arguments (argc/argv), processing options, etc.
215
//
216
bool
217
scan_opts(int argc, char *argv[], int first,
218
          struct option_info *opts, int num_opts,
219
          void **def_arg, int def_arg_type, char *def_descr)
220
{
221
    bool ret = true;
222
    bool flag_ok;
223
    bool def_arg_set = false;
224
    int i, j;
225
    char c, *s;
226
    struct option_info *opt;
227
 
228
    if (def_arg && (def_arg_type == OPTION_ARG_TYPE_STR)) {
229
        *def_arg = (char *)0;
230
    }
231
    opt = opts;
232
    for (j = 0;  j < num_opts;  j++, opt++) {
233
        if (opt->arg_set) {
234
            *opt->arg_set = false;
235
        }
236
        if (!opt->takes_arg) {
237
            switch (opt->arg_type) {
238
            case OPTION_ARG_TYPE_NUM:
239
                *(int *)opt->arg = 0;
240
                break;
241
            case OPTION_ARG_TYPE_FLG:
242
                *(bool *)opt->arg = false;
243
                break;
244
            }
245
        }
246
    }
247
    for (i = first;  i < argc;  i++) {
248
        if (argv[i][0] == '-') {
249
            c = argv[i][1];
250
            flag_ok = false;
251
            opt = opts;
252
            for (j = 0;  j < num_opts;  j++, opt++) {
253
                if (c == opt->flag) {
254
                    if (opt->arg_set && *opt->arg_set) {
255
                        diag_printf("** Error: %s already specified\n", opt->name);
256
                        ret = false;
257
                    }
258
                    if (opt->takes_arg) {
259
                        if (argv[i][2] == '=') {
260
                            s = &argv[i][3];
261
                        } else {
262
                            s = argv[i+1];
263
                            i++;
264
                        }
265
                        switch (opt->arg_type) {
266
                        case OPTION_ARG_TYPE_NUM:
267
                            if (!parse_num(s, (unsigned long *)opt->arg, 0, 0)) {
268
                                diag_printf("** Error: invalid number '%s' for %s\n",
269
                                            s, opt->name);
270
                                ret = false;
271
                            }
272
                            break;
273
                        case OPTION_ARG_TYPE_STR:
274
                            *opt->arg = s;
275
                            break;
276
                        }
277
                        *opt->arg_set = true;
278
                    } else {
279
                        switch (opt->arg_type) {
280
                        case OPTION_ARG_TYPE_NUM:
281
                            *(int *)opt->arg = *(int *)opt->arg + 1;
282
                            break;
283
                        case OPTION_ARG_TYPE_FLG:
284
                            *(bool *)opt->arg = true;
285
                            break;
286
                        }
287
                    }
288
                    flag_ok = true;
289
                    break;
290
                }
291
            }
292
            if (!flag_ok) {
293
                diag_printf("** Error: invalid flag '%c'\n", c);
294
                ret = false;
295
            }
296
        } else {
297
            if (def_arg) {
298
                if (def_arg_set) {
299
                    diag_printf("** Error: %s already specified\n", def_descr);
300
                    ret = false;
301
                }
302
                switch (def_arg_type) {
303
                case OPTION_ARG_TYPE_NUM:
304
                    if (!parse_num(argv[i], (unsigned long *)def_arg, 0, 0)) {
305
                        diag_printf("** Error: invalid number '%s' for %s\n",
306
                                    argv[i], def_descr);
307
                        ret = false;
308
                    }
309
                    break;
310
                case OPTION_ARG_TYPE_STR:
311
                    *def_arg = argv[i];
312
                    break;
313
                }
314
                def_arg_set = true;
315
            } else {
316
                diag_printf("** Error: no default/non-flag arguments supported\n");
317
                ret = false;
318
            }
319
        }
320
    }
321
    return ret;
322
}
323
 
324
//
325
// Parse (scan) a number
326
//
327
bool
328
parse_num(char *s, unsigned long *val, char **es, char *delim)
329
{
330
    bool first = true;
331
    int radix = 10;
332
    char c;
333
    unsigned long result = 0;
334
    int digit;
335
 
336
    while (*s == ' ') s++;
337
    while (*s) {
338
        if (first && (s[0] == '0') && (_tolower(s[1]) == 'x')) {
339
            radix = 16;
340
            s += 2;
341
        }
342
        first = false;
343
        c = *s++;
344
        if (_is_hex(c) && ((digit = _from_hex(c)) < radix)) {
345
            // Valid digit
346
#ifdef CYGPKG_HAL_MIPS
347
            // FIXME: tx49 compiler generates 0x2539018 for MUL which
348
            // isn't any good.
349
            if (16 == radix)
350
                result = result << 4;
351
            else
352
                result = 10 * result;
353
            result += digit;
354
#else
355
            result = (result * radix) + digit;
356
#endif
357
        } else {
358
            if (delim != (char *)0) {
359
                // See if this character is one of the delimiters
360
                char *dp = delim;
361
                while (*dp && (c != *dp)) dp++;
362
                if (*dp) break;  // Found a good delimiter
363
            }
364
            return false;  // Malformatted number
365
        }
366
    }
367
    *val = result;
368
    if (es != (char **)0) {
369
        *es = s;
370
    }
371
    return true;
372
}
373
 
374
bool
375
parse_bool(char *s, bool *val)
376
{
377
    while (*s == ' ') s++;
378
    if ((*s == 't') || (*s == 'T')) {
379
        char *p = "rue";
380
        char *P = "RUE";
381
        // check for (partial) rest of the word and no extra including the
382
        // terminating zero.  "tru" will match; "truef" will not.
383
        while ( *++s ) {
384
            if ( *p != *s && *P != *s ) return false;
385
            p++; P++;
386
        }
387
        *val = true;
388
    } else
389
    if ((*s == 'f') || (*s == 'F')) {
390
        char *p = "alse";
391
        char *P = "ALSE";
392
        while ( *++s ) {
393
            if ( *p != *s && *P != *s ) return false;
394
            p++; P++;
395
        }
396
        *val = false;
397
    } else {
398
        return false;
399
    }
400
    return true;
401
}
402
 

powered by: WebSVN 2.1.0

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