blob: da7622a90a823893bac0dbfbaa16cabfd73d61bd [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. */
Dave Barachc3799992016-08-15 11:12:27 -040041uword
42_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. */
Dave Barachc3799992016-08-15 11:12:27 -040090u8 *
91format_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. */
Dave Barachc3799992016-08-15 11:12:27 -0400142u8 *
143format_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
271uword
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 */
320uword
321unformat_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. */
327uword
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 {
341 /* Parse range. */
342 if (s[0] < s[2] && s[1] == '-')
343 {
344 for (i = s[0]; i <= s[2]; i++)
345 map[i] = 1;
346 s = s + 3;
Dave Barachc3799992016-08-15 11:12:27 -0400347 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348 else
349 {
350 map[s[0]] = 1;
351 s = s + 1;
352 }
353 }
354
355 s = 0;
356 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
357 {
Dave Barachc3799992016-08-15 11:12:27 -0400358 if (!map[c])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700359 {
360 unformat_put_input (input);
361 break;
362 }
Dave Barachc3799992016-08-15 11:12:27 -0400363
Ed Warnickecb9cada2015-12-08 15:45:58 -0700364 vec_add1 (s, c);
365 }
366
367 if (vec_len (s) == 0)
368 return 0;
369
370 *string_return = s;
371 return 1;
372}
373
374/* Unformat (parse) function which reads a %s string and converts it
375 to and unformat_input_t. */
Dave Barachc3799992016-08-15 11:12:27 -0400376uword
377unformat_input (unformat_input_t * i, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700378{
Dave Barachc3799992016-08-15 11:12:27 -0400379 unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
380 u8 *s;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700381
382 if (unformat (i, "%v", &s))
383 {
384 unformat_init_vector (sub_input, s);
385 return 1;
386 }
387
388 return 0;
389}
390
391/* Parse a line ending with \n and return it. */
Dave Barachc3799992016-08-15 11:12:27 -0400392uword
393unformat_line (unformat_input_t * i, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394{
Dave Barachc3799992016-08-15 11:12:27 -0400395 u8 *line = 0, **result = va_arg (*va, u8 **);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700396 uword c;
397
Dave Barachc3799992016-08-15 11:12:27 -0400398 while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700399 {
400 vec_add1 (line, c);
401 }
402
403 *result = line;
Alexander Kotov28160f32017-07-10 18:23:31 +0300404 return vec_len (line);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405}
406
407/* Parse a line ending with \n and return it as an unformat_input_t. */
Dave Barachc3799992016-08-15 11:12:27 -0400408uword
409unformat_line_input (unformat_input_t * i, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700410{
Dave Barachc3799992016-08-15 11:12:27 -0400411 unformat_input_t *result = va_arg (*va, unformat_input_t *);
412 u8 *line;
Alexander Kotov28160f32017-07-10 18:23:31 +0300413 if (!unformat_user (i, unformat_line, &line))
414 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700415 unformat_init_vector (result, line);
416 return 1;
417}
418
419/* Values for is_signed. */
420#define UNFORMAT_INTEGER_SIGNED 1
421#define UNFORMAT_INTEGER_UNSIGNED 0
422
423static uword
424unformat_integer (unformat_input_t * input,
Dave Barachc3799992016-08-15 11:12:27 -0400425 va_list * va, uword base, uword is_signed, uword data_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700426{
427 uword c, digit;
428 uword value = 0;
429 uword n_digits = 0;
430 uword n_input = 0;
431 uword sign = 0;
432
433 /* We only support bases <= 64. */
434 if (base < 2 || base > 64)
435 goto error;
436
437 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
438 {
439 switch (c)
440 {
441 case '-':
442 if (n_input == 0)
443 {
444 if (is_signed)
445 {
446 sign = 1;
447 goto next_digit;
448 }
449 else
450 /* Leading sign for unsigned number. */
451 goto error;
452 }
453 /* Sign after input (e.g. 100-200). */
454 goto put_input_done;
455
456 case '+':
Dave Barachc3799992016-08-15 11:12:27 -0400457 if (n_input > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700458 goto put_input_done;
459 sign = 0;
460 goto next_digit;
461
462 case '0' ... '9':
463 digit = c - '0';
464 break;
465
466 case 'a' ... 'z':
467 digit = 10 + (c - 'a');
468 break;
469
470 case 'A' ... 'Z':
471 digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A');
472 break;
473
474 case '/':
475 digit = 62;
476 break;
477
478 case '?':
479 digit = 63;
480 break;
481
482 default:
483 goto put_input_done;
484 }
485
486 if (digit >= base)
487 {
488 put_input_done:
489 unformat_put_input (input);
490 goto done;
491 }
492
493 {
Dave Barachc3799992016-08-15 11:12:27 -0400494 uword new_value = base * value + digit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700495
496 /* Check for overflow. */
497 if (new_value < value)
498 goto error;
499 value = new_value;
500 }
501 n_digits += 1;
502
503 next_digit:
504 n_input++;
505 }
506
Dave Barachc3799992016-08-15 11:12:27 -0400507done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700508 if (sign)
509 value = -value;
510
511 if (n_digits > 0)
512 {
Dave Barachc3799992016-08-15 11:12:27 -0400513 void *v = va_arg (*va, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700514
515 if (data_bytes == ~0)
Dave Barachc3799992016-08-15 11:12:27 -0400516 data_bytes = sizeof (int);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700517
518 switch (data_bytes)
519 {
Dave Barachc3799992016-08-15 11:12:27 -0400520 case 1:
521 *(u8 *) v = value;
522 break;
523 case 2:
524 *(u16 *) v = value;
525 break;
526 case 4:
527 *(u32 *) v = value;
528 break;
529 case 8:
530 *(u64 *) v = value;
531 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700532 default:
Dave Barachc3799992016-08-15 11:12:27 -0400533 goto error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700534 }
535
536 return 1;
537 }
538
Dave Barachc3799992016-08-15 11:12:27 -0400539error:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700540 return 0;
541}
542
543/* Return x 10^n */
Dave Barachc3799992016-08-15 11:12:27 -0400544static f64
545times_power_of_ten (f64 x, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700546{
547 if (n >= 0)
548 {
549 static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
550 while (n >= 8)
551 {
552 x *= 1e+8;
553 n -= 8;
554 }
555 return x * t[n];
556 }
557 else
558 {
559 static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
560 while (n <= -8)
561 {
562 x *= 1e-8;
563 n += 8;
564 }
565 return x * t[-n];
566 }
Dave Barachc3799992016-08-15 11:12:27 -0400567
Ed Warnickecb9cada2015-12-08 15:45:58 -0700568}
569
570static uword
Dave Barachc3799992016-08-15 11:12:27 -0400571unformat_float (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700572{
573 uword c;
574 u64 values[3];
575 uword n_digits[3], value_index = 0;
576 uword signs[2], sign_index = 0;
577 uword n_input = 0;
578
Dave Barachb7b92992018-10-17 10:38:51 -0400579 clib_memset (values, 0, sizeof (values));
580 clib_memset (n_digits, 0, sizeof (n_digits));
581 clib_memset (signs, 0, sizeof (signs));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700582
583 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
584 {
585 switch (c)
586 {
587 case '-':
588 if (value_index == 2 && n_digits[2] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400589 /* sign of exponent: it's ok. */ ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700590
591 else if (value_index < 2 && n_digits[0] > 0)
592 {
593 /* 123- */
594 unformat_put_input (input);
595 goto done;
596 }
597
598 else if (n_input > 0)
599 goto error;
600
601 signs[sign_index++] = 1;
602 goto next_digit;
603
604 case '+':
605 if (value_index == 2 && n_digits[2] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400606 /* sign of exponent: it's ok. */ ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700607
608 else if (value_index < 2 && n_digits[0] > 0)
609 {
610 /* 123+ */
611 unformat_put_input (input);
612 goto done;
613 }
614
615 else if (n_input > 0)
616 goto error;
617 signs[sign_index++] = 0;
618 goto next_digit;
619
620 case 'e':
621 case 'E':
622 if (n_input == 0)
623 goto error;
624 value_index = 2;
625 sign_index = 1;
626 break;
627
628 case '.':
629 if (value_index > 0)
630 goto error;
631 value_index = 1;
632 break;
633
634 case '0' ... '9':
635 {
636 u64 tmp;
637
638 tmp = values[value_index] * 10 + c - '0';
639
640 /* Check for overflow. */
641 if (tmp < values[value_index])
642 goto error;
643 values[value_index] = tmp;
644 n_digits[value_index] += 1;
645 }
646 break;
647
648 default:
649 unformat_put_input (input);
650 goto done;
651 }
652
653 next_digit:
654 n_input++;
655 }
656
Dave Barachc3799992016-08-15 11:12:27 -0400657done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658 {
Dave Barachc3799992016-08-15 11:12:27 -0400659 f64 f_values[2], *value_return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700660 word expon;
661
662 /* Must have either whole or fraction digits. */
663 if (n_digits[0] + n_digits[1] <= 0)
664 goto error;
665
666 f_values[0] = values[0];
667 if (signs[0])
668 f_values[0] = -f_values[0];
669
670 f_values[1] = values[1];
671 f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]);
672
673 f_values[0] += f_values[1];
674
675 expon = values[2];
676 if (signs[1])
677 expon = -expon;
678
679 f_values[0] = times_power_of_ten (f_values[0], expon);
680
681 value_return = va_arg (*va, f64 *);
682 *value_return = f_values[0];
683 return 1;
684 }
685
Dave Barachc3799992016-08-15 11:12:27 -0400686error:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700687 return 0;
688}
689
Neale Ranns32e1c012016-11-22 17:07:28 +0000690static const char *
691match_input_with_format (unformat_input_t * input, const char *f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700692{
693 uword cf, ci;
694
695 ASSERT (*f != 0);
696
697 while (1)
698 {
699 cf = *f;
700 if (cf == 0 || cf == '%' || cf == ' ')
701 break;
702 f++;
703
704 ci = unformat_get_input (input);
705
706 if (cf != ci)
707 return 0;
708 }
709 return f;
710}
711
Neale Ranns32e1c012016-11-22 17:07:28 +0000712static const char *
713do_percent (unformat_input_t * input, va_list * va, const char *f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700714{
715 uword cf, n, data_bytes = ~0;
716
717 cf = *f++;
718
719 switch (cf)
720 {
721 default:
722 break;
723
724 case 'w':
725 /* Word types. */
726 cf = *f++;
727 data_bytes = sizeof (uword);
728 break;
729
730 case 'l':
731 cf = *f++;
732 if (cf == 'l')
733 {
734 cf = *f++;
735 data_bytes = sizeof (long long);
736 }
737 else
738 {
739 data_bytes = sizeof (long);
740 }
741 break;
Dave Barachc3799992016-08-15 11:12:27 -0400742
Ed Warnickecb9cada2015-12-08 15:45:58 -0700743 case 'L':
744 cf = *f++;
745 data_bytes = sizeof (long long);
746 break;
747 }
748
749 n = 0;
750 switch (cf)
751 {
752 case 'D':
753 data_bytes = va_arg (*va, int);
754 case 'd':
755 n = unformat_integer (input, va, 10,
756 UNFORMAT_INTEGER_SIGNED, data_bytes);
757 break;
758
759 case 'u':
760 n = unformat_integer (input, va, 10,
761 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
762 break;
763
764 case 'b':
765 n = unformat_integer (input, va, 2,
766 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
767 break;
768
769 case 'o':
770 n = unformat_integer (input, va, 8,
771 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
772 break;
773
774 case 'X':
775 data_bytes = va_arg (*va, int);
776 case 'x':
777 n = unformat_integer (input, va, 16,
778 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
779 break;
780
781 case 'f':
782 n = unformat_float (input, va);
783 break;
784
785 case 's':
786 case 'v':
787 n = unformat_string (input, f[0], cf, va);
788 break;
789
790 case 'U':
791 {
Dave Barachc3799992016-08-15 11:12:27 -0400792 unformat_function_t *f = va_arg (*va, unformat_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700793 n = f (input, va);
794 }
795 break;
796
797 case '=':
798 case '|':
799 {
Dave Barachc3799992016-08-15 11:12:27 -0400800 int *var = va_arg (*va, int *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700801 uword val = va_arg (*va, int);
802
803 if (cf == '|')
804 val |= *var;
805 *var = val;
806 n = 1;
807 }
808 break;
809 }
810
811 return n ? f : 0;
812}
813
Dave Barachc3799992016-08-15 11:12:27 -0400814uword
815unformat_skip_white_space (unformat_input_t * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700816{
817 uword n = 0;
818 uword c;
819
820 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
821 {
Dave Barachc3799992016-08-15 11:12:27 -0400822 if (!is_white_space (c))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700823 {
824 unformat_put_input (input);
825 break;
826 }
827 n++;
828 }
829 return n;
830}
831
832uword
Neale Ranns32e1c012016-11-22 17:07:28 +0000833va_unformat (unformat_input_t * input, const char *fmt, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700834{
Neale Ranns32e1c012016-11-22 17:07:28 +0000835 const char *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700836 uword input_matches_format;
837 uword default_skip_input_white_space;
838 uword n_input_white_space_skipped;
839 uword last_non_white_space_match_percent;
840 uword last_non_white_space_match_format;
841
Dave Barachc3799992016-08-15 11:12:27 -0400842 vec_add1_aligned (input->buffer_marks, input->index,
843 sizeof (input->buffer_marks[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700844
845 f = fmt;
846 default_skip_input_white_space = 1;
847 input_matches_format = 0;
848 last_non_white_space_match_percent = 0;
849 last_non_white_space_match_format = 0;
Dave Barachc3799992016-08-15 11:12:27 -0400850
Ed Warnickecb9cada2015-12-08 15:45:58 -0700851 while (1)
852 {
853 char cf;
854 uword is_percent, skip_input_white_space;
855
856 cf = *f;
857 is_percent = 0;
858
859 /* Always skip input white space at start of format string.
Dave Barachc3799992016-08-15 11:12:27 -0400860 Otherwise use default skip value which can be changed by %_
861 (see below). */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700862 skip_input_white_space = f == fmt || default_skip_input_white_space;
863
864 /* Spaces in format request skipping input white space. */
865 if (is_white_space (cf))
866 {
867 skip_input_white_space = 1;
868
869 /* Multiple format spaces are equivalent to a single white
870 space. */
871 while (is_white_space (*++f))
872 ;
873 }
874 else if (cf == '%')
875 {
876 /* %_ toggles whether or not to skip input white space. */
877 switch (*++f)
878 {
879 case '_':
Dave Barachc3799992016-08-15 11:12:27 -0400880 default_skip_input_white_space =
881 !default_skip_input_white_space;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700882 f++;
883 /* For transition from skip to no-skip in middle of format
Dave Barachc3799992016-08-15 11:12:27 -0400884 string, skip input white space. For example, the following matches:
885 fmt = "%_%d.%d%_->%_%d.%d%_"
886 input "1.2 -> 3.4"
887 Without this the space after -> does not get skipped. */
888 if (!default_skip_input_white_space
889 && !(f == fmt + 2 || *f == 0))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700890 unformat_skip_white_space (input);
891 continue;
892
Dave Barachc3799992016-08-15 11:12:27 -0400893 /* %% means match % */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700894 case '%':
895 break;
896
Dave Barachc3799992016-08-15 11:12:27 -0400897 /* % at end of format string. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700898 case 0:
899 goto parse_fail;
900
901 default:
902 is_percent = 1;
903 break;
904 }
905 }
906
907 n_input_white_space_skipped = 0;
908 if (skip_input_white_space)
909 n_input_white_space_skipped = unformat_skip_white_space (input);
910
911 /* End of format string. */
912 if (cf == 0)
913 {
914 /* Force parse error when format string ends and input is
915 not white or at end. As an example, this is to prevent
916 format "foo" from matching input "food".
917 The last_non_white_space_match_percent is to make
918 "foo %d" match input "foo 10,bletch" with %d matching 10. */
919 if (skip_input_white_space
Dave Barachc3799992016-08-15 11:12:27 -0400920 && !last_non_white_space_match_percent
921 && !last_non_white_space_match_format
Ed Warnickecb9cada2015-12-08 15:45:58 -0700922 && n_input_white_space_skipped == 0
923 && input->index != UNFORMAT_END_OF_INPUT)
924 goto parse_fail;
925 break;
926 }
927
928 last_non_white_space_match_percent = is_percent;
929 last_non_white_space_match_format = 0;
930
931 /* Explicit spaces in format must match input white space. */
932 if (cf == ' ' && !default_skip_input_white_space)
933 {
934 if (n_input_white_space_skipped == 0)
935 goto parse_fail;
936 }
937
938 else if (is_percent)
939 {
Dave Barachc3799992016-08-15 11:12:27 -0400940 if (!(f = do_percent (input, va, f)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700941 goto parse_fail;
942 }
943
944 else
945 {
Neale Ranns32e1c012016-11-22 17:07:28 +0000946 const char *g = match_input_with_format (input, f);
Dave Barachc3799992016-08-15 11:12:27 -0400947 if (!g)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700948 goto parse_fail;
949 last_non_white_space_match_format = g > f;
950 f = g;
951 }
952 }
953
954 input_matches_format = 1;
Dave Barachc3799992016-08-15 11:12:27 -0400955parse_fail:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700956
957 /* Rewind buffer marks. */
958 {
959 uword l = vec_len (input->buffer_marks);
960
961 /* If we did not match back up buffer to last mark. */
Dave Barachc3799992016-08-15 11:12:27 -0400962 if (!input_matches_format)
963 input->index = input->buffer_marks[l - 1];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700964
965 _vec_len (input->buffer_marks) = l - 1;
966 }
967
968 return input_matches_format;
969}
970
971uword
Neale Ranns32e1c012016-11-22 17:07:28 +0000972unformat (unformat_input_t * input, const char *fmt, ...)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700973{
974 va_list va;
975 uword result;
976 va_start (va, fmt);
977 result = va_unformat (input, fmt, &va);
978 va_end (va);
979 return result;
980}
981
982uword
983unformat_user (unformat_input_t * input, unformat_function_t * func, ...)
984{
985 va_list va;
986 uword result, l;
987
988 /* Save place in input buffer in case parse fails. */
989 l = vec_len (input->buffer_marks);
Dave Barachc3799992016-08-15 11:12:27 -0400990 vec_add1_aligned (input->buffer_marks, input->index,
991 sizeof (input->buffer_marks[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700992
993 va_start (va, func);
994 result = func (input, &va);
995 va_end (va);
996
Dave Barachdddccea2016-10-26 14:03:20 -0400997 if (!result && input->index != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700998 input->index = input->buffer_marks[l];
999
1000 _vec_len (input->buffer_marks) = l;
1001
1002 return result;
1003}
1004
1005/* Setup for unformat of Unix style command line. */
Dave Barachc3799992016-08-15 11:12:27 -04001006void
1007unformat_init_command_line (unformat_input_t * input, char *argv[])
Ed Warnickecb9cada2015-12-08 15:45:58 -07001008{
1009 uword i;
1010
1011 unformat_init (input, 0, 0);
1012
1013 /* Concatenate argument strings with space in between. */
1014 for (i = 1; argv[i]; i++)
1015 {
1016 vec_add (input->buffer, argv[i], strlen (argv[i]));
1017 if (argv[i + 1])
1018 vec_add1 (input->buffer, ' ');
1019 }
1020}
1021
Dave Barachc3799992016-08-15 11:12:27 -04001022void
1023unformat_init_string (unformat_input_t * input, char *string, int string_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001024{
1025 unformat_init (input, 0, 0);
1026 if (string_len > 0)
1027 vec_add (input->buffer, string, string_len);
1028}
1029
Dave Barachc3799992016-08-15 11:12:27 -04001030void
1031unformat_init_vector (unformat_input_t * input, u8 * vector_string)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001032{
1033 unformat_init (input, 0, 0);
1034 input->buffer = vector_string;
1035}
1036
1037#ifdef CLIB_UNIX
1038
Dave Barachc3799992016-08-15 11:12:27 -04001039static uword
Dave Barach59b25652017-09-10 15:04:27 -04001040clib_file_fill_buffer (unformat_input_t * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001041{
1042 int fd = pointer_to_uword (input->fill_buffer_arg);
1043 uword l, n;
1044
1045 l = vec_len (input->buffer);
1046 vec_resize (input->buffer, 4096);
1047 n = read (fd, input->buffer + l, 4096);
1048 if (n > 0)
1049 _vec_len (input->buffer) = l + n;
1050
1051 if (n <= 0)
1052 return UNFORMAT_END_OF_INPUT;
1053 else
1054 return input->index;
1055}
1056
Dave Barachc3799992016-08-15 11:12:27 -04001057void
Dave Barach59b25652017-09-10 15:04:27 -04001058unformat_init_clib_file (unformat_input_t * input, int file_descriptor)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001059{
Dave Barach59b25652017-09-10 15:04:27 -04001060 unformat_init (input, clib_file_fill_buffer,
Ed Warnickecb9cada2015-12-08 15:45:58 -07001061 uword_to_pointer (file_descriptor, void *));
1062}
1063
1064/* Take input from Unix environment variable. */
Dave Barachc3799992016-08-15 11:12:27 -04001065uword
1066unformat_init_unix_env (unformat_input_t * input, char *var)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001067{
Dave Barachc3799992016-08-15 11:12:27 -04001068 char *val = getenv (var);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001069 if (val)
1070 unformat_init_string (input, val, strlen (val));
1071 return val != 0;
1072}
1073
1074#endif /* CLIB_UNIX */
1075
Dave Barachc3799992016-08-15 11:12:27 -04001076
1077/*
1078 * fd.io coding-style-patch-verification: ON
1079 *
1080 * Local Variables:
1081 * eval: (c-set-style "gnu")
1082 * End:
1083 */