diff options
author | Damjan Marion <damarion@cisco.com> | 2016-12-19 23:05:39 +0100 |
---|---|---|
committer | Damjan Marion <damarion@cisco.com> | 2016-12-28 12:25:14 +0100 |
commit | 7cd468a3d7dee7d6c92f69a0bb7061ae208ec727 (patch) | |
tree | 5de62f8dbd3a752f5a676ca600e43d2652d1ff1a /vppinfra/vppinfra/unformat.c | |
parent | 696f1adec0df3b8f161862566dd9c86174302658 (diff) |
Reorganize source tree to use single autotools instance
Change-Id: I7b51f88292e057c6443b12224486f2d0c9f8ae23
Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'vppinfra/vppinfra/unformat.c')
-rw-r--r-- | vppinfra/vppinfra/unformat.c | 1077 |
1 files changed, 0 insertions, 1077 deletions
diff --git a/vppinfra/vppinfra/unformat.c b/vppinfra/vppinfra/unformat.c deleted file mode 100644 index ac8b7ddc712..00000000000 --- a/vppinfra/vppinfra/unformat.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> - -/* Call user's function to fill input buffer. */ -uword -_unformat_fill_input (unformat_input_t * i) -{ - uword l, first_mark; - - if (i->index == UNFORMAT_END_OF_INPUT) - return i->index; - - first_mark = l = vec_len (i->buffer); - if (vec_len (i->buffer_marks) > 0) - first_mark = i->buffer_marks[0]; - - /* Re-use buffer when no marks. */ - if (first_mark > 0) - vec_delete (i->buffer, first_mark, 0); - - i->index = vec_len (i->buffer); - for (l = 0; l < vec_len (i->buffer_marks); l++) - i->buffer_marks[l] -= first_mark; - - /* Call user's function to fill the buffer. */ - if (i->fill_buffer) - i->index = i->fill_buffer (i); - - /* If input pointer is still beyond end of buffer even after - fill then we've run out of input. */ - if (i->index >= vec_len (i->buffer)) - i->index = UNFORMAT_END_OF_INPUT; - - return i->index; -} - -always_inline uword -is_white_space (uword c) -{ - switch (c) - { - case ' ': - case '\t': - case '\n': - case '\r': - return 1; - - default: - return 0; - } -} - -/* Format function for dumping input stream. */ -u8 * -format_unformat_error (u8 * s, va_list * va) -{ - unformat_input_t *i = va_arg (*va, unformat_input_t *); - uword l = vec_len (i->buffer); - - /* Only show so much of the input buffer (it could be really large). */ - uword n_max = 30; - - if (i->index < l) - { - uword n = l - i->index; - u8 *p, *p_end; - - p = i->buffer + i->index; - p_end = p + (n > n_max ? n_max : n); - - /* Skip white space at end. */ - if (n <= n_max) - { - while (p_end > p && is_white_space (p_end[-1])) - p_end--; - } - - while (p < p_end) - { - switch (*p) - { - case '\r': - vec_add (s, "\\r", 2); - break; - case '\n': - vec_add (s, "\\n", 2); - break; - case '\t': - vec_add (s, "\\t", 2); - break; - default: - vec_add1 (s, *p); - break; - } - p++; - } - - if (n > n_max) - vec_add (s, "...", 3); - } - - return s; -} - -/* Print everything: not just error context. */ -u8 * -format_unformat_input (u8 * s, va_list * va) -{ - unformat_input_t *i = va_arg (*va, unformat_input_t *); - uword l, n; - - if (i->index == UNFORMAT_END_OF_INPUT) - s = format (s, "{END_OF_INPUT}"); - else - { - l = vec_len (i->buffer); - n = l - i->index; - if (n > 0) - vec_add (s, i->buffer + i->index, n); - } - - return s; -} - -#if CLIB_DEBUG > 0 -void -di (unformat_input_t * i) -{ - fformat (stderr, "%U\n", format_unformat_input, i); -} -#endif - -/* Parse delimited vector string. If string starts with { then string - is delimited by balenced parenthesis. Other string is delimited by - white space. {} were chosen since they are special to the shell. */ -static uword -unformat_string (unformat_input_t * input, - uword delimiter_character, - uword format_character, va_list * va) -{ - u8 **string_return = va_arg (*va, u8 **); - u8 *s = 0; - word paren = 0; - word is_paren_delimited = 0; - word backslash = 0; - uword c; - - switch (delimiter_character) - { - case '%': - case ' ': - case '\t': - delimiter_character = 0; - break; - } - - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - word add_to_vector; - - /* Null return string means to skip over delimited input. */ - add_to_vector = string_return != 0; - - if (backslash) - backslash = 0; - else - switch (c) - { - case '\\': - backslash = 1; - add_to_vector = 0; - break; - - case '{': - if (paren == 0 && vec_len (s) == 0) - { - is_paren_delimited = 1; - add_to_vector = 0; - } - paren++; - break; - - case '}': - paren--; - if (is_paren_delimited && paren == 0) - goto done; - break; - - case ' ': - case '\t': - case '\n': - case '\r': - if (!is_paren_delimited) - { - unformat_put_input (input); - goto done; - } - break; - - default: - if (!is_paren_delimited && c == delimiter_character) - { - unformat_put_input (input); - goto done; - } - } - - if (add_to_vector) - vec_add1 (s, c); - } - -done: - if (string_return) - { - /* Match the string { END-OF-INPUT as a single brace. */ - if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0 && paren == 1) - vec_add1 (s, '{'); - - /* Don't match null string. */ - if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0) - return 0; - - /* Null terminate C string. */ - if (format_character == 's') - vec_add1 (s, 0); - - *string_return = s; - } - else - vec_free (s); /* just to make sure */ - - return 1; -} - -uword -unformat_hex_string (unformat_input_t * input, va_list * va) -{ - u8 **hexstring_return = va_arg (*va, u8 **); - u8 *s; - uword n, d, c; - - n = 0; - d = 0; - s = 0; - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - if (c >= '0' && c <= '9') - d = 16 * d + c - '0'; - else if (c >= 'a' && c <= 'f') - d = 16 * d + 10 + c - 'a'; - else if (c >= 'A' && c <= 'F') - d = 16 * d + 10 + c - 'A'; - else - { - unformat_put_input (input); - break; - } - n++; - - if (n == 2) - { - vec_add1 (s, d); - n = d = 0; - } - } - - /* Hex string must have even number of digits. */ - if (n % 2) - { - vec_free (s); - return 0; - } - - *hexstring_return = s; - return 1; -} - -/* unformat (input "foo%U", unformat_eof) matches terminal foo only */ -uword -unformat_eof (unformat_input_t * input, va_list * va) -{ - return unformat_check_input (input) == UNFORMAT_END_OF_INPUT; -} - -/* Parse a token containing given set of characters. */ -uword -unformat_token (unformat_input_t * input, va_list * va) -{ - u8 *token_chars = va_arg (*va, u8 *); - u8 **string_return = va_arg (*va, u8 **); - u8 *s, map[256]; - uword i, c; - - if (!token_chars) - token_chars = (u8 *) "a-zA-Z0-9_"; - - memset (map, 0, sizeof (map)); - for (s = token_chars; *s;) - { - /* Parse range. */ - if (s[0] < s[2] && s[1] == '-') - { - for (i = s[0]; i <= s[2]; i++) - map[i] = 1; - s = s + 3; - } - else - { - map[s[0]] = 1; - s = s + 1; - } - } - - s = 0; - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - if (!map[c]) - { - unformat_put_input (input); - break; - } - - vec_add1 (s, c); - } - - if (vec_len (s) == 0) - return 0; - - *string_return = s; - return 1; -} - -/* Unformat (parse) function which reads a %s string and converts it - to and unformat_input_t. */ -uword -unformat_input (unformat_input_t * i, va_list * args) -{ - unformat_input_t *sub_input = va_arg (*args, unformat_input_t *); - u8 *s; - - if (unformat (i, "%v", &s)) - { - unformat_init_vector (sub_input, s); - return 1; - } - - return 0; -} - -/* Parse a line ending with \n and return it. */ -uword -unformat_line (unformat_input_t * i, va_list * va) -{ - u8 *line = 0, **result = va_arg (*va, u8 **); - uword c; - - while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT) - { - vec_add1 (line, c); - } - - *result = line; - return 1; -} - -/* Parse a line ending with \n and return it as an unformat_input_t. */ -uword -unformat_line_input (unformat_input_t * i, va_list * va) -{ - unformat_input_t *result = va_arg (*va, unformat_input_t *); - u8 *line; - unformat_user (i, unformat_line, &line); - unformat_init_vector (result, line); - return 1; -} - -/* Values for is_signed. */ -#define UNFORMAT_INTEGER_SIGNED 1 -#define UNFORMAT_INTEGER_UNSIGNED 0 - -static uword -unformat_integer (unformat_input_t * input, - va_list * va, uword base, uword is_signed, uword data_bytes) -{ - uword c, digit; - uword value = 0; - uword n_digits = 0; - uword n_input = 0; - uword sign = 0; - - /* We only support bases <= 64. */ - if (base < 2 || base > 64) - goto error; - - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - switch (c) - { - case '-': - if (n_input == 0) - { - if (is_signed) - { - sign = 1; - goto next_digit; - } - else - /* Leading sign for unsigned number. */ - goto error; - } - /* Sign after input (e.g. 100-200). */ - goto put_input_done; - - case '+': - if (n_input > 0) - goto put_input_done; - sign = 0; - goto next_digit; - - case '0' ... '9': - digit = c - '0'; - break; - - case 'a' ... 'z': - digit = 10 + (c - 'a'); - break; - - case 'A' ... 'Z': - digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A'); - break; - - case '/': - digit = 62; - break; - - case '?': - digit = 63; - break; - - default: - goto put_input_done; - } - - if (digit >= base) - { - put_input_done: - unformat_put_input (input); - goto done; - } - - { - uword new_value = base * value + digit; - - /* Check for overflow. */ - if (new_value < value) - goto error; - value = new_value; - } - n_digits += 1; - - next_digit: - n_input++; - } - -done: - if (sign) - value = -value; - - if (n_digits > 0) - { - void *v = va_arg (*va, void *); - - if (data_bytes == ~0) - data_bytes = sizeof (int); - - switch (data_bytes) - { - case 1: - *(u8 *) v = value; - break; - case 2: - *(u16 *) v = value; - break; - case 4: - *(u32 *) v = value; - break; - case 8: - *(u64 *) v = value; - break; - default: - goto error; - } - - return 1; - } - -error: - return 0; -} - -/* Return x 10^n */ -static f64 -times_power_of_ten (f64 x, int n) -{ - if (n >= 0) - { - static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, }; - while (n >= 8) - { - x *= 1e+8; - n -= 8; - } - return x * t[n]; - } - else - { - static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, }; - while (n <= -8) - { - x *= 1e-8; - n += 8; - } - return x * t[-n]; - } - -} - -static uword -unformat_float (unformat_input_t * input, va_list * va) -{ - uword c; - u64 values[3]; - uword n_digits[3], value_index = 0; - uword signs[2], sign_index = 0; - uword n_input = 0; - - memset (values, 0, sizeof (values)); - memset (n_digits, 0, sizeof (n_digits)); - memset (signs, 0, sizeof (signs)); - - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - switch (c) - { - case '-': - if (value_index == 2 && n_digits[2] == 0) - /* sign of exponent: it's ok. */ ; - - else if (value_index < 2 && n_digits[0] > 0) - { - /* 123- */ - unformat_put_input (input); - goto done; - } - - else if (n_input > 0) - goto error; - - signs[sign_index++] = 1; - goto next_digit; - - case '+': - if (value_index == 2 && n_digits[2] == 0) - /* sign of exponent: it's ok. */ ; - - else if (value_index < 2 && n_digits[0] > 0) - { - /* 123+ */ - unformat_put_input (input); - goto done; - } - - else if (n_input > 0) - goto error; - signs[sign_index++] = 0; - goto next_digit; - - case 'e': - case 'E': - if (n_input == 0) - goto error; - value_index = 2; - sign_index = 1; - break; - - case '.': - if (value_index > 0) - goto error; - value_index = 1; - break; - - case '0' ... '9': - { - u64 tmp; - - tmp = values[value_index] * 10 + c - '0'; - - /* Check for overflow. */ - if (tmp < values[value_index]) - goto error; - values[value_index] = tmp; - n_digits[value_index] += 1; - } - break; - - default: - unformat_put_input (input); - goto done; - } - - next_digit: - n_input++; - } - -done: - { - f64 f_values[2], *value_return; - word expon; - - /* Must have either whole or fraction digits. */ - if (n_digits[0] + n_digits[1] <= 0) - goto error; - - f_values[0] = values[0]; - if (signs[0]) - f_values[0] = -f_values[0]; - - f_values[1] = values[1]; - f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]); - - f_values[0] += f_values[1]; - - expon = values[2]; - if (signs[1]) - expon = -expon; - - f_values[0] = times_power_of_ten (f_values[0], expon); - - value_return = va_arg (*va, f64 *); - *value_return = f_values[0]; - return 1; - } - -error: - return 0; -} - -static char * -match_input_with_format (unformat_input_t * input, char *f) -{ - uword cf, ci; - - ASSERT (*f != 0); - - while (1) - { - cf = *f; - if (cf == 0 || cf == '%' || cf == ' ') - break; - f++; - - ci = unformat_get_input (input); - - if (cf != ci) - return 0; - } - return f; -} - -static char * -do_percent (unformat_input_t * input, va_list * va, char *f) -{ - uword cf, n, data_bytes = ~0; - - cf = *f++; - - switch (cf) - { - default: - break; - - case 'w': - /* Word types. */ - cf = *f++; - data_bytes = sizeof (uword); - break; - - case 'l': - cf = *f++; - if (cf == 'l') - { - cf = *f++; - data_bytes = sizeof (long long); - } - else - { - data_bytes = sizeof (long); - } - break; - - case 'L': - cf = *f++; - data_bytes = sizeof (long long); - break; - } - - n = 0; - switch (cf) - { - case 'D': - data_bytes = va_arg (*va, int); - case 'd': - n = unformat_integer (input, va, 10, - UNFORMAT_INTEGER_SIGNED, data_bytes); - break; - - case 'u': - n = unformat_integer (input, va, 10, - UNFORMAT_INTEGER_UNSIGNED, data_bytes); - break; - - case 'b': - n = unformat_integer (input, va, 2, - UNFORMAT_INTEGER_UNSIGNED, data_bytes); - break; - - case 'o': - n = unformat_integer (input, va, 8, - UNFORMAT_INTEGER_UNSIGNED, data_bytes); - break; - - case 'X': - data_bytes = va_arg (*va, int); - case 'x': - n = unformat_integer (input, va, 16, - UNFORMAT_INTEGER_UNSIGNED, data_bytes); - break; - - case 'f': - n = unformat_float (input, va); - break; - - case 's': - case 'v': - n = unformat_string (input, f[0], cf, va); - break; - - case 'U': - { - unformat_function_t *f = va_arg (*va, unformat_function_t *); - n = f (input, va); - } - break; - - case '=': - case '|': - { - int *var = va_arg (*va, int *); - uword val = va_arg (*va, int); - - if (cf == '|') - val |= *var; - *var = val; - n = 1; - } - break; - } - - return n ? f : 0; -} - -uword -unformat_skip_white_space (unformat_input_t * input) -{ - uword n = 0; - uword c; - - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - if (!is_white_space (c)) - { - unformat_put_input (input); - break; - } - n++; - } - return n; -} - -uword -va_unformat (unformat_input_t * input, char *fmt, va_list * va) -{ - char *f; - uword input_matches_format; - uword default_skip_input_white_space; - uword n_input_white_space_skipped; - uword last_non_white_space_match_percent; - uword last_non_white_space_match_format; - - vec_add1_aligned (input->buffer_marks, input->index, - sizeof (input->buffer_marks[0])); - - f = fmt; - default_skip_input_white_space = 1; - input_matches_format = 0; - last_non_white_space_match_percent = 0; - last_non_white_space_match_format = 0; - - while (1) - { - char cf; - uword is_percent, skip_input_white_space; - - cf = *f; - is_percent = 0; - - /* Always skip input white space at start of format string. - Otherwise use default skip value which can be changed by %_ - (see below). */ - skip_input_white_space = f == fmt || default_skip_input_white_space; - - /* Spaces in format request skipping input white space. */ - if (is_white_space (cf)) - { - skip_input_white_space = 1; - - /* Multiple format spaces are equivalent to a single white - space. */ - while (is_white_space (*++f)) - ; - } - else if (cf == '%') - { - /* %_ toggles whether or not to skip input white space. */ - switch (*++f) - { - case '_': - default_skip_input_white_space = - !default_skip_input_white_space; - f++; - /* For transition from skip to no-skip in middle of format - string, skip input white space. For example, the following matches: - fmt = "%_%d.%d%_->%_%d.%d%_" - input "1.2 -> 3.4" - Without this the space after -> does not get skipped. */ - if (!default_skip_input_white_space - && !(f == fmt + 2 || *f == 0)) - unformat_skip_white_space (input); - continue; - - /* %% means match % */ - case '%': - break; - - /* % at end of format string. */ - case 0: - goto parse_fail; - - default: - is_percent = 1; - break; - } - } - - n_input_white_space_skipped = 0; - if (skip_input_white_space) - n_input_white_space_skipped = unformat_skip_white_space (input); - - /* End of format string. */ - if (cf == 0) - { - /* Force parse error when format string ends and input is - not white or at end. As an example, this is to prevent - format "foo" from matching input "food". - The last_non_white_space_match_percent is to make - "foo %d" match input "foo 10,bletch" with %d matching 10. */ - if (skip_input_white_space - && !last_non_white_space_match_percent - && !last_non_white_space_match_format - && n_input_white_space_skipped == 0 - && input->index != UNFORMAT_END_OF_INPUT) - goto parse_fail; - break; - } - - last_non_white_space_match_percent = is_percent; - last_non_white_space_match_format = 0; - - /* Explicit spaces in format must match input white space. */ - if (cf == ' ' && !default_skip_input_white_space) - { - if (n_input_white_space_skipped == 0) - goto parse_fail; - } - - else if (is_percent) - { - if (!(f = do_percent (input, va, f))) - goto parse_fail; - } - - else - { - char *g = match_input_with_format (input, f); - if (!g) - goto parse_fail; - last_non_white_space_match_format = g > f; - f = g; - } - } - - input_matches_format = 1; -parse_fail: - - /* Rewind buffer marks. */ - { - uword l = vec_len (input->buffer_marks); - - /* If we did not match back up buffer to last mark. */ - if (!input_matches_format) - input->index = input->buffer_marks[l - 1]; - - _vec_len (input->buffer_marks) = l - 1; - } - - return input_matches_format; -} - -uword -unformat (unformat_input_t * input, char *fmt, ...) -{ - va_list va; - uword result; - va_start (va, fmt); - result = va_unformat (input, fmt, &va); - va_end (va); - return result; -} - -uword -unformat_user (unformat_input_t * input, unformat_function_t * func, ...) -{ - va_list va; - uword result, l; - - /* Save place in input buffer in case parse fails. */ - l = vec_len (input->buffer_marks); - vec_add1_aligned (input->buffer_marks, input->index, - sizeof (input->buffer_marks[0])); - - va_start (va, func); - result = func (input, &va); - va_end (va); - - if (!result && input->index != UNFORMAT_END_OF_INPUT) - input->index = input->buffer_marks[l]; - - _vec_len (input->buffer_marks) = l; - - return result; -} - -/* Setup for unformat of Unix style command line. */ -void -unformat_init_command_line (unformat_input_t * input, char *argv[]) -{ - uword i; - - unformat_init (input, 0, 0); - - /* Concatenate argument strings with space in between. */ - for (i = 1; argv[i]; i++) - { - vec_add (input->buffer, argv[i], strlen (argv[i])); - if (argv[i + 1]) - vec_add1 (input->buffer, ' '); - } -} - -void -unformat_init_string (unformat_input_t * input, char *string, int string_len) -{ - unformat_init (input, 0, 0); - if (string_len > 0) - vec_add (input->buffer, string, string_len); -} - -void -unformat_init_vector (unformat_input_t * input, u8 * vector_string) -{ - unformat_init (input, 0, 0); - input->buffer = vector_string; -} - -#ifdef CLIB_UNIX - -static uword -unix_file_fill_buffer (unformat_input_t * input) -{ - int fd = pointer_to_uword (input->fill_buffer_arg); - uword l, n; - - l = vec_len (input->buffer); - vec_resize (input->buffer, 4096); - n = read (fd, input->buffer + l, 4096); - if (n > 0) - _vec_len (input->buffer) = l + n; - - if (n <= 0) - return UNFORMAT_END_OF_INPUT; - else - return input->index; -} - -void -unformat_init_unix_file (unformat_input_t * input, int file_descriptor) -{ - unformat_init (input, unix_file_fill_buffer, - uword_to_pointer (file_descriptor, void *)); -} - -/* Take input from Unix environment variable. */ -uword -unformat_init_unix_env (unformat_input_t * input, char *var) -{ - char *val = getenv (var); - if (val) - unformat_init_string (input, val, strlen (val)); - return val != 0; -} - -#endif /* CLIB_UNIX */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |