getopt_long.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // SPDX-License-Identifier: LGPL-2.1 OR BSD-3-Clause
  2. /*
  3. * Copyright (c) 2019, Chips&Media
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  16. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  19. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <assert.h>
  27. #include <errno.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include "getopt.h"
  32. extern int opterr; /* if error message should be printed */
  33. extern int optind; /* index into parent argv vector */
  34. extern int optopt; /* character checked for validity */
  35. extern int optreset; /* reset getopt */
  36. extern char *optarg; /* argument associated with option */
  37. #ifndef __P
  38. #define __P(x) x
  39. #endif
  40. #define _DIAGASSERT(x) assert(x)
  41. static char * __progname __P((char *));
  42. int getopt_internal __P((int, char * const *, const char *));
  43. static char *
  44. __progname(nargv0)
  45. char * nargv0;
  46. {
  47. char * tmp;
  48. _DIAGASSERT(nargv0 != NULL);
  49. tmp = strrchr(nargv0, '/');
  50. if (tmp)
  51. tmp++;
  52. else
  53. tmp = nargv0;
  54. return(tmp);
  55. }
  56. #define BADCH (int)'?'
  57. #define BADARG (int)':'
  58. #define EMSG ""
  59. /*
  60. * getopt --
  61. * Parse argc/argv argument vector.
  62. */
  63. int
  64. getopt_internal(nargc, nargv, ostr)
  65. int nargc;
  66. char * const *nargv;
  67. const char *ostr;
  68. {
  69. static char *place = EMSG; /* option letter processing */
  70. char *oli; /* option letter list index */
  71. _DIAGASSERT(nargv != NULL);
  72. _DIAGASSERT(ostr != NULL);
  73. if (optreset || !*place) { /* update scanning pointer */
  74. optreset = 0;
  75. if (optind >= nargc || *(place = nargv[optind]) != '-') {
  76. place = EMSG;
  77. return (-1);
  78. }
  79. if (place[1] && *++place == '-') { /* found "--" */
  80. /* ++optind; */
  81. place = EMSG;
  82. return (-2);
  83. }
  84. } /* option letter okay? */
  85. if ((optopt = (int)*place++) == (int)':' ||
  86. !(oli = strchr((char*)ostr, optopt))) {
  87. /*
  88. * if the user didn't specify '-' as an option,
  89. * assume it means -1.
  90. */
  91. if (optopt == (int)'-')
  92. return (-1);
  93. if (!*place)
  94. ++optind;
  95. if (opterr && *ostr != ':')
  96. (void)fprintf(stderr,
  97. "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
  98. return (BADCH);
  99. }
  100. if (*++oli != ':') { /* don't need argument */
  101. optarg = NULL;
  102. if (!*place)
  103. ++optind;
  104. } else { /* need an argument */
  105. if (*place) /* no white space */
  106. optarg = place;
  107. else if (nargc <= ++optind) { /* no arg */
  108. place = EMSG;
  109. if ((opterr) && (*ostr != ':'))
  110. (void)fprintf(stderr,
  111. "%s: option requires an argument -- %c\n",
  112. __progname(nargv[0]), optopt);
  113. return (BADARG);
  114. } else /* white space */
  115. optarg = nargv[optind];
  116. place = EMSG;
  117. ++optind;
  118. }
  119. return (optopt); /* dump back option letter */
  120. }
  121. #if 0
  122. /*
  123. * getopt --
  124. * Parse argc/argv argument vector.
  125. */
  126. int
  127. getopt2(nargc, nargv, ostr)
  128. int nargc;
  129. char * const *nargv;
  130. const char *ostr;
  131. {
  132. int retval;
  133. if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
  134. retval = -1;
  135. ++optind;
  136. }
  137. return(retval);
  138. }
  139. #endif
  140. /*
  141. * getopt_long --
  142. * Parse argc/argv argument vector.
  143. */
  144. #if defined(PLATFORM_QNX)
  145. #else
  146. int
  147. getopt_long(nargc, nargv, options, long_options, idx)
  148. int nargc;
  149. char ** nargv;
  150. char * options;
  151. struct option * long_options;
  152. int * idx;
  153. {
  154. int retval;
  155. _DIAGASSERT(nargv != NULL);
  156. _DIAGASSERT(options != NULL);
  157. _DIAGASSERT(long_options != NULL);
  158. /* index may be NULL */
  159. if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
  160. char *current_argv = nargv[optind++] + 2, *has_equal;
  161. int i, current_argv_len, match = -1;
  162. if (*current_argv == '\0') {
  163. return(-1);
  164. }
  165. if ((has_equal = strchr(current_argv, '=')) != NULL) {
  166. current_argv_len = has_equal - current_argv;
  167. has_equal++;
  168. } else
  169. current_argv_len = strlen(current_argv);
  170. for (i = 0; long_options[i].name; i++) {
  171. if (strncmp(current_argv, long_options[i].name, current_argv_len))
  172. continue;
  173. if (strlen(long_options[i].name) == (unsigned)current_argv_len) {
  174. match = i;
  175. break;
  176. }
  177. if (match == -1)
  178. match = i;
  179. }
  180. if (match != -1) {
  181. if (long_options[match].has_arg == required_argument ||
  182. long_options[match].has_arg == optional_argument) {
  183. if (has_equal)
  184. optarg = has_equal;
  185. else
  186. optarg = nargv[optind++];
  187. }
  188. if ((long_options[match].has_arg == required_argument)
  189. && (optarg == NULL)) {
  190. /*
  191. * Missing argument, leading :
  192. * indicates no error should be generated
  193. */
  194. if ((opterr) && (*options != ':'))
  195. (void)fprintf(stderr,
  196. "%s: option requires an argument -- %s\n",
  197. __progname(nargv[0]), current_argv);
  198. return (BADARG);
  199. }
  200. } else { /* No matching argument */
  201. if ((opterr) && (*options != ':'))
  202. (void)fprintf(stderr,
  203. "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
  204. return (BADCH);
  205. }
  206. if (long_options[match].flag) {
  207. *long_options[match].flag = long_options[match].val;
  208. retval = 0;
  209. } else
  210. retval = long_options[match].val;
  211. if (idx)
  212. *idx = match;
  213. }
  214. return(retval);
  215. }
  216. #endif