New upstream version 17.08
[deb_dpdk.git] / app / test-eventdev / parser.c
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 }