xref: /openbmc/linux/tools/power/acpi/common/getopt.c (revision bc05aa6e)
1 /******************************************************************************
2  *
3  * Module Name: getopt
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2018, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 /*
45  * ACPICA getopt() implementation
46  *
47  * Option strings:
48  *    "f"       - Option has no arguments
49  *    "f:"      - Option requires an argument
50  *    "f+"      - Option has an optional argument
51  *    "f^"      - Option has optional single-char sub-options
52  *    "f|"      - Option has required single-char sub-options
53  */
54 
55 #include <acpi/acpi.h>
56 #include "accommon.h"
57 #include "acapps.h"
58 
59 #define ACPI_OPTION_ERROR(msg, badchar) \
60 	if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);}
61 
62 int acpi_gbl_opterr = 1;
63 int acpi_gbl_optind = 1;
64 int acpi_gbl_sub_opt_char = 0;
65 char *acpi_gbl_optarg;
66 
67 static int current_char_ptr = 1;
68 
69 /*******************************************************************************
70  *
71  * FUNCTION:    acpi_getopt_argument
72  *
73  * PARAMETERS:  argc, argv          - from main
74  *
75  * RETURN:      0 if an argument was found, -1 otherwise. Sets acpi_gbl_Optarg
76  *              to point to the next argument.
77  *
78  * DESCRIPTION: Get the next argument. Used to obtain arguments for the
79  *              two-character options after the original call to acpi_getopt.
80  *              Note: Either the argument starts at the next character after
81  *              the option, or it is pointed to by the next argv entry.
82  *              (After call to acpi_getopt, we need to backup to the previous
83  *              argv entry).
84  *
85  ******************************************************************************/
86 
87 int acpi_getopt_argument(int argc, char **argv)
88 {
89 
90 	acpi_gbl_optind--;
91 	current_char_ptr++;
92 
93 	if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
94 		acpi_gbl_optarg =
95 		    &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)];
96 	} else if (++acpi_gbl_optind >= argc) {
97 		ACPI_OPTION_ERROR("\nOption requires an argument", 0);
98 
99 		current_char_ptr = 1;
100 		return (-1);
101 	} else {
102 		acpi_gbl_optarg = argv[acpi_gbl_optind++];
103 	}
104 
105 	current_char_ptr = 1;
106 	return (0);
107 }
108 
109 /*******************************************************************************
110  *
111  * FUNCTION:    acpi_getopt
112  *
113  * PARAMETERS:  argc, argv          - from main
114  *              opts                - options info list
115  *
116  * RETURN:      Option character or ACPI_OPT_END
117  *
118  * DESCRIPTION: Get the next option
119  *
120  ******************************************************************************/
121 
122 int acpi_getopt(int argc, char **argv, char *opts)
123 {
124 	int current_char;
125 	char *opts_ptr;
126 
127 	if (current_char_ptr == 1) {
128 		if (acpi_gbl_optind >= argc ||
129 		    argv[acpi_gbl_optind][0] != '-' ||
130 		    argv[acpi_gbl_optind][1] == '\0') {
131 			return (ACPI_OPT_END);
132 		} else if (strcmp(argv[acpi_gbl_optind], "--") == 0) {
133 			acpi_gbl_optind++;
134 			return (ACPI_OPT_END);
135 		}
136 	}
137 
138 	/* Get the option */
139 
140 	current_char = argv[acpi_gbl_optind][current_char_ptr];
141 
142 	/* Make sure that the option is legal */
143 
144 	if (current_char == ':' ||
145 	    (opts_ptr = strchr(opts, current_char)) == NULL) {
146 		ACPI_OPTION_ERROR("Illegal option: -", current_char);
147 
148 		if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') {
149 			acpi_gbl_optind++;
150 			current_char_ptr = 1;
151 		}
152 
153 		return ('?');
154 	}
155 
156 	/* Option requires an argument? */
157 
158 	if (*++opts_ptr == ':') {
159 		if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
160 			acpi_gbl_optarg =
161 			    &argv[acpi_gbl_optind++][(int)
162 						     (current_char_ptr + 1)];
163 		} else if (++acpi_gbl_optind >= argc) {
164 			ACPI_OPTION_ERROR("Option requires an argument: -",
165 					  current_char);
166 
167 			current_char_ptr = 1;
168 			return ('?');
169 		} else {
170 			acpi_gbl_optarg = argv[acpi_gbl_optind++];
171 		}
172 
173 		current_char_ptr = 1;
174 	}
175 
176 	/* Option has an optional argument? */
177 
178 	else if (*opts_ptr == '+') {
179 		if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
180 			acpi_gbl_optarg =
181 			    &argv[acpi_gbl_optind++][(int)
182 						     (current_char_ptr + 1)];
183 		} else if (++acpi_gbl_optind >= argc) {
184 			acpi_gbl_optarg = NULL;
185 		} else {
186 			acpi_gbl_optarg = argv[acpi_gbl_optind++];
187 		}
188 
189 		current_char_ptr = 1;
190 	}
191 
192 	/* Option has optional single-char arguments? */
193 
194 	else if (*opts_ptr == '^') {
195 		if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
196 			acpi_gbl_optarg =
197 			    &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)];
198 		} else {
199 			acpi_gbl_optarg = "^";
200 		}
201 
202 		acpi_gbl_sub_opt_char = acpi_gbl_optarg[0];
203 		acpi_gbl_optind++;
204 		current_char_ptr = 1;
205 	}
206 
207 	/* Option has a required single-char argument? */
208 
209 	else if (*opts_ptr == '|') {
210 		if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
211 			acpi_gbl_optarg =
212 			    &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)];
213 		} else {
214 			ACPI_OPTION_ERROR
215 			    ("Option requires a single-character suboption: -",
216 			     current_char);
217 
218 			current_char_ptr = 1;
219 			return ('?');
220 		}
221 
222 		acpi_gbl_sub_opt_char = acpi_gbl_optarg[0];
223 		acpi_gbl_optind++;
224 		current_char_ptr = 1;
225 	}
226 
227 	/* Option with no arguments */
228 
229 	else {
230 		if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') {
231 			current_char_ptr = 1;
232 			acpi_gbl_optind++;
233 		}
234 
235 		acpi_gbl_optarg = NULL;
236 	}
237 
238 	return (current_char);
239 }
240