vppinfra: fix buffer overflow in unformat_token
[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 balanced 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   clib_memset (map, 0, sizeof (map));
339   for (s = token_chars; *s;)
340     {
341       /*
342        * Parse range.
343        * The test order is important: s[1] is valid because s[0] != '\0' but
344        * s[2] might not if s[1] == '\0'
345        * Also, if s[1] == '-' but s[2] == '\0' the test s[0] < s[2] will
346        * (correctly) fail
347        */
348       if (s[1] == '-' && s[0] < s[2])
349         {
350           for (i = s[0]; i <= s[2]; i++)
351             map[i] = 1;
352           s = s + 3;
353         }
354       else
355         {
356           map[s[0]] = 1;
357           s = s + 1;
358         }
359     }
360
361   s = 0;
362   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
363     {
364       if (!map[c])
365         {
366           unformat_put_input (input);
367           break;
368         }
369
370       vec_add1 (s, c);
371     }
372
373   if (vec_len (s) == 0)
374     return 0;
375
376   *string_return = s;
377   return 1;
378 }
379
380 /* Unformat (parse) function which reads a %s string and converts it
381    to and unformat_input_t. */
382 uword
383 unformat_input (unformat_input_t * i, va_list * args)
384 {
385   unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
386   u8 *s;
387
388   if (unformat (i, "%v", &s))
389     {
390       unformat_init_vector (sub_input, s);
391       return 1;
392     }
393
394   return 0;
395 }
396
397 /* Parse a line ending with \n and return it. */
398 uword
399 unformat_line (unformat_input_t * i, va_list * va)
400 {
401   u8 *line = 0, **result = va_arg (*va, u8 **);
402   uword c;
403
404   while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT)
405     {
406       vec_add1 (line, c);
407     }
408
409   *result = line;
410   return vec_len (line);
411 }
412
413 /* Parse a line ending with \n and return it as an unformat_input_t. */
414 uword
415 unformat_line_input (unformat_input_t * i, va_list * va)
416 {
417   unformat_input_t *result = va_arg (*va, unformat_input_t *);
418   u8 *line;
419   if (!unformat_user (i, unformat_line, &line))
420     return 0;
421   unformat_init_vector (result, line);
422   return 1;
423 }
424
425 /* Values for is_signed. */
426 #define UNFORMAT_INTEGER_SIGNED         1
427 #define UNFORMAT_INTEGER_UNSIGNED       0
428
429 static uword
430 unformat_integer (unformat_input_t * input,
431                   va_list * va, uword base, uword is_signed, uword data_bytes)
432 {
433   uword c, digit;
434   uword value = 0;
435   uword n_digits = 0;
436   uword n_input = 0;
437   uword sign = 0;
438
439   /* We only support bases <= 64. */
440   if (base < 2 || base > 64)
441     goto error;
442
443   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
444     {
445       switch (c)
446         {
447         case '-':
448           if (n_input == 0)
449             {
450               if (is_signed)
451                 {
452                   sign = 1;
453                   goto next_digit;
454                 }
455               else
456                 /* Leading sign for unsigned number. */
457                 goto error;
458             }
459           /* Sign after input (e.g. 100-200). */
460           goto put_input_done;
461
462         case '+':
463           if (n_input > 0)
464             goto put_input_done;
465           sign = 0;
466           goto next_digit;
467
468         case '0' ... '9':
469           digit = c - '0';
470           break;
471
472         case 'a' ... 'z':
473           digit = 10 + (c - 'a');
474           break;
475
476         case 'A' ... 'Z':
477           digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A');
478           break;
479
480         case '/':
481           digit = 62;
482           break;
483
484         case '?':
485           digit = 63;
486           break;
487
488         default:
489           goto put_input_done;
490         }
491
492       if (digit >= base)
493         {
494         put_input_done:
495           unformat_put_input (input);
496           goto done;
497         }
498
499       {
500         uword new_value = base * value + digit;
501
502         /* Check for overflow. */
503         if (new_value < value)
504           goto error;
505         value = new_value;
506       }
507       n_digits += 1;
508
509     next_digit:
510       n_input++;
511     }
512
513 done:
514   if (sign)
515     value = -value;
516
517   if (n_digits > 0)
518     {
519       void *v = va_arg (*va, void *);
520
521       if (data_bytes == ~0)
522         data_bytes = sizeof (int);
523
524       switch (data_bytes)
525         {
526         case 1:
527           *(u8 *) v = value;
528           break;
529         case 2:
530           *(u16 *) v = value;
531           break;
532         case 4:
533           *(u32 *) v = value;
534           break;
535         case 8:
536           *(u64 *) v = value;
537           break;
538         default:
539           goto error;
540         }
541
542       return 1;
543     }
544
545 error:
546   return 0;
547 }
548
549 /* Return x 10^n */
550 static f64
551 times_power_of_ten (f64 x, int n)
552 {
553   if (n >= 0)
554     {
555       static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
556       while (n >= 8)
557         {
558           x *= 1e+8;
559           n -= 8;
560         }
561       return x * t[n];
562     }
563   else
564     {
565       static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
566       while (n <= -8)
567         {
568           x *= 1e-8;
569           n += 8;
570         }
571       return x * t[-n];
572     }
573
574 }
575
576 static uword
577 unformat_float (unformat_input_t * input, va_list * va)
578 {
579   uword c;
580   u64 values[3];
581   uword n_digits[3], value_index = 0;
582   uword signs[2], sign_index = 0;
583   uword n_input = 0;
584
585   clib_memset (values, 0, sizeof (values));
586   clib_memset (n_digits, 0, sizeof (n_digits));
587   clib_memset (signs, 0, sizeof (signs));
588
589   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
590     {
591       switch (c)
592         {
593         case '-':
594           if (value_index == 2 && n_digits[2] == 0)
595             /* sign of exponent: it's ok. */ ;
596
597           else if (value_index < 2 && n_digits[0] > 0)
598             {
599               /* 123- */
600               unformat_put_input (input);
601               goto done;
602             }
603
604           else if (n_input > 0)
605             goto error;
606
607           signs[sign_index++] = 1;
608           goto next_digit;
609
610         case '+':
611           if (value_index == 2 && n_digits[2] == 0)
612             /* sign of exponent: it's ok. */ ;
613
614           else if (value_index < 2 && n_digits[0] > 0)
615             {
616               /* 123+ */
617               unformat_put_input (input);
618               goto done;
619             }
620
621           else if (n_input > 0)
622             goto error;
623           signs[sign_index++] = 0;
624           goto next_digit;
625
626         case 'e':
627         case 'E':
628           if (n_input == 0)
629             goto error;
630           value_index = 2;
631           sign_index = 1;
632           break;
633
634         case '.':
635           if (value_index > 0)
636             goto error;
637           value_index = 1;
638           break;
639
640         case '0' ... '9':
641           {
642             u64 tmp;
643
644             tmp = values[value_index] * 10 + c - '0';
645
646             /* Check for overflow. */
647             if (tmp < values[value_index])
648               goto error;
649             values[value_index] = tmp;
650             n_digits[value_index] += 1;
651           }
652           break;
653
654         default:
655           unformat_put_input (input);
656           goto done;
657         }
658
659     next_digit:
660       n_input++;
661     }
662
663 done:
664   {
665     f64 f_values[2], *value_return;
666     word expon;
667
668     /* Must have either whole or fraction digits. */
669     if (n_digits[0] + n_digits[1] <= 0)
670       goto error;
671
672     f_values[0] = values[0];
673     if (signs[0])
674       f_values[0] = -f_values[0];
675
676     f_values[1] = values[1];
677     f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]);
678
679     f_values[0] += f_values[1];
680
681     expon = values[2];
682     if (signs[1])
683       expon = -expon;
684
685     f_values[0] = times_power_of_ten (f_values[0], expon);
686
687     value_return = va_arg (*va, f64 *);
688     *value_return = f_values[0];
689     return 1;
690   }
691
692 error:
693   return 0;
694 }
695
696 static const char *
697 match_input_with_format (unformat_input_t * input, const char *f)
698 {
699   uword cf, ci;
700
701   ASSERT (*f != 0);
702
703   while (1)
704     {
705       cf = *f;
706       if (cf == 0 || cf == '%' || cf == ' ')
707         break;
708       f++;
709
710       ci = unformat_get_input (input);
711
712       if (cf != ci)
713         return 0;
714     }
715   return f;
716 }
717
718 static const char *
719 do_percent (unformat_input_t * input, va_list * va, const char *f)
720 {
721   uword cf, n, data_bytes = ~0;
722
723   cf = *f++;
724
725   switch (cf)
726     {
727     default:
728       break;
729
730     case 'w':
731       /* Word types. */
732       cf = *f++;
733       data_bytes = sizeof (uword);
734       break;
735
736     case 'l':
737       cf = *f++;
738       if (cf == 'l')
739         {
740           cf = *f++;
741           data_bytes = sizeof (long long);
742         }
743       else
744         {
745           data_bytes = sizeof (long);
746         }
747       break;
748
749     case 'L':
750       cf = *f++;
751       data_bytes = sizeof (long long);
752       break;
753     }
754
755   n = 0;
756   switch (cf)
757     {
758     case 'D':
759       data_bytes = va_arg (*va, int);
760     case 'd':
761       n = unformat_integer (input, va, 10,
762                             UNFORMAT_INTEGER_SIGNED, data_bytes);
763       break;
764
765     case 'u':
766       n = unformat_integer (input, va, 10,
767                             UNFORMAT_INTEGER_UNSIGNED, data_bytes);
768       break;
769
770     case 'b':
771       n = unformat_integer (input, va, 2,
772                             UNFORMAT_INTEGER_UNSIGNED, data_bytes);
773       break;
774
775     case 'o':
776       n = unformat_integer (input, va, 8,
777                             UNFORMAT_INTEGER_UNSIGNED, data_bytes);
778       break;
779
780     case 'X':
781       data_bytes = va_arg (*va, int);
782     case 'x':
783       n = unformat_integer (input, va, 16,
784                             UNFORMAT_INTEGER_UNSIGNED, data_bytes);
785       break;
786
787     case 'f':
788       n = unformat_float (input, va);
789       break;
790
791     case 's':
792     case 'v':
793       n = unformat_string (input, f[0], cf, va);
794       break;
795
796     case 'U':
797       {
798         unformat_function_t *f = va_arg (*va, unformat_function_t *);
799         n = f (input, va);
800       }
801       break;
802
803     case '=':
804     case '|':
805       {
806         int *var = va_arg (*va, int *);
807         uword val = va_arg (*va, int);
808
809         if (cf == '|')
810           val |= *var;
811         *var = val;
812         n = 1;
813       }
814       break;
815     }
816
817   return n ? f : 0;
818 }
819
820 uword
821 unformat_skip_white_space (unformat_input_t * input)
822 {
823   uword n = 0;
824   uword c;
825
826   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
827     {
828       if (!is_white_space (c))
829         {
830           unformat_put_input (input);
831           break;
832         }
833       n++;
834     }
835   return n;
836 }
837
838 uword
839 va_unformat (unformat_input_t * input, const char *fmt, va_list * va)
840 {
841   const char *f;
842   uword input_matches_format;
843   uword default_skip_input_white_space;
844   uword n_input_white_space_skipped;
845   uword last_non_white_space_match_percent;
846   uword last_non_white_space_match_format;
847
848   vec_add1_aligned (input->buffer_marks, input->index,
849                     sizeof (input->buffer_marks[0]));
850
851   f = fmt;
852   default_skip_input_white_space = 1;
853   input_matches_format = 0;
854   last_non_white_space_match_percent = 0;
855   last_non_white_space_match_format = 0;
856
857   while (1)
858     {
859       char cf;
860       uword is_percent, skip_input_white_space;
861
862       cf = *f;
863       is_percent = 0;
864
865       /* Always skip input white space at start of format string.
866          Otherwise use default skip value which can be changed by %_
867          (see below). */
868       skip_input_white_space = f == fmt || default_skip_input_white_space;
869
870       /* Spaces in format request skipping input white space. */
871       if (is_white_space (cf))
872         {
873           skip_input_white_space = 1;
874
875           /* Multiple format spaces are equivalent to a single white
876              space. */
877           while (is_white_space (*++f))
878             ;
879         }
880       else if (cf == '%')
881         {
882           /* %_ toggles whether or not to skip input white space. */
883           switch (*++f)
884             {
885             case '_':
886               default_skip_input_white_space =
887                 !default_skip_input_white_space;
888               f++;
889               /* For transition from skip to no-skip in middle of format
890                  string, skip input white space.  For example, the following matches:
891                  fmt = "%_%d.%d%_->%_%d.%d%_"
892                  input "1.2 -> 3.4"
893                  Without this the space after -> does not get skipped. */
894               if (!default_skip_input_white_space
895                   && !(f == fmt + 2 || *f == 0))
896                 unformat_skip_white_space (input);
897               continue;
898
899               /* %% means match % */
900             case '%':
901               break;
902
903               /* % at end of format string. */
904             case 0:
905               goto parse_fail;
906
907             default:
908               is_percent = 1;
909               break;
910             }
911         }
912
913       n_input_white_space_skipped = 0;
914       if (skip_input_white_space)
915         n_input_white_space_skipped = unformat_skip_white_space (input);
916
917       /* End of format string. */
918       if (cf == 0)
919         {
920           /* Force parse error when format string ends and input is
921              not white or at end.  As an example, this is to prevent
922              format "foo" from matching input "food".
923              The last_non_white_space_match_percent is to make
924              "foo %d" match input "foo 10,bletch" with %d matching 10. */
925           if (skip_input_white_space
926               && !last_non_white_space_match_percent
927               && !last_non_white_space_match_format
928               && n_input_white_space_skipped == 0
929               && input->index != UNFORMAT_END_OF_INPUT)
930             goto parse_fail;
931           break;
932         }
933
934       last_non_white_space_match_percent = is_percent;
935       last_non_white_space_match_format = 0;
936
937       /* Explicit spaces in format must match input white space. */
938       if (cf == ' ' && !default_skip_input_white_space)
939         {
940           if (n_input_white_space_skipped == 0)
941             goto parse_fail;
942         }
943
944       else if (is_percent)
945         {
946           if (!(f = do_percent (input, va, f)))
947             goto parse_fail;
948         }
949
950       else
951         {
952           const char *g = match_input_with_format (input, f);
953           if (!g)
954             goto parse_fail;
955           last_non_white_space_match_format = g > f;
956           f = g;
957         }
958     }
959
960   input_matches_format = 1;
961 parse_fail:
962
963   /* Rewind buffer marks. */
964   {
965     uword l = vec_len (input->buffer_marks);
966
967     /* If we did not match back up buffer to last mark. */
968     if (!input_matches_format)
969       input->index = input->buffer_marks[l - 1];
970
971     _vec_len (input->buffer_marks) = l - 1;
972   }
973
974   return input_matches_format;
975 }
976
977 uword
978 unformat (unformat_input_t * input, const char *fmt, ...)
979 {
980   va_list va;
981   uword result;
982   va_start (va, fmt);
983   result = va_unformat (input, fmt, &va);
984   va_end (va);
985   return result;
986 }
987
988 uword
989 unformat_user (unformat_input_t * input, unformat_function_t * func, ...)
990 {
991   va_list va;
992   uword result, l;
993
994   /* Save place in input buffer in case parse fails. */
995   l = vec_len (input->buffer_marks);
996   vec_add1_aligned (input->buffer_marks, input->index,
997                     sizeof (input->buffer_marks[0]));
998
999   va_start (va, func);
1000   result = func (input, &va);
1001   va_end (va);
1002
1003   if (!result && input->index != UNFORMAT_END_OF_INPUT)
1004     input->index = input->buffer_marks[l];
1005
1006   _vec_len (input->buffer_marks) = l;
1007
1008   return result;
1009 }
1010
1011 /* Setup for unformat of Unix style command line. */
1012 void
1013 unformat_init_command_line (unformat_input_t * input, char *argv[])
1014 {
1015   uword i;
1016
1017   unformat_init (input, 0, 0);
1018
1019   /* Concatenate argument strings with space in between. */
1020   for (i = 1; argv[i]; i++)
1021     {
1022       vec_add (input->buffer, argv[i], strlen (argv[i]));
1023       if (argv[i + 1])
1024         vec_add1 (input->buffer, ' ');
1025     }
1026 }
1027
1028 void
1029 unformat_init_string (unformat_input_t * input, char *string, int string_len)
1030 {
1031   unformat_init (input, 0, 0);
1032   if (string_len > 0)
1033     vec_add (input->buffer, string, string_len);
1034 }
1035
1036 void
1037 unformat_init_vector (unformat_input_t * input, u8 * vector_string)
1038 {
1039   unformat_init (input, 0, 0);
1040   input->buffer = vector_string;
1041 }
1042
1043 #ifdef CLIB_UNIX
1044
1045 static uword
1046 clib_file_fill_buffer (unformat_input_t * input)
1047 {
1048   int fd = pointer_to_uword (input->fill_buffer_arg);
1049   uword l, n;
1050
1051   l = vec_len (input->buffer);
1052   vec_resize (input->buffer, 4096);
1053   n = read (fd, input->buffer + l, 4096);
1054   if (n > 0)
1055     _vec_len (input->buffer) = l + n;
1056
1057   if (n <= 0)
1058     return UNFORMAT_END_OF_INPUT;
1059   else
1060     return input->index;
1061 }
1062
1063 void
1064 unformat_init_clib_file (unformat_input_t * input, int file_descriptor)
1065 {
1066   unformat_init (input, clib_file_fill_buffer,
1067                  uword_to_pointer (file_descriptor, void *));
1068 }
1069
1070 /* Take input from Unix environment variable. */
1071 uword
1072 unformat_init_unix_env (unformat_input_t * input, char *var)
1073 {
1074   char *val = getenv (var);
1075   if (val)
1076     unformat_init_string (input, val, strlen (val));
1077   return val != 0;
1078 }
1079
1080 #endif /* CLIB_UNIX */
1081
1082
1083 /*
1084  * fd.io coding-style-patch-verification: ON
1085  *
1086  * Local Variables:
1087  * eval: (c-set-style "gnu")
1088  * End:
1089  */