attr_dissector_fn_t
[wireshark-sm.git] / wiretap / ascend_parser.lemon
blob48ce972198485e46323e5cfd5e2d1fa7e0770dbb
1 %include {
2 /* ascend_parser.lemon
3  *
4  * Wiretap Library
5  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
11     Example 'pridisp' output data - one paragraph/frame:
13 PRI-XMIT-27: (task "l1Task" at 0x10216fe0, time: 560194.01) 4 octets @ 0x1027c5b0
14   [0000]: 00 01 01 a9                                         ....
15 PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
16   [0000]: 00 01 01 dd
18     Example 'pridisp' output data - two paragraphs/frame for XMIT case only:
20 PRI-XMIT-19/1:  (task "l1Task" at 0x10216840, time: 274759.98) 4 octets @ 0x1027f230
21   [0000]: 00 01 30 d8                                         ..0.
22 PRI-XMIT-19/2 (task "l1Task" at 0x10216840, time: 274759.98) 11 octets @ 0x1027f234
23   [0000]: 08 02 8c bf 02 18 04 e9  82 83 8f                   ........ ...
25     Example 'ether-disp' output data:
27 ETHER3ND RECV: (task "_sarTask" at 0x802c6eb0, time: 259848.03) 775 octets @ 0xa8fb2020
28   [0000]: 00 d0 52 04 e7 1e 08 00  20 ae 51 b5 08 00 45 00    ..R..... .Q...E.
29   [0010]: 02 f9 05 e6 40 00 3f 11  6e 39 87 fe c4 95 3c 3c    ....@.?.  n9....<<
30   [0020]: 3c 05 13 c4 13 c4 02 e5  ef ed 49 4e 56 49 54 45    <.......  ..INVITE
31   [0030]: 20 73 69 70 3a 35 32 30  37 33 40 36 30 2e 36 30     sip:520 73@60.60
32   [0040]: 2e 36 30 2e 35 20 53 49  50 2f 32 2e 30 0d 0a 56    .60.5 SI P/2.0..V
33   [0050]: 69 61 3a 20 53 49 50 2f  32 2e 30 2f 55 44 50 20    ia: SIP/ 2.0/UDP
34   [0060]: 31 33 35 2e                                         135.
36     Example 'wandsess' output data:
38 RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94
39   [0000]: FF 03 00 3D C0 06 CA 22 2F 45 00 00 28 6A 3B 40
40   [0010]: 00 3F 03 D7 37 CE 41 62 12 CF 00 FB 08 20 27 00
41   [0020]: 50 E4 08 DD D7 7C 4C 71 92 50 10 7D 78 67 C8 00
42   [0030]: 00
43 XMIT-iguana:241:(task: B04E12C0, time: 1975432.85) 53 octets @ 8009EB16
44   [0000]: FF 03 00 3D C0 09 1E 31 21 45 00 00 2C 2D BD 40
45   [0010]: 00 7A 06 D8 B1 CF 00 FB 08 CE 41 62 12 00 50 20
46   [0020]: 29 7C 4C 71 9C 9A 6A 93 A4 60 12 22 38 3F 10 00
47   [0030]: 00 02 04 05 B4
49     Example 'wdd' output data:
51 Date: 01/12/1990.  Time: 12:22:33
52 Cause an attempt to place call to 14082750382
53 WD_DIALOUT_DISP: chunk 2515EE type IP.
54 (task: 251790, time: 994953.28) 44 octets @ 2782B8
55   [0000]: 00 C0 7B 71 45 6C 00 60 08 16 AA 51 08 00 45 00
56   [0010]: 00 2C 66 1C 40 00 80 06 53 F6 AC 14 00 18 CC 47
57   [0020]: C8 45 0A 31 00 50 3B D9 5B 75 00 00
59     The following output comes from a MAX with Software 7.2.3:
61 RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0
62   [0000]: FF 03 00 21 45 00 00 60 E3 49 00 00 7F 11 FD 7B
63   [0010]: C0 A8 F7 05 8A C8 18 51 00 89 00 89 00 4C C7 C1
64   [0020]: CC 8E 40 00 00 01 00 00 00 00 00 01 20 45 4A 45
65   [0030]: 42 45 43 45 48 43 4E 46 43 46 41 43 41 43 41 43
66   [0040]: 41 43 41 43 41 43 41 43 41 43 41 42 4E 00 00 20
67   [0050]: 00 01 C0 0C 00 20 00 01 00 04 93 E0 00 06 60 00
68   [0060]: C0 A8 F7 05
69 XMIT-187:(task: B0292CA0, time: 18042248.04) 60 octets @ 800AD576
70   [0000]: FF 03 00 21 45 00 00 38 D7 EE 00 00 0F 01 11 2B
71   [0010]: 0A FF FF FE C0 A8 F7 05 03 0D 33 D3 00 00 00 00
72   [0020]: 45 00 00 60 E3 49 00 00 7E 11 FE 7B C0 A8 F7 05
73   [0030]: 8A C8 18 51 00 89 00 89 00 4C C7 C1
74 RECV-187:(task: B0292CA0, time: 18042251.92) 16 octets @ 800018E8
75   [0000]: FF 03 C0 21 09 01 00 0C DE 61 96 4B 00 30 94 92
77   In TAOS 8.0, Lucent slightly changed the format as follows:
79     Example 'wandisp' output data (TAOS 8.0.3): (same format is used
80     for 'wanopen' and 'wannext' command)
82 RECV-14: (task "idle task" at 0xb05e6e00, time: 1279.01) 29 octets @ 0x8000e0fc
83   [0000]: ff 03 c0 21 01 01 00 19  01 04 05 f4 11 04 05 f4    ...!.... ........
84   [0010]: 13 09 03 00 c0 7b 9a 9f  2d 17 04 10 00             .....{.. -....
85 XMIT-14: (task "idle task" at 0xb05e6e00, time: 1279.02) 38 octets @ 0x8007fd56
86   [0000]: ff 03 c0 21 01 01 00 22  00 04 00 00 01 04 05 f4    ...!..." ........
87   [0010]: 03 05 c2 23 05 11 04 05  f4 13 09 03 00 c0 7b 80    ...#.... ......{.
88   [0020]: 7c ef 17 04 0e 00                                   |.....
89 XMIT-14: (task "idle task" at 0xb05e6e00, time: 1279.02) 29 octets @ 0x8007fa36
90   [0000]: ff 03 c0 21 02 01 00 19  01 04 05 f4 11 04 05 f4    ...!.... ........
91   [0010]: 13 09 03 00 c0 7b 9a 9f  2d 17 04 10 00             .....{.. -....
93     Example 'wandsess' output data (TAOS 8.0.3):
95 RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198
96   [0000]: ff 03 00 3d c0 00 00 04  80 fd 02 01 00 0a 11 06    ...=.... ........
97   [0010]: 00 01 01 03                                         ....
98 XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 26 octets @ 0x800806b6
99   [0000]: ff 03 00 3d c0 00 00 00  80 21 01 01 00 10 02 06    ...=.... .!......
100   [0010]: 00 2d 0f 01 03 06 89 64  03 08                      .-.....d ..
101 XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 20 octets @ 0x8007f716
102   [0000]: ff 03 00 3d c0 00 00 01  80 fd 01 01 00 0a 11 06    ...=.... ........
103   [0010]: 00 01 01 03                                         ....
105   The changes since TAOS 7.X are:
107     1) White space is added before "(task".
108     2) Task has a name, indicated by a subsequent string surrounded by a
109        double-quote.
110     3) Address expressed in hex number has a preceding "0x".
111     4) Hex numbers are in lower case.
112     5) There is a character display corresponding to hex data in each line.
114  */
116 #include "config.h"
117 #include <assert.h>
118 #include <stdlib.h>
119 #include <string.h>
121 #include "wtap-int.h"
122 #include "ascendtext.h"
123 #include "ascend-int.h"
124 #include "ascend_parser.h"
125 #include "ascend_scanner_lex.h"
126 #include "file_wrappers.h"
127 #include <wsutil/wslog.h>
129 #define NO_USER "<none>"
131 static void *AscendParserAlloc(void *(*mallocProc)(size_t));
132 static void AscendParser(void *yyp, int yymajor, ascend_token_t yyminor, ascend_state_t *state);
133 static void AscendParserFree(void *p, void (*freeProc)(void*));
135 #if 0
136 #define ASCEND_PARSER_DEBUG 1
137 #undef NDEBUG
138 #define ascend_debug(...) ws_warning(__VA_ARGS__)
139 #else
140 #define ascend_debug(...)
141 #endif
143 DIAG_OFF_LEMON()
144 } /* end of %include */
146 %code {
147 DIAG_ON_LEMON()
150 %name AscendParser
152 %extra_argument { ascend_state_t *parser_state }
154 %token_type { ascend_token_t }
156 %token_destructor {
157     (void) parser_state;
158     (void) yypminor;
161 %type STRING { ascend_token_t* }
162 %type KEYWORD { ascend_token_t* }
163 %type WDD_DATE { ascend_token_t* }
164 %type WDD_DECNUM { ascend_token_t* }
165 %type WDD_TIME { ascend_token_t* }
166 %type WDD_CAUSE { ascend_token_t* }
167 %type WDD_CALLNUM { ascend_token_t* }
168 %type WDD_CHUNK { ascend_token_t* }
169 %type COUNTER { ascend_token_t* }
170 %type SLASH_SUFFIX { ascend_token_t* }
172 %type WDS_PREFIX { ascend_token_t* }
173 %type ISDN_PREFIX { ascend_token_t* }
174 %type ETHER_PREFIX { ascend_token_t* }
175 %type DECNUM { ascend_token_t* }
176 %type YEAR { ascend_token_t* }
177 %type MONTH { ascend_token_t* }
178 %type MDAY { ascend_token_t* }
179 %type HEXNUM { ascend_token_t* }
181 %type HEXBYTE { ascend_token_t* }
183 data_packet ::= ether_hdr datagroup .
184 data_packet ::= deferred_isdn_hdr datagroup deferred_isdn_hdr datagroup .
185 data_packet ::= isdn_hdr datagroup .
186 data_packet ::= wds_hdr datagroup .
187 data_packet ::= wds8_hdr datagroup .
188 data_packet ::= wdp7_hdr datagroup .
189 data_packet ::= wdp8_hdr datagroup .
190 data_packet ::= wdd_date wdd_hdr datagroup .
191 data_packet ::= wdd_hdr datagroup .
193 %type isdn_prefix { uint16_t }
194 isdn_prefix(U16) ::= ISDN_PREFIX(A_TOK) . { U16 = A_TOK.u16_val; }
196 %type ether_prefix { uint16_t }
197 ether_prefix(U16) ::= ETHER_PREFIX(A_TOK) . { U16 = A_TOK.u16_val; }
199 %type wds_prefix { uint16_t }
200 wds_prefix(U16) ::= WDS_PREFIX(A_TOK) . { U16 = A_TOK.u16_val; }
202 string ::= STRING .
204 %type decnum { uint32_t }
205 decnum(U32) ::= DECNUM(A_TOK) . { U32 = A_TOK.u32_val; }
207 %type hexnum { uint32_t }
208 hexnum(U32) ::= HEXNUM(A_TOK) . { U32 = A_TOK.u32_val; }
210 %type wdd_decnum { uint32_t }
211 wdd_decnum(U32) ::= WDD_DECNUM(A_TOK) . { U32 = A_TOK.u32_val; }
214   pridisp special case - I-frame header printed separately from contents,
215   one frame across two messages.
217 PRI-XMIT-0/1:  (task "l1Task" at 0x80152b20, time: 283529.65) 4 octets @
218 0x80128220
219   [0000]: 00 01 ae b2                                         ....
220 PRI-XMIT-0/2 (task "l1Task" at 0x80152b20, time: 283529.65) 10 octets @
221 0x80128224
222   [0000]: 08 02 d7 e3 02 18 03 a9  83 8a                      ........
225 deferred_isdn_hdr ::= isdn_prefix(TYPE) decnum(SESS) SLASH_SUFFIX KEYWORD string KEYWORD hexnum(TASK) KEYWORD decnum(SECS) decnum(USECS) decnum(WIRELEN) KEYWORD HEXNUM . {
226     parser_state->wirelen += WIRELEN;
227     parser_state->secs = SECS;
228     parser_state->usecs = USECS;
229     if (parser_state->pseudo_header != NULL) {
230         parser_state->pseudo_header->type = TYPE;
231         parser_state->pseudo_header->sess = SESS;
232         parser_state->pseudo_header->call_num[0] = '\0';
233         parser_state->pseudo_header->chunk = 0;
234         parser_state->pseudo_header->task = TASK;
235     }
236     /* because we have two data groups */
237     parser_state->first_hexbyte = 0;
241 PRI-XMIT-19:  (task "l1Task" at 0x10216840, time: 274758.67) 4 octets @ 0x1027c1c0
242  ... or ...
243 PRI-RCV-27:  (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
245 isdn_hdr ::= isdn_prefix(TYPE) decnum(SESS) KEYWORD string KEYWORD hexnum(TASK) KEYWORD decnum(SECS) decnum(USECS) decnum(WIRELEN) KEYWORD HEXNUM . {
246     parser_state->wirelen += WIRELEN;
247     parser_state->secs = SECS;
248     parser_state->usecs = USECS;
249     if (parser_state->pseudo_header != NULL) {
250         parser_state->pseudo_header->type = TYPE;
251         parser_state->pseudo_header->sess = SESS;
252         parser_state->pseudo_header->call_num[0] = '\0';
253         parser_state->pseudo_header->chunk = 0;
254         parser_state->pseudo_header->task = TASK;
255     }
256     parser_state->first_hexbyte = 0;
260 ETHER3ND XMIT: (task "_sarTask" at 0x802c6eb0, time: 259848.11) 414 octets @ 0xa
261 885f80e
263 ether_hdr ::= ether_prefix(TYPE) string KEYWORD string KEYWORD hexnum(TASK) KEYWORD decnum(SECS) decnum(USECS) decnum(WIRELEN) KEYWORD HEXNUM . {
264     parser_state->wirelen += WIRELEN;
265     parser_state->secs = SECS;
266     parser_state->usecs = USECS;
267     if (parser_state->pseudo_header != NULL) {
268         parser_state->pseudo_header->type = TYPE;
269         parser_state->pseudo_header->call_num[0] = '\0';
270         parser_state->pseudo_header->chunk = 0;
271         parser_state->pseudo_header->task = TASK;
272     }
275 /* RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 */
276 /*            1        2      3      4       5      6       7      8      9      10     11 */
277 wds_hdr ::= wds_prefix(TYPE) string decnum(SESS) KEYWORD hexnum(TASK) KEYWORD decnum(SECS) decnum(USECS) decnum(WIRELEN) KEYWORD HEXNUM . {
278     parser_state->wirelen += WIRELEN;
279     parser_state->secs = SECS;
280     parser_state->usecs = USECS;
281     if (parser_state->pseudo_header != NULL) {
282         /* parser_state->pseudo_header->user is set in ascend_scanner.l */
283         parser_state->pseudo_header->type = TYPE;
284         parser_state->pseudo_header->sess = SESS;
285         parser_state->pseudo_header->call_num[0] = '\0';
286         parser_state->pseudo_header->chunk = 0;
287         parser_state->pseudo_header->task = TASK;
288     }
291 /* RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198 */
292 /*                1       2       3     4       5       6      7       8      9      10     11     12      13 */
293 wds8_hdr ::= wds_prefix(TYPE) string decnum(SESS) KEYWORD string KEYWORD hexnum(TASK) KEYWORD decnum(SECS) decnum(USECS) decnum(WIRELEN) KEYWORD HEXNUM . {
294     parser_state->wirelen += WIRELEN;
295     parser_state->secs = SECS;
296     parser_state->usecs = USECS;
297     if (parser_state->pseudo_header != NULL) {
298         /* parser_state->pseudo_header->user is set in ascend_scanner.l */
299         parser_state->pseudo_header->type = TYPE;
300         parser_state->pseudo_header->sess = SESS;
301         parser_state->pseudo_header->call_num[0] = '\0';
302         parser_state->pseudo_header->chunk = 0;
303         parser_state->pseudo_header->task = TASK;
304     }
307 /* RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0 */
308 /*            1        2       3      4       5       6      7      8      9      10    */
309 wdp7_hdr ::= wds_prefix(TYPE) decnum(SESS) KEYWORD hexnum(TASK) KEYWORD decnum(SECS) decnum(USECS) decnum(WIRELEN) KEYWORD HEXNUM . {
310     parser_state->wirelen += WIRELEN;
311     parser_state->secs = SECS;
312     parser_state->usecs = USECS;
313     if (parser_state->pseudo_header != NULL) {
314         /* parser_state->pseudo_header->user is set in ascend_scanner.l */
315         parser_state->pseudo_header->type = TYPE;
316         parser_state->pseudo_header->sess = SESS;
317         parser_state->pseudo_header->call_num[0] = '\0';
318         parser_state->pseudo_header->chunk = 0;
319         parser_state->pseudo_header->task = TASK;
320     }
323 /* XMIT-44: (task "freedm_task" at 0xe051fd10, time: 6258.66) 29 octets @ 0x606d1f00 */
324 /*              1        2       3      4       5      6      7       8      9      10     11      12 */
325 wdp8_hdr ::= wds_prefix(TYPE) decnum(SESS) KEYWORD string KEYWORD hexnum(TASK) KEYWORD decnum(SECS) decnum(USECS) decnum(WIRELEN) KEYWORD HEXNUM . {
326     parser_state->wirelen += WIRELEN;
327     parser_state->secs = SECS;
328     parser_state->usecs = USECS;
329     if (parser_state->pseudo_header != NULL) {
330         /* parser_state->pseudo_header->user is set in ascend_scanner.l */
331         parser_state->pseudo_header->type = TYPE;
332         parser_state->pseudo_header->sess = SESS;
333         parser_state->pseudo_header->call_num[0] = '\0';
334         parser_state->pseudo_header->chunk = 0;
335         parser_state->pseudo_header->task = TASK;
336     }
340 Date: 01/12/1990.  Time: 12:22:33
341 Cause an attempt to place call to 14082750382
343 /*           1        2      3      4      5       6      7      8      9      10*/
344 wdd_date ::= WDD_DATE wdd_decnum(MONTH) wdd_decnum(MDAY) wdd_decnum(YEAR) WDD_TIME wdd_decnum(HOUR) wdd_decnum(MINUTE) wdd_decnum(SECOND) WDD_CAUSE WDD_CALLNUM(CN_T) . {
345     /*
346     * Supply the date/time value to the code above us; it will use the
347     * first date/time value supplied as the capture start date/time.
348     */
349     struct tm wddt;
351     wddt.tm_sec  = SECOND;
352     wddt.tm_min  = MINUTE;
353     wddt.tm_hour = HOUR;
354     wddt.tm_mday = MDAY;
355     wddt.tm_mon  = MONTH - 1;
356     wddt.tm_year = (YEAR > 1970) ? YEAR - 1900 : 70;
357     wddt.tm_isdst = -1;
359     parser_state->timestamp = (uint32_t) mktime(&wddt);
360     parser_state->saw_timestamp = true;
362     (void) g_strlcpy(parser_state->pseudo_header->call_num, CN_T.str_val, ASCEND_MAX_STR_LEN);
366 WD_DIALOUT_DISP: chunk 2515EE type IP.
367 (task: 251790, time: 994953.28) 44 octets @ 2782B8
369 /*           1        2      3       4       5      6       7      8      9      10     11*/
370 wdd_hdr ::= WDD_CHUNK hexnum(CHUNK) KEYWORD KEYWORD hexnum(TASK) KEYWORD decnum(SECS) decnum(USECS) decnum(WIRELEN) KEYWORD HEXNUM . {
371     parser_state->wirelen = WIRELEN;
372     parser_state->secs = SECS;
373     parser_state->usecs = USECS;
374     if (parser_state->pseudo_header != NULL) {
375         parser_state->pseudo_header->type = ASCEND_PFX_WDD;
376         parser_state->pseudo_header->user[0] = '\0';
377         parser_state->pseudo_header->sess = 0;
378         parser_state->pseudo_header->chunk = CHUNK;
379         parser_state->pseudo_header->task = TASK;
380     }
383 byte ::= HEXBYTE(A_TOK) . {
384     /* remember the position of the data group in the trace, to tip off
385         ascend_find_next_packet() as to where to look for the next header. */
386     if (parser_state->first_hexbyte == 0) {
387         parser_state->first_hexbyte = file_tell(parser_state->fh) - A_TOK.length;
388     }
390     /* XXX - if this test fails, it means that we parsed more bytes than
391         the header claimed there were. */
392     if (parser_state->caplen < parser_state->wirelen) {
393         parser_state->pkt_data[parser_state->caplen] = A_TOK.u8_val;
394         parser_state->caplen++;
395     }
398 /* XXX  There must be a better way to do this... */
399 bytegroup ::= byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte .
400 bytegroup ::= byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte .
401 bytegroup ::= byte byte byte byte byte byte byte byte byte byte byte byte byte byte .
402 bytegroup ::= byte byte byte byte byte byte byte byte byte byte byte byte byte .
403 bytegroup ::= byte byte byte byte byte byte byte byte byte byte byte byte .
404 bytegroup ::= byte byte byte byte byte byte byte byte byte byte byte .
405 bytegroup ::= byte byte byte byte byte byte byte byte byte byte .
406 bytegroup ::= byte byte byte byte byte byte byte byte byte .
407 bytegroup ::= byte byte byte byte byte byte byte byte .
408 bytegroup ::= byte byte byte byte byte byte byte .
409 bytegroup ::= byte byte byte byte byte byte .
410 bytegroup ::= byte byte byte byte byte .
411 bytegroup ::= byte byte byte byte .
412 bytegroup ::= byte byte byte .
413 bytegroup ::= byte byte .
414 bytegroup ::= byte .
416 dataln ::= COUNTER bytegroup .
418 datagroup ::= dataln dataln dataln dataln dataln dataln dataln dataln .
419 datagroup ::= dataln dataln dataln dataln dataln dataln dataln .
420 datagroup ::= dataln dataln dataln dataln dataln dataln .
421 datagroup ::= dataln dataln dataln dataln dataln .
422 datagroup ::= dataln dataln dataln dataln .
423 datagroup ::= dataln dataln dataln .
424 datagroup ::= dataln dataln .
425 datagroup ::= dataln .
427 %syntax_error
429     /*
430     * We might be parsing output that includes console session output along
431     * with packet dumps.
432     */
433     (void)yypParser;
434     (void)yyminor;
435     static char *err = "non-packet data";
437     parser_state->ascend_parse_error = err;
440 %code {
442 /* Run the parser. */
443 bool
444 run_ascend_parser(uint8_t *pd, ascend_state_t *parser_state, int *err, char **err_info)
446     yyscan_t scanner = NULL;
447     void *parser;
449     if (ascend_lex_init(&scanner) != 0) {
450         /* errno is set if this fails */
451         *err = errno;
452         *err_info = NULL;
453         return false;
454     }
455     /* Associate the parser state with the lexical analyzer state */
456     ascend_set_extra(parser_state, scanner);
457     parser_state->ascend_parse_error = NULL;
458     parser_state->err = 0;
459     parser_state->err_info = NULL;
460     parser_state->pkt_data = pd;
462     /*
463     * We haven't seen a time stamp yet.
464     */
465     parser_state->saw_timestamp = false;
466     parser_state->timestamp = 0;
468     parser_state->first_hexbyte = 0;
469     parser_state->caplen = 0;
470     parser_state->wirelen = 0;
472     parser_state->secs = 0;
473     parser_state->usecs = 0;
475     /*
476     * Not all packets in a "wdd" dump necessarily have a "Cause an
477     * attempt to place call to" header (I presume this can happen if
478     * there was a call in progress when the packet was sent or
479     * received), so we won't necessarily have the phone number for
480     * the packet.
481     *
482     * XXX - we could assume, in the sequential pass, that it's the
483     * phone number from the last call, and remember that for use
484     * when doing random access.
485     */
486     parser_state->pseudo_header->call_num[0] = '\0';
488     parser = AscendParserAlloc(g_malloc0);
490 #ifdef ASCEND_PARSER_DEBUG
491     AscendParserTrace(stderr, "=AP ");
492 #endif
494     int token_id;
495     do {
496         token_id = ascend_lex(scanner);
498         ascend_debug("Got token %d at %" PRId64, token_id, file_tell(parser_state->fh));
500         AscendParser(parser, token_id, parser_state->token, parser_state);
501     } while (token_id && !parser_state->err && !parser_state->ascend_parse_error && parser_state->caplen < ASCEND_MAX_PKT_LEN);
503     AscendParserFree(parser, g_free);
504     ascend_lex_destroy(scanner);
506     if (parser_state->err) {
507         *err = parser_state->err;
508         *err_info = parser_state->err_info;
509         return false;
510     }
512     return true;
515 } // %code