1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
// SPDX-License-Identifier: GPL-2.0-only
/*
* getopt.c - a simple getopt(3) implementation. See getopt.h for explanation.
*
* Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
* Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*/
#define LOG_CATEGORY LOGC_CORE
#include <getopt.h>
#include <log.h>
#include <linux/string.h>
void getopt_init_state(struct getopt_state *gs)
{
gs->index = 1;
gs->arg_index = 1;
}
int __getopt(struct getopt_state *gs, int argc, char *const argv[],
const char *optstring, bool silent)
{
char curopt; /* current option character */
const char *curoptp; /* pointer to the current option in optstring */
while (1) {
log_debug("arg_index: %d index: %d\n", gs->arg_index,
gs->index);
/* `--` indicates the end of options */
if (gs->arg_index == 1 && argv[gs->index] &&
!strcmp(argv[gs->index], "--")) {
gs->index++;
return -1;
}
/* Out of arguments */
if (gs->index >= argc)
return -1;
/* Can't parse non-options */
if (*argv[gs->index] != '-')
return -1;
/* We have found an option */
curopt = argv[gs->index][gs->arg_index];
if (curopt)
break;
/*
* no more options in current argv[] element; try the next one
*/
gs->index++;
gs->arg_index = 1;
}
/* look up current option in optstring */
curoptp = strchr(optstring, curopt);
if (!curoptp) {
if (!silent)
printf("%s: invalid option -- %c\n", argv[0], curopt);
gs->opt = curopt;
gs->arg_index++;
return '?';
}
if (*(curoptp + 1) != ':') {
/* option with no argument. Just return it */
gs->arg = NULL;
gs->arg_index++;
return curopt;
}
if (*(curoptp + 1) && *(curoptp + 2) == ':') {
/* optional argument */
if (argv[gs->index][gs->arg_index + 1]) {
/* optional argument with directly following arg */
gs->arg = argv[gs->index++] + gs->arg_index + 1;
gs->arg_index = 1;
return curopt;
}
if (gs->index + 1 == argc) {
/* We are at the last argv[] element */
gs->arg = NULL;
gs->index++;
return curopt;
}
if (*argv[gs->index + 1] != '-') {
/*
* optional argument with arg in next argv[] element
*/
gs->index++;
gs->arg = argv[gs->index++];
gs->arg_index = 1;
return curopt;
}
/* no optional argument found */
gs->arg = NULL;
gs->arg_index = 1;
gs->index++;
return curopt;
}
if (argv[gs->index][gs->arg_index + 1]) {
/* required argument with directly following arg */
gs->arg = argv[gs->index++] + gs->arg_index + 1;
gs->arg_index = 1;
return curopt;
}
gs->index++;
gs->arg_index = 1;
if (gs->index >= argc || argv[gs->index][0] == '-') {
if (!silent)
printf("option requires an argument -- %c\n", curopt);
gs->opt = curopt;
return ':';
}
gs->arg = argv[gs->index++];
return curopt;
}
|