FD.io VPP  v17.01-9-ge7dcee4
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 
310  *hexstring_return = s;
311  return 1;
312 }
313 
314 /* unformat (input "foo%U", unformat_eof) matches terminal foo only */
315 uword
316 unformat_eof (unformat_input_t * input, va_list * va)
317 {
319 }
320 
321 /* Parse a token containing given set of characters. */
322 uword
323 unformat_token (unformat_input_t * input, va_list * va)
324 {
325  u8 *token_chars = va_arg (*va, u8 *);
326  u8 **string_return = va_arg (*va, u8 **);
327  u8 *s, map[256];
328  uword i, c;
329 
330  if (!token_chars)
331  token_chars = (u8 *) "a-zA-Z0-9_";
332 
333  memset (map, 0, sizeof (map));
334  for (s = token_chars; *s;)
335  {
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;
342  }
343  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  {
353  if (!map[c])
354  {
355  unformat_put_input (input);
356  break;
357  }
358 
359  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. */
371 uword
372 unformat_input (unformat_input_t * i, va_list * args)
373 {
374  unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
375  u8 *s;
376 
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. */
387 uword
388 unformat_line (unformat_input_t * i, va_list * va)
389 {
390  u8 *line = 0, **result = va_arg (*va, u8 **);
391  uword c;
392 
393  while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT)
394  {
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. */
403 uword
405 {
406  unformat_input_t *result = va_arg (*va, unformat_input_t *);
407  u8 *line;
408  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 
417 static uword
419  va_list * va, uword base, uword is_signed, uword data_bytes)
420 {
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 '+':
451  if (n_input > 0)
452  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  {
488  uword new_value = base * value + digit;
489 
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 
501 done:
502  if (sign)
503  value = -value;
504 
505  if (n_digits > 0)
506  {
507  void *v = va_arg (*va, void *);
508 
509  if (data_bytes == ~0)
510  data_bytes = sizeof (int);
511 
512  switch (data_bytes)
513  {
514  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;
526  default:
527  goto error;
528  }
529 
530  return 1;
531  }
532 
533 error:
534  return 0;
535 }
536 
537 /* Return x 10^n */
538 static f64
540 {
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  }
561 
562 }
563 
564 static uword
565 unformat_float (unformat_input_t * input, va_list * va)
566 {
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)
583  /* sign of exponent: it's ok. */ ;
584 
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)
600  /* sign of exponent: it's ok. */ ;
601 
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 
651 done:
652  {
653  f64 f_values[2], *value_return;
654  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 
680 error:
681  return 0;
682 }
683 
684 static char *
686 {
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 
706 static char *
707 do_percent (unformat_input_t * input, va_list * va, char *f)
708 {
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;
736 
737  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  {
786  unformat_function_t *f = va_arg (*va, unformat_function_t *);
787  n = f (input, va);
788  }
789  break;
790 
791  case '=':
792  case '|':
793  {
794  int *var = va_arg (*va, int *);
795  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 
808 uword
810 {
811  uword n = 0;
812  uword c;
813 
814  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
815  {
816  if (!is_white_space (c))
817  {
818  unformat_put_input (input);
819  break;
820  }
821  n++;
822  }
823  return n;
824 }
825 
826 uword
827 va_unformat (unformat_input_t * input, char *fmt, va_list * va)
828 {
829  char *f;
830  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 
836  vec_add1_aligned (input->buffer_marks, input->index,
837  sizeof (input->buffer_marks[0]));
838 
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;
844 
845  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.
854  Otherwise use default skip value which can be changed by %_
855  (see below). */
856  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 '_':
874  default_skip_input_white_space =
875  !default_skip_input_white_space;
876  f++;
877  /* For transition from skip to no-skip in middle of format
878  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))
885  continue;
886 
887  /* %% means match % */
888  case '%':
889  break;
890 
891  /* % at end of format string. */
892  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
914  && !last_non_white_space_match_percent
915  && !last_non_white_space_match_format
916  && 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  {
934  if (!(f = do_percent (input, va, f)))
935  goto parse_fail;
936  }
937 
938  else
939  {
940  char *g = match_input_with_format (input, f);
941  if (!g)
942  goto parse_fail;
943  last_non_white_space_match_format = g > f;
944  f = g;
945  }
946  }
947 
948  input_matches_format = 1;
949 parse_fail:
950 
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. */
956  if (!input_matches_format)
957  input->index = input->buffer_marks[l - 1];
958 
959  _vec_len (input->buffer_marks) = l - 1;
960  }
961 
962  return input_matches_format;
963 }
964 
965 uword
966 unformat (unformat_input_t * input, char *fmt, ...)
967 {
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 
976 uword
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);
984  vec_add1_aligned (input->buffer_marks, input->index,
985  sizeof (input->buffer_marks[0]));
986 
987  va_start (va, func);
988  result = func (input, &va);
989  va_end (va);
990 
991  if (!result && input->index != UNFORMAT_END_OF_INPUT)
992  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. */
1000 void
1002 {
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 
1016 void
1017 unformat_init_string (unformat_input_t * input, char *string, int string_len)
1018 {
1019  unformat_init (input, 0, 0);
1020  if (string_len > 0)
1021  vec_add (input->buffer, string, string_len);
1022 }
1023 
1024 void
1025 unformat_init_vector (unformat_input_t * input, u8 * vector_string)
1026 {
1027  unformat_init (input, 0, 0);
1028  input->buffer = vector_string;
1029 }
1030 
1031 #ifdef CLIB_UNIX
1032 
1033 static uword
1035 {
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 
1051 void
1052 unformat_init_unix_file (unformat_input_t * input, int file_descriptor)
1053 {
1055  uword_to_pointer (file_descriptor, void *));
1056 }
1057 
1058 /* Take input from Unix environment variable. */
1059 uword
1061 {
1062  char *val = getenv (var);
1063  if (val)
1064  unformat_init_string (input, val, strlen (val));
1065  return val != 0;
1066 }
1067 
1068 #endif /* CLIB_UNIX */
1069 
1070 
1071 /*
1072  * fd.io coding-style-patch-verification: ON
1073  *
1074  * Local Variables:
1075  * eval: (c-set-style "gnu")
1076  * End:
1077  */
void unformat_init_unix_file(unformat_input_t *input, int file_descriptor)
Definition: unformat.c:1052
static uword unformat_get_input(unformat_input_t *input)
Definition: format.h:190
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
uword( unformat_function_t)(unformat_input_t *input, va_list *args)
Definition: format.h:231
static void unformat_init(unformat_input_t *i, uword(*fill_buffer)(unformat_input_t *), void *fill_buffer_arg)
Definition: format.h:151
static char * do_percent(unformat_input_t *input, va_list *va, char *f)
Definition: unformat.c:707
void unformat_init_vector(unformat_input_t *input, u8 *vector_string)
Definition: unformat.c:1025
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static uword unformat_float(unformat_input_t *input, va_list *va)
Definition: unformat.c:565
static char * match_input_with_format(unformat_input_t *input, char *f)
Definition: unformat.c:685
uword unformat_line(unformat_input_t *i, va_list *va)
Definition: unformat.c:388
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
static void unformat_put_input(unformat_input_t *input)
Definition: format.h:203
uword unformat_hex_string(unformat_input_t *input, va_list *va)
Definition: unformat.c:272
uword va_unformat(unformat_input_t *input, char *fmt, va_list *va)
Definition: unformat.c:827
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:559
#define UNFORMAT_INTEGER_UNSIGNED
Definition: unformat.c:415
static uword unformat_integer(unformat_input_t *input, va_list *va, uword base, uword is_signed, uword data_bytes)
Definition: unformat.c:418
#define vec_add1_aligned(V, E, A)
Add 1 element to end of vector (alignment specified).
Definition: vec.h:492
#define always_inline
Definition: clib.h:84
uword unformat_token(unformat_input_t *input, va_list *va)
Definition: unformat.c:323
static uword is_white_space(uword c)
Definition: unformat.c:74
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:201
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
static uword pointer_to_uword(const void *p)
Definition: types.h:131
#define v
Definition: acl.c:314
void unformat_init_command_line(unformat_input_t *input, char *argv[])
Definition: unformat.c:1001
uword unformat_skip_white_space(unformat_input_t *input)
Definition: unformat.c:809
uword unformat(unformat_input_t *input, char *fmt,...)
Definition: unformat.c:966
#define uword_to_pointer(u, type)
Definition: types.h:136
svmdb_client_t * c
uword unformat_input(unformat_input_t *i, va_list *args)
Definition: unformat.c:372
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
static f64 times_power_of_ten(f64 x, int n)
Definition: unformat.c:539
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:745
static uword unix_file_fill_buffer(unformat_input_t *input)
Definition: unformat.c:1034
#define UNFORMAT_INTEGER_SIGNED
Definition: unformat.c:414
uword unformat_line_input(unformat_input_t *i, va_list *va)
Definition: unformat.c:404
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
word fformat(FILE *f, char *fmt,...)
Definition: format.c:452
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
uword unformat_init_unix_env(unformat_input_t *input, char *var)
Definition: unformat.c:1060
struct _unformat_input_t unformat_input_t
uword unformat_eof(unformat_input_t *input, va_list *va)
Definition: unformat.c:316
void unformat_init_string(unformat_input_t *input, char *string, int string_len)
Definition: unformat.c:1017
static uword unformat_string(unformat_input_t *input, uword delimiter_character, uword format_character, va_list *va)
Definition: unformat.c:173