Initial commit of vpp code.
[vpp.git] / vppinfra / 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 _unformat_fill_input (unformat_input_t * i)
42 {
43   uword l, first_mark;
44
45   if (i->index == UNFORMAT_END_OF_INPUT)
46     return i->index;
47
48   first_mark = l = vec_len (i->buffer);
49   if (vec_len (i->buffer_marks) > 0)
50     first_mark = i->buffer_marks[0];
51
52   /* Re-use buffer when no marks. */
53   if (first_mark > 0)
54     vec_delete (i->buffer, first_mark, 0);
55
56   i->index = vec_len (i->buffer);
57   for (l = 0; l < vec_len (i->buffer_marks); l++)
58     i->buffer_marks[l] -= first_mark;
59
60   /* Call user's function to fill the buffer. */
61   if (i->fill_buffer)
62     i->index = i->fill_buffer (i);
63
64   /* If input pointer is still beyond end of buffer even after
65      fill then we've run out of input. */
66   if (i->index >= vec_len (i->buffer))
67     i->index = UNFORMAT_END_OF_INPUT;
68
69   return i->index;
70 }
71
72 always_inline uword
73 is_white_space (uword c)
74 {
75   switch (c)
76     {
77     case ' ':  case '\t':
78     case '\n': case '\r':
79       return 1;
80
81     default:
82       return 0;
83     }
84 }
85
86 /* Format function for dumping input stream. */
87 u8 * format_unformat_error (u8 * s, va_list * va)
88 {
89   unformat_input_t * i = va_arg (*va, unformat_input_t *);
90   uword l = vec_len (i->buffer);
91
92   /* Only show so much of the input buffer (it could be really large). */
93   uword n_max = 30;
94
95   if (i->index < l)
96     {
97       uword n = l - i->index;
98       u8 * p, * p_end;
99
100       p = i->buffer + i->index;
101       p_end = p + (n > n_max ? n_max : n);
102
103       /* Skip white space at end. */
104       if (n <= n_max)
105         {
106           while (p_end > p && is_white_space (p_end[-1]))
107             p_end--;
108         }
109
110       while (p < p_end)
111         {
112           switch (*p)
113             {
114             case '\r': vec_add (s, "\\r", 2); break;
115             case '\n': vec_add (s, "\\n", 2); break;
116             case '\t': vec_add (s, "\\t", 2); break;
117             default: vec_add1 (s, *p); break;
118             }
119           p++;
120         }
121
122       if (n > n_max)
123         vec_add (s, "...", 3);
124     }
125
126   return s;
127 }
128
129 /* Print everything: not just error context. */
130 u8 * format_unformat_input (u8 * s,
131                             va_list * va)
132 {
133   unformat_input_t * i = va_arg (*va, unformat_input_t *);
134   uword l, n;
135
136   if (i->index == UNFORMAT_END_OF_INPUT)
137     s = format (s, "{END_OF_INPUT}");
138   else
139     {
140       l = vec_len (i->buffer);
141       n = l - i->index;
142       if (n > 0)
143         vec_add (s, i->buffer + i->index, n);
144     }
145
146   return s;
147 }
148
149 #if CLIB_DEBUG > 0
150 void di (unformat_input_t * i)
151 { fformat (stderr, "%U\n", format_unformat_input, i); }
152 #endif
153
154 /* Parse delimited vector string.  If string starts with { then string
155    is delimited by balenced parenthesis.  Other string is delimited by
156    white space.  {} were chosen since they are special to the shell. */
157 static uword
158 unformat_string (unformat_input_t * input,
159                  uword delimiter_character,
160                  uword format_character,
161                  va_list * va)
162 {
163   u8 ** string_return = va_arg (*va, u8 **);
164   u8 * s = 0;
165   word paren = 0;
166   word is_paren_delimited = 0;
167   word backslash = 0;
168   uword c;
169
170   switch (delimiter_character)
171     {
172     case '%':
173     case ' ':
174     case '\t':
175       delimiter_character = 0;
176       break;
177     }
178
179   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
180     {
181       word add_to_vector;
182
183       /* Null return string means to skip over delimited input. */
184       add_to_vector = string_return != 0;
185
186       if (backslash)
187         backslash = 0;
188       else
189         switch (c)
190           {
191           case '\\':
192             backslash = 1;
193             add_to_vector = 0;
194             break;
195
196           case '{':
197             if (paren == 0 && vec_len (s) == 0)
198               {
199                 is_paren_delimited = 1;
200                 add_to_vector = 0;
201               }
202             paren++;
203             break;
204
205           case '}':
206             paren--;
207             if (is_paren_delimited && paren == 0)
208               goto done;
209             break;
210
211           case ' ':
212           case '\t':
213           case '\n':
214           case '\r':
215             if (! is_paren_delimited)
216               {
217                 unformat_put_input (input);
218                 goto done;
219               }
220             break;
221
222           default:
223             if (! is_paren_delimited && c == delimiter_character)
224               {
225                 unformat_put_input (input);
226                 goto done;
227               }
228           }
229
230       if (add_to_vector)
231         vec_add1 (s, c);
232     }
233
234  done:
235   if (string_return)
236     {
237       /* Match the string { END-OF-INPUT as a single brace. */
238       if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0 && paren == 1)
239         vec_add1 (s, '{');
240
241       /* Don't match null string. */
242       if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0)
243         return 0;
244   
245       /* Null terminate C string. */
246       if (format_character == 's')
247         vec_add1 (s, 0);
248
249       *string_return = s;
250     }
251   else
252     vec_free (s);               /* just to make sure */
253
254   return 1;
255 }
256
257 uword
258 unformat_hex_string (unformat_input_t * input,
259                      va_list * va)
260 {
261   u8 ** hexstring_return = va_arg (*va, u8 **);
262   u8 * s;
263   uword n, d, c;
264
265   n = 0;
266   d = 0;
267   s = 0;
268   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
269     {
270       if (c >= '0' && c <= '9')
271         d = 16*d + c - '0';
272       else if (c >= 'a' && c <= 'f')
273         d = 16*d + 10 + c - 'a';
274       else if (c >= 'A' && c <= 'F')
275         d = 16*d + 10 + c - 'A';
276       else
277         {
278           unformat_put_input (input);
279           break;
280         }
281       n++;
282
283       if (n == 2)
284         {
285           vec_add1 (s, d);
286           n = d = 0;
287         }
288     }
289
290   /* Hex string must have even number of digits. */
291   if (n % 2)
292     {
293       vec_free (s);
294       return 0;
295     }
296
297   *hexstring_return = s;
298   return 1;
299 }
300
301 /* unformat (input "foo%U", unformat_eof) matches terminal foo only */
302 uword
303 unformat_eof (unformat_input_t * input, va_list * va)
304 {
305   return unformat_check_input (input) == UNFORMAT_END_OF_INPUT;
306 }
307
308 /* Parse a token containing given set of characters. */
309 uword
310 unformat_token (unformat_input_t * input,
311                 va_list * va)
312 {
313   u8 * token_chars = va_arg (*va, u8 *);
314   u8 ** string_return = va_arg (*va, u8 **);
315   u8 * s, map[256];
316   uword i, c;
317
318   if (! token_chars)
319     token_chars = (u8 *) "a-zA-Z0-9_";
320
321   memset (map, 0, sizeof (map));
322   for (s = token_chars; *s; )
323     {
324       /* Parse range. */
325       if (s[0] < s[2] && s[1] == '-')
326         {
327           for (i = s[0]; i <= s[2]; i++)
328             map[i] = 1;
329           s = s + 3;
330         }       
331       else
332         {
333           map[s[0]] = 1;
334           s = s + 1;
335         }
336     }
337
338   s = 0;
339   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
340     {
341       if (! map[c])
342         {
343           unformat_put_input (input);
344           break;
345         }
346         
347       vec_add1 (s, c);
348     }
349
350   if (vec_len (s) == 0)
351     return 0;
352
353   *string_return = s;
354   return 1;
355 }
356
357 /* Unformat (parse) function which reads a %s string and converts it
358    to and unformat_input_t. */
359 uword unformat_input (unformat_input_t * i, va_list * args)
360 {
361   unformat_input_t * sub_input = va_arg (*args, unformat_input_t *);
362   u8 * s;
363
364   if (unformat (i, "%v", &s))
365     {
366       unformat_init_vector (sub_input, s);
367       return 1;
368     }
369
370   return 0;
371 }
372
373 /* Parse a line ending with \n and return it. */
374 uword unformat_line (unformat_input_t * i, va_list * va)
375 {
376   u8 * line = 0, ** result = va_arg (*va, u8 **);
377   uword c;
378
379   while ((c = unformat_get_input (i)) != '\n'
380          && c != UNFORMAT_END_OF_INPUT)
381     {
382       vec_add1 (line, c);
383     }
384
385   *result = line;
386   return 1;
387 }
388
389 /* Parse a line ending with \n and return it as an unformat_input_t. */
390 uword unformat_line_input (unformat_input_t * i, va_list * va)
391 {
392   unformat_input_t * result = va_arg (*va, unformat_input_t *);
393   u8 * line;
394   unformat_user (i, unformat_line, &line);
395   unformat_init_vector (result, line);
396   return 1;
397 }
398
399 /* Values for is_signed. */
400 #define UNFORMAT_INTEGER_SIGNED         1
401 #define UNFORMAT_INTEGER_UNSIGNED       0
402
403 static uword
404 unformat_integer (unformat_input_t * input,
405                   va_list * va,
406                   uword base,
407                   uword is_signed,
408                   uword data_bytes)
409 {
410   uword c, digit;
411   uword value = 0;
412   uword n_digits = 0;
413   uword n_input = 0;
414   uword sign = 0;
415
416   /* We only support bases <= 64. */
417   if (base < 2 || base > 64)
418     goto error;
419
420   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
421     {
422       switch (c)
423         {
424         case '-':
425           if (n_input == 0)
426             {
427               if (is_signed)
428                 {
429                   sign = 1;
430                   goto next_digit;
431                 }
432               else
433                 /* Leading sign for unsigned number. */
434                 goto error;
435             }
436           /* Sign after input (e.g. 100-200). */
437           goto put_input_done;
438
439         case '+':
440           if (n_input > 0) 
441             goto put_input_done;
442           sign = 0;
443           goto next_digit;
444
445         case '0' ... '9':
446           digit = c - '0';
447           break;
448
449         case 'a' ... 'z':
450           digit = 10 + (c - 'a');
451           break;
452
453         case 'A' ... 'Z':
454           digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A');
455           break;
456
457         case '/':
458           digit = 62;
459           break;
460
461         case '?':
462           digit = 63;
463           break;
464
465         default:
466           goto put_input_done;
467         }
468
469       if (digit >= base)
470         {
471         put_input_done:
472           unformat_put_input (input);
473           goto done;
474         }
475
476       {
477         uword new_value = base*value + digit;
478
479         /* Check for overflow. */
480         if (new_value < value)
481           goto error;
482         value = new_value;
483       }
484       n_digits += 1;
485
486     next_digit:
487       n_input++;
488     }
489
490  done:
491   if (sign)
492     value = -value;
493
494   if (n_digits > 0)
495     {
496       void * v = va_arg (*va, void *);
497
498       if (data_bytes == ~0)
499           data_bytes = sizeof (int);
500
501       switch (data_bytes)
502         {
503         case 1: *(u8  *) v = value; break;
504         case 2: *(u16 *) v = value; break;
505         case 4: *(u32 *) v = value; break;
506         case 8: *(u64 *) v = value; break;
507         default:
508             goto error;
509         }
510
511       return 1;
512     }
513
514  error:
515   return 0;
516 }
517
518 /* Return x 10^n */
519 static f64 times_power_of_ten (f64 x, int n)
520 {
521   if (n >= 0)
522     {
523       static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
524       while (n >= 8)
525         {
526           x *= 1e+8;
527           n -= 8;
528         }
529       return x * t[n];
530     }
531   else
532     {
533       static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
534       while (n <= -8)
535         {
536           x *= 1e-8;
537           n += 8;
538         }
539       return x * t[-n];
540     }
541   
542 }
543
544 static uword
545 unformat_float (unformat_input_t * input,
546                 va_list * va)
547 {
548   uword c;
549   u64 values[3];
550   uword n_digits[3], value_index = 0;
551   uword signs[2], sign_index = 0;
552   uword n_input = 0;
553
554   memset (values, 0, sizeof (values));
555   memset (n_digits, 0, sizeof (n_digits));
556   memset (signs, 0, sizeof (signs));
557
558   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
559     {
560       switch (c)
561         {
562         case '-':
563           if (value_index == 2 && n_digits[2] == 0)
564             /* sign of exponent: it's ok. */;
565
566           else if (value_index < 2 && n_digits[0] > 0)
567             {
568               /* 123- */
569               unformat_put_input (input);
570               goto done;
571             }
572
573           else if (n_input > 0)
574             goto error;
575
576           signs[sign_index++] = 1;
577           goto next_digit;
578
579         case '+':
580           if (value_index == 2 && n_digits[2] == 0)
581             /* sign of exponent: it's ok. */;
582
583           else if (value_index < 2 && n_digits[0] > 0)
584             {
585               /* 123+ */
586               unformat_put_input (input);
587               goto done;
588             }
589
590           else if (n_input > 0)
591             goto error;
592           signs[sign_index++] = 0;
593           goto next_digit;
594
595         case 'e':
596         case 'E':
597           if (n_input == 0)
598             goto error;
599           value_index = 2;
600           sign_index = 1;
601           break;
602
603         case '.':
604           if (value_index > 0)
605             goto error;
606           value_index = 1;
607           break;
608
609         case '0' ... '9':
610           {
611             u64 tmp;
612
613             tmp = values[value_index] * 10 + c - '0';
614
615             /* Check for overflow. */
616             if (tmp < values[value_index])
617               goto error;
618             values[value_index] = tmp;
619             n_digits[value_index] += 1;
620           }
621           break;
622
623         default:
624           unformat_put_input (input);
625           goto done;
626         }
627
628     next_digit:
629       n_input++;
630     }
631
632  done:
633   {
634     f64 f_values[2], * value_return;
635     word expon;
636
637     /* Must have either whole or fraction digits. */
638     if (n_digits[0] + n_digits[1] <= 0)
639       goto error;
640
641     f_values[0] = values[0];
642     if (signs[0])
643       f_values[0] = -f_values[0];
644
645     f_values[1] = values[1];
646     f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]);
647
648     f_values[0] += f_values[1];
649
650     expon = values[2];
651     if (signs[1])
652       expon = -expon;
653
654     f_values[0] = times_power_of_ten (f_values[0], expon);
655
656     value_return = va_arg (*va, f64 *);
657     *value_return = f_values[0];
658     return 1;
659   }
660
661  error:
662   return 0;
663 }
664
665 static char * match_input_with_format (unformat_input_t * input, char * f)
666 {
667   uword cf, ci;
668
669   ASSERT (*f != 0);
670
671   while (1)
672     {
673       cf = *f;
674       if (cf == 0 || cf == '%' || cf == ' ')
675         break;
676       f++;
677
678       ci = unformat_get_input (input);
679
680       if (cf != ci)
681         return 0;
682     }
683   return f;
684 }
685
686 static char * do_percent (unformat_input_t * input, va_list * va, char * f)
687 {
688   uword cf, n, data_bytes = ~0;
689
690   cf = *f++;
691
692   switch (cf)
693     {
694     default:
695       break;
696
697     case 'w':
698       /* Word types. */
699       cf = *f++;
700       data_bytes = sizeof (uword);
701       break;
702
703     case 'l':
704       cf = *f++;
705       if (cf == 'l')
706         {
707           cf = *f++;
708           data_bytes = sizeof (long long);
709         }
710       else
711         {
712           data_bytes = sizeof (long);
713         }
714       break;
715               
716     case 'L':
717       cf = *f++;
718       data_bytes = sizeof (long long);
719       break;
720     }
721
722   n = 0;
723   switch (cf)
724     {
725     case 'D':
726       data_bytes = va_arg (*va, int);
727     case 'd':
728       n = unformat_integer (input, va, 10,
729                             UNFORMAT_INTEGER_SIGNED, data_bytes);
730       break;
731
732     case 'u':
733       n = unformat_integer (input, va, 10,
734                             UNFORMAT_INTEGER_UNSIGNED, data_bytes);
735       break;
736
737     case 'b':
738       n = unformat_integer (input, va, 2,
739                             UNFORMAT_INTEGER_UNSIGNED, data_bytes);
740       break;
741
742     case 'o':
743       n = unformat_integer (input, va, 8,
744                             UNFORMAT_INTEGER_UNSIGNED, data_bytes);
745       break;
746
747     case 'X':
748       data_bytes = va_arg (*va, int);
749     case 'x':
750       n = unformat_integer (input, va, 16,
751                             UNFORMAT_INTEGER_UNSIGNED, data_bytes);
752       break;
753
754     case 'f':
755       n = unformat_float (input, va);
756       break;
757
758     case 's':
759     case 'v':
760       n = unformat_string (input, f[0], cf, va);
761       break;
762
763     case 'U':
764       {
765         unformat_function_t * f = va_arg (*va, unformat_function_t *);
766         n = f (input, va);
767       }
768       break;
769
770     case '=':
771     case '|':
772       {
773         int * var = va_arg (*va, int *);
774         uword val = va_arg (*va, int);
775
776         if (cf == '|')
777           val |= *var;
778         *var = val;
779         n = 1;
780       }
781       break;
782     }
783
784   return n ? f : 0;
785 }
786
787 uword unformat_skip_white_space (unformat_input_t * input)
788 {
789   uword n = 0;
790   uword c;
791
792   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
793     {
794       if (! is_white_space (c))
795         {
796           unformat_put_input (input);
797           break;
798         }
799       n++;
800     }
801   return n;
802 }
803
804 uword
805 va_unformat (unformat_input_t * input, char * fmt, va_list * va)
806 {
807   char * f;
808   uword input_matches_format;
809   uword default_skip_input_white_space;
810   uword n_input_white_space_skipped;
811   uword last_non_white_space_match_percent;
812   uword last_non_white_space_match_format;
813
814   vec_add1_aligned (input->buffer_marks, input->index, sizeof (input->buffer_marks[0]));
815
816   f = fmt;
817   default_skip_input_white_space = 1;
818   input_matches_format = 0;
819   last_non_white_space_match_percent = 0;
820   last_non_white_space_match_format = 0;
821   
822   while (1)
823     {
824       char cf;
825       uword is_percent, skip_input_white_space;
826
827       cf = *f;
828       is_percent = 0;
829
830       /* Always skip input white space at start of format string.
831          Otherwise use default skip value which can be changed by %_ 
832          (see below). */
833       skip_input_white_space = f == fmt || default_skip_input_white_space;
834
835       /* Spaces in format request skipping input white space. */
836       if (is_white_space (cf))
837         {
838           skip_input_white_space = 1;
839
840           /* Multiple format spaces are equivalent to a single white
841              space. */
842           while (is_white_space (*++f))
843             ;
844         }
845       else if (cf == '%')
846         {
847           /* %_ toggles whether or not to skip input white space. */
848           switch (*++f)
849             {
850             case '_':
851               default_skip_input_white_space = !default_skip_input_white_space;
852               f++;
853               /* For transition from skip to no-skip in middle of format
854                  string, skip input white space.  For example, the following matches:
855                     fmt = "%_%d.%d%_->%_%d.%d%_"
856                     input "1.2 -> 3.4"
857                  Without this the space after -> does not get skipped. */
858               if (! default_skip_input_white_space
859                   && ! (f == fmt + 2 || *f == 0))
860                 unformat_skip_white_space (input);
861               continue;
862
863             /* %% means match % */
864             case '%':
865               break;
866
867             /* % at end of format string. */
868             case 0:
869               goto parse_fail;
870
871             default:
872               is_percent = 1;
873               break;
874             }
875         }
876
877       n_input_white_space_skipped = 0;
878       if (skip_input_white_space)
879         n_input_white_space_skipped = unformat_skip_white_space (input);
880
881       /* End of format string. */
882       if (cf == 0)
883         {
884           /* Force parse error when format string ends and input is
885              not white or at end.  As an example, this is to prevent
886              format "foo" from matching input "food".
887              The last_non_white_space_match_percent is to make
888              "foo %d" match input "foo 10,bletch" with %d matching 10. */
889           if (skip_input_white_space
890               && ! last_non_white_space_match_percent
891               && ! last_non_white_space_match_format
892               && n_input_white_space_skipped == 0
893               && input->index != UNFORMAT_END_OF_INPUT)
894             goto parse_fail;
895           break;
896         }
897
898       last_non_white_space_match_percent = is_percent;
899       last_non_white_space_match_format = 0;
900
901       /* Explicit spaces in format must match input white space. */
902       if (cf == ' ' && !default_skip_input_white_space)
903         {
904           if (n_input_white_space_skipped == 0)
905             goto parse_fail;
906         }
907
908       else if (is_percent)
909         {
910           if (! (f = do_percent (input, va, f)))
911             goto parse_fail;
912         }
913
914       else
915         {
916           char * g = match_input_with_format (input, f);
917           if (! g)
918             goto parse_fail;
919           last_non_white_space_match_format = g > f;
920           f = g;
921         }
922     }
923
924   input_matches_format = 1;
925  parse_fail:
926
927   /* Rewind buffer marks. */
928   {
929     uword l = vec_len (input->buffer_marks);
930
931     /* If we did not match back up buffer to last mark. */
932     if (! input_matches_format)
933       input->index = input->buffer_marks[l-1];
934
935     _vec_len (input->buffer_marks) = l - 1;
936   }
937
938   return input_matches_format;
939 }
940
941 uword
942 unformat (unformat_input_t * input, char * fmt, ...)
943 {
944   va_list va;
945   uword result;
946   va_start (va, fmt);
947   result = va_unformat (input, fmt, &va);
948   va_end (va);
949   return result;
950 }
951
952 uword
953 unformat_user (unformat_input_t * input, unformat_function_t * func, ...)
954 {
955   va_list va;
956   uword result, l;
957
958   /* Save place in input buffer in case parse fails. */
959   l = vec_len (input->buffer_marks);
960   vec_add1_aligned (input->buffer_marks, input->index, sizeof (input->buffer_marks[0]));
961
962   va_start (va, func);
963   result = func (input, &va);
964   va_end (va);
965
966   if (! result)
967     input->index = input->buffer_marks[l];
968
969   _vec_len (input->buffer_marks) = l;
970
971   return result;
972 }
973
974 /* Setup for unformat of Unix style command line. */
975 void unformat_init_command_line (unformat_input_t * input,
976                                  char * argv[])
977 {
978   uword i;
979
980   unformat_init (input, 0, 0);
981
982   /* Concatenate argument strings with space in between. */
983   for (i = 1; argv[i]; i++)
984     {
985       vec_add (input->buffer, argv[i], strlen (argv[i]));
986       if (argv[i + 1])
987         vec_add1 (input->buffer, ' ');
988     }
989 }
990
991 void unformat_init_string (unformat_input_t * input,
992                            char * string,
993                            int string_len)
994 {
995   unformat_init (input, 0, 0);
996   if (string_len > 0)
997     vec_add (input->buffer, string, string_len);
998 }
999
1000 void unformat_init_vector (unformat_input_t * input,
1001                            u8 * vector_string)
1002 {
1003   unformat_init (input, 0, 0);
1004   input->buffer = vector_string;
1005 }
1006
1007 #ifdef CLIB_UNIX
1008
1009 static uword unix_file_fill_buffer (unformat_input_t * input)
1010 {
1011   int fd = pointer_to_uword (input->fill_buffer_arg);
1012   uword l, n;
1013
1014   l = vec_len (input->buffer);
1015   vec_resize (input->buffer, 4096);
1016   n = read (fd, input->buffer + l, 4096);
1017   if (n > 0)
1018     _vec_len (input->buffer) = l + n;
1019
1020   if (n <= 0)
1021     return UNFORMAT_END_OF_INPUT;
1022   else
1023     return input->index;
1024 }
1025
1026 void unformat_init_unix_file (unformat_input_t * input,
1027                               int file_descriptor)
1028 {
1029   unformat_init (input, unix_file_fill_buffer,
1030                  uword_to_pointer (file_descriptor, void *));
1031 }
1032
1033 /* Take input from Unix environment variable. */
1034 uword unformat_init_unix_env (unformat_input_t * input, char * var)
1035 {
1036   char * val = getenv (var);
1037   if (val)
1038     unformat_init_string (input, val, strlen (val));
1039   return val != 0;
1040 }
1041
1042 #endif /* CLIB_UNIX */
1043