GNU Linux-libre 6.9.1-gnu
[releases.git] / tools / power / acpi / common / getopt.c
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 }