]> git.proxmox.com Git - ceph.git/blob - ceph/src/dpdk/lib/librte_cmdline/cmdline_parse_num.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / dpdk / lib / librte_cmdline / cmdline_parse_num.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
36 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * * Neither the name of the University of California, Berkeley nor the
46 * names of its contributors may be used to endorse or promote products
47 * derived from this software without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
50 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
52 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
53 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
54 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
55 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
56 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */
60
61 #include <stdio.h>
62 #include <stdint.h>
63 #include <inttypes.h>
64 #include <ctype.h>
65 #include <string.h>
66 #include <stdarg.h>
67 #include <errno.h>
68 #include <rte_string_fns.h>
69
70 #include "cmdline_parse.h"
71 #include "cmdline_parse_num.h"
72
73 #ifdef RTE_LIBRTE_CMDLINE_DEBUG
74 #define debug_printf(args...) printf(args)
75 #else
76 #define debug_printf(args...) do {} while(0)
77 #endif
78
79 struct cmdline_token_ops cmdline_token_num_ops = {
80 .parse = cmdline_parse_num,
81 .complete_get_nb = NULL,
82 .complete_get_elt = NULL,
83 .get_help = cmdline_get_help_num,
84 };
85
86
87 enum num_parse_state_t {
88 START,
89 DEC_NEG,
90 BIN,
91 HEX,
92
93 ERROR,
94
95 FIRST_OK, /* not used */
96 ZERO_OK,
97 HEX_OK,
98 OCTAL_OK,
99 BIN_OK,
100 DEC_NEG_OK,
101 DEC_POS_OK,
102 };
103
104 /* Keep it sync with enum in .h */
105 static const char * num_help[] = {
106 "UINT8", "UINT16", "UINT32", "UINT64",
107 "INT8", "INT16", "INT32", "INT64",
108 };
109
110 static inline int
111 add_to_res(unsigned int c, uint64_t *res, unsigned int base)
112 {
113 /* overflow */
114 if ( (UINT64_MAX - c) / base < *res ) {
115 return -1;
116 }
117
118 *res = (uint64_t) (*res * base + c);
119 return 0;
120 }
121
122 static int
123 check_res_size(struct cmdline_token_num_data *nd, unsigned ressize)
124 {
125 switch (nd->type) {
126 case INT8:
127 case UINT8:
128 if (ressize < sizeof(int8_t))
129 return -1;
130 break;
131 case INT16:
132 case UINT16:
133 if (ressize < sizeof(int16_t))
134 return -1;
135 break;
136 case INT32:
137 case UINT32:
138 if (ressize < sizeof(int32_t))
139 return -1;
140 break;
141 case INT64:
142 case UINT64:
143 if (ressize < sizeof(int64_t))
144 return -1;
145 break;
146 default:
147 return -1;
148 }
149 return 0;
150 }
151
152 /* parse an int */
153 int
154 cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res,
155 unsigned ressize)
156 {
157 struct cmdline_token_num_data nd;
158 enum num_parse_state_t st = START;
159 const char * buf;
160 char c;
161 uint64_t res1 = 0;
162
163 if (!tk)
164 return -1;
165
166 if (!srcbuf || !*srcbuf)
167 return -1;
168
169 buf = srcbuf;
170 c = *buf;
171
172 memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd));
173
174 /* check that we have enough room in res */
175 if (res) {
176 if (check_res_size(&nd, ressize) < 0)
177 return -1;
178 }
179
180 while ( st != ERROR && c && ! cmdline_isendoftoken(c) ) {
181 debug_printf("%c %x -> ", c, c);
182 switch (st) {
183 case START:
184 if (c == '-') {
185 st = DEC_NEG;
186 }
187 else if (c == '0') {
188 st = ZERO_OK;
189 }
190 else if (c >= '1' && c <= '9') {
191 if (add_to_res(c - '0', &res1, 10) < 0)
192 st = ERROR;
193 else
194 st = DEC_POS_OK;
195 }
196 else {
197 st = ERROR;
198 }
199 break;
200
201 case ZERO_OK:
202 if (c == 'x') {
203 st = HEX;
204 }
205 else if (c == 'b') {
206 st = BIN;
207 }
208 else if (c >= '0' && c <= '7') {
209 if (add_to_res(c - '0', &res1, 10) < 0)
210 st = ERROR;
211 else
212 st = OCTAL_OK;
213 }
214 else {
215 st = ERROR;
216 }
217 break;
218
219 case DEC_NEG:
220 if (c >= '0' && c <= '9') {
221 if (add_to_res(c - '0', &res1, 10) < 0)
222 st = ERROR;
223 else
224 st = DEC_NEG_OK;
225 }
226 else {
227 st = ERROR;
228 }
229 break;
230
231 case DEC_NEG_OK:
232 if (c >= '0' && c <= '9') {
233 if (add_to_res(c - '0', &res1, 10) < 0)
234 st = ERROR;
235 }
236 else {
237 st = ERROR;
238 }
239 break;
240
241 case DEC_POS_OK:
242 if (c >= '0' && c <= '9') {
243 if (add_to_res(c - '0', &res1, 10) < 0)
244 st = ERROR;
245 }
246 else {
247 st = ERROR;
248 }
249 break;
250
251 case HEX:
252 st = HEX_OK;
253 /* no break */
254 case HEX_OK:
255 if (c >= '0' && c <= '9') {
256 if (add_to_res(c - '0', &res1, 16) < 0)
257 st = ERROR;
258 }
259 else if (c >= 'a' && c <= 'f') {
260 if (add_to_res(c - 'a' + 10, &res1, 16) < 0)
261 st = ERROR;
262 }
263 else if (c >= 'A' && c <= 'F') {
264 if (add_to_res(c - 'A' + 10, &res1, 16) < 0)
265 st = ERROR;
266 }
267 else {
268 st = ERROR;
269 }
270 break;
271
272
273 case OCTAL_OK:
274 if (c >= '0' && c <= '7') {
275 if (add_to_res(c - '0', &res1, 8) < 0)
276 st = ERROR;
277 }
278 else {
279 st = ERROR;
280 }
281 break;
282
283 case BIN:
284 st = BIN_OK;
285 /* no break */
286 case BIN_OK:
287 if (c >= '0' && c <= '1') {
288 if (add_to_res(c - '0', &res1, 2) < 0)
289 st = ERROR;
290 }
291 else {
292 st = ERROR;
293 }
294 break;
295 default:
296 debug_printf("not impl ");
297
298 }
299
300 debug_printf("(%"PRIu64")\n", res1);
301
302 buf ++;
303 c = *buf;
304
305 /* token too long */
306 if (buf-srcbuf > 127)
307 return -1;
308 }
309
310 switch (st) {
311 case ZERO_OK:
312 case DEC_POS_OK:
313 case HEX_OK:
314 case OCTAL_OK:
315 case BIN_OK:
316 if ( nd.type == INT8 && res1 <= INT8_MAX ) {
317 if (res) *(int8_t *)res = (int8_t) res1;
318 return buf-srcbuf;
319 }
320 else if ( nd.type == INT16 && res1 <= INT16_MAX ) {
321 if (res) *(int16_t *)res = (int16_t) res1;
322 return buf-srcbuf;
323 }
324 else if ( nd.type == INT32 && res1 <= INT32_MAX ) {
325 if (res) *(int32_t *)res = (int32_t) res1;
326 return buf-srcbuf;
327 }
328 else if ( nd.type == INT64 && res1 <= INT64_MAX ) {
329 if (res) *(int64_t *)res = (int64_t) res1;
330 return buf-srcbuf;
331 }
332 else if ( nd.type == UINT8 && res1 <= UINT8_MAX ) {
333 if (res) *(uint8_t *)res = (uint8_t) res1;
334 return buf-srcbuf;
335 }
336 else if (nd.type == UINT16 && res1 <= UINT16_MAX ) {
337 if (res) *(uint16_t *)res = (uint16_t) res1;
338 return buf-srcbuf;
339 }
340 else if ( nd.type == UINT32 && res1 <= UINT32_MAX ) {
341 if (res) *(uint32_t *)res = (uint32_t) res1;
342 return buf-srcbuf;
343 }
344 else if ( nd.type == UINT64 ) {
345 if (res) *(uint64_t *)res = res1;
346 return buf-srcbuf;
347 }
348 else {
349 return -1;
350 }
351 break;
352
353 case DEC_NEG_OK:
354 if ( nd.type == INT8 && res1 <= INT8_MAX + 1 ) {
355 if (res) *(int8_t *)res = (int8_t) (-res1);
356 return buf-srcbuf;
357 }
358 else if ( nd.type == INT16 && res1 <= (uint16_t)INT16_MAX + 1 ) {
359 if (res) *(int16_t *)res = (int16_t) (-res1);
360 return buf-srcbuf;
361 }
362 else if ( nd.type == INT32 && res1 <= (uint32_t)INT32_MAX + 1 ) {
363 if (res) *(int32_t *)res = (int32_t) (-res1);
364 return buf-srcbuf;
365 }
366 else if ( nd.type == INT64 && res1 <= (uint64_t)INT64_MAX + 1 ) {
367 if (res) *(int64_t *)res = (int64_t) (-res1);
368 return buf-srcbuf;
369 }
370 else {
371 return -1;
372 }
373 break;
374 default:
375 debug_printf("error\n");
376 return -1;
377 }
378 }
379
380
381 /* parse an int */
382 int
383 cmdline_get_help_num(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size)
384 {
385 struct cmdline_token_num_data nd;
386 int ret;
387
388 if (!tk)
389 return -1;
390
391 memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd));
392
393 /* should not happen.... don't so this test */
394 /* if (nd.type >= (sizeof(num_help)/sizeof(const char *))) */
395 /* return -1; */
396
397 ret = snprintf(dstbuf, size, "%s", num_help[nd.type]);
398 if (ret < 0)
399 return -1;
400 dstbuf[size-1] = '\0';
401 return 0;
402 }