FD.io VPP  v19.04.1-1-ge4a0f9f
Vector Packet Processing
unformat.c
Go to the documentation of this file.
1 /*
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. */
41 uword
42 _unformat_fill_input (unformat_input_t * i)
43 {
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 
75 {
76  switch (c)
77  {
78  case ' ':
79  case '\t':
80  case '\n':
81  case '\r':
82  return 1;
83 
84  default:
85  return 0;
86  }
87 }
88 
89 /* Format function for dumping input stream. */
90 u8 *
91 format_unformat_error (u8 * s, va_list * va)
92 {
93  unformat_input_t *i = va_arg (*va, unformat_input_t *);
94  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;
102  u8 *p, *p_end;
103 
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  {
118  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;
130  }
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. */
142 u8 *
143 format_unformat_input (u8 * s, va_list * va)
144 {
145  unformat_input_t *i = va_arg (*va, unformat_input_t *);
146  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
162 void
164 {
165  fformat (stderr, "%U\n", format_unformat_input, i);
166 }
167 #endif
168 
169 /* Parse delimited vector string. If string starts with { then string
170  is delimited by balanced parenthesis. Other string is delimited by
171  white space. {} were chosen since they are special to the shell. */
172 static uword
174  uword delimiter_character,
175  uword format_character, va_list * va)
176 {
177  u8 **string_return = va_arg (*va, u8 **);
178  u8 *s = 0;
179  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':
229  if (!is_paren_delimited)
230  {
231  unformat_put_input (input);
232  goto done;
233  }
234  break;
235 
236  default:
237  if (!is_paren_delimited && c == delimiter_character)
238  {
239  unformat_put_input (input);
240  goto done;
241  }
242  }
243 
244  if (add_to_vector)
245  vec_add1 (s, c);
246  }
247 
248 done:
249  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)
253  vec_add1 (s, '{');
254 
255  /* Don't match null string. */
256  if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0)
257  return 0;
258 
259  /* 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 
271 uword
272 unformat_hex_string (unformat_input_t * input, va_list * va)
273 {
274  u8 **hexstring_return = va_arg (*va, u8 **);
275  u8 *s;
276  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')
284  d = 16 * d + c - '0';
285  else if (c >= 'a' && c <= 'f')
286  d = 16 * d + 10 + c - 'a';
287  else if (c >= 'A' && c <= 'F')
288  d = 16 * d + 10 + c - 'A';
289  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  /* Make sure something was processed. */
310  else if (s == 0)
311  {
312  return 0;
313  }
314 
315  *hexstring_return = s;
316  return 1;
317 }
318 
319 /* unformat (input "foo%U", unformat_eof) matches terminal foo only */
320 uword
321 unformat_eof (unformat_input_t * input, va_list * va)
322 {
324 }
325 
326 /* Parse a token containing given set of characters. */
327 uword
328 unformat_token (unformat_input_t * input, va_list * va)
329 {
330  u8 *token_chars = va_arg (*va, u8 *);
331  u8 **string_return = va_arg (*va, u8 **);
332  u8 *s, map[256];
333  uword i, c;
334 
335  if (!token_chars)
336  token_chars = (u8 *) "a-zA-Z0-9_";
337 
338  clib_memset (map, 0, sizeof (map));
339  for (s = token_chars; *s;)
340  {
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;
347  }
348  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  {
358  if (!map[c])
359  {
360  unformat_put_input (input);
361  break;
362  }
363 
364  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. */
376 uword
377 unformat_input (unformat_input_t * i, va_list * args)
378 {
379  unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
380  u8 *s;
381 
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. */
392 uword
393 unformat_line (unformat_input_t * i, va_list * va)
394 {
395  u8 *line = 0, **result = va_arg (*va, u8 **);
396  uword c;
397 
398  while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT)
399  {
400  vec_add1 (line, c);
401  }
402 
403  *result = line;
404  return vec_len (line);
405 }
406 
407 /* Parse a line ending with \n and return it as an unformat_input_t. */
408 uword
410 {
411  unformat_input_t *result = va_arg (*va, unformat_input_t *);
412  u8 *line;
413  if (!unformat_user (i, unformat_line, &line))
414  return 0;
415  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 
423 static uword
425  va_list * va, uword base, uword is_signed, uword data_bytes)
426 {
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 '+':
457  if (n_input > 0)
458  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  {
494  uword new_value = base * value + digit;
495 
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 
507 done:
508  if (sign)
509  value = -value;
510 
511  if (n_digits > 0)
512  {
513  void *v = va_arg (*va, void *);
514 
515  if (data_bytes == ~0)
516  data_bytes = sizeof (int);
517 
518  switch (data_bytes)
519  {
520  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;
532  default:
533  goto error;
534  }
535 
536  return 1;
537  }
538 
539 error:
540  return 0;
541 }
542 
543 /* Return x 10^n */
544 static f64
546 {
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  }
567 
568 }
569 
570 static uword
571 unformat_float (unformat_input_t * input, va_list * va)
572 {
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 
579  clib_memset (values, 0, sizeof (values));
580  clib_memset (n_digits, 0, sizeof (n_digits));
581  clib_memset (signs, 0, sizeof (signs));
582 
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)
589  /* sign of exponent: it's ok. */ ;
590 
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)
606  /* sign of exponent: it's ok. */ ;
607 
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 
657 done:
658  {
659  f64 f_values[2], *value_return;
660  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 
686 error:
687  return 0;
688 }
689 
690 static const char *
692 {
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 
712 static const char *
713 do_percent (unformat_input_t * input, va_list * va, const char *f)
714 {
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;
742 
743  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  {
792  unformat_function_t *f = va_arg (*va, unformat_function_t *);
793  n = f (input, va);
794  }
795  break;
796 
797  case '=':
798  case '|':
799  {
800  int *var = va_arg (*va, int *);
801  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 
814 uword
816 {
817  uword n = 0;
818  uword c;
819 
820  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
821  {
822  if (!is_white_space (c))
823  {
824  unformat_put_input (input);
825  break;
826  }
827  n++;
828  }
829  return n;
830 }
831 
832 uword
833 va_unformat (unformat_input_t * input, const char *fmt, va_list * va)
834 {
835  const char *f;
836  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 
842  vec_add1_aligned (input->buffer_marks, input->index,
843  sizeof (input->buffer_marks[0]));
844 
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;
850 
851  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.
860  Otherwise use default skip value which can be changed by %_
861  (see below). */
862  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 '_':
880  default_skip_input_white_space =
881  !default_skip_input_white_space;
882  f++;
883  /* For transition from skip to no-skip in middle of format
884  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))
891  continue;
892 
893  /* %% means match % */
894  case '%':
895  break;
896 
897  /* % at end of format string. */
898  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
920  && !last_non_white_space_match_percent
921  && !last_non_white_space_match_format
922  && 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  {
940  if (!(f = do_percent (input, va, f)))
941  goto parse_fail;
942  }
943 
944  else
945  {
946  const char *g = match_input_with_format (input, f);
947  if (!g)
948  goto parse_fail;
949  last_non_white_space_match_format = g > f;
950  f = g;
951  }
952  }
953 
954  input_matches_format = 1;
955 parse_fail:
956 
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. */
962  if (!input_matches_format)
963  input->index = input->buffer_marks[l - 1];
964 
965  _vec_len (input->buffer_marks) = l - 1;
966  }
967 
968  return input_matches_format;
969 }
970 
971 uword
972 unformat (unformat_input_t * input, const char *fmt, ...)
973 {
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 
982 uword
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);
990  vec_add1_aligned (input->buffer_marks, input->index,
991  sizeof (input->buffer_marks[0]));
992 
993  va_start (va, func);
994  result = func (input, &va);
995  va_end (va);
996 
997  if (!result && input->index != UNFORMAT_END_OF_INPUT)
998  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. */
1006 void
1008 {
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 
1022 void
1023 unformat_init_string (unformat_input_t * input, char *string, int string_len)
1024 {
1025  unformat_init (input, 0, 0);
1026  if (string_len > 0)
1027  vec_add (input->buffer, string, string_len);
1028 }
1029 
1030 void
1031 unformat_init_vector (unformat_input_t * input, u8 * vector_string)
1032 {
1033  unformat_init (input, 0, 0);
1034  input->buffer = vector_string;
1035 }
1036 
1037 #ifdef CLIB_UNIX
1038 
1039 static uword
1041 {
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 
1057 void
1058 unformat_init_clib_file (unformat_input_t * input, int file_descriptor)
1059 {
1061  uword_to_pointer (file_descriptor, void *));
1062 }
1063 
1064 /* Take input from Unix environment variable. */
1065 uword
1067 {
1068  char *val = getenv (var);
1069  if (val)
1070  unformat_init_string (input, val, strlen (val));
1071  return val != 0;
1072 }
1073 
1074 #endif /* CLIB_UNIX */
1075 
1076 
1077 /*
1078  * fd.io coding-style-patch-verification: ON
1079  *
1080  * Local Variables:
1081  * eval: (c-set-style "gnu")
1082  * End:
1083  */
void unformat_init_clib_file(unformat_input_t *input, int file_descriptor)
Definition: unformat.c:1058
uword( unformat_function_t)(unformat_input_t *input, va_list *args)
Definition: format.h:232
static uword unformat_get_input(unformat_input_t *input)
Definition: format.h:191
void unformat_init_vector(unformat_input_t *input, u8 *vector_string)
Definition: unformat.c:1031
unsigned long u64
Definition: types.h:89
static uword unformat_float(unformat_input_t *input, va_list *va)
Definition: unformat.c:571
uword unformat_line(unformat_input_t *i, va_list *va)
Definition: unformat.c:393
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
int i
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
uword unformat_hex_string(unformat_input_t *input, va_list *va)
Definition: unformat.c:272
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:598
#define UNFORMAT_INTEGER_UNSIGNED
Definition: unformat.c:421
static uword unformat_integer(unformat_input_t *input, va_list *va, uword base, uword is_signed, uword data_bytes)
Definition: unformat.c:424
#define vec_add1_aligned(V, E, A)
Add 1 element to end of vector (alignment specified).
Definition: vec.h:531
i64 word
Definition: types.h:111
#define always_inline
Definition: clib.h:98
uword unformat_token(unformat_input_t *input, va_list *va)
Definition: unformat.c:328
static uword is_white_space(uword c)
Definition: unformat.c:74
static const char * do_percent(unformat_input_t *input, va_list *va, const char *f)
Definition: unformat.c:713
void di(unformat_input_t *i)
Definition: unformat.c:163
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:242
unsigned int u32
Definition: types.h:88
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
void unformat_init_command_line(unformat_input_t *input, char *argv[])
Definition: unformat.c:1007
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
uword unformat_skip_white_space(unformat_input_t *input)
Definition: unformat.c:815
static void unformat_put_input(unformat_input_t *input)
Definition: format.h:204
word fformat(FILE *f, char *fmt,...)
Definition: format.c:462
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
svmdb_client_t * c
uword unformat_input(unformat_input_t *i, va_list *args)
Definition: unformat.c:377
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
static f64 times_power_of_ten(f64 x, int n)
Definition: unformat.c:545
#define uword_to_pointer(u, type)
Definition: types.h:136
#define ASSERT(truth)
uword unformat(unformat_input_t *input, const char *fmt,...)
Definition: unformat.c:972
uword va_unformat(unformat_input_t *input, const char *fmt, va_list *va)
Definition: unformat.c:833
static void unformat_init(unformat_input_t *i, uword(*fill_buffer)(unformat_input_t *), void *fill_buffer_arg)
Definition: format.h:152
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:784
#define UNFORMAT_INTEGER_SIGNED
Definition: unformat.c:420
static uword pointer_to_uword(const void *p)
Definition: types.h:131
uword unformat_line_input(unformat_input_t *i, va_list *va)
Definition: unformat.c:409
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u8 * format_unformat_input(u8 *s, va_list *va)
Definition: unformat.c:143
u64 uword
Definition: types.h:112
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
uword unformat_init_unix_env(unformat_input_t *input, char *var)
Definition: unformat.c:1066
uword unformat_eof(unformat_input_t *input, va_list *va)
Definition: unformat.c:321
void unformat_init_string(unformat_input_t *input, char *string, int string_len)
Definition: unformat.c:1023
static uword unformat_string(unformat_input_t *input, uword delimiter_character, uword format_character, va_list *va)
Definition: unformat.c:173
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
static uword clib_file_fill_buffer(unformat_input_t *input)
Definition: unformat.c:1040
static const char * match_input_with_format(unformat_input_t *input, const char *f)
Definition: unformat.c:691