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 7748387 : format_get_indent (u8 * s)
73 : {
74 7748387 : u32 indent = 0;
75 : u8 *nl;
76 :
77 7748387 : if (!s)
78 134366 : return indent;
79 :
80 7614021 : nl = vec_end (s) - 1;
81 64678777 : while (nl >= s)
82 : {
83 64651690 : if (*nl-- == '\n')
84 7586914 : break;
85 57064713 : indent++;
86 : }
87 7614021 : 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 : /* Return values for fill buffer function which indicate whether not
137 : input has been exhausted. */
138 : #define UNFORMAT_END_OF_INPUT (~0)
139 : #define UNFORMAT_MORE_INPUT 0
140 :
141 : /* User controlled argument to fill buffer function. */
142 : void *fill_buffer_arg;
143 : } unformat_input_t;
144 :
145 : always_inline void
146 1457419 : unformat_init (unformat_input_t * i,
147 : uword (*fill_buffer) (unformat_input_t *),
148 : void *fill_buffer_arg)
149 : {
150 1457419 : clib_memset (i, 0, sizeof (i[0]));
151 1457419 : i->fill_buffer = fill_buffer;
152 1457419 : i->fill_buffer_arg = fill_buffer_arg;
153 1457419 : }
154 :
155 : always_inline void
156 773456 : unformat_free (unformat_input_t * i)
157 : {
158 773456 : vec_free (i->buffer);
159 773456 : vec_free (i->buffer_marks);
160 773456 : clib_memset (i, 0, sizeof (i[0]));
161 773456 : }
162 :
163 : always_inline uword
164 50982589 : unformat_check_input (unformat_input_t * i)
165 : {
166 : /* Low level fill input function. */
167 : extern uword _unformat_fill_input (unformat_input_t * i);
168 :
169 50982589 : if (i->index >= vec_len (i->buffer) && i->index != UNFORMAT_END_OF_INPUT)
170 1505916 : _unformat_fill_input (i);
171 :
172 50982589 : return i->index;
173 : }
174 :
175 : /* Return true if input is exhausted */
176 : always_inline uword
177 0 : unformat_is_eof (unformat_input_t * input)
178 : {
179 0 : return unformat_check_input (input) == UNFORMAT_END_OF_INPUT;
180 : }
181 :
182 : /* Return next element in input vector,
183 : possibly calling fill input to get more. */
184 : always_inline uword
185 50187689 : unformat_get_input (unformat_input_t * input)
186 : {
187 50187689 : uword i = unformat_check_input (input);
188 50187689 : if (i < vec_len (input->buffer))
189 : {
190 46949725 : input->index = i + 1;
191 46949725 : i = input->buffer[i];
192 : }
193 50187689 : return i;
194 : }
195 :
196 : /* Back up input pointer by one. */
197 : always_inline void
198 10907118 : unformat_put_input (unformat_input_t * input)
199 : {
200 10907118 : input->index -= 1;
201 10907118 : }
202 :
203 : always_inline uword
204 21205300 : is_white_space (uword c)
205 : {
206 21205300 : switch (c)
207 : {
208 1315220 : case ' ':
209 : case '\t':
210 : case '\n':
211 : case '\r':
212 1315220 : return 1;
213 :
214 19890100 : default:
215 19890100 : return 0;
216 : }
217 : }
218 :
219 : /* Peek current input character without advancing. */
220 : always_inline uword
221 0 : unformat_peek_input (unformat_input_t * input)
222 : {
223 0 : uword c = unformat_get_input (input);
224 0 : if (c != UNFORMAT_END_OF_INPUT)
225 0 : unformat_put_input (input);
226 0 : return c;
227 : }
228 :
229 : /* Skip current input line. */
230 : always_inline void
231 0 : unformat_skip_line (unformat_input_t * i)
232 : {
233 : uword c;
234 :
235 0 : while ((c = unformat_get_input (i)) != UNFORMAT_END_OF_INPUT && c != '\n')
236 : ;
237 0 : }
238 :
239 : uword unformat_skip_white_space (unformat_input_t * input);
240 :
241 : /* Unformat function. */
242 : typedef uword (unformat_function_t) (unformat_input_t * input,
243 : va_list * args);
244 :
245 : /* External functions. */
246 :
247 : /* General unformatting function with programmable input stream. */
248 : uword unformat (unformat_input_t * i, const char *fmt, ...);
249 :
250 : /* Call user defined parse function.
251 : unformat_user (i, f, ...) is equivalent to unformat (i, "%U", f, ...) */
252 : uword unformat_user (unformat_input_t * input, unformat_function_t * func,
253 : ...);
254 :
255 : /* Alternate version which allows for extensions. */
256 : uword va_unformat (unformat_input_t * i, const char *fmt, va_list * args);
257 :
258 : /* Setup for unformat of Unix style command line. */
259 : void unformat_init_command_line (unformat_input_t * input, char *argv[]);
260 :
261 : /* Setup for unformat of given string. */
262 : void unformat_init_string (unformat_input_t *input, const char *string,
263 : int string_len);
264 :
265 : always_inline void
266 12 : unformat_init_cstring (unformat_input_t * input, char *string)
267 : {
268 12 : unformat_init_string (input, string, strlen (string));
269 12 : }
270 :
271 : /* Setup for unformat of given vector string; vector will be freed by unformat_string. */
272 : void unformat_init_vector (unformat_input_t * input, u8 * vector_string);
273 :
274 : /* Format function for unformat input usable when an unformat error
275 : has occurred. */
276 : u8 *format_unformat_error (u8 * s, va_list * va);
277 :
278 : #define unformat_parse_error(input) \
279 : clib_error_return (0, "parse error `%U'", format_unformat_error, input)
280 :
281 : /* Print all input: not just error context. */
282 : u8 *format_unformat_input (u8 * s, va_list * va);
283 :
284 : /* Unformat (parse) function which reads a %s string and converts it
285 : to and unformat_input_t. */
286 : unformat_function_t unformat_input;
287 :
288 : /* Parse a line ending with \n and return it. */
289 : unformat_function_t unformat_line;
290 :
291 : /* Parse a line ending with \n and return it as an unformat_input_t. */
292 : unformat_function_t unformat_line_input;
293 :
294 : /* Parse a token containing given set of characters. */
295 : unformat_function_t unformat_token;
296 :
297 : /* Parses a hexstring into a vector of bytes. */
298 : unformat_function_t unformat_hex_string;
299 :
300 : /* Returns non-zero match if input is exhausted.
301 : Useful to ensure that the entire input matches with no trailing junk. */
302 : unformat_function_t unformat_eof;
303 :
304 : /* Parse memory size e.g. 100, 100k, 100m, 100g. */
305 : unformat_function_t unformat_memory_size;
306 :
307 : /* Format base 10 e.g. 100, 100K, 100M, 100G */
308 : u8 *format_base10 (u8 *s, va_list *va);
309 :
310 : /* Unparse memory size e.g. 100, 100k, 100m, 100g. */
311 : u8 *format_memory_size (u8 * s, va_list * va);
312 :
313 : /* Parse memory page size e.g. 4K, 2M */
314 : unformat_function_t unformat_log2_page_size;
315 :
316 : /* Unparse memory page size e.g. 4K, 2M */
317 : u8 *format_log2_page_size (u8 * s, va_list * va);
318 :
319 : /* Format c identifier: e.g. a_name -> "a name". */
320 : u8 *format_c_identifier (u8 * s, va_list * va);
321 :
322 : /* Format hexdump with both hex and printable chars - compatible with text2pcap */
323 : u8 *format_hexdump (u8 * s, va_list * va);
324 : u8 *format_hexdump_u16 (u8 *s, va_list *va);
325 : u8 *format_hexdump_u32 (u8 *s, va_list *va);
326 : u8 *format_hexdump_u64 (u8 *s, va_list *va);
327 :
328 : /* Format bitmap of array of uword numbers */
329 : u8 *format_uword_bitmap (u8 *s, va_list *va);
330 :
331 : /* Unix specific formats. */
332 : #ifdef CLIB_UNIX
333 : /* Setup input from Unix file. */
334 : void unformat_init_clib_file (unformat_input_t * input, int file_descriptor);
335 :
336 : /* Take input from Unix environment variable; returns
337 : 1 if variable exists zero otherwise. */
338 : uword unformat_init_unix_env (unformat_input_t * input, char *var);
339 :
340 : /* Unformat unix group id (gid) specified as integer or string */
341 : unformat_function_t unformat_unix_gid;
342 : #endif /* CLIB_UNIX */
343 :
344 : uword unformat_data_size (unformat_input_t * input, va_list * args);
345 :
346 : /* Test code. */
347 : int test_format_main (unformat_input_t * input);
348 : int test_unformat_main (unformat_input_t * input);
349 :
350 : /* This is not the right place for this, but putting it in vec.h
351 : created circular dependency problems. */
352 : int test_vec_main (unformat_input_t * input);
353 :
354 : #endif /* included_format_h */
355 :
356 : /*
357 : * fd.io coding-style-patch-verification: ON
358 : *
359 : * Local Variables:
360 : * eval: (c-set-style "gnu")
361 : * End:
362 : */
|