getopt_long.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * getopt_long() -- long options parser
  3. *
  4. * Portions Copyright (c) 1987, 1993, 1994
  5. * The Regents of the University of California. All rights reserved.
  6. *
  7. * Portions Copyright (c) 2003
  8. * PostgreSQL Global Development Group
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * 3. Neither the name of the University nor the names of its contributors
  19. * may be used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. *
  34. * $PostgreSQL: pgsql/src/port/getopt_long.c,v 1.6 2007/03/26 21:44:11 momjian Exp $
  35. */
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include "getopt_long.h"
  39. #ifndef HAVE_INT_OPTRESET
  40. int optreset;
  41. #endif
  42. #define BADCH '?'
  43. #define BADARG ':'
  44. #define EMSG ""
  45. int
  46. getopt_long(int argc, char *const argv[],
  47. const char *optstring,
  48. const struct option * longopts, int *longindex)
  49. {
  50. static char *place = EMSG; /* option letter processing */
  51. char *oli; /* option letter list index */
  52. if (optreset || !*place)
  53. { /* update scanning pointer */
  54. optreset = 0;
  55. if (optind >= argc)
  56. {
  57. place = EMSG;
  58. return -1;
  59. }
  60. place = argv[optind];
  61. if (place[0] != '-')
  62. {
  63. place = EMSG;
  64. return -1;
  65. }
  66. place++;
  67. if (place[0] && place[0] == '-' && place[1] == '\0')
  68. { /* found "--" */
  69. ++optind;
  70. place = EMSG;
  71. return -1;
  72. }
  73. if (place[0] && place[0] == '-' && place[1])
  74. {
  75. /* long option */
  76. size_t namelen;
  77. int i;
  78. place++;
  79. namelen = strcspn(place, "=");
  80. for (i = 0; longopts[i].name != NULL; i++)
  81. {
  82. if (strlen(longopts[i].name) == namelen
  83. && strncmp(place, longopts[i].name, namelen) == 0)
  84. {
  85. if (longopts[i].has_arg)
  86. {
  87. if (place[namelen] == '=')
  88. optarg = place + namelen + 1;
  89. else if (optind < argc - 1)
  90. {
  91. optind++;
  92. optarg = argv[optind];
  93. }
  94. else
  95. {
  96. if (optstring[0] == ':')
  97. return BADARG;
  98. if (opterr)
  99. fprintf(stderr,
  100. "%s: option requires an argument -- %s\n",
  101. argv[0], place);
  102. place = EMSG;
  103. optind++;
  104. return BADCH;
  105. }
  106. }
  107. else
  108. {
  109. optarg = NULL;
  110. if (place[namelen] != 0)
  111. {
  112. /* XXX error? */
  113. }
  114. }
  115. optind++;
  116. if (longindex)
  117. *longindex = i;
  118. place = EMSG;
  119. if (longopts[i].flag == NULL)
  120. return longopts[i].val;
  121. else
  122. {
  123. *longopts[i].flag = longopts[i].val;
  124. return 0;
  125. }
  126. }
  127. }
  128. if (opterr && optstring[0] != ':')
  129. fprintf(stderr,
  130. "%s: illegal option -- %s\n", argv[0], place);
  131. place = EMSG;
  132. optind++;
  133. return BADCH;
  134. }
  135. }
  136. /* short option */
  137. optopt = (int) *place++;
  138. oli = strchr(optstring, optopt);
  139. if (!oli)
  140. {
  141. if (!*place)
  142. ++optind;
  143. if (opterr && *optstring != ':')
  144. fprintf(stderr,
  145. "%s: illegal option -- %c\n", argv[0], optopt);
  146. return BADCH;
  147. }
  148. if (oli[1] != ':')
  149. { /* don't need argument */
  150. optarg = NULL;
  151. if (!*place)
  152. ++optind;
  153. }
  154. else
  155. { /* need an argument */
  156. if (*place) /* no white space */
  157. optarg = place;
  158. else if (argc <= ++optind)
  159. { /* no arg */
  160. place = EMSG;
  161. if (*optstring == ':')
  162. return BADARG;
  163. if (opterr)
  164. fprintf(stderr,
  165. "%s: option requires an argument -- %c\n",
  166. argv[0], optopt);
  167. return BADCH;
  168. }
  169. else
  170. /* white space */
  171. optarg = argv[optind];
  172. place = EMSG;
  173. ++optind;
  174. }
  175. return optopt;
  176. }