SLJ Test  1.0
System Latency Jitter Test
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
getopt.c
Go to the documentation of this file.
1 
87 /* include files */
88 #include <stdio.h>
89 #include <stdlib.h>
90 #include <string.h>
91 #ifndef REPLGETOPT_H
92 #include "replgetopt.h"
93 #endif
94 
95 /* macros */
96 
97 /* types */
98 typedef enum GETOPT_ORDERING_T
99 {
104 
105 /* globally-defined variables */
106 char *optarg = NULL;
107 int optind = 0;
108 int opterr = 1;
109 int optopt = '?';
110 
111 /* functions */
112 
113 /* reverse_argv_elements: reverses num elements starting at argv */
114 static void
115 reverse_argv_elements (char **argv, int num)
116 {
117  int i;
118  char *tmp;
119 
120  for (i = 0; i < (num >> 1); i++)
121  {
122  tmp = argv[i];
123  argv[i] = argv[num - i - 1];
124  argv[num - i - 1] = tmp;
125  }
126 }
127 
128 /* permute: swap two blocks of argv-elements given their lengths */
129 static void
130 permute (char **argv, int len1, int len2)
131 {
132  reverse_argv_elements (argv, len1);
133  reverse_argv_elements (argv, len1 + len2);
134  reverse_argv_elements (argv, len2);
135 }
136 
137 /* is_option: is this argv-element an option or the end of the option list? */
138 static int
139 is_option (char *argv_element, int only)
140 {
141  return ((argv_element == NULL)
142  || (argv_element[0] == '-') || (only && argv_element[0] == '+'));
143 }
144 
145 /* getopt_internal: the function that does all the dirty work */
146 static int
147 getopt_internal (int argc, char **argv, const char * shortopts,
148  const struct option * longopts, int *longind, int only)
149 {
150  GETOPT_ORDERING_T ordering = PERMUTE;
151  static size_t optwhere = 0;
152  size_t permute_from = 0;
153  int num_nonopts = 0;
154  int optindex = 0;
155  size_t match_chars = 0;
156  char *possible_arg = NULL;
157  int longopt_match = -1;
158  int has_arg = -1;
159  char *cp = NULL;
160  int arg_next = 0;
161 
162  /* first, deal with silly parameters and easy stuff */
163  if (argc == 0 || argv == NULL || (shortopts == NULL && longopts == NULL))
164  return (optopt = '?');
165  if (optind >= argc || argv[optind] == NULL)
166  return EOF;
167  if (strcmp (argv[optind], "--") == 0)
168  {
169  optind++;
170  return EOF;
171  }
172  /* if this is our first time through */
173  if (optind == 0)
174  optind = optwhere = 1;
175 
176  /* define ordering */
177  if (shortopts != NULL && (*shortopts == '-' || *shortopts == '+'))
178  {
179  ordering = (*shortopts == '-') ? RETURN_IN_ORDER : REQUIRE_ORDER;
180  shortopts++;
181  }
182  else
183  ordering = (getenv ("POSIXLY_CORRECT") != NULL) ? REQUIRE_ORDER : PERMUTE;
184 
185  /*
186  * based on ordering, find our next option, if we're at the beginning of
187  * one
188  */
189  if (optwhere == 1)
190  {
191  switch (ordering)
192  {
193  case PERMUTE:
194  permute_from = optind;
195  num_nonopts = 0;
196  while (!is_option (argv[optind], only))
197  {
198  optind++;
199  num_nonopts++;
200  }
201  if (argv[optind] == NULL)
202  {
203  /* no more options */
204  optind = permute_from;
205  return EOF;
206  }
207  else if (strcmp (argv[optind], "--") == 0)
208  {
209  /* no more options, but have to get `--' out of the way */
210  permute (argv + permute_from, num_nonopts, 1);
211  optind = permute_from + 1;
212  return EOF;
213  }
214  break;
215  case RETURN_IN_ORDER:
216  if (!is_option (argv[optind], only))
217  {
218  optarg = argv[optind++];
219  return (optopt = 1);
220  }
221  break;
222  case REQUIRE_ORDER:
223  if (!is_option (argv[optind], only))
224  return EOF;
225  break;
226  }
227  }
228  /* we've got an option, so parse it */
229 
230  /* first, is it a long option? */
231  if (longopts != NULL
232  && (memcmp (argv[optind], "--", 2) == 0
233  || (only && argv[optind][0] == '+')) && optwhere == 1)
234  {
235  /* handle long options */
236  if (memcmp (argv[optind], "--", 2) == 0)
237  optwhere = 2;
238  longopt_match = -1;
239  possible_arg = strchr (argv[optind] + optwhere, '=');
240  if (possible_arg == NULL)
241  {
242  /* no =, so next argv might be arg */
243  match_chars = strlen (argv[optind]);
244  possible_arg = argv[optind] + match_chars;
245  match_chars = match_chars - optwhere;
246  }
247  else
248  match_chars = (possible_arg - argv[optind]) - optwhere;
249  for (optindex = 0; longopts[optindex].name != NULL; optindex++)
250  {
251  if (memcmp (argv[optind] + optwhere,
252  longopts[optindex].name, match_chars) == 0)
253  {
254  /* do we have an exact match? */
255  if (match_chars == (int) (strlen (longopts[optindex].name)))
256  {
257  longopt_match = optindex;
258  break;
259  }
260  /* do any characters match? */
261  else
262  {
263  if (longopt_match < 0)
264  longopt_match = optindex;
265  else
266  {
267  /* we have ambiguous options */
268  if (opterr)
269  fprintf (stderr, "%s: option `%s' is ambiguous "
270  "(could be `--%s' or `--%s')\n",
271  argv[0],
272  argv[optind],
273  longopts[longopt_match].name,
274  longopts[optindex].name);
275  return (optopt = '?');
276  }
277  }
278  }
279  }
280  if (longopt_match >= 0)
281  has_arg = longopts[longopt_match].has_arg;
282  }
283  /* if we didn't find a long option, is it a short option? */
284  if (longopt_match < 0 && shortopts != NULL)
285  {
286  cp = strchr (shortopts, argv[optind][optwhere]);
287  if (cp == NULL)
288  {
289  /* couldn't find option in shortopts */
290  if (opterr)
291  fprintf (stderr,
292  "%s: invalid option -- `-%c'\n",
293  argv[0], argv[optind][optwhere]);
294  optwhere++;
295  if (argv[optind][optwhere] == '\0')
296  {
297  optind++;
298  optwhere = 1;
299  }
300  return (optopt = '?');
301  }
302  has_arg = ((cp[1] == ':')
303  ? ((cp[2] == ':') ? optional_argument : required_argument) : no_argument);
304  possible_arg = argv[optind] + optwhere + 1;
305  optopt = *cp;
306  }
307  /* get argument and reset optwhere */
308  arg_next = 0;
309  switch (has_arg)
310  {
311  case optional_argument:
312  if (*possible_arg == '=')
313  possible_arg++;
314  if (*possible_arg != '\0')
315  {
316  optarg = possible_arg;
317  optwhere = 1;
318  }
319  else
320  optarg = NULL;
321  break;
322  case required_argument:
323  if (*possible_arg == '=')
324  possible_arg++;
325  if (*possible_arg != '\0')
326  {
327  optarg = possible_arg;
328  optwhere = 1;
329  }
330  else if (optind + 1 >= argc)
331  {
332  if (opterr)
333  {
334  fprintf (stderr, "%s: argument required for option `", argv[0]);
335  if (longopt_match >= 0)
336  fprintf (stderr, "--%s'\n", longopts[longopt_match].name);
337  else
338  fprintf (stderr, "-%c'\n", *cp);
339  }
340  optind++;
341  return (optopt = ':');
342  }
343  else
344  {
345  optarg = argv[optind + 1];
346  arg_next = 1;
347  optwhere = 1;
348  }
349  break;
350  case no_argument:
351  if (longopt_match < 0)
352  {
353  optwhere++;
354  if (argv[optind][optwhere] == '\0')
355  optwhere = 1;
356  }
357  else
358  optwhere = 1;
359  optarg = NULL;
360  break;
361  }
362 
363  /* do we have to permute or otherwise modify optind? */
364  if (ordering == PERMUTE && optwhere == 1 && num_nonopts != 0)
365  {
366  permute (argv + permute_from, num_nonopts, 1 + arg_next);
367  optind = permute_from + 1 + arg_next;
368  }
369  else if (optwhere == 1)
370  optind = optind + 1 + arg_next;
371 
372  /* finally return */
373  if (longopt_match >= 0)
374  {
375  if (longind != NULL)
376  *longind = longopt_match;
377  if (longopts[longopt_match].flag != NULL)
378  {
379  *(longopts[longopt_match].flag) = longopts[longopt_match].val;
380  return 0;
381  }
382  else
383  return longopts[longopt_match].val;
384  }
385  else
386  return optopt;
387 }
388 
389 #if NEED_GETOPT
390 int
391 getopt (int argc, char **argv, const char * optstring)
392 {
393  return getopt_internal (argc, argv, optstring, NULL, NULL, 0);
394 }
395 #endif
396 
397 #if NEED_GETOPT_LONG
398 int
399 getopt_long (int argc, char **argv, const char * shortopts,
400  const struct option * longopts, int *longind)
401 {
402  return getopt_internal (argc, argv, shortopts, longopts, longind, 0);
403 }
404 
405 int
406 getopt_long_only (int argc, char **argv, const char * shortopts,
407  const struct option * longopts, int *longind)
408 {
409  return getopt_internal (argc, argv, shortopts, longopts, longind, 1);
410 }
411 #endif
412 
413 /* end of file GETOPT.C */