FD.io VPP  v17.04.2-2-ga8f93f8
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 balenced 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  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 1;
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  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 
422 static uword
424  va_list * va, uword base, uword is_signed, uword data_bytes)
425 {
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 '+':
456  if (n_input > 0)
457  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  {
493  uword new_value = base * value + digit;
494 
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 
506 done:
507  if (sign)
508  value = -value;
509 
510  if (n_digits > 0)
511  {
512  void *v = va_arg (*va, void *);
513 
514  if (data_bytes == ~0)
515  data_bytes = sizeof (int);
516 
517  switch (data_bytes)
518  {
519  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;
531  default:
532  goto error;
533  }
534 
535  return 1;
536  }
537 
538 error:
539  return 0;
540 }
541 
542 /* Return x 10^n */
543 static f64
545 {
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  }
566 
567 }
568 
569 static uword
570 unformat_float (unformat_input_t * input, va_list * va)
571 {
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)
588  /* sign of exponent: it's ok. */ ;
589 
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)
605  /* sign of exponent: it's ok. */ ;
606 
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 
656 done:
657  {
658  f64 f_values[2], *value_return;
659  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 
685 error:
686  return 0;
687 }
688 
689 static const char *
691 {
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 
711 static const char *
712 do_percent (unformat_input_t * input, va_list * va, const char *f)
713 {
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;
741 
742  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  {
791  unformat_function_t *f = va_arg (*va, unformat_function_t *);
792  n = f (input, va);
793  }
794  break;
795 
796  case '=':
797  case '|':
798  {
799  int *var = va_arg (*va, int *);
800  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 
813 uword
815 {
816  uword n = 0;
817  uword c;
818 
819  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
820  {
821  if (!is_white_space (c))
822  {
823  unformat_put_input (input);
824  break;
825  }
826  n++;
827  }
828  return n;
829 }
830 
831 uword
832 va_unformat (unformat_input_t * input, const char *fmt, va_list * va)
833 {
834  const char *f;
835  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 
841  vec_add1_aligned (input->buffer_marks, input->index,
842  sizeof (input->buffer_marks[0]));
843 
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;
849 
850  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.
859  Otherwise use default skip value which can be changed by %_
860  (see below). */
861  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 '_':
879  default_skip_input_white_space =
880  !default_skip_input_white_space;
881  f++;
882  /* For transition from skip to no-skip in middle of format
883  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))
890  continue;
891 
892  /* %% means match % */
893  case '%':
894  break;
895 
896  /* % at end of format string. */
897  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
919  && !last_non_white_space_match_percent
920  && !last_non_white_space_match_format
921  && 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  {
939  if (!(f = do_percent (input, va, f)))
940  goto parse_fail;
941  }
942 
943  else
944  {
945  const char *g = match_input_with_format (input, f);
946  if (!g)
947  goto parse_fail;
948  last_non_white_space_match_format = g > f;
949  f = g;
950  }
951  }
952 
953  input_matches_format = 1;
954 parse_fail:
955 
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. */
961  if (!input_matches_format)
962  input->index = input->buffer_marks[l - 1];
963 
964  _vec_len (input->buffer_marks) = l - 1;
965  }
966 
967  return input_matches_format;
968 }
969 
970 uword
971 unformat (unformat_input_t * input, const char *fmt, ...)
972 {
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 
981 uword
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);
989  vec_add1_aligned (input->buffer_marks, input->index,
990  sizeof (input->buffer_marks[0]));
991 
992  va_start (va, func);
993  result = func (input, &va);
994  va_end (va);
995 
996  if (!result && input->index != UNFORMAT_END_OF_INPUT)
997  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. */
1005 void
1007 {
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 
1021 void
1022 unformat_init_string (unformat_input_t * input, char *string, int string_len)
1023 {
1024  unformat_init (input, 0, 0);
1025  if (string_len > 0)
1026  vec_add (input->buffer, string, string_len);
1027 }
1028 
1029 void
1030 unformat_init_vector (unformat_input_t * input, u8 * vector_string)
1031 {
1032  unformat_init (input, 0, 0);
1033  input->buffer = vector_string;
1034 }
1035 
1036 #ifdef CLIB_UNIX
1037 
1038 static uword
1040 {
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 
1056 void
1057 unformat_init_unix_file (unformat_input_t * input, int file_descriptor)
1058 {
1060  uword_to_pointer (file_descriptor, void *));
1061 }
1062 
1063 /* Take input from Unix environment variable. */
1064 uword
1066 {
1067  char *val = getenv (var);
1068  if (val)
1069  unformat_init_string (input, val, strlen (val));
1070  return val != 0;
1071 }
1072 
1073 #endif /* CLIB_UNIX */
1074 
1075 
1076 /*
1077  * fd.io coding-style-patch-verification: ON
1078  *
1079  * Local Variables:
1080  * eval: (c-set-style "gnu")
1081  * End:
1082  */
void unformat_init_unix_file(unformat_input_t *input, int file_descriptor)
Definition: unformat.c:1057
uword( unformat_function_t)(unformat_input_t *input, va_list *args)
Definition: format.h:231
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
static uword unformat_get_input(unformat_input_t *input)
Definition: format.h:190
void unformat_init_vector(unformat_input_t *input, u8 *vector_string)
Definition: unformat.c:1030
static uword unformat_float(unformat_input_t *input, va_list *va)
Definition: unformat.c:570
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
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
uword unformat_hex_string(unformat_input_t *input, va_list *va)
Definition: unformat.c:272
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:599
#define UNFORMAT_INTEGER_UNSIGNED
Definition: unformat.c:420
static uword unformat_integer(unformat_input_t *input, va_list *va, uword base, uword is_signed, uword data_bytes)
Definition: unformat.c:423
#define vec_add1_aligned(V, E, A)
Add 1 element to end of vector (alignment specified).
Definition: vec.h:532
#define always_inline
Definition: clib.h:84
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:712
void di(unformat_input_t *i)
Definition: unformat.c:163
unsigned long u64
Definition: types.h:89
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:241
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:982
static uword pointer_to_uword(const void *p)
Definition: types.h:131
#define v
Definition: acl.c:246
void unformat_init_command_line(unformat_input_t *input, char *argv[])
Definition: unformat.c:1006
struct _unformat_input_t unformat_input_t
uword unformat_skip_white_space(unformat_input_t *input)
Definition: unformat.c:814
static void unformat_put_input(unformat_input_t *input)
Definition: format.h:203
word fformat(FILE *f, char *fmt,...)
Definition: format.c:452
#define uword_to_pointer(u, type)
Definition: types.h:136
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
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:340
static f64 times_power_of_ten(f64 x, int n)
Definition: unformat.c:544
#define ASSERT(truth)
uword unformat(unformat_input_t *input, const char *fmt,...)
Definition: unformat.c:971
uword va_unformat(unformat_input_t *input, const char *fmt, va_list *va)
Definition: unformat.c:832
unsigned int u32
Definition: types.h:88
static void unformat_init(unformat_input_t *i, uword(*fill_buffer)(unformat_input_t *), void *fill_buffer_arg)
Definition: format.h:151
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:785
static uword unix_file_fill_buffer(unformat_input_t *input)
Definition: unformat.c:1039
#define UNFORMAT_INTEGER_SIGNED
Definition: unformat.c:419
uword unformat_line_input(unformat_input_t *i, va_list *va)
Definition: unformat.c:409
u64 uword
Definition: types.h:112
unsigned short u16
Definition: types.h:57
i64 word
Definition: types.h:111
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
u8 * format_unformat_input(u8 *s, va_list *va)
Definition: unformat.c:143
unsigned char u8
Definition: types.h:56
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:1065
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:1022
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:169
static const char * match_input_with_format(unformat_input_t *input, const char *f)
Definition: unformat.c:690