xref: /dpdk/app/test-eventdev/parser.c (revision 25d11a86c56d50947af33d0b79ede622809bd8b9)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2016 Intel Corporation. All rights reserved.
5  *   Copyright(c) 2017 Cavium, Inc. All rights reserved.
6  *   All rights reserved.
7  *
8  *   Redistribution and use in source and binary forms, with or without
9  *   modification, are permitted provided that the following conditions
10  *   are met:
11  *
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *     * Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in
16  *       the documentation and/or other materials provided with the
17  *       distribution.
18  *     * Neither the name of Intel Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <ctype.h>
39 #include <getopt.h>
40 #include <errno.h>
41 #include <stdarg.h>
42 #include <string.h>
43 #include <libgen.h>
44 #include <unistd.h>
45 #include <sys/wait.h>
46 #include <stdbool.h>
47 
48 #include <rte_errno.h>
49 #include <rte_string_fns.h>
50 
51 #include "parser.h"
52 
53 static uint32_t
54 get_hex_val(char c)
55 {
56 	switch (c) {
57 	case '0': case '1': case '2': case '3': case '4': case '5':
58 	case '6': case '7': case '8': case '9':
59 		return c - '0';
60 	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
61 		return c - 'A' + 10;
62 	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
63 		return c - 'a' + 10;
64 	default:
65 		return 0;
66 	}
67 }
68 
69 int
70 parser_read_arg_bool(const char *p)
71 {
72 	p = skip_white_spaces(p);
73 	int result = -EINVAL;
74 
75 	if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
76 		((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
77 		p += 3;
78 		result = 1;
79 	}
80 
81 	if (((p[0] == 'o') && (p[1] == 'n')) ||
82 		((p[0] == 'O') && (p[1] == 'N'))) {
83 		p += 2;
84 		result = 1;
85 	}
86 
87 	if (((p[0] == 'n') && (p[1] == 'o')) ||
88 		((p[0] == 'N') && (p[1] == 'O'))) {
89 		p += 2;
90 		result = 0;
91 	}
92 
93 	if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
94 		((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
95 		p += 3;
96 		result = 0;
97 	}
98 
99 	p = skip_white_spaces(p);
100 
101 	if (p[0] != '\0')
102 		return -EINVAL;
103 
104 	return result;
105 }
106 
107 int
108 parser_read_uint64(uint64_t *value, const char *p)
109 {
110 	char *next;
111 	uint64_t val;
112 
113 	p = skip_white_spaces(p);
114 	if (!isdigit(*p))
115 		return -EINVAL;
116 
117 	val = strtoul(p, &next, 10);
118 	if (p == next)
119 		return -EINVAL;
120 
121 	p = next;
122 	switch (*p) {
123 	case 'T':
124 		val *= 1024ULL;
125 		/* fall through */
126 	case 'G':
127 		val *= 1024ULL;
128 		/* fall through */
129 	case 'M':
130 		val *= 1024ULL;
131 		/* fall through */
132 	case 'k':
133 	case 'K':
134 		val *= 1024ULL;
135 		p++;
136 		break;
137 	}
138 
139 	p = skip_white_spaces(p);
140 	if (*p != '\0')
141 		return -EINVAL;
142 
143 	*value = val;
144 	return 0;
145 }
146 
147 int
148 parser_read_int32(int32_t *value, const char *p)
149 {
150 	char *next;
151 	int32_t val;
152 
153 	p = skip_white_spaces(p);
154 	if (!isdigit(*p))
155 		return -EINVAL;
156 
157 	val = strtol(p, &next, 10);
158 	if (p == next)
159 		return -EINVAL;
160 
161 	*value = val;
162 	return 0;
163 }
164 
165 int
166 parser_read_uint64_hex(uint64_t *value, const char *p)
167 {
168 	char *next;
169 	uint64_t val;
170 
171 	p = skip_white_spaces(p);
172 
173 	val = strtoul(p, &next, 16);
174 	if (p == next)
175 		return -EINVAL;
176 
177 	p = skip_white_spaces(next);
178 	if (*p != '\0')
179 		return -EINVAL;
180 
181 	*value = val;
182 	return 0;
183 }
184 
185 int
186 parser_read_uint32(uint32_t *value, const char *p)
187 {
188 	uint64_t val = 0;
189 	int ret = parser_read_uint64(&val, p);
190 
191 	if (ret < 0)
192 		return ret;
193 
194 	if (val > UINT32_MAX)
195 		return -ERANGE;
196 
197 	*value = val;
198 	return 0;
199 }
200 
201 int
202 parser_read_uint32_hex(uint32_t *value, const char *p)
203 {
204 	uint64_t val = 0;
205 	int ret = parser_read_uint64_hex(&val, p);
206 
207 	if (ret < 0)
208 		return ret;
209 
210 	if (val > UINT32_MAX)
211 		return -ERANGE;
212 
213 	*value = val;
214 	return 0;
215 }
216 
217 int
218 parser_read_uint16(uint16_t *value, const char *p)
219 {
220 	uint64_t val = 0;
221 	int ret = parser_read_uint64(&val, p);
222 
223 	if (ret < 0)
224 		return ret;
225 
226 	if (val > UINT16_MAX)
227 		return -ERANGE;
228 
229 	*value = val;
230 	return 0;
231 }
232 
233 int
234 parser_read_uint16_hex(uint16_t *value, const char *p)
235 {
236 	uint64_t val = 0;
237 	int ret = parser_read_uint64_hex(&val, p);
238 
239 	if (ret < 0)
240 		return ret;
241 
242 	if (val > UINT16_MAX)
243 		return -ERANGE;
244 
245 	*value = val;
246 	return 0;
247 }
248 
249 int
250 parser_read_uint8(uint8_t *value, const char *p)
251 {
252 	uint64_t val = 0;
253 	int ret = parser_read_uint64(&val, p);
254 
255 	if (ret < 0)
256 		return ret;
257 
258 	if (val > UINT8_MAX)
259 		return -ERANGE;
260 
261 	*value = val;
262 	return 0;
263 }
264 
265 int
266 parser_read_uint8_hex(uint8_t *value, const char *p)
267 {
268 	uint64_t val = 0;
269 	int ret = parser_read_uint64_hex(&val, p);
270 
271 	if (ret < 0)
272 		return ret;
273 
274 	if (val > UINT8_MAX)
275 		return -ERANGE;
276 
277 	*value = val;
278 	return 0;
279 }
280 
281 int
282 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
283 {
284 	uint32_t i;
285 
286 	if ((string == NULL) ||
287 		(tokens == NULL) ||
288 		(*n_tokens < 1))
289 		return -EINVAL;
290 
291 	for (i = 0; i < *n_tokens; i++) {
292 		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
293 		if (tokens[i] == NULL)
294 			break;
295 	}
296 
297 	if ((i == *n_tokens) &&
298 		(strtok_r(string, PARSE_DELIMITER, &string) != NULL))
299 		return -E2BIG;
300 
301 	*n_tokens = i;
302 	return 0;
303 }
304 
305 int
306 parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
307 {
308 	char *c;
309 	uint32_t len, i;
310 
311 	/* Check input parameters */
312 	if ((src == NULL) ||
313 		(dst == NULL) ||
314 		(size == NULL) ||
315 		(*size == 0))
316 		return -1;
317 
318 	len = strlen(src);
319 	if (((len & 3) != 0) ||
320 		(len > (*size) * 2))
321 		return -1;
322 	*size = len / 2;
323 
324 	for (c = src; *c != 0; c++) {
325 		if ((((*c) >= '0') && ((*c) <= '9')) ||
326 			(((*c) >= 'A') && ((*c) <= 'F')) ||
327 			(((*c) >= 'a') && ((*c) <= 'f')))
328 			continue;
329 
330 		return -1;
331 	}
332 
333 	/* Convert chars to bytes */
334 	for (i = 0; i < *size; i++)
335 		dst[i] = get_hex_val(src[2 * i]) * 16 +
336 			get_hex_val(src[2 * i + 1]);
337 
338 	return 0;
339 }
340 
341 int
342 parse_lcores_list(bool lcores[], const char *corelist)
343 {
344 	int i, idx = 0;
345 	int min, max;
346 	char *end = NULL;
347 
348 	if (corelist == NULL)
349 		return -1;
350 	while (isblank(*corelist))
351 		corelist++;
352 	i = strlen(corelist);
353 	while ((i > 0) && isblank(corelist[i - 1]))
354 		i--;
355 
356 	/* Get list of lcores */
357 	min = RTE_MAX_LCORE;
358 	do {
359 		while (isblank(*corelist))
360 			corelist++;
361 		if (*corelist == '\0')
362 			return -1;
363 		idx = strtoul(corelist, &end, 10);
364 
365 		if (end == NULL)
366 			return -1;
367 		while (isblank(*end))
368 			end++;
369 		if (*end == '-') {
370 			min = idx;
371 		} else if ((*end == ',') || (*end == '\0')) {
372 			max = idx;
373 			if (min == RTE_MAX_LCORE)
374 				min = idx;
375 			for (idx = min; idx <= max; idx++) {
376 				if (lcores[idx] == 1)
377 					return -E2BIG;
378 				lcores[idx] = 1;
379 			}
380 
381 			min = RTE_MAX_LCORE;
382 		} else
383 			return -1;
384 		corelist = end + 1;
385 	} while (*end != '\0');
386 
387 	return 0;
388 }
389