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