getopt.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * getopt() - command option parsing
  3. *
  4. * Gunnar Ritter, Freiburg i. Br., Germany, March 2002.
  5. */
  6. /* Sccsid @(#)getopt.c 1.6 (gritter) 12/16/07 */
  7. #include <sys/types.h>
  8. #include <alloca.h>
  9. #include <string.h>
  10. #include "msgselect.h"
  11. /*
  12. * One should not think that re-implementing this is necessary, but
  13. *
  14. * - Some libcs print weird messages.
  15. *
  16. * - GNU libc getopt() is totally brain-damaged, as it requires special
  17. * care _not_ to reorder parameters and can't be told to work correctly
  18. * with ':' as first optstring character at all.
  19. */
  20. char *optarg = 0;
  21. int optind = 1;
  22. int opterr = 1;
  23. int optopt = 0;
  24. extern char *pfmt_label__;
  25. static void
  26. error(const char *s, int c)
  27. {
  28. /*
  29. * Avoid including <unistd.h>, in case its getopt() declaration
  30. * conflicts.
  31. */
  32. extern ssize_t write(int, const void *, size_t);
  33. const char *msg = 0;
  34. char *buf, *bp;
  35. if (pfmt_label__)
  36. s = pfmt_label__;
  37. switch (c) {
  38. case '?':
  39. msg = ": " msgselect("I","i") "llegal option -- ";
  40. break;
  41. case ':':
  42. msg = ": " msgselect("O","o") "ption requires an argument -- ";
  43. break;
  44. }
  45. bp = buf = alloca(strlen(s) + strlen(msg) + 2);
  46. while (*s)
  47. *bp++ = *s++;
  48. while (*msg)
  49. *bp++ = *msg++;
  50. *bp++ = optopt;
  51. *bp++ = '\n';
  52. write(2, buf, bp - buf);
  53. }
  54. int
  55. getopt(int argc, char *const argv[], const char *optstring)
  56. {
  57. int colon;
  58. static const char *lastp;
  59. const char *curp;
  60. if (optstring[0] == ':') {
  61. colon = 1;
  62. optstring++;
  63. } else
  64. colon = 0;
  65. if (lastp) {
  66. curp = lastp;
  67. lastp = 0;
  68. } else {
  69. if (optind >= argc || argv[optind] == 0 ||
  70. argv[optind][0] != '-' ||
  71. argv[optind][1] == '\0')
  72. return -1;
  73. if (argv[optind][1] == '-' && argv[optind][2] == '\0') {
  74. optind++;
  75. return -1;
  76. }
  77. curp = &argv[optind][1];
  78. }
  79. optopt = curp[0] & 0377;
  80. while (optstring[0]) {
  81. if (optstring[0] == ':') {
  82. optstring++;
  83. continue;
  84. }
  85. if ((optstring[0] & 0377) == optopt) {
  86. if (optstring[1] == ':') {
  87. if (curp[1] != '\0') {
  88. optarg = (char *)&curp[1];
  89. optind++;
  90. } else {
  91. if ((optind += 2) > argc) {
  92. if (!colon && opterr)
  93. error(argv[0], ':');
  94. return colon ? ':' : '?';
  95. }
  96. optarg = argv[optind - 1];
  97. }
  98. } else {
  99. if (curp[1] != '\0')
  100. lastp = &curp[1];
  101. else
  102. optind++;
  103. optarg = 0;
  104. }
  105. return optopt;
  106. }
  107. optstring++;
  108. }
  109. if (!colon && opterr)
  110. error(argv[0], '?');
  111. if (curp[1] != '\0')
  112. lastp = &curp[1];
  113. else
  114. optind++;
  115. optarg = 0;
  116. return '?';
  117. }
  118. #ifdef __APPLE__
  119. /*
  120. * Starting with Mac OS 10.5 Leopard, <unistd.h> turns getopt()
  121. * into getopt$UNIX2003() by default. Consequently, this function
  122. * is called instead of the one defined above. However, optind is
  123. * still taken from this file, so in effect, options are not
  124. * properly handled. Defining an own getopt$UNIX2003() function
  125. * works around this issue.
  126. */
  127. int
  128. getopt$UNIX2003(int argc, char *const argv[], const char *optstring)
  129. {
  130. return getopt(argc, argv, optstring);
  131. }
  132. #endif /* __APPLE__ */