aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/Makefile.am6
-rw-r--r--wiretap/ascend-int.h43
-rw-r--r--wiretap/ascend.y395
-rw-r--r--wiretap/ascend_scanner.l126
-rw-r--r--wiretap/ascendtext.c133
-rw-r--r--wiretap/k12text.l268
6 files changed, 563 insertions, 408 deletions
diff --git a/wiretap/Makefile.am b/wiretap/Makefile.am
index e30efcfbbe..597e77d27b 100644
--- a/wiretap/Makefile.am
+++ b/wiretap/Makefile.am
@@ -53,6 +53,8 @@ libwiretap_generated_la_SOURCES = \
libwiretap_generated_la_CFLAGS = $(GENERATED_CFLAGS)
+BUILT_SOURCES = $(GENERATED_HEADER_FILES)
+
EXTRA_DIST = \
.editorconfig \
README.airmagnet \
@@ -71,11 +73,9 @@ k12text_lex.h : k12text.c
ascend_scanner_lex.h : ascend_scanner.c
-ascend_scanner.c: ascend.h
-
ascend.h: ascend.c
-ascend.c: ascend.y
+ascend.c: $(srcdir)/ascend.y ascend_scanner_lex.h
@if [ -z "$(YACC)" ]; then \
echo "Neither bison nor byacc has been found"; \
exit 1; \
diff --git a/wiretap/ascend-int.h b/wiretap/ascend-int.h
index 049bf8599d..0d8e70b6d6 100644
--- a/wiretap/ascend-int.h
+++ b/wiretap/ascend-int.h
@@ -27,31 +27,34 @@
#include <glib.h>
#include "ws_symbol_export.h"
-extern const gchar *ascend_parse_error;
-
-/*
- * Pointer to the pseudo-header for the current packet.
- */
-extern struct ascend_phdr *pseudo_header;
-
typedef struct {
time_t inittime;
gboolean adjusted;
gint64 next_packet_seek_start;
} ascend_t;
-/* Here we provide interfaces to make our scanner act and look like lex */
-int ascendlex(void);
-
-void init_parse_ascend(void);
-void ascend_init_lexer(FILE_T fh);
-gboolean check_ascend(FILE_T fh, struct wtap_pkthdr *phdr);
-typedef enum {
- PARSED_RECORD,
- PARSED_NONRECORD,
- PARSE_FAILED
-} parse_t;
-parse_t parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr,
- Buffer *buf, guint length);
+typedef struct {
+ FILE_T fh;
+ const gchar *ascend_parse_error;
+ int *err;
+ gchar **err_info;
+ struct ascend_phdr *pseudo_header;
+ guint8 *pkt_data;
+
+ gboolean saw_timestamp;
+ guint32 timestamp;
+
+ unsigned int bcur;
+ gint64 first_hexbyte;
+ guint32 wirelen;
+ guint32 caplen;
+ time_t secs;
+ guint32 usecs;
+} ascend_state_t;
+#define YY_EXTRA_TYPE ascend_state_t *
+
+extern int
+run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd,
+ ascend_state_t *parser_state, int *err, gchar **err_info);
#endif /* ! __ASCEND_INT_H__ */
diff --git a/wiretap/ascend.y b/wiretap/ascend.y
index dc30a9e78f..31f9cbc88e 100644
--- a/wiretap/ascend.y
+++ b/wiretap/ascend.y
@@ -1,3 +1,28 @@
+/*
+ * We want a reentrant parser.
+ */
+%pure-parser
+
+/*
+ * We also want a reentrant scanner, so we have to pass the
+ * handle for the reentrant scanner to the parser, and the
+ * parser has to pass it to the lexical analyzer.
+ *
+ * We use void * rather than yyscan_t because, at least with some
+ * versions of Flex and Bison, if you use yyscan_t in %parse-param and
+ * %lex-param, you have to include the ascend_lex_scanner.h before
+ * ascend.h to get yyscan_t declared, and you have to include ascend.h
+ * before ascend_lex_scanner.h to get YYSTYPE declared. Using void *
+ * breaks the cycle; the Flex documentation says yyscan_t is just a void *.
+ */
+%parse-param {void *yyscanner}
+%lex-param {void *yyscanner}
+
+/*
+ * And we need to pass the parser state to the scanner.
+ */
+%parse-param {ascend_state_t *parser_state}
+
%{
/* ascend.y
*
@@ -135,22 +160,13 @@ XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 20 octet
#include <wsutil/buffer.h>
#include "ascendtext.h"
#include "ascend-int.h"
+#include "ascend.h"
+#include "ascend_scanner_lex.h"
#include "file_wrappers.h"
#define NO_USER "<none>"
-int yyparse(FILE_T fh);
-void yyerror(FILE_T fh _U_, const char *);
-
-const gchar *ascend_parse_error;
-
-static unsigned int bcur;
-static guint32 start_time, usecs, caplen, wirelen;
-static time_t secs;
-struct ascend_phdr *pseudo_header;
-static guint8 *pkt_data;
-static gint64 first_hexbyte;
-
+extern void yyerror (void *yyscanner, ascend_state_t *state, FILE_T fh _U_, const char *s);
%}
%union {
@@ -208,19 +224,19 @@ PRI-XMIT-0/2 (task "l1Task" at 0x80152b20, time: 283529.65) 10 octets @
*/
deferred_isdn_hdr: isdn_prefix decnum SLASH_SUFFIX KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen += $11;
- caplen += $11;
- secs = $9;
- usecs = $10;
- if (pseudo_header != NULL) {
- pseudo_header->type = $1;
- pseudo_header->sess = $2;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $7;
+ parser_state->wirelen += $11;
+ parser_state->caplen += $11;
+ parser_state->secs = $9;
+ parser_state->usecs = $10;
+ if (parser_state->pseudo_header != NULL) {
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $2;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $7;
}
/* because we have two data groups */
- first_hexbyte = 0;
+ parser_state->first_hexbyte = 0;
}
;
@@ -230,18 +246,18 @@ PRI-XMIT-19: (task "l1Task" at 0x10216840, time: 274758.67) 4 octets @ 0x1027c1
PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
*/
isdn_hdr: isdn_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $10;
- caplen = $10;
- secs = $8;
- usecs = $9;
- if (pseudo_header != NULL) {
- pseudo_header->type = $1;
- pseudo_header->sess = $2;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $6;
+ parser_state->wirelen = $10;
+ parser_state->caplen = $10;
+ parser_state->secs = $8;
+ parser_state->usecs = $9;
+ if (parser_state->pseudo_header != NULL) {
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $2;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $6;
}
- first_hexbyte = 0;
+ parser_state->first_hexbyte = 0;
}
;
@@ -251,15 +267,15 @@ ETHER3ND XMIT: (task "_sarTask" at 0x802c6eb0, time: 259848.11) 414 octets @ 0xa
*/
ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decnum
decnum KEYWORD HEXNUM {
- wirelen = $10;
- caplen = $10;
- secs = $8;
- usecs = $9;
- if (pseudo_header != NULL) {
- pseudo_header->type = $1;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $6;
+ parser_state->wirelen = $10;
+ parser_state->caplen = $10;
+ parser_state->secs = $8;
+ parser_state->usecs = $9;
+ if (parser_state->pseudo_header != NULL) {
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $6;
}
}
;
@@ -267,17 +283,17 @@ ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decn
/* RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 */
/* 1 2 3 4 5 6 7 8 9 10 11 */
wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $9;
- caplen = $9;
- secs = $7;
- usecs = $8;
- if (pseudo_header != NULL) {
- /* pseudo_header->user is set in ascend_scanner.l */
- pseudo_header->type = $1;
- pseudo_header->sess = $3;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $5;
+ parser_state->wirelen = $9;
+ parser_state->caplen = $9;
+ parser_state->secs = $7;
+ parser_state->usecs = $8;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->user is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $3;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $5;
}
}
;
@@ -285,17 +301,17 @@ wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KE
/* RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198 */
/* 1 2 3 4 5 6 7 8 9 10 11 12 13 */
wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $11;
- caplen = $11;
- secs = $9;
- usecs = $10;
- if (pseudo_header != NULL) {
- /* pseudo_header->user is set in ascend_scanner.l */
- pseudo_header->type = $1;
- pseudo_header->sess = $3;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $7;
+ parser_state->wirelen = $11;
+ parser_state->caplen = $11;
+ parser_state->secs = $9;
+ parser_state->usecs = $10;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->user is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $3;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $7;
}
}
;
@@ -303,17 +319,17 @@ wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum
/* RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0 */
/* 1 2 3 4 5 6 7 8 9 10 */
wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $8;
- caplen = $8;
- secs = $6;
- usecs = $7;
- if (pseudo_header != NULL) {
- /* pseudo_header->user is set in ascend_scanner.l */
- pseudo_header->type = $1;
- pseudo_header->sess = $2;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $4;
+ parser_state->wirelen = $8;
+ parser_state->caplen = $8;
+ parser_state->secs = $6;
+ parser_state->usecs = $7;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->user is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $2;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $4;
}
}
;
@@ -321,17 +337,17 @@ wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD
/* XMIT-44: (task "freedm_task" at 0xe051fd10, time: 6258.66) 29 octets @ 0x606d1f00 */
/* 1 2 3 4 5 6 7 8 9 10 11 12 */
wdp8_hdr: wds_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $10;
- caplen = $10;
- secs = $8;
- usecs = $9;
- if (pseudo_header != NULL) {
- /* pseudo_header->user is set in ascend_scanner.l */
- pseudo_header->type = $1;
- pseudo_header->sess = $2;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $6;
+ parser_state->wirelen = $10;
+ parser_state->caplen = $10;
+ parser_state->secs = $8;
+ parser_state->usecs = $9;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->user is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $2;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $6;
}
}
;
@@ -356,7 +372,8 @@ wdd_date: WDD_DATE decnum decnum decnum KEYWORD decnum decnum decnum KEYWORD str
wddt.tm_year = ($4 > 1970) ? $4 - 1900 : 70;
wddt.tm_isdst = -1;
- start_time = (guint32) mktime(&wddt);
+ parser_state->timestamp = (guint32) mktime(&wddt);
+ parser_state->saw_timestamp = TRUE;
}
;
@@ -366,17 +383,17 @@ WD_DIALOUT_DISP: chunk 2515EE type IP.
*/
/* 1 2 3 4 5 6 7 8 9 10 11*/
wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $9;
- caplen = $9;
- secs = $7;
- usecs = $8;
- if (pseudo_header != NULL) {
- /* pseudo_header->call_num is set in ascend_scanner.l */
- pseudo_header->type = ASCEND_PFX_WDD;
- pseudo_header->user[0] = '\0';
- pseudo_header->sess = 0;
- pseudo_header->chunk = $2;
- pseudo_header->task = $5;
+ parser_state->wirelen = $9;
+ parser_state->caplen = $9;
+ parser_state->secs = $7;
+ parser_state->usecs = $8;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->call_num is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = ASCEND_PFX_WDD;
+ parser_state->pseudo_header->user[0] = '\0';
+ parser_state->pseudo_header->sess = 0;
+ parser_state->pseudo_header->chunk = $2;
+ parser_state->pseudo_header->task = $5;
}
}
;
@@ -384,16 +401,16 @@ wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KE
byte: HEXBYTE {
/* remember the position of the data group in the trace, to tip
off ascend_seek() as to where to look for the next header. */
- if (first_hexbyte == 0)
- first_hexbyte = file_tell(fh);
+ if (parser_state->first_hexbyte == 0)
+ parser_state->first_hexbyte = file_tell(fh);
- if (bcur < caplen) {
- pkt_data[bcur] = $1;
- bcur++;
+ if (parser_state->bcur < parser_state->caplen) {
+ parser_state->pkt_data[parser_state->bcur] = $1;
+ parser_state->bcur++;
}
/* arbitrary safety maximum... */
- if (bcur >= ASCEND_MAX_PKT_LEN)
+ if (parser_state->bcur >= ASCEND_MAX_PKT_LEN)
YYACCEPT;
}
;
@@ -431,27 +448,42 @@ datagroup: dataln
%%
-void
-init_parse_ascend(void)
-{
- start_time = 0; /* we haven't see a date/time yet */
-}
-
/* Run the parser. */
-static int
-run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd)
+int
+run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd,
+ ascend_state_t *parser_state, int *err, gchar **err_info)
{
- /* yydebug = 1; */
+ yyscan_t scanner = NULL;
int retval;
- ascend_init_lexer(fh);
- pseudo_header = &phdr->pseudo_header.ascend;
- pkt_data = pd;
+ if (ascendlex_init(&scanner) != 0) {
+ /* errno is set if this fails */
+ *err = errno;
+ *err_info = NULL;
+ return 1;
+ }
+ /* Associate the parser state with the lexical analyzer state */
+ ascendset_extra(parser_state, scanner);
+ parser_state->fh = fh;
+ parser_state->ascend_parse_error = NULL;
+ parser_state->err = err;
+ parser_state->err_info = err_info;
+ parser_state->pseudo_header = &phdr->pseudo_header.ascend;
+ parser_state->pkt_data = pd;
+
+ /*
+ * We haven't seen a time stamp yet.
+ */
+ parser_state->saw_timestamp = FALSE;
+ parser_state->timestamp = 0;
- bcur = 0;
- first_hexbyte = 0;
- wirelen = 0;
- caplen = 0;
+ parser_state->bcur = 0;
+ parser_state->first_hexbyte = 0;
+ parser_state->wirelen = 0;
+ parser_state->caplen = 0;
+
+ parser_state->secs = 0;
+ parser_state->usecs = 0;
/*
* Not all packets in a "wdd" dump necessarily have a "Cause an
@@ -464,125 +496,16 @@ run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd)
* phone number from the last call, and remember that for use
* when doing random access.
*/
- pseudo_header->call_num[0] = '\0';
-
- retval = yyparse(fh);
-
- caplen = bcur;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ retval = yyparse(scanner, parser_state, fh);
+ if (retval == 0)
+ parser_state->caplen = parser_state->bcur;
return retval;
}
-/* Parse the capture file.
- Returns:
- TRUE if we got a packet
- FALSE otherwise. */
-gboolean
-check_ascend(FILE_T fh, struct wtap_pkthdr *phdr)
-{
- guint8 buf[ASCEND_MAX_PKT_LEN];
-
- run_ascend_parser(fh, phdr, buf);
-
- /* if we got at least some data, return success even if the parser
- reported an error. This is because the debug header gives the number
- of bytes on the wire, not actually how many bytes are in the trace.
- We won't know where the data ends until we run into the next packet. */
- return (caplen != 0);
-}
-
-/* Parse the capture file.
- Returns:
- PARSED_RECORD if we got a packet
- PARSED_NONRECORD if the parser succeeded but didn't see a packet
- PARSE_FAILED if the parser failed. */
-parse_t
-parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
- guint length)
-{
- int retval;
-
- ws_buffer_assure_space(buf, length);
- retval = run_ascend_parser(fh, phdr, ws_buffer_start_ptr(buf));
-
- /* did we see any data (hex bytes)? if so, tip off ascend_seek()
- as to where to look for the next packet, if any. If we didn't,
- maybe this record was broken. Advance so we don't get into
- an infinite loop reading a broken trace. */
- if (first_hexbyte) {
- ascend->next_packet_seek_start = first_hexbyte;
- } else {
- /* Sometimes, a header will be printed but the data will be omitted, or
- worse -- two headers will be printed, followed by the data for each.
- Because of this, we need to be fairly tolerant of what we accept
- here. If we didn't find any hex bytes, skip over what we've read so
- far so we can try reading a new packet. */
- ascend->next_packet_seek_start = file_tell(fh);
- retval = 0;
- }
-
- /* if we got at least some data, return success even if the parser
- reported an error. This is because the debug header gives the number
- of bytes on the wire, not actually how many bytes are in the trace.
- We won't know where the data ends until we run into the next packet. */
- if (caplen) {
- if (! ascend->adjusted) {
- ascend->adjusted = TRUE;
- if (start_time != 0) {
- /*
- * Capture file contained a date and time.
- * We do this only if this is the very first packet we've seen -
- * i.e., if "ascend->adjusted" is false - because
- * if we get a date and time after the first packet, we can't
- * go back and adjust the time stamps of the packets we've already
- * processed, and basing the time stamps of this and following
- * packets on the time stamp from the file text rather than the
- * ctime of the capture file means times before this and after
- * this can't be compared.
- */
- ascend->inittime = start_time;
- }
- if (ascend->inittime > secs)
- ascend->inittime -= secs;
- }
- phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
- phdr->ts.secs = secs + ascend->inittime;
- phdr->ts.nsecs = usecs * 1000;
- phdr->caplen = caplen;
- phdr->len = wirelen;
-
- /*
- * For these types, the encapsulation we use is not WTAP_ENCAP_ASCEND,
- * so set the pseudo-headers appropriately for the type (WTAP_ENCAP_ISDN
- * or WTAP_ENCAP_ETHERNET).
- */
- switch(phdr->pseudo_header.ascend.type) {
- case ASCEND_PFX_ISDN_X:
- phdr->pseudo_header.isdn.uton = TRUE;
- phdr->pseudo_header.isdn.channel = 0;
- break;
-
- case ASCEND_PFX_ISDN_R:
- phdr->pseudo_header.isdn.uton = FALSE;
- phdr->pseudo_header.isdn.channel = 0;
- break;
-
- case ASCEND_PFX_ETHER:
- phdr->pseudo_header.eth.fcs_len = 0;
- break;
- }
- return PARSED_RECORD;
- }
-
- /* Didn't see any data. Still, perhaps the parser was happy. */
- if (retval)
- return PARSE_FAILED;
- else
- return PARSED_NONRECORD;
-}
-
void
-yyerror (FILE_T fh _U_, const char *s)
+yyerror (void *yyscanner, ascend_state_t *state _U_, FILE_T fh _U_, const char *s)
{
- ascend_parse_error = s;
+ ascendget_extra(yyscanner)->ascend_parse_error = s;
}
diff --git a/wiretap/ascend_scanner.l b/wiretap/ascend_scanner.l
index 950df9fd3d..24b539e512 100644
--- a/wiretap/ascend_scanner.l
+++ b/wiretap/ascend_scanner.l
@@ -1,4 +1,15 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
+ * We want to generate code that can be used by a reentrant parser
+ * generated by Bison or Berkeley YACC.
+ */
+%option bison-bridge
+
+/*
* We don't read interactively from the terminal.
*/
%option never-interactive
@@ -14,6 +25,19 @@
*/
%option prefix="ascend"
+/*
+ * 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
+
%{
/* ascend_scanner.l
*
@@ -42,14 +66,24 @@
#include "wtap-int.h"
#include "ascendtext.h"
-#include "ascend.h"
#include "ascend-int.h"
+#include "ascend.h"
#include "file_wrappers.h"
-#include "ascend_scanner_lex.h"
-FILE_T yy_fh;
-#define YY_INPUT(buf,result,max_size) { int c = file_getc(yy_fh); \
-result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); }
+#define YY_INPUT(buf,result,max_size) { \
+ ascend_state_t *parser_state = ascendget_extra(yyscanner); \
+ int c = file_getc(parser_state->fh); \
+ if (c == EOF) { \
+ *(parser_state->err) = file_error(parser_state->fh, \
+ parser_state->err_info); \
+ if (*(parser_state->err) == 0) \
+ *(parser_state->err) = WTAP_ERR_SHORT_READ; \
+ result = YY_NULL; \
+ } else { \
+ buf[0] = c; \
+ result = 1; \
+ } \
+}
#define NO_USER "<none>"
@@ -57,6 +91,17 @@ result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); }
#define YY_NO_UNISTD_H
#endif
+/*
+ * 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 ascendtext_alloc(size, yyscanner) (void *)malloc(size)
+#define ascendtext_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define ascendtext_free(ptr, yyscanner) free((char *)ptr)
%}
@@ -110,43 +155,43 @@ WDD_TYPE "type "[^\n\r\t ]+
<INITIAL,sc_gen_byte>{ETHER_PFX} {
BEGIN(sc_ether_direction);
- ascendlval.d = ASCEND_PFX_ETHER;
+ yylval->d = ASCEND_PFX_ETHER;
return ETHER_PREFIX;
}
<INITIAL,sc_gen_byte>{ISDN_XPFX} {
BEGIN(sc_isdn_call);
- ascendlval.d = ASCEND_PFX_ISDN_X;
+ yylval->d = ASCEND_PFX_ISDN_X;
return ISDN_PREFIX;
}
<INITIAL,sc_gen_byte>{ISDN_RPFX} {
BEGIN(sc_isdn_call);
- ascendlval.d = ASCEND_PFX_ISDN_R;
+ yylval->d = ASCEND_PFX_ISDN_R;
return ISDN_PREFIX;
}
<INITIAL,sc_gen_byte>{WAN_XPFX} {
BEGIN(sc_wds_user);
- ascendlval.d = ASCEND_PFX_WDS_X;
+ yylval->d = ASCEND_PFX_WDS_X;
return WDS_PREFIX;
}
<INITIAL,sc_gen_byte>{WAN_RPFX} {
BEGIN(sc_wds_user);
- ascendlval.d = ASCEND_PFX_WDS_R;
+ yylval->d = ASCEND_PFX_WDS_R;
return WDS_PREFIX;
}
<INITIAL,sc_gen_byte>{PPP_XPFX} {
BEGIN(sc_wds_user);
- ascendlval.d = ASCEND_PFX_WDS_X;
+ yylval->d = ASCEND_PFX_WDS_X;
return WDS_PREFIX;
}
<INITIAL,sc_gen_byte>{PPP_RPFX} {
BEGIN(sc_wds_user);
- ascendlval.d = ASCEND_PFX_WDS_R;
+ yylval->d = ASCEND_PFX_WDS_R;
return WDS_PREFIX;
}
@@ -161,26 +206,26 @@ WDD_TYPE "type "[^\n\r\t ]+
}
<sc_wds_user>[^:]{2,20} {
- char *atcopy = g_strdup(ascendtext);
- char colon = input();
- char after = input();
+ char *atcopy = g_strdup(yytext);
+ char colon = input(yyscanner);
+ char after = input(yyscanner);
int retval = STRING;
unput(after); unput(colon);
if (after != '(' && after != ' ') {
BEGIN(sc_wds_sess);
- if (pseudo_header != NULL) {
- g_strlcpy(pseudo_header->user, atcopy, ASCEND_MAX_STR_LEN);
+ if (yyextra->pseudo_header != NULL) {
+ g_strlcpy(yyextra->pseudo_header->user, atcopy, ASCEND_MAX_STR_LEN);
}
} else { /* We have a version 7 file */
BEGIN(sc_gen_task);
- if (pseudo_header != NULL) {
- g_strlcpy(pseudo_header->user, NO_USER, ASCEND_MAX_STR_LEN);
+ if (yyextra->pseudo_header != NULL) {
+ g_strlcpy(yyextra->pseudo_header->user, NO_USER, ASCEND_MAX_STR_LEN);
}
/* Are valid values ever > 2^32? If so we need to adjust YYSTYPE and a lot of */
/* upstream code accordingly. */
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
retval = DECNUM;
}
g_free (atcopy);
@@ -189,13 +234,13 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wds_sess>{D}* {
BEGIN(sc_gen_task);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_gen_task>(0x|0X)?{H}{2,8} {
BEGIN(sc_gen_time_s);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 16);
+ yylval->d = (guint32) strtoul(yytext, NULL, 16);
return HEXNUM;
}
@@ -205,24 +250,24 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_gen_time_s>{D}{1,10} {
BEGIN(sc_gen_time_u);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_gen_time_u>{D}{1,6} {
- char *atcopy = g_strdup(ascendtext);
+ char *atcopy = g_strdup(yytext);
BEGIN(sc_gen_octets);
/* only want the most significant 2 digits. convert to usecs */
if (strlen(atcopy) > 2)
atcopy[2] = '\0';
- ascendlval.d = (guint32) strtoul(atcopy, NULL, 10) * 10000;
+ yylval->d = (guint32) strtoul(atcopy, NULL, 10) * 10000;
g_free(atcopy);
return DECNUM;
}
<sc_gen_octets>{D}{1,10} {
BEGIN(sc_gen_counter);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
@@ -232,7 +277,7 @@ WDD_TYPE "type "[^\n\r\t ]+
}
<sc_gen_byte>{H}{2} {
- ascendlval.b = (guint8)(guint32) strtoul(ascendtext, NULL, 16);
+ yylval->b = (guint8)(guint32) strtoul(yytext, NULL, 16);
return HEXBYTE;
}
@@ -251,19 +296,19 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wdd_date_d>{D}{2} {
BEGIN(sc_wdd_date_m);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_wdd_date_m>{D}{2} {
BEGIN(sc_wdd_date_y);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_wdd_date_y>{D}{4} {
BEGIN(sc_wdd_time);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
@@ -274,19 +319,19 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wdd_time_h>{D}{2} {
BEGIN(sc_wdd_time_m);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_wdd_time_m>{D}{2} {
BEGIN(sc_wdd_time_s);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_wdd_time_s>{D}{2} {
BEGIN(sc_wdd_cause);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
@@ -297,8 +342,8 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wdd_callnum>{WDD_CALLNUM} {
BEGIN(sc_wdd_chunk);
- if (pseudo_header != NULL) {
- g_strlcpy(pseudo_header->call_num, ascendtext, ASCEND_MAX_STR_LEN);
+ if (yyextra->pseudo_header != NULL) {
+ g_strlcpy(yyextra->pseudo_header->call_num, yytext, ASCEND_MAX_STR_LEN);
}
return STRING;
}
@@ -310,7 +355,7 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wdd_chunknum>{H}{1,8} {
BEGIN(sc_wdd_type);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 16);
+ yylval->d = (guint32) strtoul(yytext, NULL, 16);
return HEXNUM;
}
@@ -330,12 +375,3 @@ task:|task|at|time:|octets { return KEYWORD; }
<<EOF>> { yyterminate(); }
(.|\n) ;
-
-%%
-
-void ascend_init_lexer(FILE_T fh)
-{
- yyrestart(0);
- yy_fh = fh;
- BEGIN(INITIAL);
-}
diff --git a/wiretap/ascendtext.c b/wiretap/ascendtext.c
index 7697c45e40..7259fa94bf 100644
--- a/wiretap/ascendtext.c
+++ b/wiretap/ascendtext.c
@@ -220,6 +220,8 @@ found:
wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info)
{
gint64 offset;
+ guint8 buf[ASCEND_MAX_PKT_LEN];
+ ascend_state_t parser_state;
ws_statb64 statbuf;
ascend_t *ascend;
@@ -236,8 +238,19 @@ wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info)
}
/* Do a trial parse of the first packet just found to see if we might really have an Ascend file */
- init_parse_ascend();
- if (!check_ascend(wth->fh, &wth->phdr)) {
+ if (run_ascend_parser(wth->fh, &wth->phdr, buf, &parser_state, err, err_info) != 0) {
+ if (*err != 0) {
+ /* An I/O error. */
+ return WTAP_OPEN_ERROR;
+ }
+ }
+
+ /* if we got at least some data, and didn't get an I/O error, return
+ success even if the parser reported an error. This is because the
+ debug header gives the number of bytes on the wire, not actually
+ how many bytes are in the trace. We won't know where the data ends
+ until we run into the next packet. */
+ if (parser_state.caplen == 0) {
return WTAP_OPEN_NOT_MINE;
}
@@ -280,11 +293,113 @@ wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info)
ascend->adjusted = FALSE;
wth->file_tsprec = WTAP_TSPREC_USEC;
- init_parse_ascend();
-
return WTAP_OPEN_MINE;
}
+typedef enum {
+ PARSED_RECORD,
+ PARSED_NONRECORD,
+ PARSE_FAILED
+} parse_t;
+
+/* Parse the capture file.
+ Returns:
+ PARSED_RECORD if we got a packet
+ PARSED_NONRECORD if the parser succeeded but didn't see a packet
+ PARSE_FAILED if the parser failed. */
+static parse_t
+parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
+ guint length, int *err, gchar **err_info)
+{
+ ascend_state_t parser_state;
+ int retval;
+
+ ws_buffer_assure_space(buf, length);
+ retval = run_ascend_parser(fh, phdr, ws_buffer_start_ptr(buf), &parser_state,
+ err, err_info);
+
+ /* did we see any data (hex bytes)? if so, tip off ascend_seek()
+ as to where to look for the next packet, if any. If we didn't,
+ maybe this record was broken. Advance so we don't get into
+ an infinite loop reading a broken trace. */
+ if (parser_state.first_hexbyte) {
+ ascend->next_packet_seek_start = parser_state.first_hexbyte;
+ } else {
+ /* Sometimes, a header will be printed but the data will be omitted, or
+ worse -- two headers will be printed, followed by the data for each.
+ Because of this, we need to be fairly tolerant of what we accept
+ here. If we didn't find any hex bytes, skip over what we've read so
+ far so we can try reading a new packet. */
+ ascend->next_packet_seek_start = file_tell(fh);
+ retval = 0;
+ }
+
+ /* if we got at least some data, return success even if the parser
+ reported an error. This is because the debug header gives the number
+ of bytes on the wire, not actually how many bytes are in the trace.
+ We won't know where the data ends until we run into the next packet. */
+ if (parser_state.caplen) {
+ if (! ascend->adjusted) {
+ ascend->adjusted = TRUE;
+ if (parser_state.saw_timestamp) {
+ /*
+ * Capture file contained a date and time.
+ * We do this only if this is the very first packet we've seen -
+ * i.e., if "ascend->adjusted" is false - because
+ * if we get a date and time after the first packet, we can't
+ * go back and adjust the time stamps of the packets we've already
+ * processed, and basing the time stamps of this and following
+ * packets on the time stamp from the file text rather than the
+ * ctime of the capture file means times before this and after
+ * this can't be compared.
+ */
+ ascend->inittime = parser_state.timestamp;
+ }
+ if (ascend->inittime > parser_state.secs)
+ ascend->inittime -= parser_state.secs;
+ }
+ phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
+ phdr->ts.secs = parser_state.secs + ascend->inittime;
+ phdr->ts.nsecs = parser_state.usecs * 1000;
+ phdr->caplen = parser_state.caplen;
+ phdr->len = parser_state.wirelen;
+
+ /*
+ * For these types, the encapsulation we use is not WTAP_ENCAP_ASCEND,
+ * so set the pseudo-headers appropriately for the type (WTAP_ENCAP_ISDN
+ * or WTAP_ENCAP_ETHERNET).
+ */
+ switch(phdr->pseudo_header.ascend.type) {
+ case ASCEND_PFX_ISDN_X:
+ phdr->pseudo_header.isdn.uton = TRUE;
+ phdr->pseudo_header.isdn.channel = 0;
+ break;
+
+ case ASCEND_PFX_ISDN_R:
+ phdr->pseudo_header.isdn.uton = FALSE;
+ phdr->pseudo_header.isdn.channel = 0;
+ break;
+
+ case ASCEND_PFX_ETHER:
+ phdr->pseudo_header.eth.fcs_len = 0;
+ break;
+ }
+ return PARSED_RECORD;
+ }
+
+ /* Didn't see any data. Still, perhaps the parser was happy. */
+ if (retval) {
+ if (*err == 0) {
+ /* Not a bad record, so a parse error. Return WTAP_ERR_BAD_FILE,
+ with the parse error as the error string. */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup((parser_state.ascend_parse_error != NULL) ? parser_state.ascend_parse_error : "parse error");
+ }
+ return PARSE_FAILED;
+ } else
+ return PARSED_NONRECORD;
+}
+
/* Read the next packet; called from wtap_read(). */
static gboolean ascend_read(wtap *wth, int *err, gchar **err_info,
gint64 *data_offset)
@@ -304,11 +419,8 @@ static gboolean ascend_read(wtap *wth, int *err, gchar **err_info,
if (offset == -1)
return FALSE;
if (parse_ascend(ascend, wth->fh, &wth->phdr, wth->frame_buffer,
- wth->snapshot_length) != PARSED_RECORD) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error");
+ wth->snapshot_length, err, err_info) != PARSED_RECORD)
return FALSE;
- }
*data_offset = offset;
return TRUE;
@@ -323,11 +435,8 @@ static gboolean ascend_seek_read(wtap *wth, gint64 seek_off,
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
if (parse_ascend(ascend, wth->random_fh, phdr, buf,
- wth->snapshot_length) != PARSED_RECORD) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error");
+ wth->snapshot_length, err, err_info) != PARSED_RECORD)
return FALSE;
- }
return TRUE;
}
diff --git a/wiretap/k12text.l b/wiretap/k12text.l
index 3ff7ca8610..4cdea9c951 100644
--- a/wiretap/k12text.l
+++ b/wiretap/k12text.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -19,10 +24,15 @@
%option noyywrap
/*
- * Prefix scanner routines with "K12Text_" rather than "yy", so this scanner
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="k12text_state_t *"
+
+/*
+ * Prefix scanner routines with "k12text_" rather than "yy", so this scanner
* can coexist with other scanners.
*/
-%option prefix="K12Text_"
+%option prefix="k12text_"
%option outfile="k12text.c"
@@ -45,6 +55,19 @@
/* %option noline */
/* %option debug */
+/*
+ * 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
+
%{
/* k12text.l
*
@@ -82,41 +105,64 @@
#include "file_wrappers.h"
#include <wsutil/buffer.h>
#include "k12.h"
-#include "k12text_lex.h"
#ifndef HAVE_UNISTD_H
#define YY_NO_UNISTD_H
#endif
-static guint g_h;
-static guint g_m;
-static guint g_s;
-static guint g_ms;
-static guint g_ns;
-static gint g_encap;
-static guint8 bb[WTAP_MAX_PACKET_SIZE];
-static guint ii;
-static gboolean is_k12text;
-static gboolean at_eof;
-static guint junk_chars;
-static void finalize_frame(void);
-static gchar* error_str;
-static guint64 file_bytes_read;
-static gboolean ok_frame;
-static FILE_T yy_fh;
-
-#define KERROR(text) do { error_str = g_strdup(text); yyterminate(); } while(0)
-#define SET_HOURS(text) g_h = (guint) strtoul(text,NULL,10)
-#define SET_MINUTES(text) g_m = (guint) strtoul(text,NULL,10)
-#define SET_SECONDS(text) g_s = (guint) strtoul(text,NULL,10)
-#define SET_MS(text) g_ms = (guint) strtoul(text,NULL,10)
-#define SET_NS(text) g_ns = (guint) strtoul(text,NULL,10)
-#define ADD_BYTE(text) do {if (ii >= WTAP_MAX_PACKET_SIZE) {KERROR("frame too large");} bb[ii++] = (guint8)strtoul(text,NULL,16); } while(0)
-#define FINALIZE_FRAME() finalize_frame()
+/*
+ * State kept by the scanner.
+ */
+typedef struct {
+ FILE_T fh;
+ int *err;
+ gchar **err_info;
+ int start_state;
+
+ guint g_h;
+ guint g_m;
+ guint g_s;
+ guint g_ms;
+ guint g_ns;
+ gint g_encap;
+ guint8 bb[WTAP_MAX_PACKET_SIZE];
+ guint ii;
+ gboolean is_k12text;
+ gboolean at_eof;
+ guint junk_chars;
+ gchar* error_str;
+ guint64 file_bytes_read;
+ gboolean ok_frame;
+} k12text_state_t;
+
+#define KERROR(text) do { yyextra->error_str = g_strdup(text); yyterminate(); } while(0)
+#define SET_HOURS(text) yyextra->g_h = (guint) strtoul(text,NULL,10)
+#define SET_MINUTES(text) yyextra->g_m = (guint) strtoul(text,NULL,10)
+#define SET_SECONDS(text) yyextra->g_s = (guint) strtoul(text,NULL,10)
+#define SET_MS(text) yyextra->g_ms = (guint) strtoul(text,NULL,10)
+#define SET_NS(text) yyextra->g_ns = (guint) strtoul(text,NULL,10)
+#define ADD_BYTE(text) do {if (yyextra->ii >= WTAP_MAX_PACKET_SIZE) {KERROR("frame too large");} yyextra->bb[yyextra->ii++] = (guint8)strtoul(text,NULL,16); } while(0)
+#define FINALIZE_FRAME() do { yyextra->ok_frame = TRUE; } while (0)
/*~ #define ECHO*/
-#define YY_USER_ACTION file_bytes_read += yyleng;
-#define YY_INPUT(buf,result,max_size) { int c = file_getc(yy_fh); result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); }
-
+#define YY_USER_ACTION yyextra->file_bytes_read += yyleng;
+#define YY_USER_INIT { \
+ k12text_state_t *scanner_state = k12text_get_extra(yyscanner); \
+ BEGIN(scanner_state->start_state); \
+}
+#define YY_INPUT(buf,result,max_size) { \
+ k12text_state_t *scanner_state = k12text_get_extra(yyscanner); \
+ int c = file_getc(scanner_state->fh); \
+ if (c == EOF) { \
+ *(scanner_state->err) = file_error(scanner_state->fh, \
+ scanner_state->err_info); \
+ if (*(scanner_state->err) == 0) \
+ *(scanner_state->err) = WTAP_ERR_SHORT_READ; \
+ result = YY_NULL; \
+ } else { \
+ buf[0] = c; \
+ result = 1; \
+ } \
+}
#define MAX_JUNK 400000
#define ECHO
@@ -134,6 +180,19 @@ typedef struct {
*/
gint64 next_frame_offset;
} k12text_t;
+
+/*
+ * 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 k12text_alloc(size, yyscanner) (void *)malloc(size)
+#define k12text_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define k12text_free(ptr, yyscanner) free((char *)ptr)
+
%}
start_timestamp \053[\055]{9}\053[\055]{15,100}\053[\055]{10,100}\053
oneormoredigits [0-9]+:
@@ -153,9 +212,9 @@ hdlc HDLC
%START MAGIC NEXT_FRAME HOURS MINUTES M2S SECONDS S2M MS M2N NS ENCAP STARTBYTES BYTE
%%
-<MAGIC>{start_timestamp} { is_k12text = TRUE; yyterminate(); }
+<MAGIC>{start_timestamp} { yyextra->is_k12text = TRUE; yyterminate(); }
-<MAGIC>. { if (++ junk_chars > MAX_JUNK) { is_k12text = FALSE; yyterminate(); } }
+<MAGIC>. { if (++ yyextra->junk_chars > MAX_JUNK) { yyextra->is_k12text = FALSE; yyterminate(); } }
<NEXT_FRAME>{start_timestamp} {BEGIN(HOURS); }
<HOURS>{oneormoredigits} { SET_HOURS(yytext); BEGIN(MINUTES); }
@@ -166,42 +225,39 @@ hdlc HDLC
<MS>{threedigits} { SET_MS(yytext); BEGIN(M2N); }
<M2N>{comma} { BEGIN(NS); }
<NS>{threedigits} { SET_NS(yytext); BEGIN(ENCAP);}
-<ENCAP>{eth} {g_encap = WTAP_ENCAP_ETHERNET; BEGIN(STARTBYTES); }
-<ENCAP>{mtp2} {g_encap = WTAP_ENCAP_MTP2; BEGIN(STARTBYTES); }
-<ENCAP>{sscop} {g_encap = WTAP_ENCAP_ATM_PDUS; BEGIN(STARTBYTES); }
-<ENCAP>{sscfnni} {g_encap = WTAP_ENCAP_MTP3; BEGIN(STARTBYTES); }
-<ENCAP>{hdlc} {g_encap = WTAP_ENCAP_CHDLC; BEGIN(STARTBYTES); }
+<ENCAP>{eth} {yyextra->g_encap = WTAP_ENCAP_ETHERNET; BEGIN(STARTBYTES); }
+<ENCAP>{mtp2} {yyextra->g_encap = WTAP_ENCAP_MTP2; BEGIN(STARTBYTES); }
+<ENCAP>{sscop} {yyextra->g_encap = WTAP_ENCAP_ATM_PDUS; BEGIN(STARTBYTES); }
+<ENCAP>{sscfnni} {yyextra->g_encap = WTAP_ENCAP_MTP3; BEGIN(STARTBYTES); }
+<ENCAP>{hdlc} {yyextra->g_encap = WTAP_ENCAP_CHDLC; BEGIN(STARTBYTES); }
<ENCAP,STARTBYTES>{start_bytes} { BEGIN(BYTE); }
<BYTE>{byte} { ADD_BYTE(yytext); }
<BYTE>{bytes_junk} ;
<BYTE>{end_bytes} { FINALIZE_FRAME(); yyterminate(); }
-. { if (++junk_chars > MAX_JUNK) { KERROR("too much junk"); } }
-<<EOF>> { at_eof = TRUE; yyterminate(); }
+. { if (++yyextra->junk_chars > MAX_JUNK) { KERROR("too much junk"); } }
+<<EOF>> { yyextra->at_eof = TRUE; yyterminate(); }
%%
-static void finalize_frame(void) {
- ok_frame = TRUE;
-}
-
/* Fill in pkthdr */
static gboolean
-k12text_set_headers(struct wtap_pkthdr *phdr, int *err, gchar **err_info)
+k12text_set_headers(struct wtap_pkthdr *phdr, k12text_state_t *state,
+ int *err, gchar **err_info)
{
phdr->rec_type = REC_TYPE_PACKET;
phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
- phdr->ts.secs = 946681200 + (3600*g_h) + (60*g_m) + g_s;
- phdr->ts.nsecs = 1000000*g_ms + 1000*g_ns;
+ phdr->ts.secs = 946681200 + (3600*state->g_h) + (60*state->g_m) + state->g_s;
+ phdr->ts.nsecs = 1000000*state->g_ms + 1000*state->g_ns;
- phdr->caplen = phdr->len = ii;
+ phdr->caplen = phdr->len = state->ii;
- phdr->pkt_encap = g_encap;
+ phdr->pkt_encap = state->g_encap;
/* The file-encap is WTAP_ENCAP_PER_PACKET */
- switch(g_encap) {
+ switch(state->g_encap) {
case WTAP_ENCAP_ETHERNET:
phdr->pseudo_header.eth.fcs_len = 0;
break;
@@ -236,30 +292,54 @@ k12text_set_headers(struct wtap_pkthdr *phdr, int *err, gchar **err_info)
/* used even when multiple files are open simultaneously (as for */
/* a file merge). */
-static void
-k12text_reset(FILE_T fh)
+static gboolean
+k12text_run_scanner(k12text_state_t *state, FILE_T fh, int start_state,
+ int *err, gchar **err_info)
{
- yy_fh = fh;
- yyrestart(0);
- g_encap = WTAP_ENCAP_UNKNOWN;
- ok_frame = FALSE;
- is_k12text = FALSE;
- at_eof = FALSE;
- junk_chars = 0;
- error_str = NULL;
- file_bytes_read=0;
- g_h=0;
- g_m=0;
- g_s=0;
- g_ns=0;
- g_ms=0;
- ii=0;
+ yyscan_t scanner = NULL;
+
+ if (yylex_init(&scanner) != 0) {
+ /* errno is set if this fails */
+ *err = errno;
+ *err_info = NULL;
+ return FALSE;
+ }
+ state->fh = fh;
+ state->err = err;
+ state->err_info = err_info;
+ state->start_state = start_state;
+
+ state->g_encap = WTAP_ENCAP_UNKNOWN;
+ state->ok_frame = FALSE;
+ state->is_k12text = FALSE;
+ state->at_eof = FALSE;
+ state->junk_chars = 0;
+ state->error_str = NULL;
+ state->file_bytes_read=0;
+ state->g_h=0;
+ state->g_m=0;
+ state->g_s=0;
+ state->g_ns=0;
+ state->g_ms=0;
+ state->ii=0;
+
+ /* Associate the state with the scanner */
+ k12text_set_extra(state, scanner);
+
+ yylex(scanner);
+ yylex_destroy(scanner);
+ if (*err != 0 && *err != WTAP_ERR_SHORT_READ) {
+ /* I/O error. */
+ return FALSE;
+ }
+ return TRUE;
}
static gboolean
k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset)
{
k12text_t *k12text = (k12text_t *)wth->priv;
+ k12text_state_t state;
/*
* We seek to the file position after the end of the previous frame
@@ -273,30 +353,29 @@ k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset)
if ( file_seek(wth->fh, k12text->next_frame_offset, SEEK_SET, err) == -1) {
return FALSE;
}
- k12text_reset(wth->fh); /* init lexer buffer and vars set by lexer */
-
- BEGIN(NEXT_FRAME);
- yylex();
+ if (!k12text_run_scanner(&state, wth->fh, NEXT_FRAME, err, err_info)) {
+ return FALSE;
+ }
- if (ok_frame == FALSE) {
- if (at_eof) {
+ if (state.ok_frame == FALSE) {
+ if (state.at_eof) {
*err = 0;
*err_info = NULL;
} else {
*err = WTAP_ERR_BAD_FILE;
- *err_info = error_str;
+ *err_info = state.error_str;
}
return FALSE;
}
- *data_offset = k12text->next_frame_offset; /* file position for beginning of this frame */
- k12text->next_frame_offset += file_bytes_read; /* file position after end of this frame */
+ *data_offset = k12text->next_frame_offset; /* file position for beginning of this frame */
+ k12text->next_frame_offset += state.file_bytes_read; /* file position after end of this frame */
- if (!k12text_set_headers(&wth->phdr, err, err_info))
+ if (!k12text_set_headers(&wth->phdr, &state, err, err_info))
return FALSE;
ws_buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
- memcpy(ws_buffer_start_ptr(wth->frame_buffer), bb, wth->phdr.caplen);
+ memcpy(ws_buffer_start_ptr(wth->frame_buffer), state.bb, wth->phdr.caplen);
return TRUE;
}
@@ -304,30 +383,31 @@ k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset)
static gboolean
k12text_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int *err, char **err_info)
{
+ k12text_state_t state;
+
if ( file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) {
return FALSE;
}
- k12text_reset(wth->random_fh); /* init lexer buffer and vars set by lexer */
-
- BEGIN(NEXT_FRAME);
- yylex();
+ if (!k12text_run_scanner(&state, wth->random_fh, NEXT_FRAME, err, err_info)) {
+ return FALSE;
+ }
- if (ok_frame == FALSE) {
+ if (state.ok_frame == FALSE) {
*err = WTAP_ERR_BAD_FILE;
- if (at_eof) {
+ if (state.at_eof) {
/* What happened ? The desired frame was previously read without a problem */
*err_info = g_strdup("Unexpected EOF (program error ?)");
} else {
- *err_info = error_str;
+ *err_info = state.error_str;
}
return FALSE;
}
- if (!k12text_set_headers(phdr, err, err_info))
+ if (!k12text_set_headers(phdr, &state, err, err_info))
return FALSE;
ws_buffer_assure_space(buf, phdr->caplen);
- memcpy(ws_buffer_start_ptr(buf), bb, phdr->caplen);
+ memcpy(ws_buffer_start_ptr(buf), state.bb, phdr->caplen);
return TRUE;
}
@@ -336,13 +416,17 @@ wtap_open_return_val
k12text_open(wtap *wth, int *err, gchar **err_info _U_)
{
k12text_t *k12text;
+ k12text_state_t state;
- k12text_reset(wth->fh); /* init lexer buffer and vars set by lexer */
-
- BEGIN(MAGIC);
- yylex();
+ if (!k12text_run_scanner(&state, wth->fh, MAGIC, err, err_info)) {
+ return WTAP_OPEN_ERROR;
+ }
- if (! is_k12text) return WTAP_OPEN_NOT_MINE;
+ if (!state.is_k12text) {
+ /* *err might have been set to WTAP_ERR_SHORT_READ */
+ *err = 0;
+ return WTAP_OPEN_NOT_MINE;
+ }
if ( file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
return WTAP_OPEN_ERROR;