getopt_cpp.cpp 6.2 KB

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