getopt for windows

新一發表於2017-12-02

  Glibc庫裡有個getopt用於解析命令列引數,挺方便的,下面的是別人從Glibc原始碼的獲取的幾個getopt相關的檔案,已經將平臺相關的修改掉,windows下可以呼叫,本來是要用沒用到就沒去看正確性,具體以最新的Glibc原始碼為準。

  

  1 /*
  2 getopt.c
  3 
  4 Copyright (C) 2012, coreBugZJ, all rights reserved.
  5 
  6 在 Windows 平臺下使用 Linux 的 getopt, getopt_long, getopt_long_only 函式。
  7 
  8 修改自 glibc 2.8 中 getopt.c 檔案,
  9 */
 10 
 11 
 12 
 13 
 14 /* Getopt for GNU.
 15    NOTE: getopt is part of the C library, so if you don't know what
 16    "Keep this file name-space clean" means, talk to drepper@gnu.org
 17    before changing it!
 18    Copyright (C) 1987-1996,1998-2004,2008 Free Software Foundation, Inc.
 19    This file is part of the GNU C Library.
 20 
 21    The GNU C Library is free software; you can redistribute it and/or
 22    modify it under the terms of the GNU Lesser General Public
 23    License as published by the Free Software Foundation; either
 24    version 2.1 of the License, or (at your option) any later version.
 25 
 26    The GNU C Library is distributed in the hope that it will be useful,
 27    but WITHOUT ANY WARRANTY; without even the implied warranty of
 28    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 29    Lesser General Public License for more details.
 30 
 31    You should have received a copy of the GNU Lesser General Public
 32    License along with the GNU C Library; if not, write to the Free
 33    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 34    02111-1307 USA.  */
 35 
 36 #include <stdio.h>
 37 
 38 /* Comment out all this code if we are using the GNU C Library, and are not
 39    actually compiling the library itself.  This code is part of the GNU C
 40    Library, but also included in many other GNU distributions.  Compiling
 41    and linking in this code is a waste when using the GNU C library
 42    (especially if it is a shared library).  Rather than having every GNU
 43    program understand `configure --with-gnu-libc' and omit the object files,
 44    it is simpler to just do this in the source for each such file.  */
 45 
 46 
 47 #include <string.h>
 48 
 49 #define _(msgid) (msgid)
 50 
 51 
 52 #ifndef attribute_hidden
 53 # define attribute_hidden
 54 #endif
 55 
 56 /* This version of `getopt' appears to the caller like standard Unix `getopt'
 57    but it behaves differently for the user, since it allows the user
 58    to intersperse the options with the other arguments.
 59 
 60    As `getopt' works, it permutes the elements of ARGV so that,
 61    when it is done, all the options precede everything else.  Thus
 62    all application programs are extended to handle flexible argument order.
 63 
 64    Setting the environment variable POSIXLY_CORRECT disables permutation.
 65    Then the behavior is completely standard.
 66 
 67    GNU application programs can use a third alternative mode in which
 68    they can distinguish the relative order of options and other arguments.  */
 69 
 70 #include "getopt.h"
 71 #include "getopt_int.h"
 72 
 73 /* For communication from `getopt' to the caller.
 74    When `getopt' finds an option that takes an argument,
 75    the argument value is returned here.
 76    Also, when `ordering' is RETURN_IN_ORDER,
 77    each non-option ARGV-element is returned here.  */
 78 
 79 char *optarg;
 80 
 81 /* Index in ARGV of the next element to be scanned.
 82    This is used for communication to and from the caller
 83    and for communication between successive calls to `getopt'.
 84 
 85    On entry to `getopt', zero means this is the first call; initialize.
 86 
 87    When `getopt' returns -1, this is the index of the first of the
 88    non-option elements that the caller should itself scan.
 89 
 90    Otherwise, `optind' communicates from one call to the next
 91    how much of ARGV has been scanned so far.  */
 92 
 93 /* 1003.2 says this must be 1 before any call.  */
 94 int optind = 1;
 95 
 96 /* Callers store zero here to inhibit the error message
 97    for unrecognized options.  */
 98 
 99 int opterr = 1;
