Line data Source code
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 :
43 : #include <vppinfra/clib.h> /* for CLIB_UNIX, etc. */
44 : #include <vppinfra/vec.h>
45 : #include <vppinfra/error.h> /* for ASSERT */
46 : #include <vppinfra/string.h>
47 :
48 : typedef u8 *(format_function_t) (u8 * s, va_list * args);
49 :
50 : u8 *va_format (u8 * s, const char *format, va_list * args);
51 : u8 *format (u8 * s, const char *format, ...);
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 :
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, ...);
70 :
71 : always_inline u32
72 8361523 : format_get_indent (u8 * s)
73 : {
74 8361523 : u32 indent = 0;
75 : u8 *nl;
76 :
77 8361523 : if (!s)
78 136430 : return indent;
79 :
80 8225093 : nl = vec_end (s) - 1;
81 69931587 : while (nl >= s)
82 : {
83 69903180 : if (*nl-- == '\n')
84 8196676 : break;
85 61706490 : indent++;
86 : }
87 8225093 : return indent;
88 : }
89 :
90 : #define _(f) __clib_export u8 * f (u8 * s, va_list * va)
91 :
92 : /* Standard user-defined formats. */
93 : _(format_vec32);
94 : _(format_vec_uword);
95 : _(format_ascii_bytes);
96 : _(format_hex_bytes);
97 : _(format_hex_bytes_no_wrap);
98 : _(format_white_space);
99 : _(format_f64);
100 : _(format_time_interval);
101 : _ (format_duration);
102 :
103 : #ifdef CLIB_UNIX
104 : /* Unix specific formats. */
105 : _(format_address_family);
106 : _(format_network_address);
107 : _(format_network_protocol);
108 : _(format_network_port);
109 : _(format_sockaddr);
110 : _(format_timeval);
111 : _(format_time_float);
112 : _(format_signal);
113 : _(format_ucontext_pc);
114 : #endif
115 :
116 : #undef _
117 :
118 : /* Unformat. */
119 :
120 : typedef struct _unformat_input_t
121 : {
122 : /* Input buffer (vector). */
123 : u8 *buffer;
124 :
125 : /* Current index in input buffer. */
126 : uword index;
127 :
128 : /* Vector of buffer marks. Used to delineate pieces of the buffer
129 : for error reporting and for parse recovery. */
130 : uword *buffer_marks;
131 :
132 : /* User's function to fill the buffer when its empty
133 : (and argument). */
134 : uword (*fill_buffer) (struct _unformat_input_t * i);
135 :
136 : /* User's function to be called on input_free */
137 : void (*free) (struct _unformat_input_t *i);
138 :
139 : /* Return values for fill buffer function which indicate whether not
140 : input has been exhausted. */
141 : #define UNFORMAT_END_OF_INPUT (~0)
142 : #define UNFORMAT_MORE_INPUT 0
143 :
144 : /* User controlled argument to fill buffer function. */
145 : void *fill_buffer_arg;
146 : } unformat_input_t;
147 :
148 : always_inline void
149 1466499 : unformat_init (unformat_input_t * i,
150 : uword (*fill_buffer) (unformat_input_t *),
151 : void *fill_buffer_arg)
152 : {
153 1466499 : clib_memset (i, 0, sizeof (i[0]));
154 1466499 : i->fill_buffer = fill_buffer;
155 1466499 : i->fill_buffer_arg = fill_buffer_arg;
156 1466499 : }
157 :
158 : always_inline void
159 592183 : unformat_free (unformat_input_t * i)
160 : {
161 592183 : if (i->free)
162 0 : i->free (i);
163 592183 : vec_free (i->buffer);
164 592183 : vec_free (i->buffer_marks);
165 592183 : clib_memset (i, 0, sizeof (i[0]));
166 592183 : }
167 :
168 : always_inline uword
169 53397530 : 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 :
174 53397530 : if (i->index >= vec_len (i->buffer) && i->index != UNFORMAT_END_OF_INPUT)
175 1517473 : _unformat_fill_input (i);
176 :
177 53397530 : return i->index;
178 : }
179 :
180 : /* Return true if input is exhausted */
181 : always_inline uword
182 0 : unformat_is_eof (unformat_input_t * input)
183 : {
184 0 : 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 52568080 : unformat_get_input (unformat_input_t * input)
191 : {
192 52568080 : uword i = unformat_check_input (input);
193 52568080 : if (i < vec_len (input->buffer))
194 : {
195 49463592 : input->index = i + 1;
196 49463592 : i = input->buffer[i];
197 : }
198 52568080 : return i;
199 : }
200 :
201 : /* Back up input pointer by one. */
202 : always_inline void
203 11632844 : unformat_put_input (unformat_input_t * input)
204 : {
205 11632844 : input->index -= 1;
206 11632844 : }
207 :
208 : always_inline uword
209 22427700 : is_white_space (uword c)
210 : {
211 22427700 : switch (c)
212 : {
213 1533500 : case ' ':
214 : case '\t':
215 : case '\n':
216 : case '\r':
217 1533500 : return 1;
218 :
219 20894200 : default:
220 20894200 : return 0;
221 : }
222 : }
223 :
224 : /* Peek current input character without advancing. */
225 : always_inline uword
226 0 : unformat_peek_input (unformat_input_t * input)
227 : {
228 0 : uword c = unformat_get_input (input);
229 0 : if (c != UNFORMAT_END_OF_INPUT)
230 0 : unformat_put_input (input);
231 0 : return c;
232 : }
233 :
234 : /* Skip current input line. */
235 : always_inline void
236 0 : unformat_skip_line (unformat_input_t * i)
237 : {
238 : uword c;
239 :
240 0 : while ((c = unformat_get_input (i)) != UNFORMAT_END_OF_INPUT && c != '\n')
241 : ;
242 0 : }
243 :
244 : uword unformat_skip_white_space (unformat_input_t * input);
245 :
246 : /* Unformat function. */
247 : typedef uword (unformat_function_t) (unformat_input_t * input,
248 : va_list * args);
249 :
250 : /* External functions. */
251 :
252 : /* General unformatting function with programmable input stream. */
253 : uword unformat (unformat_input_t * i, const char *fmt, ...);
254 :
255 : /* Call user defined parse function.
256 : unformat_user (i, f, ...) is equivalent to unformat (i, "%U", f, ...) */
257 : uword unformat_user (unformat_input_t * input, unformat_function_t * func,
258 : ...);
259 :
260 : /* Alternate version which allows for extensions. */
261 : uword va_unformat (unformat_input_t * i, const char *fmt, va_list * args);
262 :
263 : /* Setup for unformat of Unix style command line. */
264 : void unformat_init_command_line (unformat_input_t * input, char *argv[]);
265 :
266 : /* Setup for unformat of given string. */
267 : void unformat_init_string (unformat_input_t *input, const char *string,
268 : int string_len);
269 :
270 : always_inline void
271 12 : unformat_init_cstring (unformat_input_t * input, char *string)
272 : {
273 12 : unformat_init_string (input, string, strlen (string));
274 12 : }
275 :
276 : /* Setup for unformat of given vector string; vector will be freed by unformat_string. */
277 : void unformat_init_vector (unformat_input_t * input, u8 * vector_string);
278 :
279 : /* Format function for unformat input usable when an unformat error
280 : has occurred. */
281 : u8 *format_unformat_error (u8 * s, va_list * va);
282 :
283 : #define unformat_parse_error(input) \
284 : clib_error_return (0, "parse error `%U'", format_unformat_error, input)
285 :
286 : /* Print all input: not just error context. */
287 : u8 *format_unformat_input (u8 * s, va_list * va);
288 :
289 : /* Unformat (parse) function which reads a %s string and converts it
290 : to and unformat_input_t. */
291 : unformat_function_t unformat_input;
292 :
293 : /* Parse a line ending with \n and return it. */
294 : unformat_function_t unformat_line;
295 :
296 : /* Parse a line ending with \n and return it as an unformat_input_t. */
297 : unformat_function_t unformat_line_input;
298 :
299 : /* Parse a token containing given set of characters. */
300 : unformat_function_t unformat_token;
301 :
302 : /* Parses a hexstring into a vector of bytes. */
303 : unformat_function_t unformat_hex_string;
304 :
305 : /* Returns non-zero match if input is exhausted.
306 : Useful to ensure that the entire input matches with no trailing junk. */
307 : unformat_function_t unformat_eof;
308 :
309 : /* Parse memory size e.g. 100, 100k, 100m, 100g. */
310 : unformat_function_t unformat_memory_size;
311 :
312 : /* Unformat C string array, takes array length as 2nd argument */
313 : unformat_function_t unformat_c_string_array;
314 :
315 : /* Format base 10 e.g. 100, 100K, 100M, 100G */
316 : u8 *format_base10 (u8 *s, va_list *va);
317 :
318 : /* Unparse memory size e.g. 100, 100k, 100m, 100g. */
319 : u8 *format_memory_size (u8 * s, va_list * va);
320 :
321 : /* Parse memory page size e.g. 4K, 2M */
322 : unformat_function_t unformat_log2_page_size;
323 :
324 : /* Unparse memory page size e.g. 4K, 2M */
325 : u8 *format_log2_page_size (u8 * s, va_list * va);
326 :
327 : /* Format c identifier: e.g. a_name -> "a name". */
328 : u8 *format_c_identifier (u8 * s, va_list * va);
329 :
330 : /* Format hexdump with both hex and printable chars - compatible with text2pcap */
331 : u8 *format_hexdump (u8 * s, va_list * va);
332 : u8 *format_hexdump_u16 (u8 *s, va_list *va);
333 : u8 *format_hexdump_u32 (u8 *s, va_list *va);
334 : u8 *format_hexdump_u64 (u8 *s, va_list *va);
335 :
336 : /* Format bitmap of array of uword numbers */
337 : u8 *format_uword_bitmap (u8 *s, va_list *va);
338 :
339 : /* Unix specific formats. */
340 : #ifdef CLIB_UNIX
341 : /* Setup input from Unix file. */
342 : void unformat_init_clib_file (unformat_input_t * input, int file_descriptor);
343 :
344 : /* Setup input from flesystem path. */
345 : uword unformat_init_file (unformat_input_t *input, char *fmt, ...);
346 :
347 : /* Take input from Unix environment variable; returns
348 : 1 if variable exists zero otherwise. */
349 : uword unformat_init_unix_env (unformat_input_t * input, char *var);
350 :
351 : /* Unformat unix group id (gid) specified as integer or string */
352 : unformat_function_t unformat_unix_gid;
353 : #endif /* CLIB_UNIX */
354 :
355 : uword unformat_data_size (unformat_input_t * input, va_list * args);
356 :
357 : /* Test code. */
358 : int test_format_main (unformat_input_t * input);
359 : int test_unformat_main (unformat_input_t * input);
360 :
361 : /* This is not the right place for this, but putting it in vec.h
362 : created circular dependency problems. */
363 : int test_vec_main (unformat_input_t * input);
364 :
365 : #endif /* included_format_h */
366 :
367 : /*
368 : * fd.io coding-style-patch-verification: ON
369 : *
370 : * Local Variables:
371 : * eval: (c-set-style "gnu")
372 : * End:
373 : */
|