NEEDED??? epan/dissectors/packet-dcerpc.c dissect_ndr_c_and_or_v_array_core dissect_n...
[wireshark-sm.git] / wiretap / candump_parser.lemon
blobb4659018fd8f96c767b10fca8094e81b7e662a4a
1 %include {
3 /* candump_parser.lemon
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
8  * Support for candump 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"
16 #include <ws_diag_control.h>
17 #include <assert.h>
18 #include <string.h>
19 #include <wiretap/file_wrappers.h>
20 #include <wsutil/array.h>
21 #include "candump_priv.h"
23 extern void *CandumpParserAlloc(void *(*mallocProc)(size_t));
24 extern void CandumpParser(void *yyp, int yymajor, token_t yyminor, candump_state_t *state);
25 extern void CandumpParserFree(void *p, void (*freeProc)(void*));
27 #ifdef CANDUMP_DEBUG
28 extern void CandumpParserTrace(FILE *TraceFILE, char *zTracePrompt);
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 CandumpParser
47 %token_prefix TOKEN_
49 %token_type { token_t }
51 %token_destructor
53     (void)state;
54     (void)yypParser;
55     (void)yypminor;
58 %extra_argument { candump_state_t* state }
60 %syntax_error
62     (void)yypParser;
63     (void)yyminor;
65 #ifdef CANDUMP_DEBUG
66     const int n = array_length(yyTokenName);
67     candump_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             candump_debug_printf("%s: possible token: %s\n", G_STRFUNC, yyTokenName[i]);
72         }
73     }
74 #endif
76     g_free(state->parse_error);
77     state->parse_error = ws_strdup_printf("Syntax Error");
78 #ifdef CANDUMP_DEBUG
79     candump_debug_printf("%s: Syntax Error\n", G_STRFUNC);
80 #endif
83 %parse_failure
85     g_free(state->parse_error);
86     state->parse_error = g_strdup("Parse Error");
87 #ifdef CANDUMP_DEBUG
88     candump_debug_printf("%s: Parse Error\n", G_STRFUNC);
89 #endif
92 %type msg { msg_t }
94 %type timestamp { nstime_t }
95 %type id { uint32_t }
96 %type flags { uint8_t }
98 %type byte { uint8_t }
99 %type data_max_8 { msg_data_t }
100 %type data_max_64 { msg_data_t }
101 %type data0 { msg_data_t }
102 %type data1 { msg_data_t }
103 %type data2 { msg_data_t }
104 %type data3 { msg_data_t }
105 %type data4 { msg_data_t }
106 %type data5 { msg_data_t }
107 %type data6 { msg_data_t }
108 %type data7 { msg_data_t }
109 %type data8 { msg_data_t }
110 %type data12 { msg_data_t }
111 %type data16 { msg_data_t }
112 %type data20 { msg_data_t }
113 %type data24 { msg_data_t }
114 %type data32 { msg_data_t }
115 %type data48 { msg_data_t }
116 %type data64 { msg_data_t }
118 %start_symbol line
120 line ::= maybe_spaces msg(M) .
122 #ifdef CANDUMP_DEBUG
123     candump_debug_printf("%s: read message\n", G_STRFUNC);
124 #endif
126     state->msg          = M;
127     state->is_msg_valid = true;
130 line ::= maybe_spaces .
132 #ifdef CANDUMP_DEBUG
133     candump_debug_printf("%s: read empty line\n", G_STRFUNC);
134 #endif
137 maybe_spaces ::= maybe_spaces SPACE .
138 maybe_spaces ::= .
140 msg(M) ::= timestamp(T) SPACE ifname SPACE id(I) RTR(R) .
142     M.ts          = T;
143     M.is_fd       = false;
144     M.id          = I | CAN_RTR_FLAG;
145     M.data.length = (uint8_t)R.v0;
147     memset(M.data.data, 0, sizeof(M.data.data));
150 msg(M) ::= timestamp(T) SPACE ifname SPACE id(I) data_max_8(D) .
152     M.ts    = T;
153     M.is_fd = false;
154     M.id    = I;
155     M.data  = D;
158 msg(M) ::= timestamp(T) SPACE ifname SPACE id(I) flags(F) data_max_64(D) .
160     M.ts    = T;
161     M.is_fd = true;
162     M.id    = I;
163     M.flags = F;
164     M.data  = D;
167 timestamp(R) ::= TIMESTAMP(A) .
169     R.secs  = (time_t)A.v0;
170     R.nsecs = (int)A.v1 * 1000;
173 ifname ::= ifname any .
174 ifname ::= any .
176 any ::= UNKNOWN .
177 any ::= RTR .
178 any ::= STD_ID .
179 any ::= EXT_ID .
180 any ::= FLAGS .
181 any ::= TIMESTAMP .
182 any ::= BYTE .
184 id(R) ::= STD_ID(A) .
186     R = (uint32_t)A.v0;
189 id(R) ::= EXT_ID(A) .
191     R = (uint32_t)A.v0;
193     if (!(R & CAN_ERR_FLAG))
194         R |= CAN_EFF_FLAG;
197 flags(R) ::= FLAGS(A) .
199     R = (uint8_t)A.v0;
202 data_max_8 ::= data0 .
203 data_max_8 ::= data1 .
204 data_max_8 ::= data2 .
205 data_max_8 ::= data3 .
206 data_max_8 ::= data4 .
207 data_max_8 ::= data5 .
208 data_max_8 ::= data6 .
209 data_max_8 ::= data7 .
210 data_max_8 ::= data8 .
212 data_max_64 ::= data_max_8 .
213 data_max_64 ::= data12 .
214 data_max_64 ::= data16 .
215 data_max_64 ::= data20 .
216 data_max_64 ::= data24 .
217 data_max_64 ::= data32 .
218 data_max_64 ::= data48 .
219 data_max_64 ::= data64 .
221 byte(R) ::= BYTE(A) .
223     R = (uint8_t)A.v0;
226 data0(R) ::= .
228     R.length = 0;
231 data1(R) ::= byte(A) .
233     R.length  = 1;
234     R.data[0] = A;
237 data2(R) ::= byte(A) byte(B) .
239     R.length  = 2;
240     R.data[0] = A;
241     R.data[1] = B;
244 data3(R) ::= byte(A) byte(B) byte(C) .
246     R.length  = 3;
247     R.data[0] = A;
248     R.data[1] = B;
249     R.data[2] = C;
252 data4(R) ::= byte(A) byte(B) byte(C) byte(D) .
254     R.length  = 4;
255     R.data[0] = A;
256     R.data[1] = B;
257     R.data[2] = C;
258     R.data[3] = D;
261 data5(R)  ::= data4(A)  data1(B) .  { merge_msg_data(&R, &A, &B); }
262 data6(R)  ::= data4(A)  data2(B) .  { merge_msg_data(&R, &A, &B); }
263 data7(R)  ::= data4(A)  data3(B) .  { merge_msg_data(&R, &A, &B); }
264 data8(R)  ::= data4(A)  data4(B) .  { merge_msg_data(&R, &A, &B); }
265 data12(R) ::= data8(A)  data4(B) .  { merge_msg_data(&R, &A, &B); }
266 data16(R) ::= data8(A)  data8(B) .  { merge_msg_data(&R, &A, &B); }
267 data20(R) ::= data16(A) data4(B) .  { merge_msg_data(&R, &A, &B); }
268 data24(R) ::= data16(A) data8(B) .  { merge_msg_data(&R, &A, &B); }
269 data32(R) ::= data16(A) data16(B) . { merge_msg_data(&R, &A, &B); }
270 data48(R) ::= data32(A) data16(B) . { merge_msg_data(&R, &A, &B); }
271 data64(R) ::= data32(A) data32(B) . { merge_msg_data(&R, &A, &B); }
273 %code {
275 #include "candump_scanner_lex.h"
276 #include "candump_parser.h"
278 bool
279 run_candump_parser(candump_state_t *state, int *err, char **err_info)
281     int              lex_code;
282     yyscan_t         scanner;
283     void            *parser;
285     state->err         = 0;
286     state->err_info    = NULL;
287     state->parse_error = NULL;
289     if (candump_lex_init_extra(state, &scanner) != 0)
290     {
291         *err      = errno;
292         *err_info = g_strdup(g_strerror(errno));
294         return false;
295     }
297     parser = CandumpParserAlloc(g_malloc0);
299 #ifdef CANDUMP_DEBUG
300     CandumpParserTrace(stdout, "parser >> ");
302     candump_debug_printf("%s: Starting parsing\n", G_STRFUNC);
303 #endif
305     do
306     {
307         lex_code = candump_lex(scanner);
309 #ifdef CANDUMP_DEBUG
310         if (lex_code)
311             candump_debug_printf("%s: Feeding %s '%s'\n",
312                             G_STRFUNC, yyTokenName[lex_code],
313                             candump_get_text(scanner));
314         else
315             candump_debug_printf("%s: Feeding %s\n",
316                             G_STRFUNC, yyTokenName[lex_code]);
317 #endif
319         CandumpParser(parser, lex_code, state->token, state);
321         if (state->err || state->err_info || state->parse_error)
322             break;
323     }
324     while (lex_code);
326 #ifdef CANDUMP_DEBUG
327     candump_debug_printf("%s: Done (%d)\n", G_STRFUNC, lex_code);
328 #endif
330     CandumpParserFree(parser, g_free);
331     candump_lex_destroy(scanner);
333     if (state->err || state->err_info || state->parse_error)
334     {
335         if (state->err_info)
336         {
337             *err_info = state->err_info;
338             g_free(state->parse_error);
339         }
340         else
341         {
342             *err_info = state->parse_error;
343         }
345         if (state->err)
346             *err = state->err;
347         else
348             *err = WTAP_ERR_BAD_FILE;
350         return false;
351     }
353     return true;