blob: 0f6da4fd3b942fbac0df83080024f494dbaeec7c [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
25
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
28
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36*/
37
38#include <vppinfra/format.h>
39
40/* Call user's function to fill input buffer. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +020041__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -040042_unformat_fill_input (unformat_input_t * i)
Ed Warnickecb9cada2015-12-08 15:45:58 -070043{
44 uword l, first_mark;
45
46 if (i->index == UNFORMAT_END_OF_INPUT)
47 return i->index;
48
49 first_mark = l = vec_len (i->buffer);
50 if (vec_len (i->buffer_marks) > 0)
51 first_mark = i->buffer_marks[0];
52
53 /* Re-use buffer when no marks. */
54 if (first_mark > 0)
55 vec_delete (i->buffer, first_mark, 0);
56
57 i->index = vec_len (i->buffer);
58 for (l = 0; l < vec_len (i->buffer_marks); l++)
59 i->buffer_marks[l] -= first_mark;
60
61 /* Call user's function to fill the buffer. */
62 if (i->fill_buffer)
63 i->index = i->fill_buffer (i);
64
65 /* If input pointer is still beyond end of buffer even after
66 fill then we've run out of input. */
67 if (i->index >= vec_len (i->buffer))
68 i->index = UNFORMAT_END_OF_INPUT;
69
70 return i->index;
71}
72
73always_inline uword
74is_white_space (uword c)
75{
76 switch (c)
77 {
Dave Barachc3799992016-08-15 11:12:27 -040078 case ' ':
79 case '\t':
80 case '\n':
81 case '\r':
Ed Warnickecb9cada2015-12-08 15:45:58 -070082 return 1;
83
84 default:
85 return 0;
86 }
87}
88
89/* Format function for dumping input stream. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +020090__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -040091format_unformat_error (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070092{
Dave Barachc3799992016-08-15 11:12:27 -040093 unformat_input_t *i = va_arg (*va, unformat_input_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070094 uword l = vec_len (i->buffer);
95
96 /* Only show so much of the input buffer (it could be really large). */
97 uword n_max = 30;
98
99 if (i->index < l)
100 {
101 uword n = l - i->index;
Dave Barachc3799992016-08-15 11:12:27 -0400102 u8 *p, *p_end;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700103
104 p = i->buffer + i->index;
105 p_end = p + (n > n_max ? n_max : n);
106
107 /* Skip white space at end. */
108 if (n <= n_max)
109 {
110 while (p_end > p && is_white_space (p_end[-1]))
111 p_end--;
112 }
113
114 while (p < p_end)
115 {
116 switch (*p)
117 {
Dave Barachc3799992016-08-15 11:12:27 -0400118 case '\r':
119 vec_add (s, "\\r", 2);
120 break;
121 case '\n':
122 vec_add (s, "\\n", 2);
123 break;
124 case '\t':
125 vec_add (s, "\\t", 2);
126 break;
127 default:
128 vec_add1 (s, *p);
129 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130 }
131 p++;
132 }
133
134 if (n > n_max)
135 vec_add (s, "...", 3);
136 }
137
138 return s;
139}
140
141/* Print everything: not just error context. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200142__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400143format_unformat_input (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700144{
Dave Barachc3799992016-08-15 11:12:27 -0400145 unformat_input_t *i = va_arg (*va, unformat_input_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700146 uword l, n;
147
148 if (i->index == UNFORMAT_END_OF_INPUT)
149 s = format (s, "{END_OF_INPUT}");
150 else
151 {
152 l = vec_len (i->buffer);
153 n = l - i->index;
154 if (n > 0)
155 vec_add (s, i->buffer + i->index, n);
156 }
157
158 return s;
159}
160
161#if CLIB_DEBUG > 0
Dave Barachc3799992016-08-15 11:12:27 -0400162void
163di (unformat_input_t * i)
164{
165 fformat (stderr, "%U\n", format_unformat_input, i);
166}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700167#endif
168
169/* Parse delimited vector string. If string starts with { then string
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700170 is delimited by balanced parenthesis. Other string is delimited by
Ed Warnickecb9cada2015-12-08 15:45:58 -0700171 white space. {} were chosen since they are special to the shell. */
172static uword
173unformat_string (unformat_input_t * input,
174 uword delimiter_character,
Dave Barachc3799992016-08-15 11:12:27 -0400175 uword format_character, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700176{
Dave Barachc3799992016-08-15 11:12:27 -0400177 u8 **string_return = va_arg (*va, u8 **);
178 u8 *s = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700179 word paren = 0;
180 word is_paren_delimited = 0;
181 word backslash = 0;
182 uword c;
183
184 switch (delimiter_character)
185 {
186 case '%':
187 case ' ':
188 case '\t':
189 delimiter_character = 0;
190 break;
191 }
192
193 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
194 {
195 word add_to_vector;
196
197 /* Null return string means to skip over delimited input. */
198 add_to_vector = string_return != 0;
199
200 if (backslash)
201 backslash = 0;
202 else
203 switch (c)
204 {
205 case '\\':
206 backslash = 1;
207 add_to_vector = 0;
208 break;
209
210 case '{':
211 if (paren == 0 && vec_len (s) == 0)
212 {
213 is_paren_delimited = 1;
214 add_to_vector = 0;
215 }
216 paren++;
217 break;
218
219 case '}':
220 paren--;
221 if (is_paren_delimited && paren == 0)
222 goto done;
223 break;
224
225 case ' ':
226 case '\t':
227 case '\n':
228 case '\r':
Dave Barachc3799992016-08-15 11:12:27 -0400229 if (!is_paren_delimited)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700230 {
231 unformat_put_input (input);
232 goto done;
233 }
234 break;
235
236 default:
Dave Barachc3799992016-08-15 11:12:27 -0400237 if (!is_paren_delimited && c == delimiter_character)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700238 {
239 unformat_put_input (input);
240 goto done;
241 }
242 }
243
244 if (add_to_vector)
245 vec_add1 (s, c);
246 }
247
Dave Barachc3799992016-08-15 11:12:27 -0400248done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700249 if (string_return)
250 {
251 /* Match the string { END-OF-INPUT as a single brace. */
252 if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0 && paren == 1)
Dave Barachc3799992016-08-15 11:12:27 -0400253 vec_add1 (s, '{');
Ed Warnickecb9cada2015-12-08 15:45:58 -0700254
255 /* Don't match null string. */
256 if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0)
257 return 0;
Dave Barachc3799992016-08-15 11:12:27 -0400258
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259 /* Null terminate C string. */
260 if (format_character == 's')
261 vec_add1 (s, 0);
262
263 *string_return = s;
264 }
265 else
266 vec_free (s); /* just to make sure */
267
268 return 1;
269}
270
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200271__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400272unformat_hex_string (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700273{
Dave Barachc3799992016-08-15 11:12:27 -0400274 u8 **hexstring_return = va_arg (*va, u8 **);
275 u8 *s;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700276 uword n, d, c;
277
278 n = 0;
279 d = 0;
280 s = 0;
281 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
282 {
283 if (c >= '0' && c <= '9')
Dave Barachc3799992016-08-15 11:12:27 -0400284 d = 16 * d + c - '0';
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285 else if (c >= 'a' && c <= 'f')
Dave Barachc3799992016-08-15 11:12:27 -0400286 d = 16 * d + 10 + c - 'a';
Ed Warnickecb9cada2015-12-08 15:45:58 -0700287 else if (c >= 'A' && c <= 'F')
Dave Barachc3799992016-08-15 11:12:27 -0400288 d = 16 * d + 10 + c - 'A';
Ed Warnickecb9cada2015-12-08 15:45:58 -0700289 else
290 {
291 unformat_put_input (input);
292 break;
293 }
294 n++;
295
296 if (n == 2)
297 {
298 vec_add1 (s, d);
299 n = d = 0;
300 }
301 }
302
303 /* Hex string must have even number of digits. */
304 if (n % 2)
305 {
306 vec_free (s);
307 return 0;
308 }
Billy McFall205e9342017-02-15 09:03:06 -0500309 /* Make sure something was processed. */
310 else if (s == 0)
311 {
312 return 0;
313 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700314
315 *hexstring_return = s;
316 return 1;
317}
318
319/* unformat (input "foo%U", unformat_eof) matches terminal foo only */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200320__clib_export uword
Ed Warnickecb9cada2015-12-08 15:45:58 -0700321unformat_eof (unformat_input_t * input, va_list * va)
322{
323 return unformat_check_input (input) == UNFORMAT_END_OF_INPUT;
324}
325
326/* Parse a token containing given set of characters. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200327__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400328unformat_token (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700329{
Dave Barachc3799992016-08-15 11:12:27 -0400330 u8 *token_chars = va_arg (*va, u8 *);
331 u8 **string_return = va_arg (*va, u8 **);
332 u8 *s, map[256];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700333 uword i, c;
334
Dave Barachc3799992016-08-15 11:12:27 -0400335 if (!token_chars)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700336 token_chars = (u8 *) "a-zA-Z0-9_";
337
Dave Barachb7b92992018-10-17 10:38:51 -0400338 clib_memset (map, 0, sizeof (map));
Dave Barachc3799992016-08-15 11:12:27 -0400339 for (s = token_chars; *s;)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700340 {
BenoƮt Ganne052bda32019-04-18 17:42:24 +0200341 /*
342 * Parse range.
343 * The test order is important: s[1] is valid because s[0] != '\0' but
344 * s[2] might not if s[1] == '\0'
345 * Also, if s[1] == '-' but s[2] == '\0' the test s[0] < s[2] will
346 * (correctly) fail
347 */
348 if (s[1] == '-' && s[0] < s[2])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700349 {
350 for (i = s[0]; i <= s[2]; i++)
351 map[i] = 1;
352 s = s + 3;
Dave Barachc3799992016-08-15 11:12:27 -0400353 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700354 else
355 {
356 map[s[0]] = 1;
357 s = s + 1;
358 }
359 }
360
361 s = 0;
362 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
363 {
Dave Barachc3799992016-08-15 11:12:27 -0400364 if (!map[c])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700365 {
366 unformat_put_input (input);
367 break;
368 }
Dave Barachc3799992016-08-15 11:12:27 -0400369
Ed Warnickecb9cada2015-12-08 15:45:58 -0700370 vec_add1 (s, c);
371 }
372
373 if (vec_len (s) == 0)
374 return 0;
375
376 *string_return = s;
377 return 1;
378}
379
380/* Unformat (parse) function which reads a %s string and converts it
381 to and unformat_input_t. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200382__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400383unformat_input (unformat_input_t * i, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700384{
Dave Barachc3799992016-08-15 11:12:27 -0400385 unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
386 u8 *s;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700387
388 if (unformat (i, "%v", &s))
389 {
390 unformat_init_vector (sub_input, s);
391 return 1;
392 }
393
394 return 0;
395}
396
397/* Parse a line ending with \n and return it. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200398__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400399unformat_line (unformat_input_t * i, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700400{
Dave Barachc3799992016-08-15 11:12:27 -0400401 u8 *line = 0, **result = va_arg (*va, u8 **);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700402 uword c;
403
Dave Barachc3799992016-08-15 11:12:27 -0400404 while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405 {
406 vec_add1 (line, c);
407 }
408
409 *result = line;
Alexander Kotov28160f32017-07-10 18:23:31 +0300410 return vec_len (line);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700411}
412
413/* Parse a line ending with \n and return it as an unformat_input_t. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200414__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400415unformat_line_input (unformat_input_t * i, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700416{
Dave Barachc3799992016-08-15 11:12:27 -0400417 unformat_input_t *result = va_arg (*va, unformat_input_t *);
418 u8 *line;
Alexander Kotov28160f32017-07-10 18:23:31 +0300419 if (!unformat_user (i, unformat_line, &line))
420 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700421 unformat_init_vector (result, line);
422 return 1;
423}
424
425/* Values for is_signed. */
426#define UNFORMAT_INTEGER_SIGNED 1
427#define UNFORMAT_INTEGER_UNSIGNED 0
428
429static uword
430unformat_integer (unformat_input_t * input,
Dave Barachc3799992016-08-15 11:12:27 -0400431 va_list * va, uword base, uword is_signed, uword data_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700432{
433 uword c, digit;
434 uword value = 0;
435 uword n_digits = 0;
436 uword n_input = 0;
437 uword sign = 0;
438
439 /* We only support bases <= 64. */
440 if (base < 2 || base > 64)
441 goto error;
442
443 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
444 {
445 switch (c)
446 {
447 case '-':
448 if (n_input == 0)
449 {
450 if (is_signed)
451 {
452 sign = 1;
453 goto next_digit;
454 }
455 else
456 /* Leading sign for unsigned number. */
457 goto error;
458 }
459 /* Sign after input (e.g. 100-200). */
460 goto put_input_done;
461
462 case '+':
Dave Barachc3799992016-08-15 11:12:27 -0400463 if (n_input > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700464 goto put_input_done;
465 sign = 0;
466 goto next_digit;
467
468 case '0' ... '9':
469 digit = c - '0';
470 break;
471
472 case 'a' ... 'z':
473 digit = 10 + (c - 'a');
474 break;
475
476 case 'A' ... 'Z':
477 digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A');
478 break;
479
480 case '/':
481 digit = 62;
482 break;
483
484 case '?':
485 digit = 63;
486 break;
487
488 default:
489 goto put_input_done;
490 }
491
492 if (digit >= base)
493 {
494 put_input_done:
495 unformat_put_input (input);
496 goto done;
497 }
498
499 {
Dave Barachc3799992016-08-15 11:12:27 -0400500 uword new_value = base * value + digit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700501
502 /* Check for overflow. */
503 if (new_value < value)
504 goto error;
505 value = new_value;
506 }
507 n_digits += 1;
508
509 next_digit:
510 n_input++;
511 }
512
Dave Barachc3799992016-08-15 11:12:27 -0400513done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700514 if (sign)
515 value = -value;
516
517 if (n_digits > 0)
518 {
Dave Barachc3799992016-08-15 11:12:27 -0400519 void *v = va_arg (*va, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700520
521 if (data_bytes == ~0)
Dave Barachc3799992016-08-15 11:12:27 -0400522 data_bytes = sizeof (int);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700523
524 switch (data_bytes)
525 {
Dave Barachc3799992016-08-15 11:12:27 -0400526 case 1:
527 *(u8 *) v = value;
528 break;
529 case 2:
530 *(u16 *) v = value;
531 break;
532 case 4:
533 *(u32 *) v = value;
534 break;
535 case 8:
536 *(u64 *) v = value;
537 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700538 default:
Dave Barachc3799992016-08-15 11:12:27 -0400539 goto error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700540 }
541
542 return 1;
543 }
544
Dave Barachc3799992016-08-15 11:12:27 -0400545error:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700546 return 0;
547}
548
549/* Return x 10^n */
Dave Barachc3799992016-08-15 11:12:27 -0400550static f64
551times_power_of_ten (f64 x, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700552{
553 if (n >= 0)
554 {
555 static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
556 while (n >= 8)
557 {
558 x *= 1e+8;
559 n -= 8;
560 }
561 return x * t[n];
562 }
563 else
564 {
565 static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
566 while (n <= -8)
567 {
568 x *= 1e-8;
569 n += 8;
570 }
571 return x * t[-n];
572 }
Dave Barachc3799992016-08-15 11:12:27 -0400573
Ed Warnickecb9cada2015-12-08 15:45:58 -0700574}
575
576static uword
Dave Barachc3799992016-08-15 11:12:27 -0400577unformat_float (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700578{
579 uword c;
580 u64 values[3];
581 uword n_digits[3], value_index = 0;
582 uword signs[2], sign_index = 0;
583 uword n_input = 0;
584
Dave Barachb7b92992018-10-17 10:38:51 -0400585 clib_memset (values, 0, sizeof (values));
586 clib_memset (n_digits, 0, sizeof (n_digits));
587 clib_memset (signs, 0, sizeof (signs));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700588
589 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
590 {
591 switch (c)
592 {
593 case '-':
594 if (value_index == 2 && n_digits[2] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400595 /* sign of exponent: it's ok. */ ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700596
597 else if (value_index < 2 && n_digits[0] > 0)
598 {
599 /* 123- */
600 unformat_put_input (input);
601 goto done;
602 }
603
604 else if (n_input > 0)
605 goto error;
606
607 signs[sign_index++] = 1;
608 goto next_digit;
609
610 case '+':
611 if (value_index == 2 && n_digits[2] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400612 /* sign of exponent: it's ok. */ ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700613
614 else if (value_index < 2 && n_digits[0] > 0)
615 {
616 /* 123+ */
617 unformat_put_input (input);
618 goto done;
619 }
620
621 else if (n_input > 0)
622 goto error;
623 signs[sign_index++] = 0;
624 goto next_digit;
625
626 case 'e':
627 case 'E':
628 if (n_input == 0)
629 goto error;
630 value_index = 2;
631 sign_index = 1;
632 break;
633
634 case '.':
635 if (value_index > 0)
636 goto error;
637 value_index = 1;
638 break;
639
640 case '0' ... '9':
641 {
642 u64 tmp;
643
644 tmp = values[value_index] * 10 + c - '0';
645
646 /* Check for overflow. */
647 if (tmp < values[value_index])
648 goto error;
649 values[value_index] = tmp;
650 n_digits[value_index] += 1;
651 }
652 break;
653
654 default:
655 unformat_put_input (input);
656 goto done;
657 }
658
659 next_digit:
660 n_input++;
661 }
662
Dave Barachc3799992016-08-15 11:12:27 -0400663done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700664 {
Dave Barachc3799992016-08-15 11:12:27 -0400665 f64 f_values[2], *value_return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700666 word expon;
667
668 /* Must have either whole or fraction digits. */
669 if (n_digits[0] + n_digits[1] <= 0)
670 goto error;
671
672 f_values[0] = values[0];
673 if (signs[0])
674 f_values[0] = -f_values[0];
675
676 f_values[1] = values[1];
677 f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]);
678
679 f_values[0] += f_values[1];
680
681 expon = values[2];
682 if (signs[1])
683 expon = -expon;
684
685 f_values[0] = times_power_of_ten (f_values[0], expon);
686
687 value_return = va_arg (*va, f64 *);
688 *value_return = f_values[0];
689 return 1;
690 }
691
Dave Barachc3799992016-08-15 11:12:27 -0400692error:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700693 return 0;
694}
695
Neale Ranns32e1c012016-11-22 17:07:28 +0000696static const char *
697match_input_with_format (unformat_input_t * input, const char *f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700698{
699 uword cf, ci;
700
701 ASSERT (*f != 0);
702
703 while (1)
704 {
705 cf = *f;
706 if (cf == 0 || cf == '%' || cf == ' ')
707 break;
708 f++;
709
710 ci = unformat_get_input (input);
711
712 if (cf != ci)
713 return 0;
714 }
715 return f;
716}
717
Neale Ranns32e1c012016-11-22 17:07:28 +0000718static const char *
719do_percent (unformat_input_t * input, va_list * va, const char *f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700720{
721 uword cf, n, data_bytes = ~0;
722
723 cf = *f++;
724
725 switch (cf)
726 {
727 default:
728 break;
729
730 case 'w':
731 /* Word types. */
732 cf = *f++;
733 data_bytes = sizeof (uword);
734 break;
735
736 case 'l':
737 cf = *f++;
738 if (cf == 'l')
739 {
740 cf = *f++;
741 data_bytes = sizeof (long long);
742 }
743 else
744 {
745 data_bytes = sizeof (long);
746 }
747 break;
Dave Barachc3799992016-08-15 11:12:27 -0400748
Ed Warnickecb9cada2015-12-08 15:45:58 -0700749 case 'L':
750 cf = *f++;
751 data_bytes = sizeof (long long);
752 break;
753 }
754
755 n = 0;
756 switch (cf)
757 {
758 case 'D':
759 data_bytes = va_arg (*va, int);
760 case 'd':
761 n = unformat_integer (input, va, 10,
762 UNFORMAT_INTEGER_SIGNED, data_bytes);
763 break;
764
765 case 'u':
766 n = unformat_integer (input, va, 10,
767 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
768 break;
769
770 case 'b':
771 n = unformat_integer (input, va, 2,
772 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
773 break;
774
775 case 'o':
776 n = unformat_integer (input, va, 8,
777 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
778 break;
779
780 case 'X':
781 data_bytes = va_arg (*va, int);
782 case 'x':
783 n = unformat_integer (input, va, 16,
784 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
785 break;
786
787 case 'f':
788 n = unformat_float (input, va);
789 break;
790
791 case 's':
792 case 'v':
793 n = unformat_string (input, f[0], cf, va);
794 break;
795
796 case 'U':
797 {
Dave Barachc3799992016-08-15 11:12:27 -0400798 unformat_function_t *f = va_arg (*va, unformat_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700799 n = f (input, va);
800 }
801 break;
802
803 case '=':
804 case '|':
805 {
Dave Barachc3799992016-08-15 11:12:27 -0400806 int *var = va_arg (*va, int *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700807 uword val = va_arg (*va, int);
808
809 if (cf == '|')
810 val |= *var;
811 *var = val;
812 n = 1;
813 }
814 break;
815 }
816
817 return n ? f : 0;
818}
819
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200820__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400821unformat_skip_white_space (unformat_input_t * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700822{
823 uword n = 0;
824 uword c;
825
826 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
827 {
Dave Barachc3799992016-08-15 11:12:27 -0400828 if (!is_white_space (c))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700829 {
830 unformat_put_input (input);
831 break;
832 }
833 n++;
834 }
835 return n;
836}
837
Juraj LinkeŔ7aa76d42020-10-22 13:29:28 +0200838__clib_export uword
Neale Ranns32e1c012016-11-22 17:07:28 +0000839va_unformat (unformat_input_t * input, const char *fmt, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700840{
Neale Ranns32e1c012016-11-22 17:07:28 +0000841 const char *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700842 uword input_matches_format;
843 uword default_skip_input_white_space;
844 uword n_input_white_space_skipped;
845 uword last_non_white_space_match_percent;
846 uword last_non_white_space_match_format;
847
Dave Barachc3799992016-08-15 11:12:27 -0400848 vec_add1_aligned (input->buffer_marks, input->index,
849 sizeof (input->buffer_marks[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700850
851 f = fmt;
852 default_skip_input_white_space = 1;
853 input_matches_format = 0;
854 last_non_white_space_match_percent = 0;
855 last_non_white_space_match_format = 0;
Dave Barachc3799992016-08-15 11:12:27 -0400856
Ed Warnickecb9cada2015-12-08 15:45:58 -0700857 while (1)
858 {
859 char cf;
860 uword is_percent, skip_input_white_space;
861
862 cf = *f;
863 is_percent = 0;
864
865 /* Always skip input white space at start of format string.
Dave Barachc3799992016-08-15 11:12:27 -0400866 Otherwise use default skip value which can be changed by %_
867 (see below). */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700868 skip_input_white_space = f == fmt || default_skip_input_white_space;
869
870 /* Spaces in format request skipping input white space. */
871 if (is_white_space (cf))
872 {
873 skip_input_white_space = 1;
874
875 /* Multiple format spaces are equivalent to a single white
876 space. */
877 while (is_white_space (*++f))
878 ;
879 }
880 else if (cf == '%')
881 {
882 /* %_ toggles whether or not to skip input white space. */
883 switch (*++f)
884 {
885 case '_':
Dave Barachc3799992016-08-15 11:12:27 -0400886 default_skip_input_white_space =
887 !default_skip_input_white_space;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700888 f++;
889 /* For transition from skip to no-skip in middle of format
Dave Barachc3799992016-08-15 11:12:27 -0400890 string, skip input white space. For example, the following matches:
891 fmt = "%_%d.%d%_->%_%d.%d%_"
892 input "1.2 -> 3.4"
893 Without this the space after -> does not get skipped. */
894 if (!default_skip_input_white_space
895 && !(f == fmt + 2 || *f == 0))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700896 unformat_skip_white_space (input);
897 continue;
898
Dave Barachc3799992016-08-15 11:12:27 -0400899 /* %% means match % */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700900 case '%':
901 break;
902
Dave Barachc3799992016-08-15 11:12:27 -0400903 /* % at end of format string. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700904 case 0:
905 goto parse_fail;
906
907 default:
908 is_percent = 1;
909 break;
910 }
911 }
912
913 n_input_white_space_skipped = 0;
914 if (skip_input_white_space)
915 n_input_white_space_skipped = unformat_skip_white_space (input);
916
917 /* End of format string. */
918 if (cf == 0)
919 {
920 /* Force parse error when format string ends and input is
921 not white or at end. As an example, this is to prevent
922 format "foo" from matching input "food".
923 The last_non_white_space_match_percent is to make
924 "foo %d" match input "foo 10,bletch" with %d matching 10. */
925 if (skip_input_white_space
Dave Barachc3799992016-08-15 11:12:27 -0400926 && !last_non_white_space_match_percent
927 && !last_non_white_space_match_format
Ed Warnickecb9cada2015-12-08 15:45:58 -0700928 && n_input_white_space_skipped == 0
929 && input->index != UNFORMAT_END_OF_INPUT)
930 goto parse_fail;
931 break;
932 }
933
934 last_non_white_space_match_percent = is_percent;
935 last_non_white_space_match_format = 0;
936
937 /* Explicit spaces in format must match input white space. */
938 if (cf == ' ' && !default_skip_input_white_space)
939 {
940 if (n_input_white_space_skipped == 0)
941 goto parse_fail;
942 }
943
944 else if (is_percent)
945 {
Dave Barachc3799992016-08-15 11:12:27 -0400946 if (!(f = do_percent (input, va, f)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700947 goto parse_fail;
948 }
949
950 else
951 {
Neale Ranns32e1c012016-11-22 17:07:28 +0000952 const char *g = match_input_with_format (input, f);
Dave Barachc3799992016-08-15 11:12:27 -0400953 if (!g)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700954 goto parse_fail;
955 last_non_white_space_match_format = g > f;
956 f = g;
957 }
958 }
959
960 input_matches_format = 1;
Dave Barachc3799992016-08-15 11:12:27 -0400961parse_fail:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700962
963 /* Rewind buffer marks. */
964 {
965 uword l = vec_len (input->buffer_marks);
966
967 /* If we did not match back up buffer to last mark. */
Dave Barachc3799992016-08-15 11:12:27 -0400968 if (!input_matches_format)
969 input->index = input->buffer_marks[l - 1];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700970
971 _vec_len (input->buffer_marks) = l - 1;
972 }
973
974 return input_matches_format;
975}
976
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200977__clib_export uword
Neale Ranns32e1c012016-11-22 17:07:28 +0000978unformat (unformat_input_t * input, const char *fmt, ...)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700979{
980 va_list va;
981 uword result;
982 va_start (va, fmt);
983 result = va_unformat (input, fmt, &va);
984 va_end (va);
985 return result;
986}
987
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200988__clib_export uword
Ed Warnickecb9cada2015-12-08 15:45:58 -0700989unformat_user (unformat_input_t * input, unformat_function_t * func, ...)
990{
991 va_list va;
992 uword result, l;
993
994 /* Save place in input buffer in case parse fails. */
995 l = vec_len (input->buffer_marks);
Dave Barachc3799992016-08-15 11:12:27 -0400996 vec_add1_aligned (input->buffer_marks, input->index,
997 sizeof (input->buffer_marks[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700998
999 va_start (va, func);
1000 result = func (input, &va);
1001 va_end (va);
1002
Dave Barachdddccea2016-10-26 14:03:20 -04001003 if (!result && input->index != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001004 input->index = input->buffer_marks[l];
1005
1006 _vec_len (input->buffer_marks) = l;
1007
1008 return result;
1009}
1010
1011/* Setup for unformat of Unix style command line. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001012__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -04001013unformat_init_command_line (unformat_input_t * input, char *argv[])
Ed Warnickecb9cada2015-12-08 15:45:58 -07001014{
1015 uword i;
1016
1017 unformat_init (input, 0, 0);
1018
1019 /* Concatenate argument strings with space in between. */
1020 for (i = 1; argv[i]; i++)
1021 {
1022 vec_add (input->buffer, argv[i], strlen (argv[i]));
1023 if (argv[i + 1])
1024 vec_add1 (input->buffer, ' ');
1025 }
1026}
1027
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001028__clib_export void
BenoƮt Ganne82f618c2021-10-13 11:35:15 +02001029unformat_init_string (unformat_input_t *input, const char *string,
1030 int string_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001031{
1032 unformat_init (input, 0, 0);
1033 if (string_len > 0)
1034 vec_add (input->buffer, string, string_len);
1035}
1036
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001037__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -04001038unformat_init_vector (unformat_input_t * input, u8 * vector_string)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001039{
1040 unformat_init (input, 0, 0);
1041 input->buffer = vector_string;
1042}
1043
1044#ifdef CLIB_UNIX
1045
Dave Barachc3799992016-08-15 11:12:27 -04001046static uword
Dave Barach59b25652017-09-10 15:04:27 -04001047clib_file_fill_buffer (unformat_input_t * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001048{
1049 int fd = pointer_to_uword (input->fill_buffer_arg);
1050 uword l, n;
1051
1052 l = vec_len (input->buffer);
1053 vec_resize (input->buffer, 4096);
1054 n = read (fd, input->buffer + l, 4096);
1055 if (n > 0)
1056 _vec_len (input->buffer) = l + n;
1057
1058 if (n <= 0)
1059 return UNFORMAT_END_OF_INPUT;
1060 else
1061 return input->index;
1062}
1063
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001064__clib_export void
Dave Barach59b25652017-09-10 15:04:27 -04001065unformat_init_clib_file (unformat_input_t * input, int file_descriptor)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001066{
Dave Barach59b25652017-09-10 15:04:27 -04001067 unformat_init (input, clib_file_fill_buffer,
Ed Warnickecb9cada2015-12-08 15:45:58 -07001068 uword_to_pointer (file_descriptor, void *));
1069}
1070
1071/* Take input from Unix environment variable. */
Dave Barachc3799992016-08-15 11:12:27 -04001072uword
1073unformat_init_unix_env (unformat_input_t * input, char *var)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001074{
Dave Barachc3799992016-08-15 11:12:27 -04001075 char *val = getenv (var);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001076 if (val)
1077 unformat_init_string (input, val, strlen (val));
1078 return val != 0;
1079}
1080
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001081__clib_export uword
MathiasRaoul579b1652019-10-04 09:53:45 +00001082unformat_data_size (unformat_input_t * input, va_list * args)
1083{
1084 u64 _a;
1085 u64 *a = va_arg (*args, u64 *);
1086 if (unformat (input, "%lluGb", &_a))
1087 *a = _a << 30;
1088 else if (unformat (input, "%lluG", &_a))
1089 *a = _a << 30;
1090 else if (unformat (input, "%lluMb", &_a))
1091 *a = _a << 20;
1092 else if (unformat (input, "%lluM", &_a))
1093 *a = _a << 20;
1094 else if (unformat (input, "%lluKb", &_a))
1095 *a = _a << 10;
1096 else if (unformat (input, "%lluK", &_a))
1097 *a = _a << 10;
1098 else if (unformat (input, "%llu", a))
1099 ;
1100 else
1101 return 0;
1102 return 1;
1103}
1104
Ed Warnickecb9cada2015-12-08 15:45:58 -07001105#endif /* CLIB_UNIX */
1106
Dave Barachc3799992016-08-15 11:12:27 -04001107
1108/*
1109 * fd.io coding-style-patch-verification: ON
1110 *
1111 * Local Variables:
1112 * eval: (c-set-style "gnu")
1113 * End:
1114 */