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 interactively 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_"
26 * User Accessible Tables
27 * Mantain an array of user accessible data strucures
28 * One parser to fit them all
30 * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
32 * Wireshark - Network traffic analyzer
33 * By Gerald Combs <gerald@wireshark.org>
34 * Copyright 2001 Gerald Combs
36 * This program is free software; you can redistribute it and/or
37 * modify it under the terms of the GNU General Public License
38 * as published by the Free Software Foundation; either version 2
39 * of the License, or (at your option) any later version.
41 * This program is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 * GNU General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program; if not, write to the Free Software
48 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
60 #include "uat_load_lex.h"
61 #include <wsutil/file_util.h>
64 /* disable Windows VC compiler warning "signed/unsigned mismatch" associated */
65 /* with YY_INPUT code generated by flex versions such as 2.5.35. */
66 #pragma warning (disable:4018)
70 static gboolean valid_record;
77 static gchar *parse_str;
78 static size_t parse_str_pos;
80 #define ERROR(fmtd) do { \
81 char* fmt_str = g_strdup_printf fmtd; \
82 error = g_strdup_printf("%s:%d: %s",uat->filename,linenum,fmt_str); \
89 if (uat->fields[colnum].cb.chk) { \
90 if ( ! uat->fields[colnum].cb.chk(record, ptrx, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data, &errx) ) { \
91 error = g_strdup_printf("%s:%d: %s",uat->filename,linenum,errx); \
93 valid_record = FALSE; \
96 uat->fields[colnum].cb.set(record, ptrx, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data);\
101 #ifdef DEBUG_UAT_LOAD
102 #define DUMP_FIELD(str) \
103 { 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); }
105 #define DUMP(str) printf("%s\n",str)
107 #define DUMP_FIELD(s)
111 /* Modified version of YY_INPUT generated by Flex 2.91 */
112 #define YY_INPUT(buf,result,max_size) \
116 size_t pslen = strlen(parse_str); \
117 if (parse_str_pos < pslen) \
119 n = pslen - parse_str_pos; \
120 if (n > max_size) n = max_size; \
121 memcpy(buf, parse_str + parse_str_pos, n); \
122 parse_str_pos += n; \
129 while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
131 if( errno != EINTR) \
133 YY_FATAL_ERROR( "input in flex scanner failed" ); \
143 * quoted_string below fails badly on "...\\"
144 * workarround in uat_save(), using /x5c and /x22
148 quoted_string \042([^\042]|\134\042)*\042
149 binstring ([0-9a-zA-Z][0-9a-zA-Z])*
151 newline [ \t]*[\r]?\n
155 %x START_OF_LINE NEXT_FIELD SEPARATOR END_OF_RECORD ERRORED
157 <START_OF_LINE,NEXT_FIELD>{ws} ;
158 <START_OF_LINE>{newline} linenum++;
159 <START_OF_LINE>{comment} linenum++;
161 <START_OF_LINE,NEXT_FIELD>{separator} {
165 DUMP_FIELD("empty->next");
169 if ( colnum >= uat->ncols ) {
170 ERROR(("more fields than required"));
176 <START_OF_LINE,NEXT_FIELD>{newline} {
182 yyless((int) yyleng);
185 <START_OF_LINE,NEXT_FIELD>{quoted_string} {
186 ptrx = uat_undquote(yytext, (guint) yyleng, &len);
189 if (colnum < uat->ncols - 1) {
190 DUMP("quoted_str->s");
193 DUMP("quoted_str->eor");
198 <START_OF_LINE,NEXT_FIELD>{binstring} {
199 ptrx = uat_unbinstring(yytext, (guint) yyleng, &len);
202 ERROR(("uneven hexstring for field %s",uat->fields[colnum].name));
205 if ( colnum < uat->ncols - 1 ) {
206 DUMP("binstring->s");
209 DUMP("binstring->eor");
214 <SEPARATOR>{separator} {
216 DUMP_FIELD("separator->next");
220 if ( colnum >= uat->ncols ) {
221 ERROR(("more fields than required"));
227 <SEPARATOR>{newline} {
229 ERROR(("expecting field %s in previous line",uat->fields[colnum].name));
233 ERROR(("unexpected char '%s' while looking for field %s",yytext,uat->fields[colnum].name));
236 <END_OF_RECORD>{separator} {
237 ERROR(("more fields than required"));
240 <END_OF_RECORD>{newline} {
246 DUMP_FIELD("newline->start");
250 rec = uat_add_record(uat, record, valid_record);
252 if ((uat->update_cb) && (rec != NULL)) {
253 if (!uat->update_cb(rec,&err)) {
264 /* XXX is this necessary since we free it before reusing anyway? */
265 memset(record,0,uat->record_size);
271 ERROR(("unexpected char while looking for end of line"));
274 <ERRORED>{newline} { linenum++; BEGIN START_OF_LINE; }
277 {newline} { linenum++; ERROR(("incomplete record")); }
278 . { ERROR(("unexpected input")); }
286 uat_load(uat_t *uat_in, char **errx)
288 gchar *fname = uat_get_actual_filename(uat_in, FALSE);
296 if (uat->post_update_cb)
297 uat->post_update_cb();
303 if (!(yyin = ws_fopen(fname,"r"))) {
304 *errx = g_strdup(g_strerror(errno));
313 record = g_malloc0(uat->record_size);
318 g_free(fname); /* we're done with the file name now */
324 uat->changed = FALSE;
333 if (uat->post_update_cb)
334 uat->post_update_cb();
341 uat_load_str(uat_t *uat_in, char *entry, char **err)
344 parse_str = g_strdup_printf("%s\n", entry); /* Records must end with a newline */
352 record = g_malloc0(uat->record_size);
372 if (uat->post_update_cb)
373 uat->post_update_cb();
380 * We want to stop processing when we get to the end of the input.
381 * (%option noyywrap is not used because if used then
382 * some flex versions (eg: 2.5.35) generate code which causes
383 * warnings by the Windows VC compiler).