blob: ac8b7ddc712c5b7e8afcb390d6f982349d6dbdee [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 }
309
310 *hexstring_return = s;
311 return 1;
312}
313
314/* unformat (input "foo%U", unformat_eof) matches terminal foo only */
315uword
316unformat_eof (unformat_input_t * input, va_list * va)
317{
318 return unformat_check_input (input) == UNFORMAT_END_OF_INPUT;
319}
320
321/* Parse a token containing given set of characters. */
322uword
Dave Barachc3799992016-08-15 11:12:27 -0400323unformat_token (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700324{
Dave Barachc3799992016-08-15 11:12:27 -0400325 u8 *token_chars = va_arg (*va, u8 *);
326 u8 **string_return = va_arg (*va, u8 **);
327 u8 *s, map[256];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700328 uword i, c;
329
Dave Barachc3799992016-08-15 11:12:27 -0400330 if (!token_chars)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700331 token_chars = (u8 *) "a-zA-Z0-9_";
332
333 memset (map, 0, sizeof (map));
Dave Barachc3799992016-08-15 11:12:27 -0400334 for (s = token_chars; *s;)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700335 {
336 /* Parse range. */
337 if (s[0] < s[2] && s[1] == '-')
338 {
339 for (i = s[0]; i <= s[2]; i++)
340 map[i] = 1;
341 s = s + 3;
Dave Barachc3799992016-08-15 11:12:27 -0400342 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700343 else
344 {
345 map[s[0]] = 1;
346 s = s + 1;
347 }
348 }
349
350 s = 0;
351 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
352 {
Dave Barachc3799992016-08-15 11:12:27 -0400353 if (!map[c])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700354 {
355 unformat_put_input (input);
356 break;
357 }
Dave Barachc3799992016-08-15 11:12:27 -0400358
Ed Warnickecb9cada2015-12-08 15:45:58 -0700359 vec_add1 (s, c);
360 }
361
362 if (vec_len (s) == 0)
363 return 0;
364
365 *string_return = s;
366 return 1;
367}
368
369/* Unformat (parse) function which reads a %s string and converts it
370 to and unformat_input_t. */
Dave Barachc3799992016-08-15 11:12:27 -0400371uword
372unformat_input (unformat_input_t * i, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700373{
Dave Barachc3799992016-08-15 11:12:27 -0400374 unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
375 u8 *s;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700376
377 if (unformat (i, "%v", &s))
378 {
379 unformat_init_vector (sub_input, s);
380 return 1;
381 }
382
383 return 0;
384}
385
386/* Parse a line ending with \n and return it. */
Dave Barachc3799992016-08-15 11:12:27 -0400387uword
388unformat_line (unformat_input_t * i, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700389{
Dave Barachc3799992016-08-15 11:12:27 -0400390 u8 *line = 0, **result = va_arg (*va, u8 **);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700391 uword c;
392
Dave Barachc3799992016-08-15 11:12:27 -0400393 while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394 {
395 vec_add1 (line, c);
396 }
397
398 *result = line;
399 return 1;
400}
401
402/* Parse a line ending with \n and return it as an unformat_input_t. */
Dave Barachc3799992016-08-15 11:12:27 -0400403uword
404unformat_line_input (unformat_input_t * i, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405{
Dave Barachc3799992016-08-15 11:12:27 -0400406 unformat_input_t *result = va_arg (*va, unformat_input_t *);
407 u8 *line;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700408 unformat_user (i, unformat_line, &line);
409 unformat_init_vector (result, line);
410 return 1;
411}
412
413/* Values for is_signed. */
414#define UNFORMAT_INTEGER_SIGNED 1
415#define UNFORMAT_INTEGER_UNSIGNED 0
416
417static uword
418unformat_integer (unformat_input_t * input,
Dave Barachc3799992016-08-15 11:12:27 -0400419 va_list * va, uword base, uword is_signed, uword data_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700420{
421 uword c, digit;
422 uword value = 0;
423 uword n_digits = 0;
424 uword n_input = 0;
425 uword sign = 0;
426
427 /* We only support bases <= 64. */
428 if (base < 2 || base > 64)
429 goto error;
430
431 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
432 {
433 switch (c)
434 {
435 case '-':
436 if (n_input == 0)
437 {
438 if (is_signed)
439 {
440 sign = 1;
441 goto next_digit;
442 }
443 else
444 /* Leading sign for unsigned number. */
445 goto error;
446 }
447 /* Sign after input (e.g. 100-200). */
448 goto put_input_done;
449
450 case '+':
Dave Barachc3799992016-08-15 11:12:27 -0400451 if (n_input > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700452 goto put_input_done;
453 sign = 0;
454 goto next_digit;
455
456 case '0' ... '9':
457 digit = c - '0';
458 break;
459
460 case 'a' ... 'z':
461 digit = 10 + (c - 'a');
462 break;
463
464 case 'A' ... 'Z':
465 digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A');
466 break;
467
468 case '/':
469 digit = 62;
470 break;
471
472 case '?':
473 digit = 63;
474 break;
475
476 default:
477 goto put_input_done;
478 }
479
480 if (digit >= base)
481 {
482 put_input_done:
483 unformat_put_input (input);
484 goto done;
485 }
486
487 {
Dave Barachc3799992016-08-15 11:12:27 -0400488 uword new_value = base * value + digit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489
490 /* Check for overflow. */
491 if (new_value < value)
492 goto error;
493 value = new_value;
494 }
495 n_digits += 1;
496
497 next_digit:
498 n_input++;
499 }
500
Dave Barachc3799992016-08-15 11:12:27 -0400501done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700502 if (sign)
503 value = -value;
504
505 if (n_digits > 0)
506 {
Dave Barachc3799992016-08-15 11:12:27 -0400507 void *v = va_arg (*va, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700508
509 if (data_bytes == ~0)
Dave Barachc3799992016-08-15 11:12:27 -0400510 data_bytes = sizeof (int);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700511
512 switch (data_bytes)
513 {
Dave Barachc3799992016-08-15 11:12:27 -0400514 case 1:
515 *(u8 *) v = value;
516 break;
517 case 2:
518 *(u16 *) v = value;
519 break;
520 case 4:
521 *(u32 *) v = value;
522 break;
523 case 8:
524 *(u64 *) v = value;
525 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700526 default:
Dave Barachc3799992016-08-15 11:12:27 -0400527 goto error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700528 }
529
530 return 1;
531 }
532
Dave Barachc3799992016-08-15 11:12:27 -0400533error:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700534 return 0;
535}
536
537/* Return x 10^n */
Dave Barachc3799992016-08-15 11:12:27 -0400538static f64
539times_power_of_ten (f64 x, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700540{
541 if (n >= 0)
542 {
543 static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
544 while (n >= 8)
545 {
546 x *= 1e+8;
547 n -= 8;
548 }
549 return x * t[n];
550 }
551 else
552 {
553 static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
554 while (n <= -8)
555 {
556 x *= 1e-8;
557 n += 8;
558 }
559 return x * t[-n];
560 }
Dave Barachc3799992016-08-15 11:12:27 -0400561
Ed Warnickecb9cada2015-12-08 15:45:58 -0700562}
563
564static uword
Dave Barachc3799992016-08-15 11:12:27 -0400565unformat_float (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700566{
567 uword c;
568 u64 values[3];
569 uword n_digits[3], value_index = 0;
570 uword signs[2], sign_index = 0;
571 uword n_input = 0;
572
573 memset (values, 0, sizeof (values));
574 memset (n_digits, 0, sizeof (n_digits));
575 memset (signs, 0, sizeof (signs));
576
577 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
578 {
579 switch (c)
580 {
581 case '-':
582 if (value_index == 2 && n_digits[2] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400583 /* sign of exponent: it's ok. */ ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700584
585 else if (value_index < 2 && n_digits[0] > 0)
586 {
587 /* 123- */
588 unformat_put_input (input);
589 goto done;
590 }
591
592 else if (n_input > 0)
593 goto error;
594
595 signs[sign_index++] = 1;
596 goto next_digit;
597
598 case '+':
599 if (value_index == 2 && n_digits[2] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400600 /* sign of exponent: it's ok. */ ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700601
602 else if (value_index < 2 && n_digits[0] > 0)
603 {
604 /* 123+ */
605 unformat_put_input (input);
606 goto done;
607 }
608
609 else if (n_input > 0)
610 goto error;
611 signs[sign_index++] = 0;
612 goto next_digit;
613
614 case 'e':
615 case 'E':
616 if (n_input == 0)
617 goto error;
618 value_index = 2;
619 sign_index = 1;
620 break;
621
622 case '.':
623 if (value_index > 0)
624 goto error;
625 value_index = 1;
626 break;
627
628 case '0' ... '9':
629 {
630 u64 tmp;
631
632 tmp = values[value_index] * 10 + c - '0';
633
634 /* Check for overflow. */
635 if (tmp < values[value_index])
636 goto error;
637 values[value_index] = tmp;
638 n_digits[value_index] += 1;
639 }
640 break;
641
642 default:
643 unformat_put_input (input);
644 goto done;
645 }
646
647 next_digit:
648 n_input++;
649 }
650
Dave Barachc3799992016-08-15 11:12:27 -0400651done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700652 {
Dave Barachc3799992016-08-15 11:12:27 -0400653 f64 f_values[2], *value_return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700654 word expon;
655
656 /* Must have either whole or fraction digits. */
657 if (n_digits[0] + n_digits[1] <= 0)
658 goto error;
659
660 f_values[0] = values[0];
661 if (signs[0])
662 f_values[0] = -f_values[0];
663
664 f_values[1] = values[1];
665 f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]);
666
667 f_values[0] += f_values[1];
668
669 expon = values[2];
670 if (signs[1])
671 expon = -expon;
672
673 f_values[0] = times_power_of_ten (f_values[0], expon);
674
675 value_return = va_arg (*va, f64 *);
676 *value_return = f_values[0];
677 return 1;
678 }
679
Dave Barachc3799992016-08-15 11:12:27 -0400680error:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700681 return 0;
682}
683
Dave Barachc3799992016-08-15 11:12:27 -0400684static char *
685match_input_with_format (unformat_input_t * input, char *f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700686{
687 uword cf, ci;
688
689 ASSERT (*f != 0);
690
691 while (1)
692 {
693 cf = *f;
694 if (cf == 0 || cf == '%' || cf == ' ')
695 break;
696 f++;
697
698 ci = unformat_get_input (input);
699
700 if (cf != ci)
701 return 0;
702 }
703 return f;
704}
705
Dave Barachc3799992016-08-15 11:12:27 -0400706static char *
707do_percent (unformat_input_t * input, va_list * va, char *f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700708{
709 uword cf, n, data_bytes = ~0;
710
711 cf = *f++;
712
713 switch (cf)
714 {
715 default:
716 break;
717
718 case 'w':
719 /* Word types. */
720 cf = *f++;
721 data_bytes = sizeof (uword);
722 break;
723
724 case 'l':
725 cf = *f++;
726 if (cf == 'l')
727 {
728 cf = *f++;
729 data_bytes = sizeof (long long);
730 }
731 else
732 {
733 data_bytes = sizeof (long);
734 }
735 break;
Dave Barachc3799992016-08-15 11:12:27 -0400736
Ed Warnickecb9cada2015-12-08 15:45:58 -0700737 case 'L':
738 cf = *f++;
739 data_bytes = sizeof (long long);
740 break;
741 }
742
743 n = 0;
744 switch (cf)
745 {
746 case 'D':
747 data_bytes = va_arg (*va, int);
748 case 'd':
749 n = unformat_integer (input, va, 10,
750 UNFORMAT_INTEGER_SIGNED, data_bytes);
751 break;
752
753 case 'u':
754 n = unformat_integer (input, va, 10,
755 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
756 break;
757
758 case 'b':
759 n = unformat_integer (input, va, 2,
760 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
761 break;
762
763 case 'o':
764 n = unformat_integer (input, va, 8,
765 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
766 break;
767
768 case 'X':
769 data_bytes = va_arg (*va, int);
770 case 'x':
771 n = unformat_integer (input, va, 16,
772 UNFORMAT_INTEGER_UNSIGNED, data_bytes);
773 break;
774
775 case 'f':
776 n = unformat_float (input, va);
777 break;
778
779 case 's':
780 case 'v':
781 n = unformat_string (input, f[0], cf, va);
782 break;
783
784 case 'U':
785 {
Dave Barachc3799992016-08-15 11:12:27 -0400786 unformat_function_t *f = va_arg (*va, unformat_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700787 n = f (input, va);
788 }
789 break;
790
791 case '=':
792 case '|':
793 {
Dave Barachc3799992016-08-15 11:12:27 -0400794 int *var = va_arg (*va, int *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700795 uword val = va_arg (*va, int);
796
797 if (cf == '|')
798 val |= *var;
799 *var = val;
800 n = 1;
801 }
802 break;
803 }
804
805 return n ? f : 0;
806}
807
Dave Barachc3799992016-08-15 11:12:27 -0400808uword
809unformat_skip_white_space (unformat_input_t * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700810{
811 uword n = 0;
812 uword c;
813
814 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
815 {
Dave Barachc3799992016-08-15 11:12:27 -0400816 if (!is_white_space (c))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700817 {
818 unformat_put_input (input);
819 break;
820 }
821 n++;
822 }
823 return n;
824}
825
826uword
Dave Barachc3799992016-08-15 11:12:27 -0400827va_unformat (unformat_input_t * input, char *fmt, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700828{
Dave Barachc3799992016-08-15 11:12:27 -0400829 char *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700830 uword input_matches_format;
831 uword default_skip_input_white_space;
832 uword n_input_white_space_skipped;
833 uword last_non_white_space_match_percent;
834 uword last_non_white_space_match_format;
835
Dave Barachc3799992016-08-15 11:12:27 -0400836 vec_add1_aligned (input->buffer_marks, input->index,
837 sizeof (input->buffer_marks[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700838
839 f = fmt;
840 default_skip_input_white_space = 1;
841 input_matches_format = 0;
842 last_non_white_space_match_percent = 0;
843 last_non_white_space_match_format = 0;
Dave Barachc3799992016-08-15 11:12:27 -0400844
Ed Warnickecb9cada2015-12-08 15:45:58 -0700845 while (1)
846 {
847 char cf;
848 uword is_percent, skip_input_white_space;
849
850 cf = *f;
851 is_percent = 0;
852
853 /* Always skip input white space at start of format string.
Dave Barachc3799992016-08-15 11:12:27 -0400854 Otherwise use default skip value which can be changed by %_
855 (see below). */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700856 skip_input_white_space = f == fmt || default_skip_input_white_space;
857
858 /* Spaces in format request skipping input white space. */
859 if (is_white_space (cf))
860 {
861 skip_input_white_space = 1;
862
863 /* Multiple format spaces are equivalent to a single white
864 space. */
865 while (is_white_space (*++f))
866 ;
867 }
868 else if (cf == '%')
869 {
870 /* %_ toggles whether or not to skip input white space. */
871 switch (*++f)
872 {
873 case '_':
Dave Barachc3799992016-08-15 11:12:27 -0400874 default_skip_input_white_space =
875 !default_skip_input_white_space;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700876 f++;
877 /* For transition from skip to no-skip in middle of format
Dave Barachc3799992016-08-15 11:12:27 -0400878 string, skip input white space. For example, the following matches:
879 fmt = "%_%d.%d%_->%_%d.%d%_"
880 input "1.2 -> 3.4"
881 Without this the space after -> does not get skipped. */
882 if (!default_skip_input_white_space
883 && !(f == fmt + 2 || *f == 0))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700884 unformat_skip_white_space (input);
885 continue;
886
Dave Barachc3799992016-08-15 11:12:27 -0400887 /* %% means match % */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700888 case '%':
889 break;
890
Dave Barachc3799992016-08-15 11:12:27 -0400891 /* % at end of format string. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700892 case 0:
893 goto parse_fail;
894
895 default:
896 is_percent = 1;
897 break;
898 }
899 }
900
901 n_input_white_space_skipped = 0;
902 if (skip_input_white_space)
903 n_input_white_space_skipped = unformat_skip_white_space (input);
904
905 /* End of format string. */
906 if (cf == 0)
907 {
908 /* Force parse error when format string ends and input is
909 not white or at end. As an example, this is to prevent
910 format "foo" from matching input "food".
911 The last_non_white_space_match_percent is to make
912 "foo %d" match input "foo 10,bletch" with %d matching 10. */
913 if (skip_input_white_space
Dave Barachc3799992016-08-15 11:12:27 -0400914 && !last_non_white_space_match_percent
915 && !last_non_white_space_match_format
Ed Warnickecb9cada2015-12-08 15:45:58 -0700916 && n_input_white_space_skipped == 0
917 && input->index != UNFORMAT_END_OF_INPUT)
918 goto parse_fail;
919 break;
920 }
921
922 last_non_white_space_match_percent = is_percent;
923 last_non_white_space_match_format = 0;
924
925 /* Explicit spaces in format must match input white space. */
926 if (cf == ' ' && !default_skip_input_white_space)
927 {
928 if (n_input_white_space_skipped == 0)
929 goto parse_fail;
930 }
931
932 else if (is_percent)
933 {
Dave Barachc3799992016-08-15 11:12:27 -0400934 if (!(f = do_percent (input, va, f)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700935 goto parse_fail;
936 }
937
938 else
939 {
Dave Barachc3799992016-08-15 11:12:27 -0400940 char *g = match_input_with_format (input, f);
941 if (!g)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942 goto parse_fail;
943 last_non_white_space_match_format = g > f;
944 f = g;
945 }
946 }
947
948 input_matches_format = 1;
Dave Barachc3799992016-08-15 11:12:27 -0400949parse_fail:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700950
951 /* Rewind buffer marks. */
952 {
953 uword l = vec_len (input->buffer_marks);
954
955 /* If we did not match back up buffer to last mark. */
Dave Barachc3799992016-08-15 11:12:27 -0400956 if (!input_matches_format)
957 input->index = input->buffer_marks[l - 1];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700958
959 _vec_len (input->buffer_marks) = l - 1;
960 }
961
962 return input_matches_format;
963}
964
965uword
Dave Barachc3799992016-08-15 11:12:27 -0400966unformat (unformat_input_t * input, char *fmt, ...)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700967{
968 va_list va;
969 uword result;
970 va_start (va, fmt);
971 result = va_unformat (input, fmt, &va);
972 va_end (va);
973 return result;
974}
975
976uword
977unformat_user (unformat_input_t * input, unformat_function_t * func, ...)
978{
979 va_list va;
980 uword result, l;
981
982 /* Save place in input buffer in case parse fails. */
983 l = vec_len (input->buffer_marks);
Dave Barachc3799992016-08-15 11:12:27 -0400984 vec_add1_aligned (input->buffer_marks, input->index,
985 sizeof (input->buffer_marks[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700986
987 va_start (va, func);
988 result = func (input, &va);
989 va_end (va);
990
Dave Barachdddccea2016-10-26 14:03:20 -0400991 if (!result && input->index != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700992 input->index = input->buffer_marks[l];
993
994 _vec_len (input->buffer_marks) = l;
995
996 return result;
997}
998
999/* Setup for unformat of Unix style command line. */
Dave Barachc3799992016-08-15 11:12:27 -04001000void
1001unformat_init_command_line (unformat_input_t * input, char *argv[])
Ed Warnickecb9cada2015-12-08 15:45:58 -07001002{
1003 uword i;
1004
1005 unformat_init (input, 0, 0);
1006
1007 /* Concatenate argument strings with space in between. */
1008 for (i = 1; argv[i]; i++)
1009 {
1010 vec_add (input->buffer, argv[i], strlen (argv[i]));
1011 if (argv[i + 1])
1012 vec_add1 (input->buffer, ' ');
1013 }
1014}
1015
Dave Barachc3799992016-08-15 11:12:27 -04001016void
1017unformat_init_string (unformat_input_t * input, char *string, int string_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001018{
1019 unformat_init (input, 0, 0);
1020 if (string_len > 0)
1021 vec_add (input->buffer, string, string_len);
1022}
1023
Dave Barachc3799992016-08-15 11:12:27 -04001024void
1025unformat_init_vector (unformat_input_t * input, u8 * vector_string)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001026{
1027 unformat_init (input, 0, 0);
1028 input->buffer = vector_string;
1029}
1030
1031#ifdef CLIB_UNIX
1032
Dave Barachc3799992016-08-15 11:12:27 -04001033static uword
1034unix_file_fill_buffer (unformat_input_t * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001035{
1036 int fd = pointer_to_uword (input->fill_buffer_arg);
1037 uword l, n;
1038
1039 l = vec_len (input->buffer);
1040 vec_resize (input->buffer, 4096);
1041 n = read (fd, input->buffer + l, 4096);
1042 if (n > 0)
1043 _vec_len (input->buffer) = l + n;
1044
1045 if (n <= 0)
1046 return UNFORMAT_END_OF_INPUT;
1047 else
1048 return input->index;
1049}
1050
Dave Barachc3799992016-08-15 11:12:27 -04001051void
1052unformat_init_unix_file (unformat_input_t * input, int file_descriptor)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001053{
1054 unformat_init (input, unix_file_fill_buffer,
1055 uword_to_pointer (file_descriptor, void *));
1056}
1057
1058/* Take input from Unix environment variable. */
Dave Barachc3799992016-08-15 11:12:27 -04001059uword
1060unformat_init_unix_env (unformat_input_t * input, char *var)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001061{
Dave Barachc3799992016-08-15 11:12:27 -04001062 char *val = getenv (var);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001063 if (val)
1064 unformat_init_string (input, val, strlen (val));
1065 return val != 0;
1066}
1067
1068#endif /* CLIB_UNIX */
1069
Dave Barachc3799992016-08-15 11:12:27 -04001070
1071/*
1072 * fd.io coding-style-patch-verification: ON
1073 *
1074 * Local Variables:
1075 * eval: (c-set-style "gnu")
1076 * End:
1077 */