1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: getopt |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | /* |
11 | * ACPICA getopt() implementation |
12 | * |
13 | * Option strings: |
14 | * "f" - Option has no arguments |
15 | * "f:" - Option requires an argument |
16 | * "f+" - Option has an optional argument |
17 | * "f^" - Option has optional single-char sub-options |
18 | * "f|" - Option has required single-char sub-options |
19 | */ |
20 | |
21 | #include <acpi/acpi.h> |
22 | #include "accommon.h" |
23 | #include "acapps.h" |
24 | |
25 | #define ACPI_OPTION_ERROR(msg, badchar) \ |
26 | if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);} |
27 | |
28 | int acpi_gbl_opterr = 1; |
29 | int acpi_gbl_optind = 1; |
30 | int acpi_gbl_sub_opt_char = 0; |
31 | char *acpi_gbl_optarg; |
32 | |
33 | static int current_char_ptr = 1; |
34 | |
35 | /******************************************************************************* |
36 | * |
37 | * FUNCTION: acpi_getopt_argument |
38 | * |
39 | * PARAMETERS: argc, argv - from main |
40 | * |
41 | * RETURN: 0 if an argument was found, -1 otherwise. Sets acpi_gbl_Optarg |
42 | * to point to the next argument. |
43 | * |
44 | * DESCRIPTION: Get the next argument. Used to obtain arguments for the |
45 | * two-character options after the original call to acpi_getopt. |
46 | * Note: Either the argument starts at the next character after |
47 | * the option, or it is pointed to by the next argv entry. |
48 | * (After call to acpi_getopt, we need to backup to the previous |
49 | * argv entry). |
50 | * |
51 | ******************************************************************************/ |
52 | |
53 | int acpi_getopt_argument(int argc, char **argv) |
54 | { |
55 | |
56 | acpi_gbl_optind--; |
57 | current_char_ptr++; |
58 | |
59 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { |
60 | acpi_gbl_optarg = |
61 | &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)]; |
62 | } else if (++acpi_gbl_optind >= argc) { |
63 | ACPI_OPTION_ERROR("\nOption requires an argument" , 0); |
64 | |
65 | current_char_ptr = 1; |
66 | return (-1); |
67 | } else { |
68 | acpi_gbl_optarg = argv[acpi_gbl_optind++]; |
69 | } |
70 | |
71 | current_char_ptr = 1; |
72 | return (0); |
73 | } |
74 | |
75 | /******************************************************************************* |
76 | * |
77 | * FUNCTION: acpi_getopt |
78 | * |
79 | * PARAMETERS: argc, argv - from main |
80 | * opts - options info list |
81 | * |
82 | * RETURN: Option character or ACPI_OPT_END |
83 | * |
84 | * DESCRIPTION: Get the next option |
85 | * |
86 | ******************************************************************************/ |
87 | |
88 | int acpi_getopt(int argc, char **argv, char *opts) |
89 | { |
90 | int current_char; |
91 | char *opts_ptr; |
92 | |
93 | if (current_char_ptr == 1) { |
94 | if (acpi_gbl_optind >= argc || |
95 | argv[acpi_gbl_optind][0] != '-' || |
96 | argv[acpi_gbl_optind][1] == '\0') { |
97 | return (ACPI_OPT_END); |
98 | } else if (strcmp(argv[acpi_gbl_optind], "--" ) == 0) { |
99 | acpi_gbl_optind++; |
100 | return (ACPI_OPT_END); |
101 | } |
102 | } |
103 | |
104 | /* Get the option */ |
105 | |
106 | current_char = argv[acpi_gbl_optind][current_char_ptr]; |
107 | |
108 | /* Make sure that the option is legal */ |
109 | |
110 | if (current_char == ':' || |
111 | (opts_ptr = strchr(opts, current_char)) == NULL) { |
112 | ACPI_OPTION_ERROR("Illegal option: -" , current_char); |
113 | |
114 | if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { |
115 | acpi_gbl_optind++; |
116 | current_char_ptr = 1; |
117 | } |
118 | |
119 | return ('?'); |
120 | } |
121 | |
122 | /* Option requires an argument? */ |
123 | |
124 | if (*++opts_ptr == ':') { |
125 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { |
126 | acpi_gbl_optarg = |
127 | &argv[acpi_gbl_optind++][(int) |
128 | (current_char_ptr + 1)]; |
129 | } else if (++acpi_gbl_optind >= argc) { |
130 | ACPI_OPTION_ERROR("Option requires an argument: -" , |
131 | current_char); |
132 | |
133 | current_char_ptr = 1; |
134 | return ('?'); |
135 | } else { |
136 | acpi_gbl_optarg = argv[acpi_gbl_optind++]; |
137 | } |
138 | |
139 | current_char_ptr = 1; |
140 | } |
141 | |
142 | /* Option has an optional argument? */ |
143 | |
144 | else if (*opts_ptr == '+') { |
145 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { |
146 | acpi_gbl_optarg = |
147 | &argv[acpi_gbl_optind++][(int) |
148 | (current_char_ptr + 1)]; |
149 | } else if (++acpi_gbl_optind >= argc) { |
150 | acpi_gbl_optarg = NULL; |
151 | } else { |
152 | acpi_gbl_optarg = argv[acpi_gbl_optind++]; |
153 | } |
154 | |
155 | current_char_ptr = 1; |
156 | } |
157 | |
158 | /* Option has optional single-char arguments? */ |
159 | |
160 | else if (*opts_ptr == '^') { |
161 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { |
162 | acpi_gbl_optarg = |
163 | &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; |
164 | } else { |
165 | acpi_gbl_optarg = "^" ; |
166 | } |
167 | |
168 | acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; |
169 | acpi_gbl_optind++; |
170 | current_char_ptr = 1; |
171 | } |
172 | |
173 | /* Option has a required single-char argument? */ |
174 | |
175 | else if (*opts_ptr == '|') { |
176 | if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { |
177 | acpi_gbl_optarg = |
178 | &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; |
179 | } else { |
180 | ACPI_OPTION_ERROR |
181 | ("Option requires a single-character suboption: -" , |
182 | current_char); |
183 | |
184 | current_char_ptr = 1; |
185 | return ('?'); |
186 | } |
187 | |
188 | acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; |
189 | acpi_gbl_optind++; |
190 | current_char_ptr = 1; |
191 | } |
192 | |
193 | /* Option with no arguments */ |
194 | |
195 | else { |
196 | if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { |
197 | current_char_ptr = 1; |
198 | acpi_gbl_optind++; |
199 | } |
200 | |
201 | acpi_gbl_optarg = NULL; |
202 | } |
203 | |
204 | return (current_char); |
205 | } |
206 | |