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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [newlib-1.18.0/] [newlib/] [libc/] [stdlib/] [getopt.c] - Blame information for rev 862

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

Line No. Rev Author Line
1 207 jeremybenn
/****************************************************************************
2
 
3
getopt.c - Read command line options
4
 
5
AUTHOR: Gregory Pietsch
6
CREATED Fri Jan 10 21:13:05 1997
7
 
8
DESCRIPTION:
9
 
10
The getopt() function parses the command line arguments.  Its arguments argc
11
and argv are the argument count and array as passed to the main() function
12
on program invocation.  The argument optstring is a list of available option
13
characters.  If such a character is followed by a colon (`:'), the option
14
takes an argument, which is placed in optarg.  If such a character is
15
followed by two colons, the option takes an optional argument, which is
16
placed in optarg.  If the option does not take an argument, optarg is NULL.
17
 
18
The external variable optind is the index of the next array element of argv
19
to be processed; it communicates from one call to the next which element to
20
process.
21
 
22
The getopt_long() function works like getopt() except that it also accepts
23
long options started by two dashes `--'.  If these take values, it is either
24
in the form
25
 
26
--arg=value
27
 
28
 or
29
 
30
--arg value
31
 
32
It takes the additional arguments longopts which is a pointer to the first
33
element of an array of type struct option.  The last element of the array
34
has to be filled with NULL for the name field.
35
 
36
The longind pointer points to the index of the current long option relative
37
to longopts if it is non-NULL.
38
 
39
The getopt() function returns the option character if the option was found
40
successfully, `:' if there was a missing parameter for one of the options,
41
`?' for an unknown option character, and EOF for the end of the option list.
42
 
43
The getopt_long() function's return value is described in the header file.
44
 
45
The function getopt_long_only() is identical to getopt_long(), except that a
46
plus sign `+' can introduce long options as well as `--'.
47
 
48
The following describes how to deal with options that follow non-option
49
argv-elements.
50
 
51
If the caller did not specify anything, the default is REQUIRE_ORDER if the
52
environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise.
53
 
54
REQUIRE_ORDER means don't recognize them as options; stop option processing
55
when the first non-option is seen.  This is what Unix does.  This mode of
56
operation is selected by either setting the environment variable
57
POSIXLY_CORRECT, or using `+' as the first character of the optstring
58
parameter.
59
 
60
PERMUTE is the default.  We permute the contents of ARGV as we scan, so that
61
eventually all the non-options are at the end.  This allows options to be
62
given in any order, even with programs that were not written to expect this.
63
 
64
RETURN_IN_ORDER is an option available to programs that were written to
65
expect options and other argv-elements in any order and that care about the
66
ordering of the two.  We describe each non-option argv-element as if it were
67
the argument of an option with character code 1.  Using `-' as the first
68
character of the optstring parameter selects this mode of operation.
69
 
70
The special argument `--' forces an end of option-scanning regardless of the
71
value of ordering.  In the case of RETURN_IN_ORDER, only `--' can cause
72
getopt() and friends to return EOF with optind != argc.
73
 
74
COPYRIGHT NOTICE AND DISCLAIMER:
75
 
76
Copyright (C) 1997 Gregory Pietsch
77
 
78
This file and the accompanying getopt.h header file are hereby placed in the
79
public domain without restrictions.  Just give the author credit, don't
80
claim you wrote it or prevent anyone else from using it.
81
 
82
Gregory Pietsch's current e-mail address:
83
gpietsch@comcast.net
84
****************************************************************************/
85
 
86
#ifndef HAVE_GETOPT
87
 
88
/* include files */
89
#include <stdio.h>
90
#include <stdlib.h>
91
#include <string.h>
92
#define __need_getopt_newlib
93
#include <getopt.h>
94
 
95
/* macros */
96
 
97
/* types */
98
typedef enum GETOPT_ORDERING_T
99
{
100
  PERMUTE,
101
  RETURN_IN_ORDER,
102
  REQUIRE_ORDER
103
} GETOPT_ORDERING_T;
104
 
105
/* globally-defined variables */
106
char *optarg = 0;
107
int optind = 0;
108
int opterr = 1;
109
int optopt = '?';
110
 
