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