blob: f626f05e3553b51fb42b765ebd5891e574dd489c [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
170 is delimited by balenced parenthesis. Other string is delimited by
171 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
338 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;
404 return 1;
405}
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;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700413 unformat_user (i, unformat_line, &line);
414 unformat_init_vector (result, line);
415 return 1;
416}
417
418/* Values for is_signed. */
419#define UNFORMAT_INTEGER_SIGNED 1
420#define UNFORMAT_INTEGER_UNSIGNED 0
421
422static uword
423unformat_integer (unformat_input_t * input,
Dave Barachc3799992016-08-15 11:12:27 -0400424 va_list * va, uword base, uword is_signed, uword data_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700425{
426 uword c, digit;
427 uword value = 0;
428 uword n_digits = 0;
429 uword n_input = 0;
430 uword sign = 0;
431
432 /* We only support bases <= 64. */
433 if (base < 2 || base > 64)
434 goto error;
435
436 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
437 {
438 switch (c)
439 {
440 case '-':
441 if (n_input == 0)
442 {
443 if (is_signed)
444 {
445 sign = 1;
446 goto next_digit;
447 }
448 else
449 /* Leading sign for unsigned number. */
450 goto error;
451 }
452 /* Sign after input (e.g. 100-200). */
453 goto put_input_done;
454
455 case '+':
Dave Barachc3799992016-08-15 11:12:27 -0400456 if (n_input > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700457 goto put_input_done;
458 sign = 0;
459 goto next_digit;
460
461 case '0' ... '9':
462 digit = c - '0';
463 break;
464
465 case 'a' ... 'z':
466 digit = 10 + (c - 'a');
467 break;
468
469 case 'A' ... 'Z':
470 digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A');
471 break;
472
473 case '/':
474 digit = 62;
475 break;
476
477 case '?':
478 digit = 63;
479 break;
480
481 default:
482 goto put_input_done;
483 }
484
485 if (digit >= base)
486 {
487 put_input_done:
488 unformat_put_input (input);
489 goto done;
490 }
491
492 {
Dave Barachc3799992016-08-15 11:12:27 -0400493 uword new_value = base * value + digit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700494
495 /* Check for overflow. */
496 if (new_value < value)
497 goto error;
498 value = new_value;
499 }
500 n_digits += 1;
501
502 next_digit:
503 n_input++;
504 }
505
Dave Barachc3799992016-08-15 11:12:27 -0400506done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700507 if (sign)
508 value = -value;
509
510 if (n_digits > 0)
511 {
Dave Barachc3799992016-08-15 11:12:27 -0400512 void *v = va_arg (*va, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700513
514 if (data_bytes == ~0)
Dave Barachc3799992016-08-15 11:12:27 -0400515 data_bytes = sizeof (int);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700516
517 switch (data_bytes)
518 {
Dave Barachc3799992016-08-15 11:12:27 -0400519 case 1:
520 *(u8 *) v = value;
521 break;
522 case 2:
523 *(u16 *) v = value;
524 break;
525 case 4:
526 *(u32 *) v = value;
527 break;
528 case 8:
529 *(u64 *) v = value;
530 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700531 default:
Dave Barachc3799992016-08-15 11:12:27 -0400532 goto error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700533 }
534
535 return 1;
536 }
537
Dave Barachc3799992016-08-15 11:12:27 -0400538error:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700539 return 0;
540}
541
542/* Return x 10^n */
Dave Barachc3799992016-08-15 11:12:27 -0400543static f64
544times_power_of_ten (f64 x, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700545{
546 if (n >= 0)
547 {
548 static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
549 while (n >= 8)
550 {
551 x *= 1e+8;
552 n -= 8;
553 }
554 return x * t[n];
555 }
556 else
557 {
558 static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
559 while (n <= -8)
560 {
561 x *= 1e-8;
562 n += 8;
563 }
564 return x * t[-n];
565 }
Dave Barachc3799992016-08-15 11:12:27 -0400566
Ed Warnickecb9cada2015-12-08 15:45:58 -0700567}
568
569static uword
Dave Barachc3799992016-08-15 11:12:27 -0400570unformat_float (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700571{
572 uword c;
573 u64 values[3];
574 uword n_digits[3], value_index = 0;
575 uword signs[2], sign_index = 0;
576 uword n_input = 0;
577
578 memset (values, 0, sizeof (values));
579 memset (n_digits, 0, sizeof (n_digits));
580 memset (signs, 0, sizeof (signs));
581
582 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
583 {
584 switch (c)
585 {
586 case '-':
587 if (value_index == 2 && n_digits[2] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400588 /* sign of exponent: it's ok. */ ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700589
590 else if (value_index < 2 && n_digits[0] > 0)
591 {
592 /* 123- */
593 unformat_put_input (input);
594 goto done;
595 }
596
597 else if (n_input > 0)
598 goto error;
599
600 signs[sign_index++] = 1;
601 goto next_digit;
602
603 case '+':
604 if (value_index == 2 && n_digits[2] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400605 /* sign of exponent: it's ok. */ ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700606
607 else if (value_index < 2 && n_digits[0] > 0)
608 {
609 /* 123+ */
610 unformat_put_input (input);
611 goto done;
612 }
613
614 else if (n_input > 0)
615 goto error;
616 signs[sign_index++] = 0;
617 goto next_digit;
618
619 case 'e':
620 case 'E':
621 if (n_input == 0)
622 goto error;
623 value_index = 2;
624 sign_index = 1;
625 break;
626
627 case '.':
628 if (value_index > 0)
629 goto error;
630 value_index = 1;
631 break;
632
633 case '0' ... '9':
634 {
635 u64 tmp;
636
637 tmp = values[value_index] * 10 + c - '0';
638
639 /* Check for overflow. */
640 if (tmp < values[value_index])
641 goto error;
642 values[value_index] = tmp;
643 n_digits[value_index] += 1;
644 }
645 break;
646
647 default:
648 unformat_put_input (input);
649 goto done;
650 }
651
652 next_digit:
653 n_input++;
654 }
655
Dave Barachc3799992016-08-15 11:12:27 -0400656done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700657 {
Dave Barachc3799992016-08-15 11:12:27 -0400658 f64 f_values[2], *value_return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700659 word expon;
660
661 /* Must have either whole or fraction digits. */
662 if (n_digits[0] + n_digits[1] <= 0)
663 goto error;
664
665 f_values[0] = values[0];
666 if (signs[0])
667 f_values[0] = -f_values[0];
668
669 f_values[1] = values[1];
670 f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]);
671
672 f_values[0] += f_values[1];
673
674 expon = values[2];
675 if (signs[1])
676 expon = -expon;
677
678 f_values[0] = times_power_of_ten (f_values[0], expon);
679
680 value_return = va_arg (*va, f64 *);
681 *value_return = f_values[0];
682 return 1;
683 }
684
Dave Barachc3799992016-08-15 11:12:27 -0400685error:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700686 return 0;
687}
688
Neale Ranns32e1c012016-11-22 17:07:28 +0000689static const char *
690match_input_with_format (unformat_input_t * input, const char *f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700691{
692 uword cf, ci;
693
694 ASSERT (*f != 0);
695
696 while (1)
697 {
698 cf = *f;
699 if (cf == 0 || cf == '%' || cf == ' ')
700 break;
701 f++;
702
703 ci = unformat_get_input (input);
704
705 if (cf != ci)
706 return 0;
707 }
708 return f;
709}
710
Neale Ranns32e1c012016-11-22 17:07:28 +0000711static const char *
712do_percent (unformat_input_t * input, va_list * va, const char *f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700713{
714 uword cf, n, data_bytes = ~0;
715
716 cf = *f++;
717
718 switch (cf)
719 {
720 default:
721 break;
722
723 case 'w':
724 /* Word types. */
725 cf = *f++;
726 data_bytes = sizeof (uword);
727 break;
728
729 case 'l':
730 cf = *f++;
731 if (cf == 'l')
732 {
733 cf = *f++;
734 data_bytes = sizeof (long long);
735 }
736 else
737 {
738 data_bytes = sizeof (long);
739 }
740 break;
Dave Barachc3799992016-08-15 11:12:27 -0400741
Ed Warnickecb9cada2015-12-08 15:45:58 -0700742 case 'L':
743 cf = *f++;
744 data_bytes = sizeof (long long);
745 break;
746 }
747
748 n = 0;
749 switch (cf)
750 {
751 case 'D':
752 data_bytes = va_arg (*va, int);
753 case 'd':
754 n = unformat_integer (input, va, 10,
755 UNFORMAT_INTEGER_SIGNED, data_bytes);
756 break;
757
758 case 'u':
759 n = unformat_integer (input, va, 10,
760 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
761 break;
762
763 case 'b':
764 n = unformat_integer (input, va, 2,
765 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
766 break;
767
768 case 'o':
769 n = unformat_integer (input, va, 8,
770 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
771 break;
772
773 case 'X':
774 data_bytes = va_arg (*va, int);
775 case 'x':
776 n = unformat_integer (input, va, 16,
777 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
778 break;
779
780 case 'f':
781 n = unformat_float (input, va);
782 break;
783
784 case 's':
785 case 'v':
786 n = unformat_string (input, f[0], cf, va);
787 break;
788
789 case 'U':
790 {
Dave Barachc3799992016-08-15 11:12:27 -0400791 unformat_function_t *f = va_arg (*va, unformat_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700792 n = f (input, va);
793 }
794 break;
795
796 case '=':
797 case '|':
798 {
Dave Barachc3799992016-08-15 11:12:27 -0400799 int *var = va_arg (*va, int *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700800 uword val = va_arg (*va, int);
801
802 if (cf == '|')
803 val |= *var;
804 *var = val;
805 n = 1;
806 }
807 break;
808 }
809
810 return n ? f : 0;
811}
812
Dave Barachc3799992016-08-15 11:12:27 -0400813uword
814unformat_skip_white_space (unformat_input_t * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700815{
816 uword n = 0;
817 uword c;
818
819 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
820 {
Dave Barachc3799992016-08-15 11:12:27 -0400821 if (!is_white_space (c))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700822 {
823 unformat_put_input (input);
824 break;
825 }
826 n++;
827 }
828 return n;
829}
830
831uword
Neale Ranns32e1c012016-11-22 17:07:28 +0000832va_unformat (unformat_input_t * input, const char *fmt, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700833{
Neale Ranns32e1c012016-11-22 17:07:28 +0000834 const char *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700835 uword input_matches_format;
836 uword default_skip_input_white_space;
837 uword n_input_white_space_skipped;
838 uword last_non_white_space_match_percent;
839 uword last_non_white_space_match_format;
840
Dave Barachc3799992016-08-15 11:12:27 -0400841 vec_add1_aligned (input->buffer_marks, input->index,
842 sizeof (input->buffer_marks[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700843
844 f = fmt;
845 default_skip_input_white_space = 1;
846 input_matches_format = 0;
847 last_non_white_space_match_percent = 0;
848 last_non_white_space_match_format = 0;
Dave Barachc3799992016-08-15 11:12:27 -0400849
Ed Warnickecb9cada2015-12-08 15:45:58 -0700850 while (1)
851 {
852 char cf;
853 uword is_percent, skip_input_white_space;
854
855 cf = *f;
856 is_percent = 0;
857
858 /* Always skip input white space at start of format string.
Dave Barachc3799992016-08-15 11:12:27 -0400859 Otherwise use default skip value which can be changed by %_
860 (see below). */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700861 skip_input_white_space = f == fmt || default_skip_input_white_space;
862
863 /* Spaces in format request skipping input white space. */
864 if (is_white_space (cf))
865 {
866 skip_input_white_space = 1;
867
868 /* Multiple format spaces are equivalent to a single white
869 space. */
870 while (is_white_space (*++f))
871 ;
872 }
873 else if (cf == '%')
874 {
875 /* %_ toggles whether or not to skip input white space. */
876 switch (*++f)
877 {
878 case '_':
Dave Barachc3799992016-08-15 11:12:27 -0400879 default_skip_input_white_space =
880 !default_skip_input_white_space;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700881 f++;
882 /* For transition from skip to no-skip in middle of format
Dave Barachc3799992016-08-15 11:12:27 -0400883 string, skip input white space. For example, the following matches:
884 fmt = "%_%d.%d%_->%_%d.%d%_"
885 input "1.2 -> 3.4"
886 Without this the space after -> does not get skipped. */
887 if (!default_skip_input_white_space
888 && !(f == fmt + 2 || *f == 0))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700889 unformat_skip_white_space (input);
890 continue;
891
Dave Barachc3799992016-08-15 11:12:27 -0400892 /* %% means match % */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700893 case '%':
894 break;
895
Dave Barachc3799992016-08-15 11:12:27 -0400896 /* % at end of format string. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700897 case 0:
898 goto parse_fail;
899
900 default:
901 is_percent = 1;
902 break;
903 }
904 }
905
906 n_input_white_space_skipped = 0;
907 if (skip_input_white_space)
908 n_input_white_space_skipped = unformat_skip_white_space (input);
909
910 /* End of format string. */
911 if (cf == 0)
912 {
913 /* Force parse error when format string ends and input is
914 not white or at end. As an example, this is to prevent
915 format "foo" from matching input "food".
916 The last_non_white_space_match_percent is to make
917 "foo %d" match input "foo 10,bletch" with %d matching 10. */
918 if (skip_input_white_space
Dave Barachc3799992016-08-15 11:12:27 -0400919 && !last_non_white_space_match_percent
920 && !last_non_white_space_match_format
Ed Warnickecb9cada2015-12-08 15:45:58 -0700921 && n_input_white_space_skipped == 0
922 && input->index != UNFORMAT_END_OF_INPUT)
923 goto parse_fail;
924 break;
925 }
926
927 last_non_white_space_match_percent = is_percent;
928 last_non_white_space_match_format = 0;
929
930 /* Explicit spaces in format must match input white space. */
931 if (cf == ' ' && !default_skip_input_white_space)
932 {
933 if (n_input_white_space_skipped == 0)
934 goto parse_fail;
935 }
936
937 else if (is_percent)
938 {
Dave Barachc3799992016-08-15 11:12:27 -0400939 if (!(f = do_percent (input, va, f)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700940 goto parse_fail;
941 }
942
943 else
944 {
Neale Ranns32e1c012016-11-22 17:07:28 +0000945 const char *g = match_input_with_format (input, f);
Dave Barachc3799992016-08-15 11:12:27 -0400946 if (!g)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700947 goto parse_fail;
948 last_non_white_space_match_format = g > f;
949 f = g;
950 }
951 }
952
953 input_matches_format = 1;
Dave Barachc3799992016-08-15 11:12:27 -0400954parse_fail:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700955
956 /* Rewind buffer marks. */
957 {
958 uword l = vec_len (input->buffer_marks);
959
960 /* If we did not match back up buffer to last mark. */
Dave Barachc3799992016-08-15 11:12:27 -0400961 if (!input_matches_format)
962 input->index = input->buffer_marks[l - 1];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700963
964 _vec_len (input->buffer_marks) = l - 1;
965 }
966
967 return input_matches_format;
968}
969
970uword
Neale Ranns32e1c012016-11-22 17:07:28 +0000971unformat (unformat_input_t * input, const char *fmt, ...)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700972{
973 va_list va;
974 uword result;
975 va_start (va, fmt);
976 result = va_unformat (input, fmt, &va);
977 va_end (va);
978 return result;
979}
980
981uword
982unformat_user (unformat_input_t * input, unformat_function_t * func, ...)
983{
984 va_list va;
985 uword result, l;
986
987 /* Save place in input buffer in case parse fails. */
988 l = vec_len (input->buffer_marks);
Dave Barachc3799992016-08-15 11:12:27 -0400989 vec_add1_aligned (input->buffer_marks, input->index,
990 sizeof (input->buffer_marks[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700991
992 va_start (va, func);
993 result = func (input, &va);
994 va_end (va);
995
Dave Barachdddccea2016-10-26 14:03:20 -0400996 if (!result && input->index != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700997 input->index = input->buffer_marks[l];
998
999 _vec_len (input->buffer_marks) = l;
1000
1001 return result;
1002}
1003
1004/* Setup for unformat of Unix style command line. */
Dave Barachc3799992016-08-15 11:12:27 -04001005void
1006unformat_init_command_line (unformat_input_t * input, char *argv[])
Ed Warnickecb9cada2015-12-08 15:45:58 -07001007{
1008 uword i;
1009
1010 unformat_init (input, 0, 0);
1011
1012 /* Concatenate argument strings with space in between. */
1013 for (i = 1; argv[i]; i++)
1014 {
1015 vec_add (input->buffer, argv[i], strlen (argv[i]));
1016 if (argv[i + 1])
1017 vec_add1 (input->buffer, ' ');
1018 }
1019}
1020
Dave Barachc3799992016-08-15 11:12:27 -04001021void
1022unformat_init_string (unformat_input_t * input, char *string, int string_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001023{
1024 unformat_init (input, 0, 0);
1025 if (string_len > 0)
1026 vec_add (input->buffer, string, string_len);
1027}
1028
Dave Barachc3799992016-08-15 11:12:27 -04001029void
1030unformat_init_vector (unformat_input_t * input, u8 * vector_string)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001031{
1032 unformat_init (input, 0, 0);
1033 input->buffer = vector_string;
1034}
1035
1036#ifdef CLIB_UNIX
1037
Dave Barachc3799992016-08-15 11:12:27 -04001038static uword
1039unix_file_fill_buffer (unformat_input_t * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001040{
1041 int fd = pointer_to_uword (input->fill_buffer_arg);
1042 uword l, n;
1043
1044 l = vec_len (input->buffer);
1045 vec_resize (input->buffer, 4096);
1046 n = read (fd, input->buffer + l, 4096);
1047 if (n > 0)
1048 _vec_len (input->buffer) = l + n;
1049
1050 if (n <= 0)
1051 return UNFORMAT_END_OF_INPUT;
1052 else
1053 return input->index;
1054}
1055
Dave Barachc3799992016-08-15 11:12:27 -04001056void
1057unformat_init_unix_file (unformat_input_t * input, int file_descriptor)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001058{
1059 unformat_init (input, unix_file_fill_buffer,
1060 uword_to_pointer (file_descriptor, void *));
1061}
1062
1063/* Take input from Unix environment variable. */
Dave Barachc3799992016-08-15 11:12:27 -04001064uword
1065unformat_init_unix_env (unformat_input_t * input, char *var)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001066{
Dave Barachc3799992016-08-15 11:12:27 -04001067 char *val = getenv (var);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001068 if (val)
1069 unformat_init_string (input, val, strlen (val));
1070 return val != 0;
1071}
1072
1073#endif /* CLIB_UNIX */
1074
Dave Barachc3799992016-08-15 11:12:27 -04001075
1076/*
1077 * fd.io coding-style-patch-verification: ON
1078 *
1079 * Local Variables:
1080 * eval: (c-set-style "gnu")
1081 * End:
1082 */