Add a script as a front-end for Flex, to work around various problems,
[jelmer/wireshark.git] / wiretap / k12text.l
1 /*
2  * We want to stop processing when we get to the end of the input.
3  */
4 %option noyywrap
5
6 /*
7  * We don't use unput, so don't generate code for it.
8  */
9 %option nounput 
10
11 /*
12  * We don't read from the terminal.
13  */
14 %option never-interactive
15
16 /*
17  * Prefix scanner routines with "K12Text_" rather than "yy", so this scanner
18  * can coexist with other scanners.
19  */
20 %option prefix="K12Text_"
21
22 %option outfile="k12text.c"
23
24 %{
25 /* k12text.l
26  *
27  * $Id$
28  *
29  * Wiretap Library
30  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
31  *
32  * This program is free software; you can redistribute it and/or
33  * modify it under the terms of the GNU General Public License
34  * as published by the Free Software Foundation; either version 2
35  * of the License, or (at your option) any later version.
36  *
37  * This program is distributed in the hope that it will be useful,
38  * but WITHOUT ANY WARRANTY; without even the implied warranty of
39  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40  * GNU General Public License for more details.
41  *
42  * You should have received a copy of the GNU General Public License
43  * along with this program; if not, write to the Free Software
44  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
45  */
46  
47  /* 
48   * TODO:
49   *   - fix timestamps after midnight
50   *   - verify encapsulations
51   */
52
53 #ifdef HAVE_CONFIG_H
54 #include "config.h"
55 #endif
56 #include <stdlib.h>
57 #include <string.h>
58 #include <errno.h>
59 #include <time.h>
60 #include "wtap-int.h"
61 #include "wtap.h"
62 #include "file_wrappers.h"
63 #include "buffer.h"
64 #include "k12.h"
65 #include "k12text_lex.h"
66
67 static guint h;
68 static guint m;
69 static guint s;
70 static guint ms;
71 static guint ns;
72 static gint encap;
73 static guint8 b[65536];
74 static guint i;
75 static gboolean is_k12text;
76 static gboolean at_eof;
77 static guint junk_chars = 0;
78 static void finalize_frame(void);
79 static const gchar* error_str;
80 static gint64 cum_offset;
81 static gboolean ok_frame;
82 static FILE_T yy_fh;
83
84 #define RESET() do { ok_frame = FALSE; h=0; m=0; s=0; ns=0; ms=0; i=0; is_k12text=FALSE; junk_chars = 0; error_str = NULL; } while(0)
85
86 #define KERROR(text) do { error_str = (text); yyterminate(); } while(0)
87 #define START_PACKET RESET
88 #define SET_HOURS(text) h = strtoul(text,NULL,10)
89 #define SET_MINUTES(text) m = strtoul(text,NULL,10)
90 #define SET_SECONDS(text) s = strtoul(text,NULL,10)
91 #define SET_MS(text) ms = strtoul(text,NULL,10)
92 #define SET_NS(text) ns = strtoul(text,NULL,10)
93 #define SET_ENCAP(text) set_encap(text)
94 #define ADD_BYTE(text) do {if (i >= 65536) {KERROR("frame too large");} b[i++] = (guint8)strtoul(text,NULL,16); } while(0)
95 #define FINALIZE_FRAME() finalize_frame()
96 //~ #define ECHO
97 #define YY_USER_ACTION cum_offset += yyleng;
98 #define YY_INPUT(buf,result,max_size) { int c = file_getc(yy_fh);  result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); } 
99
100 #define MAX_JUNK 400000
101 #define ECHO
102 %}
103 start_timestamp \053[\055]{9}\053[\055]{15,100}\053[\055]{10,100}\053
104 oneormoredigits [0-9]+:
105 twodigits [0-9][0-9]
106 colon :
107 comma ,
108 threedigits [0-9][0-9][0-9]
109 start_bytes \174\060\040\040\040\174
110 bytes_junk \174[A-F0-9][A-F0-9\040][A-F0-9\040][A-F0-9\040]\174
111 byte [a-f0-9][a-f0-9]\174
112 end_bytes \015\012\015\012
113 eth ETHER
114 mtp2 MTP-L2
115 sscop SSCOP
116 sscfnni SSCF
117 hdlc HDLC
118
119 %START NEXT_FRAME HOURS H2M MINUTES M2S S2M MS M2N NS ENCAP STARTBYTES BYTE ENDBYTES MAGIC SECONDS
120 %%
121 <MAGIC>{start_timestamp}  { is_k12text = TRUE; yyterminate(); }
122
123 <MAGIC>. { if (++ junk_chars > MAX_JUNK) { is_k12text = FALSE;  yyterminate(); } }
124
125 <NEXT_FRAME>{start_timestamp} { START_PACKET(); BEGIN(HOURS); }
126 <HOURS>{oneormoredigits} { SET_HOURS(yytext); BEGIN(MINUTES); }
127 <MINUTES>{twodigits} { SET_MINUTES(yytext); BEGIN(M2S);}
128 <M2S>{colon} { BEGIN(SECONDS);}
129 <SECONDS>{twodigits} { SET_SECONDS(yytext); BEGIN(S2M); }
130 <S2M>{comma}  { BEGIN(MS); }
131 <MS>{threedigits} { SET_MS(yytext); BEGIN(M2N);  }
132 <M2N>{comma}  { BEGIN(NS); }
133 <NS>{threedigits} { SET_NS(yytext); BEGIN(ENCAP);}
134 <ENCAP>{eth} {encap = WTAP_ENCAP_ETHERNET; BEGIN(STARTBYTES); }
135 <ENCAP>{mtp2} {encap = WTAP_ENCAP_MTP2; BEGIN(STARTBYTES); }
136 <ENCAP>{sscop} {encap = WTAP_ENCAP_ATM_PDUS; BEGIN(STARTBYTES); }
137 <ENCAP>{sscfnni} {encap = WTAP_ENCAP_MTP3; BEGIN(STARTBYTES); }
138 <ENCAP>{hdlc} {encap = WTAP_ENCAP_CHDLC; BEGIN(STARTBYTES); }
139 <ENCAP,STARTBYTES>{start_bytes} { BEGIN(BYTE); }
140 <BYTE>{byte} { ADD_BYTE(yytext); }
141 <BYTE>{bytes_junk} ;
142 <BYTE>{end_bytes} { FINALIZE_FRAME(); yyterminate(); }
143
144 . {  if (++junk_chars > MAX_JUNK) { KERROR("too much junk");  } }
145 <<EOF>> { at_eof = TRUE; yyterminate(); }
146
147 %%
148
149 static void finalize_frame(void) {
150         ok_frame = TRUE;
151 }
152
153 static gboolean k12text_read(wtap *wth, int *err, const gchar ** err_info _U_, gint64 *data_offset) {
154         gint64 start_offset = cum_offset;
155         
156         encap = WTAP_ENCAP_UNKNOWN;
157         ok_frame = FALSE;
158         
159         BEGIN(NEXT_FRAME);
160         yylex();
161         
162         if (ok_frame == FALSE) {
163                 if (at_eof) {
164                         *err_info = NULL;
165                         *err = 0;
166                 } else {
167                         *err_info = error_str;
168                         *err = WTAP_ERR_BAD_RECORD;
169                 }
170                 return FALSE;
171         }
172         
173         wth->data_offset = *data_offset = start_offset ;
174         
175         
176         wth->phdr.ts.secs = 946681200 + (3600*h) + (60*m) + s;
177         wth->phdr.ts.nsecs = 1000000*ms + 1000*ns;
178         
179         wth->phdr.caplen = wth->phdr.len = i;
180         
181         wth->phdr.pkt_encap = encap;
182         
183         buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
184         memcpy(buffer_start_ptr(wth->frame_buffer), b, wth->phdr.caplen);
185
186         return TRUE;
187 }
188
189 static gboolean k12text_seek_read(wtap *wth, gint64 seek_off, union wtap_pseudo_header *pseudo_header _U_, guchar *pd, int length, int *err, const gchar **err_info) {
190         gint64 save_offset = cum_offset;
191
192         ok_frame = FALSE;
193         RESET();
194
195         yy_fh = wth->random_fh;
196
197
198         if ( file_seek(yy_fh, seek_off, SEEK_SET, err) == -1) {
199                 return FALSE;
200         }
201         
202         BEGIN(NEXT_FRAME);
203         yylex();
204
205         if (ok_frame == FALSE) {
206                 *err_info = error_str;
207                 *err = WTAP_ERR_BAD_RECORD;
208                 return FALSE;
209         }
210                 
211         memcpy(pd, b, length);
212
213         cum_offset = save_offset ;
214         return TRUE;
215 }
216
217 static void k12text_close(wtap *wth _U_) {
218         (void)0;
219 }
220
221 int k12text_open(wtap *wth, int *err, gchar **err_info _U_) {
222         
223         cum_offset = 0;
224         
225         RESET();
226         yy_fh = wth->fh;
227         BEGIN(MAGIC);
228         yylex();
229
230         if (! is_k12text) return 0;
231         
232         if ( file_seek(yy_fh, 0, SEEK_SET, err) == -1) {
233                 return -1;
234         }
235
236         cum_offset = 0;
237
238         wth->data_offset = 0;
239         wth->file_type = WTAP_FILE_K12TEXT;
240         wth->file_encap = WTAP_ENCAP_PER_PACKET;
241         wth->snapshot_length = 0;
242         wth->subtype_read = (void*)k12text_read;
243         wth->subtype_seek_read = (void*)k12text_seek_read;
244         wth->subtype_close = k12text_close;
245         wth->capture.generic  = NULL;
246         wth->tsprecision = WTAP_FILE_TSPREC_NSEC;    
247
248         return 1;
249 }
250
251
252 static const struct { int e; const char* s; } encaps[] = {
253         { WTAP_ENCAP_ETHERNET, "ETHER" },
254         { WTAP_ENCAP_MTP2, "MTP-L2" },
255         { WTAP_ENCAP_ATM_PDUS, "SSCOP" },
256         { WTAP_ENCAP_MTP3, "SSCF" },
257         { WTAP_ENCAP_CHDLC, "HDLC" },
258         /* ... */
259         { WTAP_ENCAP_UNKNOWN, "UNKNOWN" },
260         { 0, NULL }
261 };
262
263 static gboolean k12text_dump(wtap_dumper *wdh _U_, const struct wtap_pkthdr *phdr,
264                          const union wtap_pseudo_header *pseudo_header _U_,
265                          const guchar *pd, int *err _U_) {
266         char buf[196808];
267         char* p=buf;
268         const char* str_enc = "";
269         guint i;
270         guint ns;
271         guint ms;
272         
273         ms = phdr->ts.nsecs / 1000000;
274         ns = (phdr->ts.nsecs - (1000000*ms))/1000;
275
276         for(i=0; encaps[i].s; i++) {
277                 str_enc = encaps[i].s;
278                 if (phdr->pkt_encap == encaps[i].e) break;
279         }
280         
281         strftime(p,90,"+---------+---------------+----------+\r\n%H:%M:%S,",gmtime(&phdr->ts.secs));
282         p+= strlen(p);
283         sprintf(p,"%.3d,%.3d   %s\r\n|0   |",ms,ns,str_enc);
284         p+= strlen(p);
285
286         for(i=0;i < phdr->caplen; i++) {
287                 sprintf(p,"%.2x|",pd[i]);
288                 p+= 3;
289         }
290         
291         sprintf(p,"\r\n\r\n");
292         
293         fwrite(buf, 1, strlen(buf), wdh->fh);
294         
295         return TRUE;
296 }
297
298
299 static gboolean k12text_dump_close(wtap_dumper *wdh _U_ , int *err _U_) {
300         return TRUE;
301 }
302
303 gboolean k12text_dump_open(wtap_dumper *wdh, gboolean cant_seek, int *err) {
304     
305     if (cant_seek) {
306         *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
307         return FALSE;
308     }
309     
310     wdh->subtype_write = k12text_dump;
311     wdh->subtype_close = k12text_dump_close;
312
313     return TRUE;
314 }
315
316 int k12text_dump_can_write_encap(int encap) {
317     switch (encap) {
318         case WTAP_ENCAP_PER_PACKET:
319         case WTAP_ENCAP_ETHERNET:
320         case WTAP_ENCAP_MTP2:
321         case WTAP_ENCAP_ATM_PDUS:
322         case WTAP_ENCAP_MTP3:
323         case WTAP_ENCAP_CHDLC:
324         case WTAP_ENCAP_UNKNOWN:
325                 return 0;
326         default:
327                 return WTAP_ERR_UNSUPPORTED_ENCAP;
328     }
329 }