public dissect_krb5_PAC_NDRHEADERBLOB
[wireshark-sm.git] / wiretap / busmaster_parser.lemon
blobcfdb7acabab8d1df200e71a6a31c0161d6eea9de
1 %include {
3 /* busmaster_parser.lemon
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
8  * Support for Busmaster log file format
9  * Copyright (c) 2019 by Maksim Salau <maksim.salau@gmail.com>
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
14 #include "config.h"
15 #include <assert.h>
16 #include <string.h>
17 #include <wireshark.h>
18 #include <wiretap/file_wrappers.h>
19 #include <wsutil/array.h>
20 #include "busmaster_priv.h"
22 extern void *BusmasterParserAlloc(void *(*mallocProc)(size_t));
23 extern void BusmasterParser(void *yyp, int yymajor, token_t yyminor, busmaster_state_t *state);
24 extern void BusmasterParserFree(void *p, void (*freeProc)(void*));
26 #if defined(BUSMASTER_DEBUG) || defined(BUSMASTER_PARSER_TRACE)
27 extern void BusmasterParserTrace(FILE *TraceFILE, char *zTracePrompt);
28 #undef NDEBUG
29 #endif
31 static void merge_msg_data(msg_data_t *dst, const msg_data_t *a, const msg_data_t *b)
33     dst->length = a->length + b->length;
34     memcpy(&dst->data[0], &a->data[0], a->length);
35     memcpy(&dst->data[a->length], &b->data[0], b->length);
38 DIAG_OFF_LEMON()
39 } /* end of %include */
41 %code {
42 DIAG_ON_LEMON()
45 %name BusmasterParser
47 %token_prefix TOKEN_
49 %token_type { token_t }
51 %token_destructor
53     (void)state;
54     (void)yypParser;
55     (void)yypminor;
58 %extra_argument { busmaster_state_t* state }
60 %syntax_error
62     (void)yypParser;
63     (void)yyminor;
65 #ifdef BUSMASTER_DEBUG
66     const int n = array_length(yyTokenName);
67     busmaster_debug_printf("%s: got token: %s\n", G_STRFUNC, yyTokenName[yymajor]);
68     for (int i = 0; i < n; ++i) {
69         int a = yy_find_shift_action((YYCODETYPE)i, yypParser->yytos->stateno);
70         if (a < YYNSTATE + YYNRULE) {
71             busmaster_debug_printf("%s: possible token: %s\n", G_STRFUNC, yyTokenName[i]);
72         }
73     }
74 #endif
76     g_free(state->parse_error);
77     state->entry_type  = LOG_ENTRY_ERROR;
78     state->parse_error = ws_strdup_printf("Syntax Error");
79     busmaster_debug_printf("%s: Syntax Error\n", G_STRFUNC);
82 %parse_failure
84     g_free(state->parse_error);
85     state->entry_type  = LOG_ENTRY_ERROR;
86     state->parse_error = g_strdup("Parse Error");
87     busmaster_debug_printf("%s: Parse Error\n", G_STRFUNC);
90 %stack_overflow
92     g_free(state->parse_error);
93     state->entry_type  = LOG_ENTRY_ERROR;
94     state->parse_error = g_strdup("Parser stack overflow");
95     busmaster_debug_printf("%s: Parser stack overflow\n", G_STRFUNC);
98 %type msg_time { msg_time_t }
99 %type msg_type { msg_type_t }
100 %type err_msg_type { msg_type_t }
101 %type msg_length { unsigned }
102 %type msg_id { uint32_t }
104 %type ref_date { msg_date_t }
105 %type ref_time { msg_time_t }
107 %type start_time { msg_date_time_t }
109 %type byte { uint8_t }
110 %type data { msg_data_t }
111 %type data0 { msg_data_t }
112 %type data1 { msg_data_t }
113 %type data2 { msg_data_t }
114 %type data3 { msg_data_t }
115 %type data4 { msg_data_t }
116 %type data5 { msg_data_t }
117 %type data6 { msg_data_t }
118 %type data7 { msg_data_t }
119 %type data8 { msg_data_t }
120 %type data12 { msg_data_t }
121 %type data16 { msg_data_t }
122 %type data20 { msg_data_t }
123 %type data24 { msg_data_t }
124 %type data32 { msg_data_t }
125 %type data48 { msg_data_t }
126 %type data64 { msg_data_t }
128 %nonassoc INVALID_CHAR .
129 %nonassoc INVALID_NUMBER .
131 %start_symbol entry
133 entry ::= empty_line .
134 entry ::= footer_and_header .
135 entry ::= header .
136 entry ::= footer .
137 entry ::= msg .
138 entry ::= err_msg .
139 entry ::= j1939_msg .
141 empty_line ::= .
143     busmaster_debug_printf("%s: EMPTY\n", G_STRFUNC);
144     state->entry_type = LOG_ENTRY_EMPTY;
147 footer_and_header ::= footer ENDL header .
149     busmaster_debug_printf("%s: FOOTER AND HEADER\n", G_STRFUNC);
150     state->entry_type = LOG_ENTRY_FOOTER_AND_HEADER;
153 header ::= version ENDL maybe_lines
154            PROTOCOL_TYPE(P) ENDL maybe_lines
155            START_SESSION ENDL maybe_lines
156            start_time(S) ENDL maybe_lines
157            DATA_MODE(D) ENDL maybe_lines
158            TIME_MODE(T) ENDL anything .
160     busmaster_debug_printf("%s: HEADER\n", G_STRFUNC);
162     state->entry_type        = LOG_ENTRY_HEADER;
163     state->header.start_date = S.date;
164     state->header.start_time = S.time;
165     state->header.protocol   = (protocol_type_t)P.v0;
166     state->header.data_mode  = (data_mode_t)D.v0;
167     state->header.time_mode  = (time_mode_t)T.v0;
170 version ::= HEADER_VER maybe_chars .
172 maybe_chars ::= .
173 maybe_chars ::= maybe_chars HEADER_CHAR .
175 maybe_lines ::= .
176 maybe_lines ::= maybe_lines maybe_chars ENDL .
178 anything ::= .
179 anything ::= anything HEADER_CHAR .
180 anything ::= anything ENDL .
182 start_time(R) ::= START_TIME ref_date(D) ref_time(T) .
184     R.date = D;
185     R.time = T;
188 footer ::= end_time ENDL STOP_SESSION .
190     busmaster_debug_printf("%s: FOOTER\n", G_STRFUNC);
191     state->entry_type = LOG_ENTRY_FOOTER;
194 end_time ::= END_TIME ref_date ref_time .
196 /* <Time><Tx/Rx><Channel><CAN ID><Type><DLC><DataBytes> */
197 msg ::= msg_time(msg_time) MSG_DIR INT msg_id(msg_id) msg_type(msg_type) msg_length(msg_length) data(msg_data) .
199     msg_t msg;
201     /* DLC is always in DEC mode, thus we need to fix the value
202      * if it was read initially as HEX. */
203     if (state->header.data_mode == DATA_MODE_HEX)
204     {
205         msg_length = (msg_length / 16) * 10 + (msg_length % 16);
206     }
208     /* Fix data in RTR frames. Data may not be present,
209      * but length field is set. */
210     if (msg_type == MSG_TYPE_STD_RTR ||
211         msg_type == MSG_TYPE_EXT_RTR)
212     {
213         memset(&msg_data, 0, sizeof(msg_data));
214         msg_data.length = msg_length;
215     }
217     msg.timestamp = msg_time;
218     msg.id        = msg_id;
219     msg.type      = msg_type;
220     msg.data      = msg_data;
222     busmaster_debug_printf("%s: MSG\n", G_STRFUNC);
224     state->msg = msg;
225     state->entry_type = LOG_ENTRY_MSG;
228 /* <Time><Tx/Rx><Channel><CAN ID><Type><Text> */
229 err_msg ::= msg_time(msg_time) MSG_DIR INT INT err_msg_type(msg_type) .
231     msg_t msg;
233     msg.timestamp   = msg_time;
234     msg.id          = 0;
235     msg.type        = msg_type;
236     msg.data.length = CAN_MAX_DLEN;
238     memset(msg.data.data, 0, sizeof(msg.data.data));
240     busmaster_debug_printf("%s: ERR MSG\n", G_STRFUNC);
242     state->msg = msg;
243     state->entry_type = LOG_ENTRY_MSG;
246 /* <Time><Channel><CAN ID><PGN><Type><Source Node><Destination Node><Priority><Tx/Rx><DLC><DataBytes> */
247 j1939_msg ::= msg_time(msg_time) INT msg_id(msg_id) INT J1939_MSG_TYPE INT INT INT MSG_DIR msg_length data(msg_data) .
249     msg_t msg;
251     msg.timestamp = msg_time;
252     msg.id        = msg_id;
253     msg.type      = MSG_TYPE_EXT;
254     msg.data      = msg_data;
256     busmaster_debug_printf("%s: J1939 MSG\n", G_STRFUNC);
258     state->msg = msg;
259     state->entry_type = LOG_ENTRY_MSG;
262 ref_date(R) ::= INT(D) COLON INT(M) COLON INT(Y) .
264     R.year  = (unsigned)Y.v0;
265     R.month = (unsigned)M.v0;
266     R.day   = (unsigned)D.v0;
269 ref_time(R) ::= INT(H) COLON INT(M) COLON INT(S) COLON INT(U) .
271     R.hours   = (unsigned)H.v0;
272     R.minutes = (unsigned)M.v0;
273     R.seconds = (unsigned)S.v0;
274     R.micros  = (unsigned)U.v0 * 1000;
277 msg_time(R) ::= MSG_TIME(M) .
279     R.hours   = (unsigned)M.v0;
280     R.minutes = (unsigned)M.v1;
281     R.seconds = (unsigned)M.v2;
282     R.micros  = (unsigned)M.v3 * 100;
285 msg_id(R) ::= INT(V) .
287     R = (unsigned)V.v0;
290 msg_length(R) ::= INT(V) .
292     R = (unsigned)V.v0;
295 msg_type(R) ::= MSG_TYPE(V) .
297     R = (msg_type_t)V.v0;
300 err_msg_type(R) ::= ERR_MSG_TYPE(V) .
302     R = (msg_type_t)V.v0;
305 data(R) ::= data0(A) .  { R = A; }
306 data(R) ::= data1(A) .  { R = A; }
307 data(R) ::= data2(A) .  { R = A; }
308 data(R) ::= data3(A) .  { R = A; }
309 data(R) ::= data4(A) .  { R = A; }
310 data(R) ::= data5(A) .  { R = A; }
311 data(R) ::= data6(A) .  { R = A; }
312 data(R) ::= data7(A) .  { R = A; }
313 data(R) ::= data8(A) .  { R = A; }
314 data(R) ::= data12(A) . { R = A; }
315 data(R) ::= data16(A) . { R = A; }
316 data(R) ::= data20(A) . { R = A; }
317 data(R) ::= data24(A) . { R = A; }
318 data(R) ::= data32(A) . { R = A; }
319 data(R) ::= data48(A) . { R = A; }
320 data(R) ::= data64(A) . { R = A; }
322 byte(R) ::= INT(A) .
324     R = (uint8_t)A.v0;
327 data0(R) ::= .
329     R.length = 0;
332 data1(R) ::= byte(A) .
334     R.length  = 1;
335     R.data[0] = A;
338 data2(R) ::= byte(A) byte(B) .
340     R.length  = 2;
341     R.data[0] = A;
342     R.data[1] = B;
345 data3(R) ::= byte(A) byte(B) byte(C) .
347     R.length  = 3;
348     R.data[0] = A;
349     R.data[1] = B;
350     R.data[2] = C;
353 data4(R) ::= byte(A) byte(B) byte(C) byte(D) .
355     R.length  = 4;
356     R.data[0] = A;
357     R.data[1] = B;
358     R.data[2] = C;
359     R.data[3] = D;
362 data5(R)  ::= data4(A)  data1(B) .  { merge_msg_data(&R, &A, &B); }
363 data6(R)  ::= data4(A)  data2(B) .  { merge_msg_data(&R, &A, &B); }
364 data7(R)  ::= data4(A)  data3(B) .  { merge_msg_data(&R, &A, &B); }
365 data8(R)  ::= data4(A)  data4(B) .  { merge_msg_data(&R, &A, &B); }
366 data12(R) ::= data8(A)  data4(B) .  { merge_msg_data(&R, &A, &B); }
367 data16(R) ::= data8(A)  data8(B) .  { merge_msg_data(&R, &A, &B); }
368 data20(R) ::= data16(A) data4(B) .  { merge_msg_data(&R, &A, &B); }
369 data24(R) ::= data16(A) data8(B) .  { merge_msg_data(&R, &A, &B); }
370 data32(R) ::= data16(A) data16(B) . { merge_msg_data(&R, &A, &B); }
371 data48(R) ::= data32(A) data16(B) . { merge_msg_data(&R, &A, &B); }
372 data64(R) ::= data32(A) data32(B) . { merge_msg_data(&R, &A, &B); }
374 %code {
376 #include "busmaster_scanner_lex.h"
377 #include "busmaster_parser.h"
379 bool
380 run_busmaster_parser(busmaster_state_t *state,
381                      int               *err, char **err_info)
383     int       lex_code;
384     yyscan_t  scanner;
385     void     *parser;
387     state->entry_type  = LOG_ENTRY_NONE;
388     state->parse_error = NULL;
389     state->err         = 0;
390     state->err_info    = NULL;
392     if (busmaster_lex_init_extra(state, &scanner) != 0)
393     {
394         *err      = errno;
395         *err_info = g_strdup(g_strerror(errno));
396         return false;
397     }
399     parser = BusmasterParserAlloc(g_malloc0);
401 #ifdef BUSMASTER_PARSER_TRACE
402     BusmasterParserTrace(stdout, "BusmasterParser >> ");
403 #endif
405     busmaster_debug_printf("%s: Starting parsing of the line\n", G_STRFUNC);
407     do
408     {
409         lex_code = busmaster_lex(scanner);
411 #ifdef BUSMASTER_DEBUG
412         if (lex_code)
413             busmaster_debug_printf("%s: Feeding %s '%s'\n",
414                                    G_STRFUNC, yyTokenName[lex_code],
415                                    busmaster_get_text(scanner));
416         else
417             busmaster_debug_printf("%s: Feeding %s\n",
418                                    G_STRFUNC, yyTokenName[lex_code]);
419 #endif
421         BusmasterParser(parser, lex_code, state->token, state);
423         if (state->err || state->err_info || state->parse_error)
424             break;
425     }
426     while (lex_code);
428     busmaster_debug_printf("%s: Done (%d)\n", G_STRFUNC, lex_code);
430     BusmasterParserFree(parser, g_free);
431     busmaster_lex_destroy(scanner);
433     if (state->err || state->err_info || state->parse_error)
434     {
435         if (state->err_info)
436         {
437             *err_info = state->err_info;
438             g_free(state->parse_error);
439         }
440         else
441         {
442             *err_info = state->parse_error;
443         }
445         if (state->err)
446             *err = state->err;
447         else
448             *err = WTAP_ERR_BAD_FILE;
450         return false;
451     }
453     return true;