libxcoder  3.5.1
ni_getopt_logan.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 with Windows API.
26 *
27 *******************************************************************************/
28 
29 #include <stdio.h>
30 #include <string.h>
31 
32 #include "ni_getopt_logan.h"
33 
34 char *optarg = NULL; // global argument pointer
35 int optind = 0; // global argv index
36 int opterr = 1; // global erroneous switch
37 int optopt = 0; // global erroneous option character
38 
39 int getopt(int argc, char *argv[], const char *optstring)
40 {
41  static char *nextchar = NULL;
42 
43  if (nextchar == NULL || *nextchar == '\0')
44  {
45  if (optind == 0)
46  optind++;
47 
48  if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
49  {
50  optarg = NULL;
51  if (optind < argc)
52  optarg = argv[optind];
53  return EOF;
54  }
55 
56  if (strncmp(argv[optind], "--", strlen("--")) == 0)
57  {
58  optind++;
59  optarg = NULL;
60  if (optind < argc)
61  optarg = argv[optind];
62  return EOF;
63  }
64 
65  nextchar = argv[optind];
66  nextchar += strlen("-");
67  optind++;
68  }
69 
70  char c = *nextchar++;
71  char *cp = strchr(optstring, c);
72  optopt = (int)c;
73  if (cp == NULL || c == ':')
74  {
75  return '?';
76  }
77 
78  cp++;
79  if (*cp == ':')
80  {
81  if (*nextchar != '\0')
82  {
83  optarg = nextchar;
84  nextchar = NULL; // for next invocation
85  }
86  else if (optind < argc)
87  {
88  optarg = argv[optind];
89  optind++;
90  }
91  else
92  {
93  return '?';
94  }
95  }
96 
97  return c;
98 }
99 
100 
101 int getopt_long(int argc, char* argv[], const char* optstring,
102  const struct option* longopts, int* longindex)
103 {
104  int i, parse_long_mismatch = 0;
105  static char* nextchar = NULL;
106 
107  if (nextchar == NULL || *nextchar == '\0')
108  {
109  if (optind == 0)
110  {
111  optind++;
112  }
113 
114  if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
115  {
116  optarg = NULL;
117  if (optind < argc)
118  {
119  optarg = argv[optind];
120  }
121  return EOF;
122  }
123 
124  nextchar = argv[optind];
125  if (strncmp(argv[optind], "--", 2) == 0)
126  {
127  parse_long_mismatch = 1;
128  nextchar += strlen("--");
129  optarg = NULL;
130  if (optind < argc)
131  {
132  optarg = argv[optind];
133  }
134  }
135  else
136  {
137  nextchar += strlen("-");
138  }
139 
140  optind++;
141  }
142 
143  // Parse long option string
144  for (i = 0; longopts != NULL && longopts[i].name != NULL; i++)
145  {
146  size_t optlen = strlen(longopts[i].name);
147  if (strncmp(nextchar, longopts[i].name, optlen) == 0)
148  {
149  nextchar += optlen;
150  switch (longopts[i].has_arg)
151  {
152  case 0:
153  if (*nextchar != '\0' || (optind < argc && argv[optind][0] != '-'))
154  {
155  optind++;
156  return '?';
157  }
158  else
159  {
160  optind++;
161  return longopts[i].flag == NULL ? longopts[i].val : 0;
162  }
163  case 1:
164  if (*nextchar == '=')
165  {
166  optarg = nextchar + 1;
167  optind++;
168  return longopts[i].flag == NULL ? longopts[i].val : 0;
169  }
170  else if (*nextchar != '\0' || (optind < argc && argv[optind][0] == '-'))
171  {
172  optind++;
173  return '?';
174  }
175  else if (optind < argc)
176  {
177  optarg = argv[optind];
178  optind++;
179  return longopts[i].flag == NULL ? longopts[i].val : 0;
180  }
181  else
182  {
183  return '?';
184  }
185  case 2:
186  if (*nextchar == '=')
187  {
188  optarg = nextchar + 1;
189  }
190  else if (*nextchar == '\0' || (optind < argc && argv[optind][0] == '-'))
191  {
192  optarg = NULL;
193  }
194  else
195  {
196  if (*nextchar == '\0' && optind < argc)
197  {
198  optarg = argv[optind];
199  }
200  }
201  optind++;
202  return longopts[i].flag == NULL ? longopts[i].val : 0;
203  default:
204  return '?';
205  }
206  }
207  }
208 
209  if (parse_long_mismatch)
210  {
211  return '?';
212  }
213 
214  // Parse short option string
215  char c = *nextchar++;
216  char* cp = strchr(optstring, c);
217  optopt = (int)c;
218  if (cp == NULL || c == ':')
219  {
220  return '?';
221  }
222 
223  cp++;
224  // Whether there is any argument
225  if (*cp == ':')
226  {
227  if (*nextchar != '\0')
228  {
229  optarg = nextchar;
230  nextchar = NULL; // for next invocation
231  }
232  else if (optind < argc)
233  {
234  optarg = argv[optind];
235  optind++;
236  }
237  else
238  {
239  return '?';
240  }
241  }
242 
243  return c;
244 }
int getopt(int argc, char *argv[], const char *optstring)
int optopt
int optind
char * optarg
int opterr
int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex)
int * flag
const char * name