libxcoder  5.2.0
ni_getopt.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Copyright (C) 2022 NETINT Technologies
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18  * SOFTWARE.
19  *
20  ******************************************************************************/
21 
22 /*!*****************************************************************************
23  * \file ni_getopt.c
24  *
25  * \brief Implementation of getopt() and getopt_long() for Windows environment
26  ******************************************************************************/
27 
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "ni_getopt.h"
32 
33 char *optarg = NULL; // global argument pointer
34 int optind = 0; // global argv index
35 int opterr = 1; // global erroneous switch
36 int optopt = 0; // global erroneous option character
37 
38 int getopt(int argc, char *argv[], const char *optstring)
39 {
40  static char *nextchar = NULL;
41 
42  if (nextchar == NULL || *nextchar == '\0')
43  {
44  if (optind == 0)
45  optind++;
46 
47  if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
48  {
49  optarg = NULL;
50  if (optind < argc)
51  optarg = argv[optind];
52  return EOF;
53  }
54 
55  if (strncmp(argv[optind], "--", strlen("--")) == 0)
56  {
57  optind++;
58  optarg = NULL;
59  if (optind < argc)
60  optarg = argv[optind];
61  return EOF;
62  }
63 
64  nextchar = argv[optind];
65  nextchar += strlen("-");
66  optind++;
67  }
68 
69  char c = *nextchar++;
70  char *cp = strchr(optstring, c);
71  optopt = (int)c;
72  if (cp == NULL || c == ':')
73  {
74  return '?';
75  }
76 
77  cp++;
78  if (*cp == ':')
79  {
80  if (*nextchar != '\0')
81  {
82  optarg = nextchar;
83  nextchar = NULL; // for next invocation
84  }
85  else if (optind < argc)
86  {
87  optarg = argv[optind];
88  optind++;
89  }
90  else
91  {
92  return '?';
93  }
94  }
95 
96  return c;
97 }
98 
99 int getopt_long(int argc, char* argv[], const char* optstring,
100  const struct option* longopts, int* longindex)
101 {
102  int i, parse_long_mismatch = 0;
103  static char* nextchar = NULL;
104 
105  if (nextchar == NULL || *nextchar == '\0')
106  {
107  if (optind == 0)
108  {
109  optind++;
110  }
111 
112  if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
113  {
114  optarg = NULL;
115  if (optind < argc)
116  {
117  optarg = argv[optind];
118  }
119  return EOF;
120  }
121 
122  nextchar = argv[optind];
123  if (strncmp(argv[optind], "--", 2) == 0)
124  {
125  parse_long_mismatch = 1;
126  nextchar += strlen("--");
127  optarg = NULL;
128  if (optind < argc)
129  {
130  optarg = argv[optind];
131  }
132  }
133  else
134  {
135  nextchar += strlen("-");
136  }
137 
138  optind++;
139  }
140 
141  // Parse long option string
142  for (i = 0; longopts != NULL && longopts[i].name != NULL; i++)
143  {
144  size_t optlen = strlen(longopts[i].name);
145  if (strncmp(nextchar, longopts[i].name, optlen) == 0)
146  {
147  nextchar += optlen;
148  switch (longopts[i].has_arg)
149  {
150  case 0:
151  if (*nextchar != '\0' || (optind < argc && argv[optind][0] != '-'))
152  {
153  optind++;
154  return '?';
155  }
156  else
157  {
158  optind++;
159  return longopts[i].flag == NULL ? longopts[i].val : 0;
160  }
161  case 1:
162  if (*nextchar == '=')
163  {
164  optarg = nextchar + 1;
165  optind++;
166  return longopts[i].flag == NULL ? longopts[i].val : 0;
167  }
168  else if (*nextchar != '\0' || (optind < argc && argv[optind][0] == '-'))
169  {
170  optind++;
171  return '?';
172  }
173  else if (optind < argc)
174  {
175  optarg = argv[optind];
176  optind++;
177  return longopts[i].flag == NULL ? longopts[i].val : 0;
178  }
179  else
180  {
181  return '?';
182  }
183  case 2:
184  if (*nextchar == '=')
185  {
186  optarg = nextchar + 1;
187  }
188  else if (*nextchar == '\0' || (optind < argc && argv[optind][0] == '-'))
189  {
190  optarg = NULL;
191  }
192  else
193  {
194  if (*nextchar == '\0' && optind < argc)
195  {
196  optarg = argv[optind];
197  }
198  }
199  optind++;
200  return longopts[i].flag == NULL ? longopts[i].val : 0;
201  default:
202  return '?';
203  }
204  }
205  }
206 
207  if (parse_long_mismatch)
208  {
209  return '?';
210  }
211 
212  // Parse short option string
213  char c = *nextchar++;
214  char* cp = strchr(optstring, c);
215  optopt = (int)c;
216  if (cp == NULL || c == ':')
217  {
218  return '?';
219  }
220 
221  cp++;
222  // Whether there is any argument
223  if (*cp == ':')
224  {
225  if (*nextchar != '\0')
226  {
227  optarg = nextchar;
228  nextchar = NULL; // for next invocation
229  }
230  else if (optind < argc)
231  {
232  optarg = argv[optind];
233  optind++;
234  }
235  else
236  {
237  return '?';
238  }
239  }
240 
241  return c;
242 }
opterr
int opterr
Definition: ni_getopt.c:35
optind
int optind
Definition: ni_getopt.c:34
optopt
int optopt
Definition: ni_getopt.c:36
option::name
const char * name
Definition: ni_getopt.h:75
option::flag
int * flag
Definition: ni_getopt.h:79
getopt_long
int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: ni_getopt.c:99
optarg
char * optarg
Definition: ni_getopt.c:33
option
Definition: ni_getopt.h:73
getopt
int getopt(int argc, char *argv[], const char *optstring)
Definition: ni_getopt.c:38
option::val
int val
Definition: ni_getopt.h:80
ni_getopt.h
Implementation of getopt() and getopt_long() for Windows environment.