Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 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 | #ifndef included_format_h |
| 39 | #define included_format_h |
| 40 | |
| 41 | #include <stdarg.h> |
| 42 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 43 | #include <vppinfra/clib.h> /* for CLIB_UNIX, etc. */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 44 | #include <vppinfra/vec.h> |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 45 | #include <vppinfra/error.h> /* for ASSERT */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 46 | #include <vppinfra/string.h> |
| 47 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 48 | typedef u8 *(format_function_t) (u8 * s, va_list * args); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 49 | |
Neale Ranns | 0bfe5d8 | 2016-08-25 15:29:12 +0100 | [diff] [blame] | 50 | u8 *va_format (u8 * s, const char *format, va_list * args); |
| 51 | u8 *format (u8 * s, const char *format, ...); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 52 | |
| 53 | #ifdef CLIB_UNIX |
| 54 | |
| 55 | #include <stdio.h> |
| 56 | |
| 57 | #else /* ! CLIB_UNIX */ |
| 58 | |
| 59 | /* We're not Unix and have not stdio.h */ |
| 60 | #define FILE void |
| 61 | #define stdin ((FILE *) 0) |
| 62 | #define stdout ((FILE *) 1) |
| 63 | #define stderr ((FILE *) 2) |
| 64 | |
| 65 | #endif |
| 66 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 67 | word va_fformat (FILE * f, char *fmt, va_list * va); |
| 68 | word fformat (FILE * f, char *fmt, ...); |
| 69 | word fdformat (int fd, char *fmt, ...); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 70 | |
| 71 | always_inline uword |
| 72 | format_get_indent (u8 * s) |
| 73 | { |
| 74 | uword indent = 0; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 75 | u8 *nl; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 76 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 77 | if (!s) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 78 | return indent; |
| 79 | |
| 80 | nl = vec_end (s) - 1; |
| 81 | while (nl >= s) |
| 82 | { |
| 83 | if (*nl-- == '\n') |
| 84 | break; |
| 85 | indent++; |
| 86 | } |
| 87 | return indent; |
| 88 | } |
| 89 | |
| 90 | #define _(f) u8 * f (u8 * s, va_list * va) |
| 91 | |
| 92 | /* Standard user-defined formats. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 93 | _(format_vec32); |
| 94 | _(format_vec_uword); |
| 95 | _(format_ascii_bytes); |
| 96 | _(format_hex_bytes); |
| 97 | _(format_white_space); |
| 98 | _(format_f64); |
| 99 | _(format_time_interval); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 100 | |
| 101 | #ifdef CLIB_UNIX |
| 102 | /* Unix specific formats. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 103 | _(format_address_family); |
| 104 | _(format_unix_arphrd); |
| 105 | _(format_unix_interface_flags); |
| 106 | _(format_network_address); |
| 107 | _(format_network_protocol); |
| 108 | _(format_network_port); |
| 109 | _(format_sockaddr); |
| 110 | _(format_ip4_tos_byte); |
| 111 | _(format_ip4_packet); |
| 112 | _(format_icmp4_type_and_code); |
| 113 | _(format_ethernet_packet); |
| 114 | _(format_hostname); |
| 115 | _(format_timeval); |
| 116 | _(format_time_float); |
| 117 | _(format_signal); |
| 118 | _(format_ucontext_pc); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 119 | #endif |
| 120 | |
| 121 | #undef _ |
| 122 | |
| 123 | /* Unformat. */ |
| 124 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 125 | typedef struct _unformat_input_t |
| 126 | { |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 127 | /* Input buffer (vector). */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 128 | u8 *buffer; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 129 | |
| 130 | /* Current index in input buffer. */ |
| 131 | uword index; |
| 132 | |
| 133 | /* Vector of buffer marks. Used to delineate pieces of the buffer |
| 134 | for error reporting and for parse recovery. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 135 | uword *buffer_marks; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 136 | |
| 137 | /* User's function to fill the buffer when its empty |
| 138 | (and argument). */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 139 | uword (*fill_buffer) (struct _unformat_input_t * i); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 140 | |
| 141 | /* Return values for fill buffer function which indicate whether not |
| 142 | input has been exhausted. */ |
| 143 | #define UNFORMAT_END_OF_INPUT (~0) |
| 144 | #define UNFORMAT_MORE_INPUT 0 |
| 145 | |
| 146 | /* User controlled argument to fill buffer function. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 147 | void *fill_buffer_arg; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 148 | } unformat_input_t; |
| 149 | |
| 150 | always_inline void |
| 151 | unformat_init (unformat_input_t * i, |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 152 | uword (*fill_buffer) (unformat_input_t *), |
| 153 | void *fill_buffer_arg) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 154 | { |
| 155 | memset (i, 0, sizeof (i[0])); |
| 156 | i->fill_buffer = fill_buffer; |
| 157 | i->fill_buffer_arg = fill_buffer_arg; |
| 158 | } |
| 159 | |
| 160 | always_inline void |
| 161 | unformat_free (unformat_input_t * i) |
| 162 | { |
| 163 | vec_free (i->buffer); |
| 164 | vec_free (i->buffer_marks); |
| 165 | memset (i, 0, sizeof (i[0])); |
| 166 | } |
| 167 | |
| 168 | always_inline uword |
| 169 | unformat_check_input (unformat_input_t * i) |
| 170 | { |
| 171 | /* Low level fill input function. */ |
| 172 | extern uword _unformat_fill_input (unformat_input_t * i); |
| 173 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 174 | if (i->index >= vec_len (i->buffer) && i->index != UNFORMAT_END_OF_INPUT) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 175 | _unformat_fill_input (i); |
| 176 | |
| 177 | return i->index; |
| 178 | } |
| 179 | |
| 180 | /* Return true if input is exhausted */ |
| 181 | always_inline uword |
| 182 | unformat_is_eof (unformat_input_t * input) |
| 183 | { |
| 184 | return unformat_check_input (input) == UNFORMAT_END_OF_INPUT; |
| 185 | } |
| 186 | |
| 187 | /* Return next element in input vector, |
| 188 | possibly calling fill input to get more. */ |
| 189 | always_inline uword |
| 190 | unformat_get_input (unformat_input_t * input) |
| 191 | { |
| 192 | uword i = unformat_check_input (input); |
| 193 | if (i < vec_len (input->buffer)) |
| 194 | { |
| 195 | input->index = i + 1; |
| 196 | i = input->buffer[i]; |
| 197 | } |
| 198 | return i; |
| 199 | } |
| 200 | |
| 201 | /* Back up input pointer by one. */ |
| 202 | always_inline void |
| 203 | unformat_put_input (unformat_input_t * input) |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 204 | { |
| 205 | input->index -= 1; |
| 206 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 207 | |
| 208 | /* Peek current input character without advancing. */ |
| 209 | always_inline uword |
| 210 | unformat_peek_input (unformat_input_t * input) |
| 211 | { |
| 212 | uword c = unformat_get_input (input); |
| 213 | if (c != UNFORMAT_END_OF_INPUT) |
| 214 | unformat_put_input (input); |
| 215 | return c; |
| 216 | } |
| 217 | |
| 218 | /* Skip current input line. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 219 | always_inline void |
| 220 | unformat_skip_line (unformat_input_t * i) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 221 | { |
| 222 | uword c; |
| 223 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 224 | while ((c = unformat_get_input (i)) != UNFORMAT_END_OF_INPUT && c != '\n') |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 225 | ; |
| 226 | } |
| 227 | |
| 228 | uword unformat_skip_white_space (unformat_input_t * input); |
| 229 | |
| 230 | /* Unformat function. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 231 | typedef uword (unformat_function_t) (unformat_input_t * input, |
| 232 | va_list * args); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 233 | |
| 234 | /* External functions. */ |
| 235 | |
| 236 | /* General unformatting function with programmable input stream. */ |
Neale Ranns | 32e1c01 | 2016-11-22 17:07:28 +0000 | [diff] [blame] | 237 | uword unformat (unformat_input_t * i, const char *fmt, ...); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 238 | |
| 239 | /* Call user defined parse function. |
| 240 | unformat_user (i, f, ...) is equivalent to unformat (i, "%U", f, ...) */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 241 | uword unformat_user (unformat_input_t * input, unformat_function_t * func, |
| 242 | ...); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 243 | |
| 244 | /* Alternate version which allows for extensions. */ |
Neale Ranns | 32e1c01 | 2016-11-22 17:07:28 +0000 | [diff] [blame] | 245 | uword va_unformat (unformat_input_t * i, const char *fmt, va_list * args); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 246 | |
| 247 | /* Setup for unformat of Unix style command line. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 248 | void unformat_init_command_line (unformat_input_t * input, char *argv[]); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 249 | |
| 250 | /* Setup for unformat of given string. */ |
| 251 | void unformat_init_string (unformat_input_t * input, |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 252 | char *string, int string_len); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 253 | |
| 254 | always_inline void |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 255 | unformat_init_cstring (unformat_input_t * input, char *string) |
| 256 | { |
| 257 | unformat_init_string (input, string, strlen (string)); |
| 258 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 259 | |
| 260 | /* Setup for unformat of given vector string; vector will be freed by unformat_string. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 261 | void unformat_init_vector (unformat_input_t * input, u8 * vector_string); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 262 | |
| 263 | /* Format function for unformat input usable when an unformat error |
| 264 | has occurred. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 265 | u8 *format_unformat_error (u8 * s, va_list * va); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 266 | |
| 267 | #define unformat_parse_error(input) \ |
| 268 | clib_error_return (0, "parse error `%U'", format_unformat_error, input) |
| 269 | |
| 270 | /* Print all input: not just error context. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 271 | u8 *format_unformat_input (u8 * s, va_list * va); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 272 | |
| 273 | /* Unformat (parse) function which reads a %s string and converts it |
| 274 | to and unformat_input_t. */ |
| 275 | unformat_function_t unformat_input; |
| 276 | |
| 277 | /* Parse a line ending with \n and return it. */ |
| 278 | unformat_function_t unformat_line; |
| 279 | |
| 280 | /* Parse a line ending with \n and return it as an unformat_input_t. */ |
| 281 | unformat_function_t unformat_line_input; |
| 282 | |
| 283 | /* Parse a token containing given set of characters. */ |
| 284 | unformat_function_t unformat_token; |
| 285 | |
| 286 | /* Parses a hexstring into a vector of bytes. */ |
| 287 | unformat_function_t unformat_hex_string; |
| 288 | |
| 289 | /* Returns non-zero match if input is exhausted. |
| 290 | Useful to ensure that the entire input matches with no trailing junk. */ |
| 291 | unformat_function_t unformat_eof; |
| 292 | |
| 293 | /* Parse memory size e.g. 100, 100k, 100m, 100g. */ |
| 294 | unformat_function_t unformat_memory_size; |
| 295 | |
| 296 | /* Unparse memory size e.g. 100, 100k, 100m, 100g. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 297 | u8 *format_memory_size (u8 * s, va_list * va); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 298 | |
| 299 | /* Format c identifier: e.g. a_name -> "a name". */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 300 | u8 *format_c_identifier (u8 * s, va_list * va); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 301 | |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 302 | /* Format hexdump with both hex and printable chars - compatible with text2pcap */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 303 | u8 *format_hexdump (u8 * s, va_list * va); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 304 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 305 | /* Unix specific formats. */ |
| 306 | #ifdef CLIB_UNIX |
| 307 | /* Setup input from Unix file. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 308 | void unformat_init_unix_file (unformat_input_t * input, int file_descriptor); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 309 | |
| 310 | /* Take input from Unix environment variable; returns |
| 311 | 1 if variable exists zero otherwise. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 312 | uword unformat_init_unix_env (unformat_input_t * input, char *var); |
Damjan Marion | a54230d | 2017-06-21 11:57:07 +0200 | [diff] [blame] | 313 | |
| 314 | /* Unformat unix group id (gid) specified as integer or string */ |
| 315 | unformat_function_t unformat_unix_gid; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 316 | #endif /* CLIB_UNIX */ |
| 317 | |
| 318 | /* Test code. */ |
| 319 | int test_format_main (unformat_input_t * input); |
| 320 | int test_unformat_main (unformat_input_t * input); |
| 321 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 322 | /* This is not the right place for this, but putting it in vec.h |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 323 | created circular dependency problems. */ |
| 324 | int test_vec_main (unformat_input_t * input); |
| 325 | |
| 326 | #endif /* included_format_h */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 327 | |
| 328 | /* |
| 329 | * fd.io coding-style-patch-verification: ON |
| 330 | * |
| 331 | * Local Variables: |
| 332 | * eval: (c-set-style "gnu") |
| 333 | * End: |
| 334 | */ |