2 * We don't use unput, so don't generate code for it.
7 * We don't read from the terminal.
9 %option never-interactive
12 * Prefix scanner routines with "uat_load_" rather than "yy", so this scanner
13 * can coexist with other scanners.
15 %option prefix="uat_load_"
23 * User Accessible Tables
24 * Mantain an array of user accessible data strucures
25 * One parser to fit them all
27 * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
29 * Wireshark - Network traffic analyzer
30 * By Gerald Combs <gerald@wireshark.org>
31 * Copyright 2001 Gerald Combs
33 * This program is free software; you can redistribute it and/or
34 * modify it under the terms of the GNU General Public License
35 * as published by the Free Software Foundation; either version 2
36 * of the License, or (at your option) any later version.
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
43 * You should have received a copy of the GNU General Public License
44 * along with this program; if not, write to the Free Software
45 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
59 #include <epan/emem.h>
61 #include "uat_load_lex.h"
62 #include <wsutil/file_util.h>
65 /* disable Windows VC compiler warning "signed/unsigned mismatch" associated */
66 /* with YY_INPUT code generated by flex versions such as 2.5.35. */
67 #pragma warning (disable:4018)
77 static gchar *parse_str;
78 static guint parse_str_pos;
80 #define ERROR(fmtd) do { error = ep_strdup_printf("%s:%d: %s",uat->filename,linenum,ep_strdup_printf fmtd); yyterminate(); } while(0)
84 if (uat->fields[colnum].cb.chk) { \
85 if ( ! uat->fields[colnum].cb.chk(record, ptr, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data, &err) ) { \
89 uat->fields[colnum].cb.set(record, ptr, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data);\
95 #define DUMP_FIELD(str) \
96 { guint i; printf("%s: %s='",str,uat->fields[colnum].name); for(i=0;i<len;i++) if (uat->fields[colnum].mode == PT_TXTMOD_HEXBYTES) { printf("%.2x ",((guint8*)ptr)[i]); } else putc(ptr[i],stdout); printf("'[%d]\n",len); }
98 #define DUMP(str) printf("%s\n",str)
100 #define DUMP_FIELD(s)
104 /* Modified version of YY_INPUT generated by Flex 2.91 */
105 #define YY_INPUT(buf,result,max_size) \
109 guint pslen = strlen(parse_str); \
110 if (parse_str_pos < pslen) \
112 n = pslen - parse_str_pos; \
113 if (n > max_size) n = max_size; \
114 memcpy(buf, parse_str + parse_str_pos, n); \
115 parse_str_pos += n; \
122 while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
124 if( errno != EINTR) \
126 YY_FATAL_ERROR( "input in flex scanner failed" ); \
136 * quoted_string below fails badly on "...\\"
137 * workarround in uat_save(), using /x5c and /x22
141 quoted_string \042([^\042]|\134\042)*\042
142 binstring ([0-9a-zA-Z][0-9a-zA-Z])*
144 newline [ \t]*[\r]?\n
148 %x START_OF_LINE NEXT_FIELD SEPARATOR END_OF_RECORD ERRORED
150 <START_OF_LINE,NEXT_FIELD>{ws} ;
151 <START_OF_LINE>{newline} linenum++;
152 <START_OF_LINE>{comment} linenum++;
154 <START_OF_LINE,NEXT_FIELD>{separator} {
158 DUMP_FIELD("empty->next");
162 if ( colnum >= uat->ncols ) {
163 ERROR(("more fields than required"));
169 <START_OF_LINE,NEXT_FIELD>{newline} {
178 <START_OF_LINE,NEXT_FIELD>{quoted_string} {
179 ptr = uat_undquote(yytext,yyleng,&len);
182 if (colnum < uat->ncols - 1) {
183 DUMP("quoted_str->s");
186 DUMP("quoted_str->eor");
191 <START_OF_LINE,NEXT_FIELD>{binstring} {
192 ptr = uat_unbinstring(yytext,yyleng,&len);
195 ERROR(("uneven hexstring for field %s",uat->fields[colnum].name));
198 if ( colnum < uat->ncols - 1 ) {
199 DUMP("binstring->s");
202 DUMP("binstring->eor");
207 <SEPARATOR>{separator} {
209 DUMP_FIELD("separator->next");
213 if ( colnum >= uat->ncols ) {
214 ERROR(("more fields than required"));
220 <SEPARATOR>{newline} {
222 ERROR(("expecting field %s in previous line",uat->fields[colnum].name));
226 ERROR(("unexpected char '%s' while looking for field %s",yytext,uat->fields[colnum].name));
229 <END_OF_RECORD>{separator} {
230 ERROR(("more fields than required"));
233 <END_OF_RECORD>{newline} {
235 const gchar* err = NULL;
239 DUMP_FIELD("newline->start");
243 rec = uat_add_record(uat, record);
246 uat->update_cb(rec,&err);
255 memset(record,0,uat->record_size);
261 ERROR(("unexpected char while looking for end of line"));
264 <ERRORED>{newline} { linenum++; BEGIN START_OF_LINE; }
267 {newline} { linenum++; ERROR(("incomplete record")); BEGIN START_OF_LINE; }
268 . { ERROR(("unexpected input")); }
275 gboolean uat_load(uat_t* uat_in, char** err) {
276 gchar* fname = uat_get_actual_filename(uat_in, FALSE);
287 if (!(yyin = ws_fopen(fname,"r"))) {
288 *err = g_strerror(errno);
295 record = g_malloc0(uat->record_size);
300 g_free(fname); /* we're done with the file name now */
306 uat->changed = FALSE;
311 *err = ep_strdup(error);
315 if (uat->post_update_cb)
316 uat->post_update_cb();
322 gboolean uat_load_str(uat_t* uat_in, char* entry, char** err) {
324 parse_str = g_strdup_printf("%s\n", entry); /* Records must end with a newline */
330 record = g_malloc0(uat->record_size);
346 *err = ep_strdup(error);
350 if (uat->post_update_cb)
351 uat->post_update_cb();
358 * We want to stop processing when we get to the end of the input.
359 * (%option noyywrap is not used because if used then
360 * some flex versions (eg: 2.5.35) generate code which causes
361 * warnings by the Windows VC compiler).