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