111
/* static variables */
112
static int optwhere = 0;
113
 
114
/* functions */
115
 
116
/* reverse_argv_elements:  reverses num elements starting at argv */
117
static void
118
reverse_argv_elements (char **argv, int num)
119
{
120
  int i;
121
  char *tmp;
122
 
123
  for (i = 0; i < (num >> 1); i++)
124
    {
125
      tmp = argv[i];
126
      argv[i] = argv[num - i - 1];
127
      argv[num - i - 1] = tmp;
128
    }
129
}
130
 
131
/* permute: swap two blocks of argv-elements given their lengths */
132
static void
133
permute (char *const argv[], int len1, int len2)
134
{
135
  reverse_argv_elements ((char **) argv, len1);
136
  reverse_argv_elements ((char **) argv, len1 + len2);
137
  reverse_argv_elements ((char **) argv, len2);
138
}
139
 
140
/* is_option: is this argv-element an option or the end of the option list? */
141
static int
142
is_option (char *argv_element, int only)
143
{
144
  return ((argv_element == 0)
145
          || (argv_element[0] == '-') || (only && argv_element[0] == '+'));
146
}
147
 
148
/* read_globals: read the values from the globals into a getopt_data
149
   structure */
150
static void
151
read_globals (struct getopt_data *data)
152
{
153
  data->optarg = optarg;
154
  data->optind = optind;
155
  data->opterr = opterr;
156
  data->optopt = optopt;
157
  data->optwhere = optwhere;
158
}
159
 
160
/* write_globals: write the values into the globals from a getopt_data
161
   structure */
162
static void
163
write_globals (struct getopt_data *data)
164
{
165
  optarg = data->optarg;
166
  optind = data->optind;
167
  opterr = data->opterr;
168
  optopt = data->optopt;
169
  optwhere = data->optwhere;
170
}
171
 
172
/* getopt_internal:  the function that does all the dirty work */
173
static int
174
getopt_internal (int argc, char *const argv[], const char *shortopts,
175
                 const struct option *longopts, int *longind, int only,
176
                 struct getopt_data *data)
