VPP-638: 'set interface ipsec key garbage' causes infinite loop
[vpp.git] / src / vppinfra / unformat.c
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
73 always_inline uword
74 is_white_space (uword c)
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
163 di (unformat_input_t * i)
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
173 unformat_string (unformat_input_t * input,
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 {
323   return unformat_check_input (input) == UNFORMAT_END_OF_INPUT;
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
409 unformat_line_input (unformat_input_t * i, va_list * va)
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
423 unformat_integer (unformat_input_t * input,
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
544 times_power_of_ten (f64 x, int n)
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 *
690 match_input_with_format (unformat_input_t * input, const char *f)
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
814 unformat_skip_white_space (unformat_input_t * input)
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))
889                 unformat_skip_white_space (input);
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
982 unformat_user (unformat_input_t * input, unformat_function_t * func, ...)
983 {
984   va_list va;
985   uword result, l;
986
987   /* Save place in input buffer in case parse fails. */
988   l = vec_len (input->buffer_marks);
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
1006 unformat_init_command_line (unformat_input_t * input, char *argv[])
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
1039 unix_file_fill_buffer (unformat_input_t * input)
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 {
1059   unformat_init (input, unix_file_fill_buffer,
1060                  uword_to_pointer (file_descriptor, void *));
1061 }
1062
1063 /* Take input from Unix environment variable. */
1064 uword
1065 unformat_init_unix_env (unformat_input_t * input, char *var)
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  */