aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2016-03-30 18:44:01 -0700
committerGuy Harris <guy@alum.mit.edu>2016-04-03 22:21:29 +0000
commit59816ef00c6dd09532d80b393ba03f8194aba236 (patch)
treef5e84c67ebe0e69542db94d56db70fa476c0db6c /wiretap
parente42a43bc58a36848316adae19981878a5f430c46 (diff)
Make the Flex scanners and YACC parser in libraries reentrant.
master-branch libpcap now generates a reentrant Flex scanner and Bison/Berkeley YACC parser for capture filter expressions, so it requires versions of Flex and Bison/Berkeley YACC that support that. We might as well do the same. For libwiretap, it means we could actually have multiple K12 text or Ascend/Lucent text files open at the same time. For libwireshark, it might not be as useful, as we only read configuration files at startup (which should only happen once, in one thread) or on demand (in which case, if we ever support multiple threads running libwireshark, we'd need a mutex to ensure that only one file reads it), but it's still the right thing to do. We also require a version of Flex that can write out a header file, so we change the runlex script to generate the header file ourselves. This means we require a version of Flex new enough to support --header-file. Clean up some other stuff encountered in the process. Change-Id: Id23078c6acea549a52fc687779bb55d715b55c16 Reviewed-on: https://code.wireshark.org/review/14719 Reviewed-by: Guy Harris <guy@alum.mit.edu>
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;