net/virtio: fix incorrect cast of void *
[dpdk.git] / cmdline / cmdline_parse_num.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation.
3  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4  * All rights reserved.
5  */
6
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <inttypes.h>
10 #include <ctype.h>
11 #include <string.h>
12 #include <stdarg.h>
13 #include <errno.h>
14 #include <rte_string_fns.h>
15
16 #include "cmdline_parse.h"
17 #include "cmdline_parse_num.h"
18
19 #ifdef RTE_LIBRTE_CMDLINE_DEBUG
20 #define debug_printf(args...) printf(args)
21 #else
22 #define debug_printf(args...) do {} while(0)
23 #endif
24
25 struct cmdline_token_ops cmdline_token_num_ops = {
26         .parse = cmdline_parse_num,
27         .complete_get_nb = NULL,
28         .complete_get_elt = NULL,
29         .get_help = cmdline_get_help_num,
30 };
31
32
33 enum num_parse_state_t {
34         START,
35         DEC_NEG,
36         BIN,
37         HEX,
38
39         ERROR,
40
41         FIRST_OK, /* not used */
42         ZERO_OK,
43         HEX_OK,
44         OCTAL_OK,
45         BIN_OK,
46         DEC_NEG_OK,
47         DEC_POS_OK,
48 };
49
50 /* Keep it sync with enum in .h */
51 static const char * num_help[] = {
52         "UINT8", "UINT16", "UINT32", "UINT64",
53         "INT8", "INT16", "INT32", "INT64",
54 };
55
56 static inline int
57 add_to_res(unsigned int c, uint64_t *res, unsigned int base)
58 {
59         /* overflow */
60         if ((UINT64_MAX - c) / base < *res)
61                 return -1;
62
63         *res = (uint64_t) (*res * base + c);
64         return 0;
65 }
66
67 static int
68 check_res_size(struct cmdline_token_num_data *nd, unsigned ressize)
69 {
70         switch (nd->type) {
71         case RTE_INT8:
72         case RTE_UINT8:
73                 if (ressize < sizeof(int8_t))
74                         return -1;
75                 break;
76         case RTE_INT16:
77         case RTE_UINT16:
78                 if (ressize < sizeof(int16_t))
79                         return -1;
80                 break;
81         case RTE_INT32:
82         case RTE_UINT32:
83                 if (ressize < sizeof(int32_t))
84                         return -1;
85                 break;
86         case RTE_INT64:
87         case RTE_UINT64:
88                 if (ressize < sizeof(int64_t))
89                         return -1;
90                 break;
91         default:
92                 return -1;
93         }
94         return 0;
95 }
96
97 /* parse an int */
98 int
99 cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res,
100         unsigned ressize)
101 {
102         struct cmdline_token_num_data nd;
103         enum num_parse_state_t st = START;
104         const char * buf;
105         char c;
106         uint64_t res1 = 0;
107
108         if (!tk)
109                 return -1;
110
111         if (!srcbuf || !*srcbuf)
112                 return -1;
113
114         buf = srcbuf;
115         c = *buf;
116
117         memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd));
118
119         /* check that we have enough room in res */
120         if (res) {
121                 if (check_res_size(&nd, ressize) < 0)
122                         return -1;
123         }
124
125         while (st != ERROR && c && !cmdline_isendoftoken(c)) {
126                 debug_printf("%c %x -> ", c, c);
127                 switch (st) {
128                 case START:
129                         if (c == '-') {
130                                 st = DEC_NEG;
131                         }
132                         else if (c == '0') {
133                                 st = ZERO_OK;
134                         }
135                         else if (c >= '1' && c <= '9') {
136                                 if (add_to_res(c - '0', &res1, 10) < 0)
137                                         st = ERROR;
138                                 else
139                                         st = DEC_POS_OK;
140                         }
141                         else  {
142                                 st = ERROR;
143                         }
144                         break;
145
146                 case ZERO_OK:
147                         if (c == 'x') {
148                                 st = HEX;
149                         }
150                         else if (c == 'b') {
151                                 st = BIN;
152                         }
153                         else if (c >= '0' && c <= '7') {
154                                 if (add_to_res(c - '0', &res1, 10) < 0)
155                                         st = ERROR;
156                                 else
157                                         st = OCTAL_OK;
158                         }
159                         else  {
160                                 st = ERROR;
161                         }
162                         break;
163
164                 case DEC_NEG:
165                         if (c >= '0' && c <= '9') {
166                                 if (add_to_res(c - '0', &res1, 10) < 0)
167                                         st = ERROR;
168                                 else
169                                         st = DEC_NEG_OK;
170                         }
171                         else {
172                                 st = ERROR;
173                         }
174                         break;
175
176                 case DEC_NEG_OK:
177                         if (c >= '0' && c <= '9') {
178                                 if (add_to_res(c - '0', &res1, 10) < 0)
179                                         st = ERROR;
180                         }
181                         else {
182                                 st = ERROR;
183                         }
184                         break;
185
186                 case DEC_POS_OK:
187                         if (c >= '0' && c <= '9') {
188                                 if (add_to_res(c - '0', &res1, 10) < 0)
189                                         st = ERROR;
190                         }
191                         else {
192                                 st = ERROR;
193                         }
194                         break;
195
196                 case HEX:
197                         st = HEX_OK;
198                         /* fall-through */
199                 case HEX_OK:
200                         if (c >= '0' && c <= '9') {
201                                 if (add_to_res(c - '0', &res1, 16) < 0)
202                                         st = ERROR;
203                         }
204                         else if (c >= 'a' && c <= 'f') {
205                                 if (add_to_res(c - 'a' + 10, &res1, 16) < 0)
206                                         st = ERROR;
207                         }
208                         else if (c >= 'A' && c <= 'F') {
209                                 if (add_to_res(c - 'A' + 10, &res1, 16) < 0)
210                                         st = ERROR;
211                         }
212                         else {
213                                 st = ERROR;
214                         }
215                         break;
216
217
218                 case OCTAL_OK:
219                         if (c >= '0' && c <= '7') {
220                                 if (add_to_res(c - '0', &res1, 8) < 0)
221                                         st = ERROR;
222                         }
223                         else {
224                                 st = ERROR;
225                         }
226                         break;
227
228                 case BIN:
229                         st = BIN_OK;
230                         /* fall-through */
231                 case BIN_OK:
232                         if (c >= '0' && c <= '1') {
233                                 if (add_to_res(c - '0', &res1, 2) < 0)
234                                         st = ERROR;
235                         }
236                         else {
237                                 st = ERROR;
238                         }
239                         break;
240                 default:
241                         debug_printf("not impl ");
242
243                 }
244
245                 debug_printf("(%"PRIu64")\n", res1);
246
247                 buf ++;
248                 c = *buf;
249
250                 /* token too long */
251                 if (buf-srcbuf > 127)
252                         return -1;
253         }
254
255         switch (st) {
256         case ZERO_OK:
257         case DEC_POS_OK:
258         case HEX_OK:
259         case OCTAL_OK:
260         case BIN_OK:
261                 if (nd.type == RTE_INT8 && res1 <= INT8_MAX) {
262                         if (res) *(int8_t *)res = (int8_t) res1;
263                         return buf-srcbuf;
264                 } else if (nd.type == RTE_INT16 && res1 <= INT16_MAX) {
265                         if (res) *(int16_t *)res = (int16_t) res1;
266                         return buf-srcbuf;
267                 } else if (nd.type == RTE_INT32 && res1 <= INT32_MAX) {
268                         if (res) *(int32_t *)res = (int32_t) res1;
269                         return buf-srcbuf;
270                 } else if (nd.type == RTE_INT64 && res1 <= INT64_MAX) {
271                         if (res) *(int64_t *)res = (int64_t) res1;
272                         return buf-srcbuf;
273                 } else if (nd.type == RTE_UINT8 && res1 <= UINT8_MAX) {
274                         if (res) *(uint8_t *)res = (uint8_t) res1;
275                         return buf-srcbuf;
276                 } else if (nd.type == RTE_UINT16  && res1 <= UINT16_MAX) {
277                         if (res) *(uint16_t *)res = (uint16_t) res1;
278                         return buf-srcbuf;
279                 } else if (nd.type == RTE_UINT32 && res1 <= UINT32_MAX) {
280                         if (res) *(uint32_t *)res = (uint32_t) res1;
281                         return buf-srcbuf;
282                 } else if (nd.type == RTE_UINT64) {
283                         if (res) *(uint64_t *)res = res1;
284                         return buf-srcbuf;
285                 } else {
286                         return -1;
287                 }
288                 break;
289
290         case DEC_NEG_OK:
291                 if (nd.type == RTE_INT8 &&
292                                 res1 <= INT8_MAX + 1) {
293                         if (res) *(int8_t *)res = (int8_t) (-res1);
294                         return buf-srcbuf;
295                 } else if (nd.type == RTE_INT16 &&
296                                 res1 <= (uint16_t)INT16_MAX + 1) {
297                         if (res) *(int16_t *)res = (int16_t) (-res1);
298                         return buf-srcbuf;
299                 } else if (nd.type == RTE_INT32 &&
300                                 res1 <= (uint32_t)INT32_MAX + 1) {
301                         if (res) *(int32_t *)res = (int32_t) (-res1);
302                         return buf-srcbuf;
303                 } else if (nd.type == RTE_INT64 &&
304                                 res1 <= (uint64_t)INT64_MAX + 1) {
305                         if (res) *(int64_t *)res = (int64_t) (-res1);
306                         return buf-srcbuf;
307                 } else {
308                         return -1;
309                 }
310                 break;
311         default:
312                 debug_printf("error\n");
313                 return -1;
314         }
315 }
316
317
318 /* parse an int */
319 int
320 cmdline_get_help_num(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size)
321 {
322         struct cmdline_token_num_data nd;
323         int ret;
324
325         if (!tk)
326                 return -1;
327
328         memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd));
329
330         /* should not happen.... don't so this test */
331         /* if (nd.type >= (sizeof(num_help)/sizeof(const char *))) */
332         /* return -1; */
333
334         ret = strlcpy(dstbuf, num_help[nd.type], size);
335         if (ret < 0)
336                 return -1;
337         dstbuf[size-1] = '\0';
338         return 0;
339 }