100 
101 /* Set to an option character which was unrecognized.
102    This must be initialized on some systems to avoid linking in the
103    system's own getopt implementation.  */
104 
105 int optopt = '?';
106 
107 /* Keep a global copy of all internal members of getopt_data.  */
108 
109 static struct _getopt_data getopt_data;
110 
111 
112 #ifndef getenv
113 extern char *getenv ();
114 #endif
115 
116  
117 # define SWAP_FLAGS(ch1, ch2)
118 
119 /* Exchange two adjacent subsequences of ARGV.
120    One subsequence is elements [first_nonopt,last_nonopt)
121    which contains all the non-options that have been skipped so far.
122    The other is elements [last_nonopt,optind), which contains all
123    the options processed since those non-options were skipped.
124 
125    `first_nonopt' and `last_nonopt' are relocated so that they describe
126    the new indices of the non-options in ARGV after they are moved.  */
127 
128 static void
129 exchange (char **argv, struct _getopt_data *d)
130 {
131   int bottom = d->__first_nonopt;
132   int middle = d->__last_nonopt;
133   int top = d->optind;
134   char *tem;
135 
136   /* Exchange the shorter segment with the far end of the longer segment.
137      That puts the shorter segment into the right place.
138      It leaves the longer segment in the right place overall,
139      but it consists of two parts that need to be swapped next.  */
140 
141   while (top > middle && middle > bottom)
142     {
143       if (top - middle > middle - bottom)
144     {
145       /* Bottom segment is the short one.  */
146       int len = middle - bottom;
147       register int i;
148 
149       /* Swap it with the top part of the top segment.  */
150       for (i = 0; i < len; i++)
151         {
152           tem = argv[bottom + i];
153           argv[bottom + i] = argv[top - (middle - bottom) + i];
154           argv[top - (middle - bottom) + i] = tem;
155           SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
156         }
157       /* Exclude the moved bottom segment from further swapping.  */
158       top -= len;
159     }
160       else
161     {
162       /* Top segment is the short one.  */
163       int len = top - middle;
164       register int i;
165 
166       /* Swap it with the bottom part of the bottom segment.  */
167       for (i = 0; i < len; i++)
168         {
169           tem = argv[bottom + i];
170           argv[bottom + i] = argv[middle + i];
171           argv[middle + i] = tem;
172           SWAP_FLAGS (bottom + i, middle + i);
173         }
174       /* Exclude the moved top segment from further swapping.  */
175       bottom += len;
176     }
177     }
178 
179   /* Update records for the slots the non-options now occupy.  */
180 
181   d->__first_nonopt += (d->optind - d->__last_nonopt);
182   d->__last_nonopt = d->optind;
183 }
184 
185 /* Initialize the internal data when the first call is made.  */
186 
187 static const char *
188 _getopt_initialize (int argc, char *const *argv, const char *optstring,
189             struct _getopt_data *d)
190 {
191   /* Start processing options with ARGV-element 1 (since ARGV-element 0
192      is the program name); the sequence of previously skipped
193      non-option ARGV-elements is empty.  */
194 
195   d->__first_nonopt = d->__last_nonopt = d->optind;
196 
197   d->__nextchar = NULL;
198 
199   d->__posixly_correct = !!getenv ("POSIXLY_CORRECT");
200 
201   /* Determine how to handle the ordering of options and nonoptions.  */
202 
203   if (optstring[0] == '-')
204     {
205       d->__ordering = RETURN_IN_ORDER;
206       ++optstring;
207     }
208   else if (optstring[0] == '+')
209     {
210       d->__ordering = REQUIRE_ORDER;
211       ++optstring;
212     }
213   else if (d->__posixly_correct)
214     d->__ordering = REQUIRE_ORDER;
215   else
216     d->__ordering = PERMUTE;
217 
218 
219   return optstring;
220 }
221  
222 /* Scan elements of ARGV (whose length is ARGC) for option characters
223    given in OPTSTRING.
224 
225    If an element of ARGV starts with '-', and is not exactly "-" or "--",
226    then it is an option element.  The characters of this element
227    (aside from the initial '-') are option characters.  If `getopt'
228    is called repeatedly, it returns successively each of the option characters
229    from each of the option elements.
230 
231    If `getopt' finds another option character, it returns that character,
232    updating `optind' and `nextchar' so that the next call to `getopt' can
233    resume the scan with the following option character or ARGV-element.
234 
235    If there are no more option characters, `getopt' returns -1.
236    Then `optind' is the index in ARGV of the first ARGV-element
237    that is not an option.  (The ARGV-elements have been permuted
238    so that those that are not options now come last.)
239 
240    OPTSTRING is a string containing the legitimate option characters.
241    If an option character is seen that is not listed in OPTSTRING,
242    return '?' after printing an error message.  If you set `opterr' to
243    zero, the error message is suppressed but we still return '?'.
244 
245    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
246    so the following text in the same ARGV-element, or the text of the following
247    ARGV-element, is returned in `optarg'.  Two colons mean an option that
248    wants an optional arg; if there is text in the current ARGV-element,
249    it is returned in `optarg', otherwise `optarg' is set to zero.
250 
251    If OPTSTRING starts with `-' or `+', it requests different methods of
252    handling the non-option ARGV-elements.
253    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
254 
255    Long-named options begin with `--' instead of `-'.
256    Their names may be abbreviated as long as the abbreviation is unique
257    or is an exact match for some defined option.  If they have an
258    argument, it follows the option name in the same ARGV-element, separated
259    from the option name by a `=', or else the in next ARGV-element.
260    When `getopt' finds a long-named option, it returns 0 if that option's
261    `flag' field is nonzero, the value of the option's `val' field
262    if the `flag' field is zero.
263 
264    The elements of ARGV aren't really const, because we permute them.
265    But we pretend they're const in the prototype to be compatible
266    with other systems.
267 
268    LONGOPTS is a vector of `struct option' terminated by an
269    element containing a name which is zero.
270 
271    LONGIND returns the index in LONGOPT of the long-named option found.
272    It is only valid when a long-named option has been found by the most
273    recent call.
274 
275    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
276    long-named options.  */
277 
278 int
279 _getopt_internal_r (int argc, char *const *argv, const char *optstring,
280             const struct option *longopts, int *longind,
281             int long_only, struct _getopt_data *d)
282 {
283   int print_errors = d->opterr;
284   if (optstring[0] == ':')
285     print_errors = 0;
286 
287   if (argc < 1)
288     return -1;
289 
290   d->optarg = NULL;
291 
292   if (d->optind == 0 || !d->__initialized)
293     {
294       if (d->optind == 0)
295     d->optind = 1;    /* Don't scan ARGV[0], the program name.  */
296       optstring = _getopt_initialize (argc, argv, optstring, d);
297       d->__initialized = 1;
298     }
299 
300   /* Test whether ARGV[optind] points to a non-option argument.
301      Either it does not have option syntax, or there is an environment flag
302      from the shell indicating it is not an option.  The later information
303      is only used when the used in the GNU libc.  */
304 # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
305 
306   if (d->__nextchar == NULL || *d->__nextchar == '\0')
307     {
308       /* Advance to the next ARGV-element.  */
309 
310       /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
311      moved back by the user (who may also have changed the arguments).  */
312       if (d->__last_nonopt > d->optind)
313     d->__last_nonopt = d->optind;
314       if (d->__first_nonopt > d->optind)
315     d->__first_nonopt = d->optind;
316 
317       if (d->__ordering == PERMUTE)
318     {
319       /* If we have just processed some options following some non-options,
320          exchange them so that the options come first.  */
321 
322       if (d->__first_nonopt != d->__last_nonopt
323           && d->__last_nonopt != d->optind)
324         exchange ((char **) argv, d);
325       else if (d->__last_nonopt != d->optind)
326         d->__first_nonopt = d->optind;
327 
328       /* Skip any additional non-options
329          and extend the range of non-options previously skipped.  */
330 
331       while (d->optind < argc && NONOPTION_P)
332         d->optind++;
333       d->__last_nonopt = d->optind;
334     }
335 
336       /* The special ARGV-element `--' means premature end of options.
337      Skip it like a null option,
338      then exchange with previous non-options as if it were an option,
339      then skip everything else like a non-option.  */
340 
341       if (d->optind != argc && !strcmp (argv[d->optind], "--"))
342     {
343       d->optind++;
344 
345       if (d->__first_nonopt != d->__last_nonopt
346           && d->__last_nonopt != d->optind)
347         exchange ((char **) argv, d);
348       else if (d->__first_nonopt == d->__last_nonopt)
349         d->__first_nonopt = d->optind;
350       d->__last_nonopt = argc;
351 
352       d->optind = argc;
353     }
354 
355       /* If we have done all the ARGV-elements, stop the scan
356      and back over any non-options that we skipped and permuted.  */
357 
358       if (d->optind == argc)
359     {
360       /* Set the next-arg-index to point at the non-options
361          that we previously skipped, so the caller will digest them.  */
362       if (d->__first_nonopt != d->__last_nonopt)
363         d->optind = d->__first_nonopt;
364       return -1;
365     }
366 
367       /* If we have come to a non-option and did not permute it,
368      either stop the scan or describe it to the caller and pass it by.  */
369 
370       if (NONOPTION_P)
371     {
372       if (d->__ordering == REQUIRE_ORDER)
373         return -1;
374       d->optarg = argv[d->optind++];
375       return 1;
376     }
377 
378       /* We have found another option-ARGV-element.
379      Skip the initial punctuation.  */
380 
381       d->__nextchar = (argv[d->optind] + 1
382           + (longopts != NULL && argv[d->optind][1] == '-'));
383     }
384 
385   /* Decode the current option-ARGV-element.  */
386 
387   /* Check whether the ARGV-element is a long option.
388 
389      If long_only and the ARGV-element has the form "-f", where f is
390      a valid short option, don't consider it an abbreviated form of
391      a long option that starts with f.  Otherwise there would be no
392      way to give the -f short option.
393 
394      On the other hand, if there's a long option "fubar" and
395      the ARGV-element is "-fu", do consider that an abbreviation of
396      the long option, just like "--fu", and not "-f" with arg "u".
397 
398      This distinction seems to be the most useful approach.  */
399 
400   if (longopts != NULL
401       && (argv[d->optind][1] == '-'
402       || (long_only && (argv[d->optind][2]
403                 || !strchr (optstring, argv[d->optind][1])))))
404     {
405       char *nameend;
406       const struct option *p;
407       const struct option *pfound = NULL;
408       int exact = 0;
409       int ambig = 0;
410       int indfound = -1;
411       int option_index;
412 
413       for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
414     /* Do nothing.  */ ;
415 
416       /* Test all long options for either exact match
417      or abbreviated matches.  */
418       for (p = longopts, option_index = 0; p->name; p++, option_index++)
419     if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
420       {
421         if ((unsigned int) (nameend - d->__nextchar)
422         == (unsigned int) strlen (p->name))
423           {
424         /* Exact match found.  */
425         pfound = p;
426         indfound = option_index;
427         exact = 1;
428         break;
429           }
430         else if (pfound == NULL)
431           {
432         /* First nonexact match found.  */
433         pfound = p;
434         indfound = option_index;
435           }
436         else if (long_only
437              || pfound->has_arg != p->has_arg
438              || pfound->flag != p->flag
439              || pfound->val != p->val)
440           /* Second or later nonexact match found.  */
441           ambig = 1;
442       }
443 
444       if (ambig && !exact)
445     {
446       if (print_errors)
447         {
448           fprintf (stderr, _("%s: option '%s' is ambiguous\n"),
449                argv[0], argv[d->optind]);
450         }
451       d->__nextchar += strlen (d->__nextchar);
452       d->optind++;
453       d->optopt = 0;
454       return '?';
455     }
456 
457       if (pfound != NULL)
458     {
459       option_index = indfound;
460       d->optind++;
461       if (*nameend)
462         {
463           /* Don't test has_arg with >, because some C compilers don't
464          allow it to be used on enums.  */
465           if (pfound->has_arg)
466         d->optarg = nameend + 1;
467           else
468         {
469           if (print_errors)
470             {
471 
472               if (argv[d->optind - 1][1] == '-')
473             {
474               /* --option */
475               fprintf (stderr, _("\
476 %s: option '--%s' doesn't allow an argument\n"),
477                    argv[0], pfound->name);
478             }
479               else
480             {
481               /* +option or -option */
482               fprintf (stderr, _("\
483 %s: option '%c%s' doesn't allow an argument\n"),
484                    argv[0], argv[d->optind - 1][0],
485                    pfound->name);
486             }
487 
488             }
489 
490           d->__nextchar += strlen (d->__nextchar);
491 
492           d->optopt = pfound->val;
493           return '?';
494         }
495         }
496       else if (pfound->has_arg == 1)
497         {
498           if (d->optind < argc)
499         d->optarg = argv[d->optind++];
500           else
501         {
502           if (print_errors)
503             {
504               fprintf (stderr,
505                    _("%s: option '%s' requires an argument\n"),
506                    argv[0], argv[d->optind - 1]);
507             }
508           d->__nextchar += strlen (d->__nextchar);
509           d->optopt = pfound->val;
510           return optstring[0] == ':' ? ':' : '?';
511         }
512         }
513       d->__nextchar += strlen (d->__nextchar);
514       if (longind != NULL)
515         *longind = option_index;
516       if (pfound->flag)
517         {
518           *(pfound->flag) = pfound->val;
519           return 0;
520         }
521       return pfound->val;
522     }
523 
524       /* Can't find it as a long option.  If this is not getopt_long_only,
525      or the option starts with '--' or is not a valid short
526      option, then it's an error.
527      Otherwise interpret it as a short option.  */
528       if (!long_only || argv[d->optind][1] == '-'
529       || strchr (optstring, *d->__nextchar) == NULL)
530     {
531       if (print_errors)
532         {
533 
534           if (argv[d->optind][1] == '-')
535         {
536           /* --option */
537           fprintf (stderr, _("%s: unrecognized option '--%s'\n"),
538                argv[0], d->__nextchar);
539         }
540           else
541         {
542           /* +option or -option */
543           fprintf (stderr, _("%s: unrecognized option '%c%s'\n"),
544                argv[0], argv[d->optind][0], d->__nextchar);
545         }
546 
547         }
548       d->__nextchar = (char *) "";
549       d->optind++;
550       d->optopt = 0;
551       return '?';
552     }
553     }
554 
555   /* Look at and handle the next short option-character.  */
556 
557   {
558     char c = *d->__nextchar++;
559     char *temp = strchr (optstring, c);
560 
561     /* Increment `optind' when we start to process its last character.  */
562     if (*d->__nextchar == '\0')
563       ++d->optind;
564 
565     if (temp == NULL || c == ':')
566       {
567     if (print_errors)
568       {
569 
570         fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
571 
572       }
573     d->optopt = c;
574     return '?';
575       }
576     /* Convenience. Treat POSIX -W foo same as long option --foo */
577     if (temp[0] == 'W' && temp[1] == ';')
578       {
579     char *nameend;
580     const struct option *p;
581     const struct option *pfound = NULL;
582     int exact = 0;
583     int ambig = 0;
584     int indfound = 0;
585     int option_index;
586 
587     /* This is an option that requires an argument.  */
588     if (*d->__nextchar != '\0')
589       {
590         d->optarg = d->__nextchar;
591         /* If we end this ARGV-element by taking the rest as an arg,
592            we must advance to the next element now.  */
593         d->optind++;
594       }
595     else if (d->optind == argc)
596       {
597         if (print_errors)
598           {
599         fprintf (stderr,
600              _("%s: option requires an argument -- '%c'\n"),
601              argv[0], c);
602           }
603         d->optopt = c;
604         if (optstring[0] == ':')
605           c = ':';
606         else
607           c = '?';
608         return c;
609       }
610     else
611       /* We already incremented `d->optind' once;
612          increment it again when taking next ARGV-elt as argument.  */
613       d->optarg = argv[d->optind++];
614 
615     /* optarg is now the argument, see if it's in the
616        table of longopts.  */
617 
618     for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
619          nameend++)
620       /* Do nothing.  */ ;
621 
622     /* Test all long options for either exact match
623        or abbreviated matches.  */
624     for (p = longopts, option_index = 0; p->name; p++, option_index++)
625       if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
626         {
627           if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
628         {
629           /* Exact match found.  */
630           pfound = p;
631           indfound = option_index;
632           exact = 1;
633           break;
634         }
635           else if (pfound == NULL)
636         {
637           /* First nonexact match found.  */
638           pfound = p;
639           indfound = option_index;
640         }
641           else
642         /* Second or later nonexact match found.  */
643         ambig = 1;
644         }
645     if (ambig && !exact)
646       {
647         if (print_errors)
648           {
649         fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"),
650              argv[0], argv[d->optind]);
651           }
652         d->__nextchar += strlen (d->__nextchar);
653         d->optind++;
654         return '?';
655       }
656     if (pfound != NULL)
657       {
658         option_index = indfound;
659         if (*nameend)
660           {
661         /* Don't test has_arg with >, because some C compilers don't
662            allow it to be used on enums.  */
663         if (pfound->has_arg)
664           d->optarg = nameend + 1;
665         else
666           {
667             if (print_errors)
668               {
669             fprintf (stderr, _("\
670 %s: option '-W %s' doesn't allow an argument\n"),
671                  argv[0], pfound->name);
672               }
673 
674             d->__nextchar += strlen (d->__nextchar);
675             return '?';
676           }
677           }
678         else if (pfound->has_arg == 1)
679           {
680         if (d->optind < argc)
681           d->optarg = argv[d->optind++];
682         else
683           {
684             if (print_errors)
685               {
686             fprintf (stderr,
687                  _("%s: option '%s' requires an argument\n"),
688                  argv[0], argv[d->optind - 1]);
689               }
690             d->__nextchar += strlen (d->__nextchar);
691             return optstring[0] == ':' ? ':' : '?';
692           }
693           }
694         d->__nextchar += strlen (d->__nextchar);
695         if (longind != NULL)
696           *longind = option_index;
697         if (pfound->flag)
698           {
699         *(pfound->flag) = pfound->val;
700         return 0;
701           }
702         return pfound->val;
703       }
704       d->__nextchar = NULL;
705       return 'W';    /* Let the application handle it.   */
706       }
707     if (temp[1] == ':')
708       {
709     if (temp[2] == ':')
710       {
711         /* This is an option that accepts an argument optionally.  */
712         if (*d->__nextchar != '\0')
713           {
714         d->optarg = d->__nextchar;
715         d->optind++;
716           }
717         else
718           d->optarg = NULL;
719         d->__nextchar = NULL;
720       }
721     else
722       {
723         /* This is an option that requires an argument.  */
724         if (*d->__nextchar != '\0')
725           {
726         d->optarg = d->__nextchar;
727         /* If we end this ARGV-element by taking the rest as an arg,
728            we must advance to the next element now.  */
729         d->optind++;
730           }
731         else if (d->optind == argc)
732           {
733         if (print_errors)
734           {
735             fprintf (stderr,
736                  _("%s: option requires an argument -- '%c'\n"),
737                  argv[0], c);
738           }
739         d->optopt = c;
740         if (optstring[0] == ':')
741           c = ':';
742         else
743           c = '?';
744           }
745         else
746           /* We already incremented `optind' once;
747          increment it again when taking next ARGV-elt as argument.  */
748           d->optarg = argv[d->optind++];
749         d->__nextchar = NULL;
750       }
751       }
752     return c;
753   }
754 }
755 
756 int
757 _getopt_internal (int argc, char *const *argv, const char *optstring,
758           const struct option *longopts, int *longind, int long_only)
759 {
760   int result;
761 
762   getopt_data.optind = optind;
763   getopt_data.opterr = opterr;
764 
765   result = _getopt_internal_r (argc, argv, optstring, longopts,
766                    longind, long_only, &getopt_data);
767 
768   optind = getopt_data.optind;
769   optarg = getopt_data.optarg;
770   optopt = getopt_data.optopt;
771 
772   return result;
773 }
774 
775 int
776 getopt (int argc, char *const *argv, const char *optstring)
777 {
778   return _getopt_internal (argc, argv, optstring,
779                (const struct option *) 0,
780                (int *) 0,
781                0);
782 }
  1 /*
  2 getopt.h
  3 
  4 Copyright (C) 2012, coreBugZJ, all rights reserved.
  5 
  6 在 Windows 平臺下使用 Linux 的 getopt, getopt_long, getopt_long_only 函式。
  7 
  8 修改自 glibc 2.8 中 getopt.h 檔案,
  9 */
 10 
 11 
 12 
 13 
 14 /* Declarations for getopt.
 15    Copyright (C) 1989-1994,1996-1999,2001,2003,2004
 16    Free Software Foundation, Inc.
 17    This file is part of the GNU C Library.
 18 
 19    The GNU C Library is free software; you can redistribute it and/or
 20    modify it under the terms of the GNU Lesser General Public
 21    License as published by the Free Software Foundation; either
 22    version 2.1 of the License, or (at your option) any later version.
 23 
 24    The GNU C Library is distributed in the hope that it will be useful,
 25    but WITHOUT ANY WARRANTY; without even the implied warranty of
 26    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 27    Lesser General Public License for more details.
 28 
 29    You should have received a copy of the GNU Lesser General Public
 30    License along with the GNU C Library; if not, write to the Free
 31    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 32    02111-1307 USA.  */
 33 
 34 #ifndef _GETOPT_H
 35 #define _GETOPT_H 1
 36 
 37 /* If __GNU_LIBRARY__ is not already defined, either we are being used
 38    standalone, or this is the first header included in the source file.
 39    If we are being used with glibc, we need to include <features.h>, but
 40    that does not exist if we are standalone.  So: if __GNU_LIBRARY__ is
 41    not defined, include <ctype.h>, which will pull in <features.h> for us
 42    if it's from glibc.  (Why ctype.h?  It's guaranteed to exist and it
 43    doesn't flood the namespace with stuff the way some other headers do.)  */
 44 #include <ctype.h>
 45 
 46 
 47 #ifdef    __cplusplus
 48 extern "C" {
 49 #endif
 50 
 51 /* For communication from `getopt' to the caller.
 52    When `getopt' finds an option that takes an argument,
 53    the argument value is returned here.
 54    Also, when `ordering' is RETURN_IN_ORDER,
 55    each non-option ARGV-element is returned here.  */
 56 
 57 extern char *optarg;
 58 
 59 /* Index in ARGV of the next element to be scanned.
 60    This is used for communication to and from the caller
 61    and for communication between successive calls to `getopt'.
 62 
 63    On entry to `getopt', zero means this is the first call; initialize.
 64 
 65    When `getopt' returns -1, this is the index of the first of the
 66    non-option elements that the caller should itself scan.
 67 
 68    Otherwise, `optind' communicates from one call to the next
 69    how much of ARGV has been scanned so far.  */
 70 
 71 extern int optind;
 72 
 73 /* Callers store zero here to inhibit the error message `getopt' prints
 74    for unrecognized options.  */
 75 
 76 extern int opterr;
 77 
 78 /* Set to an option character which was unrecognized.  */
 79 
 80 extern int optopt;
 81 
 82 /* Describe the long-named options requested by the application.
 83    The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
 84    of `struct option' terminated by an element containing a name which is
 85    zero.
 86 
 87    The field `has_arg' is:
 88    no_argument        (or 0) if the option does not take an argument,
 89    required_argument    (or 1) if the option requires an argument,
 90    optional_argument     (or 2) if the option takes an optional argument.
 91 
 92    If the field `flag' is not NULL, it points to a variable that is set
 93    to the value given in the field `val' when the option is found, but
 94    left unchanged if the option is not found.
 95 
 96    To have a long-named option do something other than set an `int' to
 97    a compiled-in constant, such as set a value from `optarg', set the
 98    option's `flag' field to zero and its `val' field to a nonzero
 99    value (the equivalent single-letter option character, if there is
100    one).  For long options that have a zero `flag' field, `getopt'
101    returns the contents of the `val' field.  */
102 
103 struct option
104 {
105   const char *name;
106   /* has_arg can't be an enum because some compilers complain about
107      type mismatches in all the code that assumes it is an int.  */
108   int has_arg;
109   int *flag;
110   int val;
111 };
112 
113 /* Names for the values of the `has_arg' field of `struct option'.  */
114 
115 #define no_argument        0
116 #define required_argument    1
117 #define optional_argument    2
118 
119 
120 /* Get definitions and prototypes for functions to process the
121    arguments in ARGV (ARGC of them, minus the program name) for
122    options given in OPTS.
123 
124    Return the option character from OPTS just read.  Return -1 when
125    there are no more options.  For unrecognized options, or options
126    missing arguments, `optopt' is set to the option letter, and '?' is
127    returned.
128 
129    The OPTS string is a list of characters which are recognized option
130    letters, optionally followed by colons, specifying that that letter
131    takes an argument, to be placed in `optarg'.
132 
133    If a letter in OPTS is followed by two colons, its argument is
134    optional.  This behavior is specific to the GNU `getopt'.
135 
136    The argument `--' causes premature termination of argument
137    scanning, explicitly telling `getopt' that there are no more
138    options.
139 
140    If OPTS begins with `--', then non-option arguments are treated as
141    arguments to the option '\0'.  This behavior is specific to the GNU
142    `getopt'.  */
143 
144 /* Many other libraries have conflicting prototypes for getopt, with
145    differences in the consts, in stdlib.h.  To avoid compilation
146    errors, only prototype getopt for the GNU C library.  */
147 extern int getopt (int ___argc, char *const *___argv, const char *__shortopts);
148 
149 extern int getopt_long (int ___argc, char *const *___argv,
150             const char *__shortopts,
151                 const struct option *__longopts, int *__longind);
152 
153 extern int getopt_long_only (int ___argc, char *const *___argv,
154                  const char *__shortopts,
155                      const struct option *__longopts, int *__longind);
156 
157 
158 #ifdef    __cplusplus
159 }
160 #endif
161 
162 
163 #endif /* getopt.h */
  1 /*
  2 getopt_int.h
  3 
  4 Copyright (C) 2012, coreBugZJ, all rights reserved.
  5 
  6 在 Windows 平臺下使用 Linux 的 getopt, getopt_long, getopt_long_only 函式。
  7 
  8 修改自 glibc 2.8 中 getopt_int.h 檔案,
  9 */
 10 
 11 
 12 
 13 
 14 
 15 /* Internal declarations for getopt.
 16    Copyright (C) 1989-1994,1996-1999,2001,2003,2004
 17    Free Software Foundation, Inc.
 18    This file is part of the GNU C Library.
 19 
 20    The GNU C Library is free software; you can redistribute it and/or
 21    modify it under the terms of the GNU Lesser General Public
 22    License as published by the Free Software Foundation; either
 23    version 2.1 of the License, or (at your option) any later version.
 24 
 25    The GNU C Library is distributed in the hope that it will be useful,
 26    but WITHOUT ANY WARRANTY; without even the implied warranty of
 27    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 28    Lesser General Public License for more details.
 29 
 30    You should have received a copy of the GNU Lesser General Public
 31    License along with the GNU C Library; if not, write to the Free
 32    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 33    02111-1307 USA.  */
 34 
 35 #ifndef _GETOPT_INT_H
 36 #define _GETOPT_INT_H    1
 37 
 38 extern int _getopt_internal (int ___argc, char *const *___argv,
 39                  const char *__shortopts,
 40                      const struct option *__longopts, int *__longind,
 41                  int __long_only);
 42 
 43  
 44 /* Reentrant versions which can handle parsing multiple argument
 45    vectors at the same time.  */
 46 
 47 /* Data type for reentrant functions.  */
 48 struct _getopt_data
 49 {
 50   /* These have exactly the same meaning as the corresponding global
 51      variables, except that they are used for the reentrant
 52      versions of getopt.  */
 53   int optind;
 54   int opterr;
 55   int optopt;
 56   char *optarg;
 57 
 58   /* Internal members.  */
 59 
 60   /* True if the internal members have been initialized.  */
 61   int __initialized;
 62 
 63   /* The next char to be scanned in the option-element
 64      in which the last option character we returned was found.
 65      This allows us to pick up the scan where we left off.
 66 
 67      If this is zero, or a null string, it means resume the scan
 68      by advancing to the next ARGV-element.  */
 69   char *__nextchar;
 70 
 71   /* Describe how to deal with options that follow non-option ARGV-elements.
 72 
 73      If the caller did not specify anything,
 74      the default is REQUIRE_ORDER if the environment variable
 75      POSIXLY_CORRECT is defined, PERMUTE otherwise.
 76 
 77      REQUIRE_ORDER means don't recognize them as options;
 78      stop option processing when the first non-option is seen.
 79      This is what Unix does.
 80      This mode of operation is selected by either setting the environment
 81      variable POSIXLY_CORRECT, or using `+' as the first character
 82      of the list of option characters.
 83 
 84      PERMUTE is the default.  We permute the contents of ARGV as we
 85      scan, so that eventually all the non-options are at the end.
 86      This allows options to be given in any order, even with programs
 87      that were not written to expect this.
 88 
 89      RETURN_IN_ORDER is an option available to programs that were
 90      written to expect options and other ARGV-elements in any order
 91      and that care about the ordering of the two.  We describe each
 92      non-option ARGV-element as if it were the argument of an option
 93      with character code 1.  Using `-' as the first character of the
 94      list of option characters selects this mode of operation.
 95 
 96      The special argument `--' forces an end of option-scanning regardless
 97      of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
 98      `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
 99 
100   enum
101     {
102       REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
103     } __ordering;
104 
105   /* If the POSIXLY_CORRECT environment variable is set.  */
106   int __posixly_correct;
107 
108 
109   /* Handle permutation of arguments.  */
110 
111   /* Describe the part of ARGV that contains non-options that have
112      been skipped.  `first_nonopt' is the index in ARGV of the first
113      of them; `last_nonopt' is the index after the last of them.  */
114 
115   int __first_nonopt;
116   int __last_nonopt;
117 };
118 
119 /* The initializer is necessary to set OPTIND and OPTERR to their
120    default values and to clear the initialization flag.  */
121 #define _GETOPT_DATA_INITIALIZER    { 1, 1 }
122 
123 extern int _getopt_internal_r (int ___argc, char *const *___argv,
124                    const char *__shortopts,
125                    const struct option *__longopts, int *__longind,
126                    int __long_only, struct _getopt_data *__data);
127 
128 extern int _getopt_long_r (int ___argc, char *const *___argv,
129                const char *__shortopts,
130                const struct option *__longopts, int *__longind,
131                struct _getopt_data *__data);
132 
133 extern int _getopt_long_only_r (int ___argc, char *const *___argv,
134                 const char *__shortopts,
135                 const struct option *__longopts,
136                 int *__longind,
137                 struct _getopt_data *__data);
138 
139 #endif /* getopt_int.h */
 1 /*
 2 getopt1.c
 3 
 4 Copyright (C) 2012, coreBugZJ, all rights reserved.
 5 
 6 在 Windows 平臺下使用 Linux 的 getopt, getopt_long, getopt_long_only 函式。
 7 
 8 修改自 glibc 2.8 中 getopt1.c 檔案,
 9 */
