2 * We don't use input, so don't generate code for it.
7 * We don't use unput, so don't generate code for it.
12 * We don't read from the terminal.
14 %option never-interactive
17 * Prefix scanner routines with "K12Text_" rather than "yy", so this scanner
18 * can coexist with other scanners.
20 %option prefix="K12Text_"
22 %option outfile="k12text.c"
24 /* Options useful for debugging */
25 /* noline: Prevent generation of #line directives */
26 /* Seems to be required when using the */
27 /* Windows VS debugger so as to be able */
28 /* to properly step through the code and */
29 /* set breakpoints & etc using the */
30 /* k12text.c file rather than the */
32 /* XXX: %option noline gives an error message: */
33 /* "unrecognized %option: line" */
34 /* with flex 2.5.35; the --noline */
35 /* command-line option works OK. */
37 /* debug: Do output of "rule acceptance" info */
47 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
49 * This program is free software; you can redistribute it and/or
50 * modify it under the terms of the GNU General Public License
51 * as published by the Free Software Foundation; either version 2
52 * of the License, or (at your option) any later version.
54 * This program is distributed in the hope that it will be useful,
55 * but WITHOUT ANY WARRANTY; without even the implied warranty of
56 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57 * GNU General Public License for more details.
59 * You should have received a copy of the GNU General Public License
60 * along with this program; if not, write to the Free Software
61 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
66 * - fix timestamps after midnight
67 * - verify encapsulations
77 #include "file_wrappers.h"
78 #include <wsutil/buffer.h>
80 #include "k12text_lex.h"
83 #define YY_NO_UNISTD_H
92 static guint8 bb[WTAP_MAX_PACKET_SIZE];
94 static gboolean is_k12text;
95 static gboolean at_eof;
96 static guint junk_chars;
97 static void finalize_frame(void);
98 static gchar* error_str;
99 static guint64 file_bytes_read;
100 static gboolean ok_frame;
103 #define KERROR(text) do { error_str = g_strdup(text); yyterminate(); } while(0)
104 #define SET_HOURS(text) g_h = (guint) strtoul(text,NULL,10)
105 #define SET_MINUTES(text) g_m = (guint) strtoul(text,NULL,10)
106 #define SET_SECONDS(text) g_s = (guint) strtoul(text,NULL,10)
107 #define SET_MS(text) g_ms = (guint) strtoul(text,NULL,10)
108 #define SET_NS(text) g_ns = (guint) strtoul(text,NULL,10)
109 #define ADD_BYTE(text) do {if (ii >= WTAP_MAX_PACKET_SIZE) {KERROR("frame too large");} bb[ii++] = (guint8)strtoul(text,NULL,16); } while(0)
110 #define FINALIZE_FRAME() finalize_frame()
112 #define YY_USER_ACTION file_bytes_read += yyleng;
113 #define YY_INPUT(buf,result,max_size) { int c = file_getc(yy_fh); result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); }
115 #define MAX_JUNK 400000
119 * Private per-file data.
123 * The file position after the end of the previous frame processed by
126 * We need to keep this around, and seek to it at the beginning of
127 * each call to k12text_read(), since the lexer undoubtedly did some
128 * amount of look-ahead when processing the previous frame.
130 gint64 next_frame_offset;
133 start_timestamp \053[\055]{9}\053[\055]{15,100}\053[\055]{10,100}\053
134 oneormoredigits [0-9]+:
138 threedigits [0-9][0-9][0-9]
139 start_bytes \174\060\040\040\040\174
140 bytes_junk \174[A-F0-9][A-F0-9\040][A-F0-9\040][A-F0-9\040]\174
141 byte [a-f0-9][a-f0-9]\174
142 end_bytes \015?\012\015?\012
149 %START MAGIC NEXT_FRAME HOURS MINUTES M2S SECONDS S2M MS M2N NS ENCAP STARTBYTES BYTE
151 <MAGIC>{start_timestamp} { is_k12text = TRUE; yyterminate(); }
153 <MAGIC>. { if (++ junk_chars > MAX_JUNK) { is_k12text = FALSE; yyterminate(); } }
155 <NEXT_FRAME>{start_timestamp} {BEGIN(HOURS); }
156 <HOURS>{oneormoredigits} { SET_HOURS(yytext); BEGIN(MINUTES); }
157 <MINUTES>{twodigits} { SET_MINUTES(yytext); BEGIN(M2S);}
158 <M2S>{colon} { BEGIN(SECONDS);}
159 <SECONDS>{twodigits} { SET_SECONDS(yytext); BEGIN(S2M); }
160 <S2M>{comma} { BEGIN(MS); }
161 <MS>{threedigits} { SET_MS(yytext); BEGIN(M2N); }
162 <M2N>{comma} { BEGIN(NS); }
163 <NS>{threedigits} { SET_NS(yytext); BEGIN(ENCAP);}
164 <ENCAP>{eth} {g_encap = WTAP_ENCAP_ETHERNET; BEGIN(STARTBYTES); }
165 <ENCAP>{mtp2} {g_encap = WTAP_ENCAP_MTP2; BEGIN(STARTBYTES); }
166 <ENCAP>{sscop} {g_encap = WTAP_ENCAP_ATM_PDUS; BEGIN(STARTBYTES); }
167 <ENCAP>{sscfnni} {g_encap = WTAP_ENCAP_MTP3; BEGIN(STARTBYTES); }
168 <ENCAP>{hdlc} {g_encap = WTAP_ENCAP_CHDLC; BEGIN(STARTBYTES); }
169 <ENCAP,STARTBYTES>{start_bytes} { fprintf(stderr, "OUCH: %s\b", yytext); BEGIN(BYTE); }
170 <BYTE>{byte} { ADD_BYTE(yytext); }
172 <BYTE>{end_bytes} { FINALIZE_FRAME(); yyterminate(); }
174 . { if (++junk_chars > MAX_JUNK) { KERROR("too much junk"); } }
175 <<EOF>> { at_eof = TRUE; yyterminate(); }
179 static void finalize_frame(void) {
186 k12text_set_headers(struct wtap_pkthdr *phdr, int *err, gchar **err_info)
188 phdr->rec_type = REC_TYPE_PACKET;
189 phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
191 phdr->ts.secs = 946681200 + (3600*g_h) + (60*g_m) + g_s;
192 phdr->ts.nsecs = 1000000*g_ms + 1000*g_ns;
194 phdr->caplen = phdr->len = ii;
196 phdr->pkt_encap = g_encap;
198 /* The file-encap is WTAP_ENCAP_PER_PACKET */
200 case WTAP_ENCAP_ETHERNET:
201 phdr->pseudo_header.eth.fcs_len = 0;
203 case WTAP_ENCAP_MTP3:
204 case WTAP_ENCAP_CHDLC:
205 /* no pseudo_header to fill in for these types */
207 case WTAP_ENCAP_MTP2: /* not (yet) supported */
208 /* XXX: I don't know how to fill in the */
209 /* pseudo_header for these types. */
210 *err = WTAP_ERR_UNSUPPORTED;
211 *err_info = g_strdup("k12text: MTP2 packets not yet supported");
213 case WTAP_ENCAP_ATM_PDUS: /* not (yet) supported */
214 /* XXX: I don't know how to fill in the */
215 /* pseudo_header for these types. */
216 *err = WTAP_ERR_UNSUPPORTED;
217 *err_info = g_strdup("k12text: SSCOP packets not yet supported");
220 *err = WTAP_ERR_UNSUPPORTED;
221 *err_info = g_strdup("k12text: unknown encapsulation type");
227 /* Note: k12text_reset is called each time data is to be processed from */
228 /* a file. This ensures that no "state" from a previous read is */
229 /* used (such as the lexer look-ahead buffer, file_handle, file */
230 /* position and so on. This allows a single lexer buffer to be */
231 /* used even when multiple files are open simultaneously (as for */
235 k12text_reset(FILE_T fh)
239 g_encap = WTAP_ENCAP_UNKNOWN;
255 k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset)
257 k12text_t *k12text = (k12text_t *)wth->priv;
260 * We seek to the file position after the end of the previous frame
261 * processed by k12text_read(), since the lexer undoubtedly did some
262 * amount of look-ahead when processing the previous frame.
264 * We also clear out any lexer state (eg: look-ahead buffer) and
265 * init vars set by lexer.
268 if ( file_seek(wth->fh, k12text->next_frame_offset, SEEK_SET, err) == -1) {
271 k12text_reset(wth->fh); /* init lexer buffer and vars set by lexer */
276 if (ok_frame == FALSE) {
281 *err = WTAP_ERR_BAD_FILE;
282 *err_info = error_str;
287 *data_offset = k12text->next_frame_offset; /* file position for beginning of this frame */
288 k12text->next_frame_offset += file_bytes_read; /* file position after end of this frame */
290 if (!k12text_set_headers(&wth->phdr, err, err_info))
293 ws_buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
294 memcpy(ws_buffer_start_ptr(wth->frame_buffer), bb, wth->phdr.caplen);
300 k12text_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int *err, char **err_info)
302 if ( file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) {
305 k12text_reset(wth->random_fh); /* init lexer buffer and vars set by lexer */
310 if (ok_frame == FALSE) {
311 *err = WTAP_ERR_BAD_FILE;
313 /* What happened ? The desired frame was previously read without a problem */
314 *err_info = g_strdup("Unexpected EOF (program error ?)");
316 *err_info = error_str;
321 if (!k12text_set_headers(phdr, err, err_info))
324 ws_buffer_assure_space(buf, phdr->caplen);
325 memcpy(ws_buffer_start_ptr(buf), bb, phdr->caplen);
331 k12text_open(wtap *wth, int *err, gchar **err_info _U_)
335 k12text_reset(wth->fh); /* init lexer buffer and vars set by lexer */
340 if (! is_k12text) return WTAP_OPEN_NOT_MINE;
342 if ( file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
343 return WTAP_OPEN_ERROR;
346 k12text = (k12text_t *)g_malloc(sizeof(k12text_t));
347 wth->priv = (void *)k12text;
348 k12text->next_frame_offset = 0;
349 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_K12TEXT;
350 wth->file_encap = WTAP_ENCAP_PER_PACKET;
351 wth->snapshot_length = 0;
352 wth->subtype_read = k12text_read;
353 wth->subtype_seek_read = k12text_seek_read;
354 wth->file_tsprec = WTAP_TSPREC_NSEC;
356 return WTAP_OPEN_MINE;
360 static const struct { int e; const char* s; } encaps[] = {
361 { WTAP_ENCAP_ETHERNET, "ETHER" },
362 { WTAP_ENCAP_MTP2, "MTP-L2" },
363 { WTAP_ENCAP_ATM_PDUS, "SSCOP" },
364 { WTAP_ENCAP_MTP3, "SSCF" },
365 { WTAP_ENCAP_CHDLC, "HDLC" },
371 k12text_dump(wtap_dumper *wdh _U_, const struct wtap_pkthdr *phdr,
372 const guint8 *pd, int *err) {
373 #define K12BUF_SIZE 196808
375 size_t left = K12BUF_SIZE;
385 /* Don't write anything bigger than we're willing to read. */
386 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
387 *err = WTAP_ERR_PACKET_TOO_LARGE;
392 for(i=0; encaps[i].s; i++) {
393 if (phdr->pkt_encap == encaps[i].e) {
394 str_enc = encaps[i].s;
398 if (str_enc == NULL) {
400 * That encapsulation type is not supported. Fail.
402 *err = WTAP_ERR_UNWRITABLE_ENCAP;
406 buf = (char *)g_malloc(K12BUF_SIZE);
409 ms = phdr->ts.nsecs / 1000000;
410 ns = (phdr->ts.nsecs - (1000000*ms))/1000;
412 tmp = gmtime(&phdr->ts.secs);
414 g_snprintf(p, 90, "+---------+---------------+----------+\r\nXX:XX:XX,");
416 strftime(p, 90, "+---------+---------------+----------+\r\n%H:%M:%S,", tmp);
421 wl = g_snprintf(p, (gulong)left, "%.3d,%.3d %s\r\n|0 |", ms, ns, str_enc);
425 for(i = 0; i < phdr->caplen && left > 2; i++) {
426 wl = g_snprintf(p, (gulong)left, "%.2x|", pd[i]);
431 wl = g_snprintf(p, (gulong)left, "\r\n\r\n");
434 ret = wtap_dump_file_write(wdh, buf, K12BUF_SIZE - left, err);
442 k12text_dump_open(wtap_dumper *wdh, int *err _U_)
444 wdh->subtype_write = k12text_dump;
450 k12text_dump_can_write_encap(int encap)
453 case WTAP_ENCAP_PER_PACKET:
454 case WTAP_ENCAP_ETHERNET:
455 case WTAP_ENCAP_MTP3:
456 case WTAP_ENCAP_CHDLC:
458 case WTAP_ENCAP_MTP2:
459 case WTAP_ENCAP_ATM_PDUS:
461 return WTAP_ERR_UNWRITABLE_ENCAP;
466 * We want to stop processing when we get to the end of the input.
467 * (%option noyywrap is not used because if used then
468 * some flex versions (eg: 2.5.35) generate code which causes
469 * warnings by the Windows VC compiler).