2 /* Include this before everything else, for various large-file definitions */
8 * We want a reentrant scanner.
13 * We don't read interactively from the terminal.
15 %option never-interactive
18 * We want to stop processing when we get to the end of the input.
23 * The type for the state we keep for the scanner (and parser).
25 %option extra-type="ascend_state_t *"
28 * Prefix scanner routines with "ascend_" rather than "yy", so this scanner
29 * can coexist with other scanners.
31 %option prefix="ascend_"
34 * We have to override the memory allocators so that we don't get
35 * "unused argument" warnings from the yyscanner argument (which
36 * we don't use, as we have a global memory allocator).
38 * We provide, as macros, our own versions of the routines generated by Flex,
39 * which just call malloc()/realloc()/free() (as the Flex versions do),
40 * discarding the extra argument.
50 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
52 * SPDX-License-Identifier: GPL-2.0-or-later
59 #include "ascendtext.h"
60 #include "ascend-int.h"
61 #include "ascend_parser.h"
62 #include "file_wrappers.h"
65 * Disable diagnostics in the code generated by Flex.
69 // The generated scanner is recursive if yywrap is enabled, but we disable it above.
70 // NOLINTBEGIN(misc-no-recursion)
72 static int ascend_yyinput(void *buf, ascend_state_t *parser_state) {
73 int c = file_getc(parser_state->fh);
75 parser_state->err = file_error(parser_state->fh,
76 &parser_state->err_info);
77 if (parser_state->err == 0)
78 parser_state->err = WTAP_ERR_SHORT_READ;
86 #define YY_INPUT(buf, result, max_size) \
87 do { (result) = ascend_yyinput((buf), yyextra); } while (0)
90 /* Count bytes read. This is required in order to rewind the file
91 * to the beginning of the next packet, since flex reads more bytes
92 * before executing the action that does yyterminate(). */
93 #define YY_USER_ACTION do { yyextra->token.length = yyleng; } while (0);
95 #define NO_USER "<none>"
98 #define YY_NO_UNISTD_H
102 * Sleazy hack to suppress compiler warnings in yy_fatal_error().
104 #define YY_EXIT_FAILURE ((void)yyscanner, 2)
107 * Macros for the allocators, to discard the extra argument.
109 #define ascend_alloc(size, yyscanner) (void *)malloc(size)
110 #define ascend_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
111 #define ascend_free(ptr, yyscanner) free((char *)ptr)
128 WDD_CAUSE "Cause an attempt to place call to "
129 WDD_CALLNUM [^\n\r\t ]+
130 WDD_CHUNK "WD_DIALOUT_DISP: chunk"
131 WDD_TYPE "type "[^\n\r\t ]+
159 %s sc_ether_direction
163 <INITIAL,sc_gen_byte>{ETHER_PFX} {
164 BEGIN(sc_ether_direction);
165 yyextra->token.u16_val = ASCEND_PFX_ETHER;
169 <INITIAL,sc_gen_byte>{ISDN_XPFX} {
171 yyextra->token.u16_val = ASCEND_PFX_ISDN_X;
175 <INITIAL,sc_gen_byte>{ISDN_RPFX} {
177 yyextra->token.u16_val = ASCEND_PFX_ISDN_R;
181 <INITIAL,sc_gen_byte>{WAN_XPFX} {
183 yyextra->token.u16_val = ASCEND_PFX_WDS_X;
187 <INITIAL,sc_gen_byte>{WAN_RPFX} {
189 yyextra->token.u16_val = ASCEND_PFX_WDS_R;
193 <INITIAL,sc_gen_byte>{PPP_XPFX} {
195 yyextra->token.u16_val = ASCEND_PFX_WDS_X;
199 <INITIAL,sc_gen_byte>{PPP_RPFX} {
201 yyextra->token.u16_val = ASCEND_PFX_WDS_R;
206 * If we allow an arbitrary non-zero number of non-left-parentheses after
207 * "ETHER", that means that some file that has ETHER followed by a lot of
208 * text (see, for example, tpncp/tpncp.dat in the source tree) can cause
209 * either an infinite loop or a loop that take forever to finish, as the
210 * scanner keeps swallowing characters. Limit it to 20 characters.
212 * XXX - any reason to require at least two of them?
214 <sc_ether_direction>[^\(]{2,20} {
220 * If we allow an arbitrary non-zero number of non-slash, non-left-parentheses,
221 * non-colon characters after "PRI-XMIT", that means that some file that has
222 * PRI-XMIT= followed by a lot of text can cause either an infinite loop or
223 * a loop that take forever to finish, as the scanner keeps swallowing
224 * characters. Limit it to 20 characters.
226 <sc_isdn_call>[^\/\(:]{1,20} {
231 <sc_wds_user>[^:]{2,20} {
232 char *atcopy = g_strdup(yytext);
233 char colon = input(yyscanner);
234 char after = input(yyscanner);
237 unput(after); unput(colon);
239 if (after != '(' && after != ' ') {
241 if (yyextra->pseudo_header != NULL && yyextra->pseudo_header->user[0] == '\0') {
242 (void) g_strlcpy(yyextra->pseudo_header->user, atcopy, ASCEND_MAX_STR_LEN);
244 } else { /* We have a version 7 file */
246 if (yyextra->pseudo_header != NULL && yyextra->pseudo_header->user[0] == '\0') {
247 (void) g_strlcpy(yyextra->pseudo_header->user, NO_USER, ASCEND_MAX_STR_LEN);
249 /* Are valid values ever > 2^32? If so we need to adjust YYSTYPE and a lot of */
250 /* upstream code accordingly. */
251 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 10);
260 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 10);
264 <sc_gen_task>(0x|0X)?{H}{2,8} {
265 BEGIN(sc_gen_time_s);
266 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 16);
270 <sc_gen_task>\"[A-Za-z0-9_ ]+\" {
274 <sc_gen_time_s>{D}{1,10} {
275 BEGIN(sc_gen_time_u);
276 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 10);
280 <sc_gen_time_u>{D}{1,6} {
281 char *atcopy = g_strdup(yytext);
282 BEGIN(sc_gen_octets);
283 /* only want the most significant 2 digits. convert to usecs */
284 if (strlen(atcopy) > 2)
286 yyextra->token.u32_val = (uint32_t) strtoul(atcopy, NULL, 10) * 10000;
291 <sc_gen_octets>{D}{1,10} {
292 BEGIN(sc_gen_counter);
293 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 10);
297 <sc_gen_counter,sc_gen_byte>"["{H}{4}"]:" {
302 <sc_gen_byte>{H}{2} {
303 yyextra->token.u8_val = (uint8_t) strtoul(yytext, NULL, 16);
307 <sc_gen_byte>" "{4} {
315 <INITIAL,sc_gen_byte>{WDD_DATE} {
316 BEGIN(sc_wdd_date_m);
321 * Scan m/d/y as three separate m, /d/, and y tokens.
322 * We could alternately treat m/d/y as a single token.
324 <sc_wdd_date_m>{D}{2} {
325 BEGIN(sc_wdd_date_d);
326 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 10);
330 <sc_wdd_date_d>\/{D}{2}\/ {
331 BEGIN(sc_wdd_date_y);
332 yyextra->token.u32_val = (uint32_t) strtoul(yytext+1, NULL, 10);
336 <sc_wdd_date_y>{D}{4} {
338 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 10);
342 <sc_wdd_time>{WDD_TIME} {
343 BEGIN(sc_wdd_time_h);
348 * Scan h:m:s as three separate h, :m:, and s tokens similar to above.
350 <sc_wdd_time_h>{D}{2} {
351 BEGIN(sc_wdd_time_m);
352 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 10);
356 <sc_wdd_time_m>:{D}{2}: {
357 BEGIN(sc_wdd_time_s);
358 yyextra->token.u32_val = (uint32_t) strtoul(yytext+1, NULL, 10);
362 <sc_wdd_time_s>{D}{2} {
364 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 10);
368 <sc_wdd_cause>{WDD_CAUSE} {
369 BEGIN(sc_wdd_callnum);
373 <sc_wdd_callnum>{WDD_CALLNUM} {
375 (void) g_strlcpy(yyextra->token.str_val, yytext, ASCEND_MAX_STR_LEN);
379 <INITIAL,sc_wdd_chunk,sc_gen_byte>{WDD_CHUNK} {
380 BEGIN(sc_wdd_chunknum);
384 <sc_wdd_chunknum>{H}{1,8} {
386 yyextra->token.u32_val = (uint32_t) strtoul(yytext, NULL, 16);
390 <sc_wdd_type>{WDD_TYPE} {
395 <sc_gen_task>\/{D}+ {
399 (0x|0X)?{H}+ { return HEXNUM; }
401 task:|task|at|time:|octets { return KEYWORD; }
403 <<EOF>> { yyterminate(); }
409 // NOLINTEND(misc-no-recursion)
412 * Turn diagnostics back on, so we check the code that we've written.