10 
11 
12 
13 
14 
15 
16 /* getopt_long and getopt_long_only entry points for GNU getopt.
17    Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
18      Free Software Foundation, Inc.
19    This file is part of the GNU C Library.
20 
21    The GNU C Library is free software; you can redistribute it and/or
22    modify it under the terms of the GNU Lesser General Public
23    License as published by the Free Software Foundation; either
24    version 2.1 of the License, or (at your option) any later version.
25 
26    The GNU C Library is distributed in the hope that it will be useful,
27    but WITHOUT ANY WARRANTY; without even the implied warranty of
28    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29    Lesser General Public License for more details.
30 
31    You should have received a copy of the GNU Lesser General Public
32    License along with the GNU C Library; if not, write to the Free
33    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
34    02111-1307 USA.  */
35 
36 
37 #include "getopt.h"
38 #include "getopt_int.h"
39 
40 
41 int
42 getopt_long (int argc, char *const *argv, const char *options,
43          const struct option *long_options, int *opt_index)
44 {
45   return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
46 }
47 
48 int
49 _getopt_long_r (int argc, char *const *argv, const char *options,
50         const struct option *long_options, int *opt_index,
51         struct _getopt_data *d)
52 {
53   return _getopt_internal_r (argc, argv, options, long_options, opt_index,
54                  0, d);
55 }
56 
57 /* Like getopt_long, but '-' as well as '--' can indicate a long option.
58    If an option that starts with '-' (not '--') doesn't match a long option,
59    but does match a short option, it is parsed as a short option
60    instead.  */
61 
62 int
63 getopt_long_only (int argc, char *const *argv, const char *options,
64           const struct option *long_options, int *opt_index)
65 {
66   return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
67 }
68 
69 int
70 _getopt_long_only_r (int argc, char *const *argv, const char *options,
71              const struct option *long_options, int *opt_index,
72              struct _getopt_data *d)
73 {
74   return _getopt_internal_r (argc, argv, options, long_options, opt_index,
75                  1, d);
76 }
  1 /*
  2 test_getopt.c
  3 
  4 Copyright (C) 2012, coreBugZJ, all rights reserved.
  5 
  6 在 Windows 平臺下使用 Linux 的 getopt, getopt_long, getopt_long_only 函式。
  7 
  8 修改自 glibc 2.8 中 getopt.c 檔案,
  9 */
 10 
 11 
 12 #include <stdio.h>
 13 #include "getopt.h"
 14 
 15 
 16 
 17 
 18 static void usage()
 19 {
 20     printf("\nNo Usage\n");
 21 }
 22 
 23 //具體應用根據實際情況修改
 24 static void conf_cmdline(int argc, char **argv)
 25 {
 26     int c;
 27 
 28     /* 
 29      * getopt作為選項的判斷,getopt_long可以指定長引數
 30      * 
 31      */
 32     while ((c = getopt(argc, argv, "e:l:m:")) != EOF)
 33         switch (c) {
 34         case 'l':
 35             printf("c\n");
 36             break;
 37         case 'm':
 38             //TODO:獲取引數n表示要獲取的符號個數,通過system呼叫findstr /<Symbol/>將相應的符號行從temp檔案中取出
 39             //將取出的資料處理只保留地址儲存到Addr檔案中。
 40             //通過while(n)來處理每一個argv的符號。
 41 
 42             printf("n\n");          
 43             break;
 44         case 'e':
 45             //TODO:獲取ELF檔案,呼叫system("nm.exe -n elf > temp.txt")將符號表儲存到temp檔案中,
 46 
 47             break;
 48         default:
 49             //列出命令列使用方法
 50             usage();
 51         //退出函式
 52             exit(1);
 53         }
 54     //多執行緒時需要重新恢復初值
 55     optind = 1;
 56 }
 57 
 58 void main(int argc, char **argv)
 59 {
 60     conf_cmdline(argc, argv);    
 61 }
 62 
 63 
 64 /*
 65 int main (int argc, char **argv)
 66 {
 67         int c;
 68         int digit_optind = 0;
 69 
 70         while (1)
 71         {
 72                 int this_option_optind = optind ? optind : 1;
 73                 int option_index = 0;
 74                 static struct option long_options[] =
 75                 {
 76                         {"add", 1, 0, 0},
 77                         {"append", 0, 0, 0},
 78                         {"delete", 1, 0, 0},
 79                         {"verbose", 0, 0, 0},
 80                         {"create", 0, 0, 0},
 81                         {"file", 1, 0, 0},
 82                         {0, 0, 0, 0}
 83                 };
 84 
 85                 c = getopt_long (argc, argv, "abc:d:0123456789",
 86                         long_options, &option_index);
 87                 if (c == -1)
 88                         break;
 89 
 90                 switch (c)
 91                 {
 92                 case 0:
 93                         printf ("option %s", long_options[option_index].name);
 94                         if (optarg)
 95                                 printf (" with arg %s", optarg);
 96                         printf ("\n");
 97                         break;
 98 
 99                 case '0':
100                 case '1':
101                 case '2':
102                 case '3':
103                 case '4':
104                 case '5':
105                 case '6':
106                 case '7':
107                 case '8':
108                 case '9':
109                         if (digit_optind != 0 && digit_optind != this_option_optind)
110                                 printf ("digits occur in two different argv-elements.\n");
111                         digit_optind = this_option_optind;
112                         printf ("option %c\n", c);
113                         break;
114 
115                 case 'a':
116                         printf ("option a\n");
117                         break;
118 
119                 case 'b':
120                         printf ("option b\n");
121                         break;
122 
123                 case 'c':
124                         printf ("option c with value `%s'\n", optarg);
125                         break;
126 
127                 case 'd':
128                         printf ("option d with value `%s'\n", optarg);
129                         break;
130 
131                 case '?':
132                         break;
133 
134                 default:
135                         printf ("?? getopt returned character code 0%o ??\n", c);
136                 }
137         }
138 
139         if (optind < argc)
140         {
141                 printf ("non-option ARGV-elements: ");
142                 while (optind < argc)
143                         printf ("%s ", argv[optind++]);
144                 printf ("\n");
145         }
146 
147         return 0;
148 }
149 */

 

相關文章