177
{
178
  GETOPT_ORDERING_T ordering = PERMUTE;
179
  size_t permute_from = 0;
180
  int num_nonopts = 0;
181
  int optindex = 0;
182
  size_t match_chars = 0;
183
  char *possible_arg = 0;
184
  int longopt_match = -1;
185
  int has_arg = -1;
186
  char *cp = 0;
187
  int arg_next = 0;
188
 
189
  /* first, deal with silly parameters and easy stuff */
190
  if (argc == 0 || argv == 0 || (shortopts == 0 && longopts == 0)
191
      || data->optind >= argc || argv[data->optind] == 0)
192
    return EOF;
193
  if (strcmp (argv[data->optind], "--") == 0)
194
    {
195
      data->optind++;
196
      return EOF;
197
    }
198
 
199
  /* if this is our first time through */
200
  if (data->optind == 0)
201
    data->optind = data->optwhere = 1;
202
 
203
  /* define ordering */
204
  if (shortopts != 0 && (*shortopts == '-' || *shortopts == '+'))
205
    {
206
      ordering = (*shortopts == '-') ? RETURN_IN_ORDER : REQUIRE_ORDER;
207
      shortopts++;
208
    }
209
  else
210
    ordering = (getenv ("POSIXLY_CORRECT") != 0) ? REQUIRE_ORDER : PERMUTE;
211
 
212
  /*
213
   * based on ordering, find our next option, if we're at the beginning of
214
   * one
215
   */
216
  if (data->optwhere == 1)
217
    {
218
      switch (ordering)
219
        {
220
        default:                /* shouldn't happen */
221
        case PERMUTE:
222
          permute_from = data->optind;
223
          num_nonopts = 0;
224
          while (!is_option (argv[data->optind], only))
225
            {
226
              data->optind++;
227
              num_nonopts++;
228
            }
229
          if (argv[data->optind] == 0)
230
            {
231
              /* no more options */
232
              data->optind = permute_from;
233
              return EOF;
234
            }
235
          else if (strcmp (argv[data->optind], "--") == 0)
236
            {
237
              /* no more options, but have to get `--' out of the way */
238
              permute (argv + permute_from, num_nonopts, 1);
239
              data->optind = permute_from + 1;
240
              return EOF;
241
            }
242
          break;
243
        case RETURN_IN_ORDER:
244
          if (!is_option (argv[data->optind], only))
245
            {
246
              data->optarg = argv[data->optind++];
247
              return (data->optopt = 1);
248
            }
249
          break;
250
        case REQUIRE_ORDER:
251
          if (!is_option (argv[data->optind], only))
252
            return EOF;
253
          break;
254
        }
255
    }
256
  /* we've got an option, so parse it */
257
 
258
  /* first, is it a long option? */
259
  if (longopts != 0
260
      && (memcmp (argv[data->optind], "--", 2) == 0
261
          || (only && argv[data->optind][0] == '+')) && data->optwhere == 1)
262
    {
263
      /* handle long options */
264
      if (memcmp (argv[data->optind], "--", 2) == 0)
265
        data->optwhere = 2;
266
      longopt_match = -1;
267
      possible_arg = strchr (argv[data->optind] + data->optwhere, '=');
268
      if (possible_arg == 0)
269
        {
270
          /* no =, so next argv might be arg */
271
          match_chars = strlen (argv[data->optind]);
272
          possible_arg = argv[data->optind] + match_chars;
273
          match_chars = match_chars - data->optwhere;
274
        }
275
      else
276
        match_chars = (possible_arg - argv[data->optind]) - data->optwhere;
277
      for (optindex = 0; longopts[optindex].name != 0; ++optindex)
278
        {
279
          if (memcmp
280
              (argv[data->optind] + data->optwhere, longopts[optindex].name,
281
               match_chars) == 0)
282
            {
283
              /* do we have an exact match? */
284
              if (match_chars == (int) (strlen (longopts[optindex].name)))
285
                {
286
                  longopt_match = optindex;
287
                  break;
288
                }
289
              /* do any characters match? */
290
              else
291
                {
292
                  if (longopt_match < 0)
293
                    longopt_match = optindex;
294
                  else
295
                    {
296
                      /* we have ambiguous options */
297
                      if (data->opterr)
298
                        fprintf (stderr, "%s: option `%s' is ambiguous "
299
                                 "(could be `--%s' or `--%s')\n",
300
                                 argv[0],
301
                                 argv[data->optind],
302
                                 longopts[longopt_match].name,
303
                                 longopts[optindex].name);
304
                      return (data->optopt = '?');
305
                    }
306
                }
307
            }
308
        }
309
      if (longopt_match >= 0)
310
        has_arg = longopts[longopt_match].has_arg;
311
    }
312
 
313
  /* if we didn't find a long option, is it a short option? */
314
  if (longopt_match < 0 && shortopts != 0)
315
    {
316
      cp = strchr (shortopts, argv[data->optind][data->optwhere]);
317
      if (cp == 0)
318
        {
319
          /* couldn't find option in shortopts */
320
          if (data->opterr)
321
            fprintf (stderr,
322
                     "%s: invalid option -- `-%c'\n",
323
                     argv[0], argv[data->optind][data->optwhere]);
324
          data->optwhere++;
325
          if (argv[data->optind][data->optwhere] == '\0')
326
            {
327
              data->optind++;
328
              data->optwhere = 1;
329
            }
330
          return (data->optopt = '?');
331
        }
332
      has_arg = ((cp[1] == ':')
333
                 ? ((cp[2] == ':') ? OPTIONAL_ARG : REQUIRED_ARG) : NO_ARG);
334
      possible_arg = argv[data->optind] + data->optwhere + 1;
335
      data->optopt = *cp;
336
    }
337
 
338
  /* get argument and reset data->optwhere */
339
  arg_next = 0;
340
  switch (has_arg)
341
    {
342
    case OPTIONAL_ARG:
343
      if (*possible_arg == '=')
344
        possible_arg++;
345
      data->optarg = (*possible_arg != '\0') ? possible_arg : 0;
346
      data->optwhere = 1;
347
      break;
348
    case REQUIRED_ARG:
349
      if (*possible_arg == '=')
350
        possible_arg++;
351
      if (*possible_arg != '\0')
352
        {
353
          data->optarg = possible_arg;
354
          data->optwhere = 1;
355
        }
356
      else if (data->optind + 1 >= argc)
357
        {
358
          if (data->opterr)
359
            {
360
              fprintf (stderr, "%s: argument required for option `", argv[0]);
361
              if (longopt_match >= 0)
362
                fprintf (stderr, "--%s'\n", longopts[longopt_match].name);
363
              else
364
                fprintf (stderr, "-%c'\n", *cp);
365
            }
366
          data->optind++;
367
          return (data->optopt = ':');
368
        }
369
      else
370
        {
371
          data->optarg = argv[data->optind + 1];
372
          arg_next = 1;
373
          data->optwhere = 1;
374
        }
375
      break;
376
    default:                    /* shouldn't happen */
377
    case NO_ARG:
378
      if (longopt_match < 0)
379
        {
380
          data->optwhere++;
381
          if (argv[data->optind][data->optwhere] == '\0')
382
            data->optwhere = 1;
383
        }
384
      else
385
        data->optwhere = 1;
386
      data->optarg = 0;
387
      break;
388
    }
389
 
390
  /* do we have to permute or otherwise modify data->optind? */
391
  if (ordering == PERMUTE && data->optwhere == 1 && num_nonopts != 0)
392
    {
393
      permute (argv + permute_from, num_nonopts, 1 + arg_next);
394
      data->optind = permute_from + 1 + arg_next;
395
    }
396
  else if (data->optwhere == 1)
397
    data->optind = data->optind + 1 + arg_next;
398
 
399
  /* finally return */
400
  if (longopt_match >= 0)
401
    {
402
      if (longind != 0)
403
        *longind = longopt_match;
404
      if (longopts[longopt_match].flag != 0)
405
        {
406
          *(longopts[longopt_match].flag) = longopts[longopt_match].val;
407
          return 0;
408
        }
409
      else
410
        return longopts[longopt_match].val;
411
    }
412
  else
413
    return data->optopt;
414
}
415
 
