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 "uat_load_" rather than "yy", so this scanner
18 * can coexist with other scanners.
20 %option prefix="uat_load_"
28 * User Accessible Tables
29 * Mantain an array of user accessible data strucures
30 * One parser to fit them all
32 * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
34 * Wireshark - Network traffic analyzer
35 * By Gerald Combs <gerald@wireshark.org>
36 * Copyright 2001 Gerald Combs
38 * This program is free software; you can redistribute it and/or
39 * modify it under the terms of the GNU General Public License
40 * as published by the Free Software Foundation; either version 2
41 * of the License, or (at your option) any later version.
43 * This program is distributed in the hope that it will be useful,
44 * but WITHOUT ANY WARRANTY; without even the implied warranty of
45 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46 * GNU General Public License for more details.
48 * You should have received a copy of the GNU General Public License
49 * along with this program; if not, write to the Free Software
50 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
62 #include <epan/emem.h>
64 #include "uat_load_lex.h"
65 #include <wsutil/file_util.h>
68 /* disable Windows VC compiler warning "signed/unsigned mismatch" associated */
69 /* with YY_INPUT code generated by flex versions such as 2.5.35. */
70 #pragma warning (disable:4018)
74 static gboolean valid_record;
81 static gchar *parse_str;
82 static guint parse_str_pos;
84 #define ERROR(fmtd) do { error = ep_strdup_printf("%s:%d: %s",uat->filename,linenum,ep_strdup_printf fmtd); yyterminate(); } while(0)
87 { const gchar* errx; \
88 if (uat->fields[colnum].cb.chk) { \
89 if ( ! uat->fields[colnum].cb.chk(record, ptrx, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data, &errx) ) { \
90 error = ep_strdup_printf("%s:%d: %s",uat->filename,linenum,ep_strdup_printf("%s",errx)); \
91 valid_record = FALSE; \
94 uat->fields[colnum].cb.set(record, ptrx, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data);\
100 #define DUMP_FIELD(str) \
101 { 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*)ptrx)[i]); } else putc(ptrx[i],stdout); printf("'[%d]\n",len); }
103 #define DUMP(str) printf("%s\n",str)
105 #define DUMP_FIELD(s)
109 /* Modified version of YY_INPUT generated by Flex 2.91 */
110 #define YY_INPUT(buf,result,max_size) \
114 guint pslen = strlen(parse_str); \
115 if (parse_str_pos < pslen) \
117 n = pslen - parse_str_pos; \
118 if (n > max_size) n = max_size; \
119 memcpy(buf, parse_str + parse_str_pos, n); \
120 parse_str_pos += n; \
127 while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
129 if( errno != EINTR) \
131 YY_FATAL_ERROR( "input in flex scanner failed" ); \
141 * quoted_string below fails badly on "...\\"
142 * workarround in uat_save(), using /x5c and /x22
146 quoted_string \042([^\042]|\134\042)*\042
147 binstring ([0-9a-zA-Z][0-9a-zA-Z])*
149 newline [ \t]*[\r]?\n
153 %x START_OF_LINE NEXT_FIELD SEPARATOR END_OF_RECORD ERRORED
155 <START_OF_LINE,NEXT_FIELD>{ws} ;
156 <START_OF_LINE>{newline} linenum++;
157 <START_OF_LINE>{comment} linenum++;
159 <START_OF_LINE,NEXT_FIELD>{separator} {
163 DUMP_FIELD("empty->next");
167 if ( colnum >= uat->ncols ) {
168 ERROR(("more fields than required"));
174 <START_OF_LINE,NEXT_FIELD>{newline} {
183 <START_OF_LINE,NEXT_FIELD>{quoted_string} {
184 ptrx = uat_undquote(yytext,yyleng,&len);
187 if (colnum < uat->ncols - 1) {
188 DUMP("quoted_str->s");
191 DUMP("quoted_str->eor");
196 <START_OF_LINE,NEXT_FIELD>{binstring} {
197 ptrx = uat_unbinstring(yytext,yyleng,&len);
200 ERROR(("uneven hexstring for field %s",uat->fields[colnum].name));
203 if ( colnum < uat->ncols - 1 ) {
204 DUMP("binstring->s");
207 DUMP("binstring->eor");
212 <SEPARATOR>{separator} {
214 DUMP_FIELD("separator->next");
218 if ( colnum >= uat->ncols ) {
219 ERROR(("more fields than required"));
225 <SEPARATOR>{newline} {
227 ERROR(("expecting field %s in previous line",uat->fields[colnum].name));
231 ERROR(("unexpected char '%s' while looking for field %s",yytext,uat->fields[colnum].name));
234 <END_OF_RECORD>{separator} {
235 ERROR(("more fields than required"));
238 <END_OF_RECORD>{newline} {
240 const gchar* err = NULL;
244 DUMP_FIELD("newline->start");
248 rec = uat_add_record(uat, record, valid_record);
250 if ((uat->update_cb) && (rec != NULL))
251 uat->update_cb(rec,&err);
262 /* XXX is this necessary since we free it before reusing anyway? */
263 memset(record,0,uat->record_size);
269 ERROR(("unexpected char while looking for end of line"));
272 <ERRORED>{newline} { linenum++; BEGIN START_OF_LINE; }
275 {newline} { linenum++; ERROR(("incomplete record")); BEGIN START_OF_LINE; }
276 . { ERROR(("unexpected input")); }
284 uat_load(uat_t *uat_in, const char **errx)
286 gchar *fname = uat_get_actual_filename(uat_in, FALSE);
294 if (uat->post_update_cb)
295 uat->post_update_cb();
301 if (!(yyin = ws_fopen(fname,"r"))) {
302 *errx = g_strerror(errno);
311 record = g_malloc0(uat->record_size);
316 g_free(fname); /* we're done with the file name now */
322 uat->changed = FALSE;
327 *errx = ep_strdup(error);
331 if (uat->post_update_cb)
332 uat->post_update_cb();
339 uat_load_str(uat_t *uat_in, char *entry, char **err)
342 parse_str = g_strdup_printf("%s\n", entry); /* Records must end with a newline */
350 record = g_malloc0(uat->record_size);
366 *err = ep_strdup(error);
370 if (uat->post_update_cb)
371 uat->post_update_cb();
378 * We want to stop processing when we get to the end of the input.
379 * (%option noyywrap is not used because if used then
380 * some flex versions (eg: 2.5.35) generate code which causes
381 * warnings by the Windows VC compiler).