diff options
Diffstat (limited to 'wiretap/busmaster_scanner.l')
-rw-r--r-- | wiretap/busmaster_scanner.l | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/wiretap/busmaster_scanner.l b/wiretap/busmaster_scanner.l new file mode 100644 index 00000000..eeaa88f5 --- /dev/null +++ b/wiretap/busmaster_scanner.l @@ -0,0 +1,199 @@ +/* busmaster_scanner.l + * + * Wiretap Library + * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu> + * + * Support for Busmaster log file format + * Copyright (c) 2019 by Maksim Salau <maksim.salau@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +%top { +/* Include this before everything else, for various large-file definitions */ +#include "config.h" +#include <wireshark.h> +} + +%option noyywrap +%option noinput +%option nounput +%option batch +%option never-interactive +%option nodefault +%option prefix="busmaster_" +%option reentrant +%option extra-type="busmaster_state_t *" + +%option noyy_scan_buffer +%option noyy_scan_bytes +%option noyy_scan_string + +/* + * We have to override the memory allocators so that we don't get + * "unused argument" warnings from the yyscanner argument (which + * we don't use, as we have a global memory allocator). + * + * We provide, as macros, our own versions of the routines generated by Flex, + * which just call malloc()/realloc()/free() (as the Flex versions do), + * discarding the extra argument. + */ +%option noyyalloc +%option noyyrealloc +%option noyyfree + +%{ + +#include <ws_diag_control.h> +#include <wiretap/file_wrappers.h> +#include "busmaster_parser.h" +#include "busmaster_priv.h" + +#ifndef HAVE_UNISTD_H +#define YY_NO_UNISTD_H +#endif + +static int busmaster_yyinput(void *buf, unsigned int length, busmaster_state_t *state) +{ + int ret = file_read(buf, length, state->fh); + + if (ret < 0) + { + state->err = file_error(state->fh, &state->err_info); + return YY_NULL; + } + + return ret; +} + +#define YY_INPUT(buf, result, max_size) \ + do { (result) = busmaster_yyinput((buf), (max_size), yyextra); } while (0) + +/* Count bytes read. This is required in order to rewind the file + * to the beginning of the next packet, since flex reads more bytes + * before executing the action that does yyterminate(). */ +#define YY_USER_ACTION do { yyextra->file_bytes_read += yyleng; } while (0); + +/* + * Sleazy hack to suppress compiler warnings in yy_fatal_error(). + */ +#define YY_EXIT_FAILURE ((void)yyscanner, 2) + +/* + * Macros for the allocators, to discard the extra argument. + */ +#define busmaster_alloc(size, yyscanner) (void *)malloc(size) +#define busmaster_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size)) +#define busmaster_free(ptr, yyscanner) free((char *)(ptr)) + +DIAG_OFF_FLEX() + +%} + +SPC [ \t]+ +ENDL [\r\n][ \t\r\n]* +INT [0-9]+ +NUM (0x)?[0-9A-Fa-f]+ + +%x HEADER TIME +%x HEADER_CHANNELS HEADER_DB_FILES + +%% + +<*>{SPC} ; +<INITIAL>{ENDL} { yyterminate(); }; +<HEADER,TIME>{ENDL} { YY_FATAL_ERROR("Unterminated header statement"); } + +"***" { BEGIN(HEADER); } +<HEADER,TIME>"***"{ENDL}"***" { BEGIN(HEADER); return TOKEN_ENDL; } +<HEADER>"***"{ENDL} { BEGIN(INITIAL); yyterminate(); } +<HEADER>"BUSMASTER" { return TOKEN_HEADER_VER; } +<HEADER>"PROTOCOL CAN" { yyextra->token.v0 = PROTOCOL_CAN; return TOKEN_PROTOCOL_TYPE; } +<HEADER>"PROTOCOL J1939" { yyextra->token.v0 = PROTOCOL_J1939; return TOKEN_PROTOCOL_TYPE; } +<HEADER>"PROTOCOL LIN" { yyextra->token.v0 = PROTOCOL_LIN; return TOKEN_PROTOCOL_TYPE; } +<HEADER>"START DATE AND TIME" { BEGIN(TIME); return TOKEN_START_TIME; } +<HEADER>"END DATE AND TIME" { BEGIN(TIME); return TOKEN_END_TIME; } +<HEADER>"DEC" { yyextra->token.v0 = DATA_MODE_DEC; return TOKEN_DATA_MODE; } +<HEADER>"HEX" { yyextra->token.v0 = DATA_MODE_HEX; return TOKEN_DATA_MODE; } +<HEADER>"ABSOLUTE MODE" { yyextra->token.v0 = TIME_MODE_ABSOLUTE; return TOKEN_TIME_MODE; } +<HEADER>"SYSTEM MODE" { yyextra->token.v0 = TIME_MODE_SYSTEM; return TOKEN_TIME_MODE; } +<HEADER>"RELATIVE MODE" { yyextra->token.v0 = TIME_MODE_RELATIVE; return TOKEN_TIME_MODE; } +<HEADER>"[START LOGGING SESSION]" { return TOKEN_START_SESSION; } +<HEADER>"[STOP LOGGING SESSION]" { return TOKEN_STOP_SESSION; } +<HEADER>"START CHANNEL BAUD RATE***" { BEGIN(HEADER_CHANNELS); } +<HEADER>"START DATABASE FILES (DBF/DBC)***" { BEGIN(HEADER_DB_FILES); } +<HEADER>. { return TOKEN_HEADER_CHAR; } + +<HEADER_CHANNELS>"***END CHANNEL BAUD RATE***"{ENDL}"***" { BEGIN(HEADER); } +<HEADER_CHANNELS>.+ ; +<HEADER_CHANNELS>{ENDL} ; + +<HEADER_DB_FILES>"***END DATABASE FILES (DBF/DBC)***"{ENDL}"***" { BEGIN(HEADER); } +<HEADER_DB_FILES>"***END OF DATABASE FILES (DBF/DBC)***"{ENDL}"***" { BEGIN(HEADER); } +<HEADER_DB_FILES>.+ ; +<HEADER_DB_FILES>{ENDL} ; + +<TIME>{INT} { yyextra->token.v0 = strtoul(yytext, NULL, 10); return TOKEN_INT; } +<TIME>: { return TOKEN_COLON; } +<TIME>. { return TOKEN_INVALID_CHAR; } + +<INITIAL>{INT}:{INT}:{INT}:{INT} { + char *endp; + char *strp; + + yyextra->token.v0 = strtoul(yytext, &endp, 10); + if (*endp != ':' || endp == yytext) + return TOKEN_INVALID_NUMBER; + + strp = endp + 1; + yyextra->token.v1 = strtoul(strp, &endp, 10); + if (*endp != ':' || endp == strp) + return TOKEN_INVALID_NUMBER; + + strp = endp + 1; + yyextra->token.v2 = strtoul(strp, &endp, 10); + if (*endp != ':' || endp == strp) + return TOKEN_INVALID_NUMBER; + + strp = endp + 1; + yyextra->token.v3 = strtoul(strp, &endp, 10); + if (*endp != '\0' || endp == strp) + return TOKEN_INVALID_NUMBER; + + return TOKEN_MSG_TIME; + } + +<INITIAL>{NUM} { + char *endp; + + if (yyextra->header.data_mode == DATA_MODE_HEX) + yyextra->token.v0 = strtoul(yytext, &endp, 16); + else if (yyextra->header.data_mode == DATA_MODE_DEC) + yyextra->token.v0 = strtoul(yytext, &endp, 10); + else + return TOKEN_INVALID_NUMBER; + + if (*endp != '\0' || endp == yytext) + return TOKEN_INVALID_NUMBER; + + return TOKEN_INT; + } + +<INITIAL>[RT]x { return TOKEN_MSG_DIR; } +<INITIAL>s { yyextra->token.v0 = MSG_TYPE_STD; return TOKEN_MSG_TYPE; } +<INITIAL>sr { yyextra->token.v0 = MSG_TYPE_STD_RTR; return TOKEN_MSG_TYPE; } +<INITIAL>x { yyextra->token.v0 = MSG_TYPE_EXT; return TOKEN_MSG_TYPE; } +<INITIAL>xr { yyextra->token.v0 = MSG_TYPE_EXT_RTR; return TOKEN_MSG_TYPE; } +<INITIAL>s-fd { yyextra->token.v0 = MSG_TYPE_STD_FD; return TOKEN_MSG_TYPE; } +<INITIAL>x-fd { yyextra->token.v0 = MSG_TYPE_EXT_FD; return TOKEN_MSG_TYPE; } +<INITIAL>ERR.* { yyextra->token.v0 = MSG_TYPE_ERR; return TOKEN_ERR_MSG_TYPE; } + +<INITIAL>("NONE"|"CMD"|"RQST"|"DATA"|"BROADCAST"|"ACK"|"GRP_FUNC"|"ACL"|"RQST_ACL"|"CA"|"BAM"|"RTS"|"CTS"|"EOM"|"CON_ABORT"|"TPDT") { + return TOKEN_J1939_MSG_TYPE; +} + +<INITIAL>. { return TOKEN_INVALID_CHAR; } + +%% + +DIAG_ON_FLEX() |