416
int
417
getopt (int argc, char *const argv[], const char *optstring)
418
{
419
  struct getopt_data data;
420
  int r;
421
 
422
  read_globals (&data);
423
  r = getopt_internal (argc, argv, optstring, 0, 0, 0, &data);
424
  write_globals (&data);
425
  return r;
426
}
427
 
428
int
429
getopt_long (int argc, char *const argv[], const char *shortopts,
430
             const struct option *longopts, int *longind)
431
{
432
  struct getopt_data data;
433
  int r;
434
 
435
  read_globals (&data);
436
  r = getopt_internal (argc, argv, shortopts, longopts, longind, 0, &data);
437
  write_globals (&data);
438
  return r;
439
}
440
 
441
int
442
getopt_long_only (int argc, char *const argv[], const char *shortopts,
443
                  const struct option *longopts, int *longind)
444
{
445
  struct getopt_data data;
446
  int r;
447
 
448
  read_globals (&data);
449
  r = getopt_internal (argc, argv, shortopts, longopts, longind, 1, &data);
450
  write_globals (&data);
451
  return r;
452
}
453
 
454
int
455
__getopt_r (int argc, char *const argv[], const char *optstring,
456
            struct getopt_data *data)
457
{
458
  return getopt_internal (argc, argv, optstring, 0, 0, 0, data);
459
}
460
 
461
int
462
__getopt_long_r (int argc, char *const argv[], const char *shortopts,
463
                 const struct option *longopts, int *longind,
464
                 struct getopt_data *data)
465
{
466
  return getopt_internal (argc, argv, shortopts, longopts, longind, 0, data);
467
}
468
 
469
int
470
__getopt_long_only_r (int argc, char *const argv[], const char *shortopts,
471
                      const struct option *longopts, int *longind,
472
                      struct getopt_data *data)
473
{
474
  return getopt_internal (argc, argv, shortopts, longopts, longind, 1, data);
475
}
476
 
477
#endif /* !HAVE_GETOPT */
478
 
479
/* end of file GETOPT.C */

powered by: WebSVN 2.1.0

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