xref: /rk3399_ARM-atf/tools/fiptool/win_posix.c (revision 7c9499623b42f1f48dd7aa0d1fa8427ca07a76b7)
1a1ee3836SEvan Lloyd /*
2*cb5c08b6SSami Mujawar  * Copyright (c) 2017 - 2020, Arm Limited and Contributors. All rights reserved.
3a1ee3836SEvan Lloyd  *
4a1ee3836SEvan Lloyd  * SPDX-License-Identifier: BSD-3-Clause
5a1ee3836SEvan Lloyd  */
6a1ee3836SEvan Lloyd 
7a1ee3836SEvan Lloyd #include <assert.h>
8a1ee3836SEvan Lloyd 
9a1ee3836SEvan Lloyd #include "win_posix.h"
10a1ee3836SEvan Lloyd 
11a1ee3836SEvan Lloyd /*
12a1ee3836SEvan Lloyd  * This variable is set by getopt to the index of the next element of the
13a1ee3836SEvan Lloyd  * argv array to be processed. Once getopt has found all of the option
14a1ee3836SEvan Lloyd  * arguments, you can use this variable to determine where the remaining
15a1ee3836SEvan Lloyd  * non-option arguments begin. The initial value of this variable is 1.
16a1ee3836SEvan Lloyd  */
17a1ee3836SEvan Lloyd int optind = 1;
18a1ee3836SEvan Lloyd 
19a1ee3836SEvan Lloyd /*
20a1ee3836SEvan Lloyd  * If the value of this variable is nonzero, then getopt prints an error
21a1ee3836SEvan Lloyd  * message to the standard error stream if it encounters an unknown option
22a1ee3836SEvan Lloyd  * default character or an option with a missing required argument.
23a1ee3836SEvan Lloyd  * If you set this variable to zero, getopt does not print any messages,
24a1ee3836SEvan Lloyd  * but it still returns the character ? to indicate an error.
25a1ee3836SEvan Lloyd  */
26a1ee3836SEvan Lloyd const int opterr; /* = 0; */
27a1ee3836SEvan Lloyd /* const because we do not implement error printing.*/
28a1ee3836SEvan Lloyd /* Not initialised to conform with the coding standard. */
29a1ee3836SEvan Lloyd 
30a1ee3836SEvan Lloyd /*
31a1ee3836SEvan Lloyd  * When getopt encounters an unknown option character or an option with a
32a1ee3836SEvan Lloyd  * missing required argument, it stores that option character in this
33a1ee3836SEvan Lloyd  * variable.
34a1ee3836SEvan Lloyd  */
35a1ee3836SEvan Lloyd int optopt;	/* = 0; */
36a1ee3836SEvan Lloyd 
37a1ee3836SEvan Lloyd /*
38a1ee3836SEvan Lloyd  * This variable is set by getopt to point at the value of the option
39a1ee3836SEvan Lloyd  * argument, for those options that accept arguments.
40a1ee3836SEvan Lloyd  */
41a1ee3836SEvan Lloyd char *optarg;	/* = 0; */
42a1ee3836SEvan Lloyd 
43a1ee3836SEvan Lloyd enum return_flags {
44a1ee3836SEvan Lloyd 	RET_ERROR = -1,
45a1ee3836SEvan Lloyd 	RET_END_OPT_LIST = -1,
46a1ee3836SEvan Lloyd 	RET_NO_PARAM = '?',
47a1ee3836SEvan Lloyd 	RET_NO_PARAM2 = ':',
48a1ee3836SEvan Lloyd 	RET_UNKNOWN_OPT = '?'
49a1ee3836SEvan Lloyd };
50a1ee3836SEvan Lloyd 
51a1ee3836SEvan Lloyd /*
52a1ee3836SEvan Lloyd  * Common initialisation on entry.
53a1ee3836SEvan Lloyd  */
54a1ee3836SEvan Lloyd static
getopt_init(void)55a1ee3836SEvan Lloyd void getopt_init(void)
56a1ee3836SEvan Lloyd {
57a1ee3836SEvan Lloyd 	optarg = (char *)0;
58a1ee3836SEvan Lloyd 	optopt = 0;
59a1ee3836SEvan Lloyd 	/* optind may be zero with some POSIX uses.
60a1ee3836SEvan Lloyd 	 * For our purposes we just change it to 1.
61a1ee3836SEvan Lloyd 	 */
62a1ee3836SEvan Lloyd 	if (optind == 0)
63a1ee3836SEvan Lloyd 		optind = 1;
64a1ee3836SEvan Lloyd }
65a1ee3836SEvan Lloyd 
66a1ee3836SEvan Lloyd /*
67a1ee3836SEvan Lloyd  * Common handling for a single letter option.
68a1ee3836SEvan Lloyd  */
69a1ee3836SEvan Lloyd static
getopt_1char(int argc,char * const argv[],const char * const opstring,const int optchar)70a1ee3836SEvan Lloyd int getopt_1char(int argc,
71a1ee3836SEvan Lloyd 		 char *const argv[],
72a1ee3836SEvan Lloyd 		 const char *const opstring,
73a1ee3836SEvan Lloyd 		 const int optchar)
74a1ee3836SEvan Lloyd {
75a1ee3836SEvan Lloyd 	size_t nlen = (opstring == 0) ? 0 : strlen(opstring);
76a1ee3836SEvan Lloyd 	size_t loptn;
77a1ee3836SEvan Lloyd 
78a1ee3836SEvan Lloyd 	for (loptn = 0; loptn < nlen; loptn++) {
79a1ee3836SEvan Lloyd 		if (optchar == opstring[loptn]) {
80a1ee3836SEvan Lloyd 			if (opstring[loptn + 1] == ':') {
81a1ee3836SEvan Lloyd 				/* Option has argument */
82a1ee3836SEvan Lloyd 				if (optind < argc) {
83a1ee3836SEvan Lloyd 					/* Found argument. */
84a1ee3836SEvan Lloyd 					assert(argv != 0);
85a1ee3836SEvan Lloyd 					optind++;
86a1ee3836SEvan Lloyd 					optarg = argv[optind++];
87a1ee3836SEvan Lloyd 					return optchar;
88a1ee3836SEvan Lloyd 				}
89a1ee3836SEvan Lloyd 				/* Missing argument. */
90a1ee3836SEvan Lloyd 				if (opstring[loptn + 2] == ':') {
91a1ee3836SEvan Lloyd 					/* OK if optional "x::". */
92a1ee3836SEvan Lloyd 					optind++;
93a1ee3836SEvan Lloyd 					return optchar;
94a1ee3836SEvan Lloyd 				}
95a1ee3836SEvan Lloyd 				/* Actual missing value. */
96a1ee3836SEvan Lloyd 				optopt = optchar;
97a1ee3836SEvan Lloyd 				return ((opstring[0] == ':')
98a1ee3836SEvan Lloyd 					? RET_NO_PARAM2
99a1ee3836SEvan Lloyd 					: RET_NO_PARAM);
100a1ee3836SEvan Lloyd 			}
101a1ee3836SEvan Lloyd 			/* No argument, just return option char */
102a1ee3836SEvan Lloyd 			optind++;
103a1ee3836SEvan Lloyd 			return optchar;
104a1ee3836SEvan Lloyd 		}
105a1ee3836SEvan Lloyd 	}
106a1ee3836SEvan Lloyd 	/*
107a1ee3836SEvan Lloyd 	 * If getopt finds an option character in argv that was not included in
108a1ee3836SEvan Lloyd 	 * options, ... it returns '?' and sets the external variable optopt to
109a1ee3836SEvan Lloyd 	 * the actual option character.
110a1ee3836SEvan Lloyd 	 */
111a1ee3836SEvan Lloyd 	optopt = optchar;
112a1ee3836SEvan Lloyd 	return RET_UNKNOWN_OPT;
113a1ee3836SEvan Lloyd }
114a1ee3836SEvan Lloyd 
getopt(int argc,char * argv[],char * opstring)115a1ee3836SEvan Lloyd int getopt(int argc,
116a1ee3836SEvan Lloyd 	   char *argv[],
117a1ee3836SEvan Lloyd 	   char *opstring)
118a1ee3836SEvan Lloyd {
119a1ee3836SEvan Lloyd 	int result = RET_END_OPT_LIST;
120a1ee3836SEvan Lloyd 	size_t argn = 0;
121a1ee3836SEvan Lloyd 	size_t nlen = strlen(opstring);
122a1ee3836SEvan Lloyd 
123a1ee3836SEvan Lloyd 	getopt_init();
124a1ee3836SEvan Lloyd 	/* If we have an argument left to play with */
125a1ee3836SEvan Lloyd 	if ((argc > optind) && (argv != 0)) {
126a1ee3836SEvan Lloyd 		const char *arg = (const char *)argv[optind];
127a1ee3836SEvan Lloyd 
128a1ee3836SEvan Lloyd 		if ((arg != 0) && (arg[0] == '-'))
129a1ee3836SEvan Lloyd 			result = getopt_1char(argc, argv, opstring, arg[1]);
130a1ee3836SEvan Lloyd 	}
131a1ee3836SEvan Lloyd 
132a1ee3836SEvan Lloyd 	return result;
133a1ee3836SEvan Lloyd }
134a1ee3836SEvan Lloyd 
135a1ee3836SEvan Lloyd /*
136a1ee3836SEvan Lloyd  * Match an argument value against an option name.
137a1ee3836SEvan Lloyd  * Note that we only match over the shorter length of the pair, to allow
138a1ee3836SEvan Lloyd  * for abbreviation or say --match=value
139a1ee3836SEvan Lloyd  * Long option names may be abbreviated if the abbreviation is unique or an
140*cb5c08b6SSami Mujawar  * exact match for some defined option. This function does not check that the
141*cb5c08b6SSami Mujawar  * abbreviations are unique and should be handled by the caller.
142a1ee3836SEvan Lloyd  * A long option may take a parameter, of the form --opt=param or --opt param.
143a1ee3836SEvan Lloyd */
144a1ee3836SEvan Lloyd static
optmatch(const char * argval,const char * optname)145a1ee3836SEvan Lloyd int optmatch(const char *argval, const char *optname)
146a1ee3836SEvan Lloyd {
147a1ee3836SEvan Lloyd 	int result = 0;
148a1ee3836SEvan Lloyd 
149a1ee3836SEvan Lloyd 	while ((result == 0) && (*optname != 0) && (*argval != 0))
150a1ee3836SEvan Lloyd 		result = (*argval++) - (*optname++);
151a1ee3836SEvan Lloyd 	return result;
152a1ee3836SEvan Lloyd }
153a1ee3836SEvan Lloyd 
154a1ee3836SEvan Lloyd /* Handling for a single long option. */
155a1ee3836SEvan Lloyd static
getopt_1long(const int argc,char * const argv[],const struct option * const longopts,const char * const optname,int * const indexptr)156a1ee3836SEvan Lloyd int getopt_1long(const int argc,
157a1ee3836SEvan Lloyd 		 char *const argv[],
158a1ee3836SEvan Lloyd 		 const struct option *const longopts,
159a1ee3836SEvan Lloyd 		 const char *const optname,
160a1ee3836SEvan Lloyd 		 int *const indexptr)
161a1ee3836SEvan Lloyd {
162a1ee3836SEvan Lloyd 	int result = RET_UNKNOWN_OPT;
163a1ee3836SEvan Lloyd 	size_t loptn = 0;
164*cb5c08b6SSami Mujawar 	bool match_found = false;
165a1ee3836SEvan Lloyd 
166*cb5c08b6SSami Mujawar 	/*
167*cb5c08b6SSami Mujawar 	 * Long option names may be abbreviated if the abbreviation
168*cb5c08b6SSami Mujawar 	 * is unique or an exact match for some defined option.
169*cb5c08b6SSami Mujawar 	 * To handle this:
170*cb5c08b6SSami Mujawar 	 * - First search for an exact match.
171*cb5c08b6SSami Mujawar 	 * - If exact match was not found search for a abbreviated match.
172*cb5c08b6SSami Mujawar 	 * By doing this an incorrect option selection can be avoided.
173*cb5c08b6SSami Mujawar 	 */
174*cb5c08b6SSami Mujawar 
175*cb5c08b6SSami Mujawar 	/* 1. Search for an exact match. */
176*cb5c08b6SSami Mujawar 	while (longopts[loptn].name != NULL) {
177*cb5c08b6SSami Mujawar 		if (strcmp(optname, longopts[loptn].name) == 0) {
178*cb5c08b6SSami Mujawar 			match_found = true;
179*cb5c08b6SSami Mujawar 			break;
180*cb5c08b6SSami Mujawar 		}
181*cb5c08b6SSami Mujawar 		++loptn;
182*cb5c08b6SSami Mujawar 	}
183*cb5c08b6SSami Mujawar 
184*cb5c08b6SSami Mujawar 	/* 2. If exact match was not found search for a abbreviated match. */
185*cb5c08b6SSami Mujawar 	if (!match_found) {
186*cb5c08b6SSami Mujawar 		loptn = 0;
187*cb5c08b6SSami Mujawar 		while (longopts[loptn].name != NULL) {
188a1ee3836SEvan Lloyd 			if (optmatch(optname, longopts[loptn].name) == 0) {
189*cb5c08b6SSami Mujawar 				match_found = true;
190*cb5c08b6SSami Mujawar 				break;
191*cb5c08b6SSami Mujawar 			}
192*cb5c08b6SSami Mujawar 			++loptn;
193*cb5c08b6SSami Mujawar 		}
194*cb5c08b6SSami Mujawar 	}
195*cb5c08b6SSami Mujawar 
196*cb5c08b6SSami Mujawar 	if (match_found) {
197a1ee3836SEvan Lloyd 		/* We found a match. */
198a1ee3836SEvan Lloyd 		result = longopts[loptn].val;
199*cb5c08b6SSami Mujawar 		if (indexptr != 0) {
200a1ee3836SEvan Lloyd 			*indexptr = loptn;
201*cb5c08b6SSami Mujawar 		}
202a1ee3836SEvan Lloyd 		switch (longopts[loptn].has_arg) {
203a1ee3836SEvan Lloyd 		case required_argument:
204a1ee3836SEvan Lloyd 			if ((optind + 1) >= argc) {
205a1ee3836SEvan Lloyd 				/* Missing argument. */
206a1ee3836SEvan Lloyd 				optopt = result;
207a1ee3836SEvan Lloyd 				return RET_NO_PARAM;
208a1ee3836SEvan Lloyd 			}
209a1ee3836SEvan Lloyd 			/* Fallthrough to get option value. */
210a1ee3836SEvan Lloyd 
211a1ee3836SEvan Lloyd 		case optional_argument:
212a1ee3836SEvan Lloyd 			if ((argc - optind) > 0) {
213a1ee3836SEvan Lloyd 				/* Found argument. */
214a1ee3836SEvan Lloyd 				optarg = argv[++optind];
215a1ee3836SEvan Lloyd 			}
216a1ee3836SEvan Lloyd 			/* Fallthrough to handle flag. */
217a1ee3836SEvan Lloyd 
218a1ee3836SEvan Lloyd 		case no_argument:
219a1ee3836SEvan Lloyd 			optind++;
220a1ee3836SEvan Lloyd 			if (longopts[loptn].flag != 0) {
221a1ee3836SEvan Lloyd 				*longopts[loptn].flag = result;
222a1ee3836SEvan Lloyd 				result = 0;
223a1ee3836SEvan Lloyd 			}
224a1ee3836SEvan Lloyd 			break;
225a1ee3836SEvan Lloyd 
226a1ee3836SEvan Lloyd 		}
227a1ee3836SEvan Lloyd 		return result;
228a1ee3836SEvan Lloyd 	}
229*cb5c08b6SSami Mujawar 
230a1ee3836SEvan Lloyd 	/*
231a1ee3836SEvan Lloyd 	 * If getopt finds an option character in argv that was not included
232a1ee3836SEvan Lloyd 	 * in options, ... it returns '?' and sets the external variable
233a1ee3836SEvan Lloyd 	 * optopt to the actual option character.
234a1ee3836SEvan Lloyd 	 */
235a1ee3836SEvan Lloyd 	return RET_UNKNOWN_OPT;
236a1ee3836SEvan Lloyd }
237a1ee3836SEvan Lloyd 
238a1ee3836SEvan Lloyd /*
239a1ee3836SEvan Lloyd  * getopt_long gets the next option argument from the argument list
240a1ee3836SEvan Lloyd  * specified by the argv and argc arguments.  Options may be either short
241a1ee3836SEvan Lloyd  * (single letter) as for getopt, or longer names (preceded by --).
242a1ee3836SEvan Lloyd  */
getopt_long(int argc,char * argv[],const char * shortopts,const struct option * longopts,int * indexptr)243a1ee3836SEvan Lloyd int getopt_long(int argc,
244a1ee3836SEvan Lloyd 		char *argv[],
245a1ee3836SEvan Lloyd 		const char *shortopts,
246a1ee3836SEvan Lloyd 		const struct option *longopts,
247a1ee3836SEvan Lloyd 		int *indexptr)
248a1ee3836SEvan Lloyd {
249a1ee3836SEvan Lloyd 	int result = RET_END_OPT_LIST;
250a1ee3836SEvan Lloyd 
251a1ee3836SEvan Lloyd 	getopt_init();
252a1ee3836SEvan Lloyd 	/* If we have an argument left to play with */
253a1ee3836SEvan Lloyd 	if ((argc > optind) && (argv != 0)) {
254a1ee3836SEvan Lloyd 		const char *arg = argv[optind];
255a1ee3836SEvan Lloyd 
256a1ee3836SEvan Lloyd 		if ((arg != 0) && (arg[0] == '-')) {
257a1ee3836SEvan Lloyd 			if (arg[1] == '-') {
258a1ee3836SEvan Lloyd 				/* Looks like a long option. */
259a1ee3836SEvan Lloyd 				result = getopt_1long(argc,
260a1ee3836SEvan Lloyd 						      argv,
261a1ee3836SEvan Lloyd 						      longopts,
262a1ee3836SEvan Lloyd 						      &arg[2],
263a1ee3836SEvan Lloyd 						      indexptr);
264a1ee3836SEvan Lloyd 			} else {
265a1ee3836SEvan Lloyd 				result = getopt_1char(argc,
266a1ee3836SEvan Lloyd 						      argv,
267a1ee3836SEvan Lloyd 						      shortopts,
268a1ee3836SEvan Lloyd 						      arg[1]);
269a1ee3836SEvan Lloyd 			}
270a1ee3836SEvan Lloyd 		}
271a1ee3836SEvan Lloyd 	}
272a1ee3836SEvan Lloyd 	return result;
273a1ee3836SEvan Lloyd }
274a1ee3836SEvan Lloyd 
275a1ee3836SEvan Lloyd /*
276a1ee3836SEvan Lloyd  * getopt_long_only gets the next option argument from the argument list
277a1ee3836SEvan Lloyd  * specified by the argv and argc arguments.  Options may be either short
278a1ee3836SEvan Lloyd  * or long as for getopt_long, but the long names may have a single '-'
279a1ee3836SEvan Lloyd  * prefix too.
280a1ee3836SEvan Lloyd  */
getopt_long_only(int argc,char * argv[],const char * shortopts,const struct option * longopts,int * indexptr)281a1ee3836SEvan Lloyd int getopt_long_only(int argc,
282a1ee3836SEvan Lloyd 		     char *argv[],
283a1ee3836SEvan Lloyd 		     const char *shortopts,
284a1ee3836SEvan Lloyd 		     const struct option *longopts,
285a1ee3836SEvan Lloyd 		     int *indexptr)
286a1ee3836SEvan Lloyd {
287a1ee3836SEvan Lloyd 	int result = RET_END_OPT_LIST;
288a1ee3836SEvan Lloyd 
289a1ee3836SEvan Lloyd 	getopt_init();
290a1ee3836SEvan Lloyd 	/* If we have an argument left to play with */
291a1ee3836SEvan Lloyd 	if ((argc > optind) && (argv != 0)) {
292a1ee3836SEvan Lloyd 		const char *arg = argv[optind];
293a1ee3836SEvan Lloyd 
294a1ee3836SEvan Lloyd 		if ((arg != 0) && (arg[0] == '-')) {
295a1ee3836SEvan Lloyd 			if (arg[1] == '-') {
296a1ee3836SEvan Lloyd 				/* Looks like a long option. */
297a1ee3836SEvan Lloyd 				result = getopt_1long(argc,
298a1ee3836SEvan Lloyd 						      argv,
299a1ee3836SEvan Lloyd 						      longopts,
300a1ee3836SEvan Lloyd 						      &arg[2],
301a1ee3836SEvan Lloyd 						      indexptr);
302a1ee3836SEvan Lloyd 			} else {
303a1ee3836SEvan Lloyd 				result = getopt_1long(argc,
304a1ee3836SEvan Lloyd 						      argv,
305a1ee3836SEvan Lloyd 						      longopts,
306a1ee3836SEvan Lloyd 						      &arg[1],
307a1ee3836SEvan Lloyd 						      indexptr);
308a1ee3836SEvan Lloyd 				if (result == RET_UNKNOWN_OPT) {
309a1ee3836SEvan Lloyd 					result = getopt_1char(argc,
310a1ee3836SEvan Lloyd 							      argv,
311a1ee3836SEvan Lloyd 							      shortopts,
312a1ee3836SEvan Lloyd 							      arg[1]);
313a1ee3836SEvan Lloyd 				}
314a1ee3836SEvan Lloyd 			}
315a1ee3836SEvan Lloyd 		}
316a1ee3836SEvan Lloyd 	}
317a1ee3836SEvan Lloyd 	return result;
318a1ee3836SEvan Lloyd }
319