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