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