summaryrefslogtreecommitdiffstats
path: root/wiretap/busmaster_scanner.l
diff options
context:
space:
mode:
Diffstat (limited to 'wiretap/busmaster_scanner.l')
-rw-r--r--wiretap/busmaster_scanner.l199
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()