2 /* Include this before everything else, for various large-file definitions */
8 * We want a reentrant scanner.
13 * We don't use input, so don't generate code for it.
18 * We don't use unput, so don't generate code for it.
23 * We don't read interactively from the terminal.
25 %option never-interactive
28 * We want to stop processing when we get to the end of the input.
33 * The type for the state we keep for a scanner.
35 %option extra-type="Dtd_Parse_scanner_state_t *"
38 * Prefix scanner routines with "Dtd_Parse_" rather than "yy", so this scanner
39 * can coexist with other scanners.
41 %option prefix="Dtd_Parse_"
43 %option outfile="dtd_parse.c"
46 * We have to override the memory allocators so that we don't get
47 * "unused argument" warnings from the yyscanner argument (which
48 * we don't use, as we have a global memory allocator).
50 * We provide, as macros, our own versions of the routines generated by Flex,
51 * which just call malloc()/realloc()/free() (as the Flex versions do),
52 * discarding the extra argument.
61 * an XML dissector for Wireshark
62 * lexical analyzer for DTDs
64 * Copyright 2004, Luis E. Garcia Ontanon <luis@ontanon.org>
66 * Wireshark - Network traffic analyzer
67 * By Gerald Combs <gerald@wireshark.org>
68 * Copyright 1998 Gerald Combs
70 * This program is free software; you can redistribute it and/or
71 * modify it under the terms of the GNU General Public License
72 * as published by the Free Software Foundation; either version 2
73 * of the License, or (at your option) any later version.
75 * This program is distributed in the hope that it will be useful,
76 * but WITHOUT ANY WARRANTY; without even the implied warranty of
77 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78 * GNU General Public License for more details.
80 * You should have received a copy of the GNU General Public License
81 * along with this program; if not, write to the Free Software
82 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
89 #include "dtd_grammar.h"
90 #include "dtd_parse.h"
93 * Disable diagnostics in the code generated by Flex.
97 struct _proto_xmlpi_attr {
103 GString* input_string;
109 } Dtd_Parse_scanner_state_t;
111 static size_t my_yyinput(Dtd_Parse_scanner_state_t *state,char* buff,size_t size);
113 static dtd_token_data_t* new_token(char*,char*);
115 static dtd_build_data_t* build_data;
117 static void set_proto_name (char* val) { g_free(build_data->proto_name); build_data->proto_name = g_strdup(val); }
118 static void set_media_type (char* val) { g_free(build_data->media_type); build_data->media_type = g_strdup(val); }
119 static void set_proto_root (char* val) { g_free(build_data->proto_root); build_data->proto_root = g_strdup(val); }
120 static void set_description (char* val) { g_free(build_data->description); build_data->description = g_strdup(val); }
121 static void set_recursive (char* val) { build_data->recursion = ( g_ascii_strcasecmp(val,"yes") == 0 ) ? true : false; }
123 #ifdef DEBUG_DTD_PARSER
124 #define DEBUG_DTD_TOKEN fprintf(stderr,"->%s (%i)%s\n",location,token_type,yytext)
126 #define DEBUG_DTD_TOKEN
129 #define DTD_PARSE(token_type) \
131 DtdParse(yyextra->pParser, (token_type), new_token(yytext, yyextra->location), build_data); \
132 if(build_data->error->len > 0) yyterminate(); \
136 #define YY_INPUT(buff,result,max_size) ( (result) = my_yyinput(yyextra,(buff),(max_size)) )
137 #define YY_USER_INIT BEGIN DTD;
140 * Flex (v 2.5.35) uses this symbol to "exclude" unistd.h
143 #define YY_NO_UNISTD_H
147 * Sleazy hack to suppress compiler warnings in yy_fatal_error().
149 #define YY_EXIT_FAILURE ((void)yyscanner, 2)
152 * Macros for the allocators, to discard the extra argument.
154 #define Dtd_Parse_alloc(size, yyscanner) (void *)malloc(size)
155 #define Dtd_Parse_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
156 #define Dtd_Parse_free(ptr, yyscanner) free((char *)ptr)
165 location_xmlpi "wireshark:location"
166 protocol_xmlpi "wireshark:protocol"
168 get_attr_quote =[:blank:]*["]
171 get_location_xmlpi [^[:blank:]]+
175 notation_tag "<!"[:blank:]*NOTATION
179 whitespace [[:blank:]\r\n]+
216 name [A-Za-z0-9][-a-zA-Z0-9_]*
220 %START DTD XMLPI LOCATION DONE PROTOCOL GET_ATTR_QUOTE GET_ATTR_VAL GET_ATTR_CLOSE_QUOTE IN_COMMENT IN_NOTATION
226 <DTD>{comment_start} { BEGIN IN_COMMENT; }
229 <IN_COMMENT>{comment_stop} { BEGIN DTD; }
231 <DTD>{notation_tag} { BEGIN IN_NOTATION; }
233 <IN_NOTATION>{special_stop} { BEGIN DTD; }
239 <XMLPI>{location_xmlpi} {
243 <XMLPI>{protocol_xmlpi} {
248 <XMLPI>{stop_xmlpi} BEGIN DTD;
250 <LOCATION>{get_location_xmlpi} {
251 g_free(yyextra->location);
252 yyextra->location = g_strdup(yytext);
256 <DONE>{stop_xmlpi} BEGIN DTD;
259 yyextra->attr_name = g_ascii_strdown(yytext, -1);
260 BEGIN GET_ATTR_QUOTE;
263 <GET_ATTR_QUOTE>{get_attr_quote} { BEGIN GET_ATTR_VAL; }
266 g_string_append_printf(build_data->error,
267 "error in wireshark:protocol xmpli at %s : could not find attribute value!",
272 <GET_ATTR_VAL>[^"]+ {
274 struct _proto_xmlpi_attr* pa;
276 static struct _proto_xmlpi_attr proto_attrs[] =
278 { "proto_name", set_proto_name },
279 { "media", set_media_type },
280 { "root", set_proto_root },
281 { "description", set_description },
282 { "hierarchy", set_recursive },
286 for(pa = proto_attrs; pa->name; pa++) {
287 if (g_ascii_strcasecmp(yyextra->attr_name,pa->name) == 0) {
295 g_string_append_printf(build_data->error,
296 "error in wireshark:protocol xmpli at %s : no such parameter %s!",
297 yyextra->location, yyextra->attr_name);
298 g_free(yyextra->attr_name);
302 g_free(yyextra->attr_name);
304 BEGIN GET_ATTR_CLOSE_QUOTE;
307 <GET_ATTR_CLOSE_QUOTE>{dquote} { BEGIN PROTOCOL;}
309 <PROTOCOL>{stop_xmlpi} BEGIN DTD;
311 <DTD>{special_start} { DTD_PARSE(TOKEN_TAG_START); }
312 <DTD>{special_stop} { DTD_PARSE(TOKEN_TAG_STOP); }
314 <DTD>{attlist_kw} { DTD_PARSE(TOKEN_ATTLIST_KW); }
315 <DTD>{element_kw} { DTD_PARSE(TOKEN_ELEMENT_KW); }
316 <DTD>{doctype_kw} { DTD_PARSE(TOKEN_DOCTYPE_KW); }
318 <DTD>{pcdata} { DTD_PARSE(TOKEN_ELEM_DATA); }
319 <DTD>{any} { DTD_PARSE(TOKEN_ELEM_DATA); }
320 <DTD>{cdata} { DTD_PARSE(TOKEN_ELEM_DATA); }
321 <DTD>{empty} { DTD_PARSE(TOKEN_EMPTY_KW); }
323 <DTD>{iD} { DTD_PARSE(TOKEN_ATT_TYPE); }
324 <DTD>{idref} { DTD_PARSE(TOKEN_ATT_TYPE); }
325 <DTD>{idrefs} { DTD_PARSE(TOKEN_ATT_TYPE); }
326 <DTD>{nmtoken} { DTD_PARSE(TOKEN_ATT_TYPE); }
327 <DTD>{nmtokens} { DTD_PARSE(TOKEN_ATT_TYPE); }
328 <DTD>{entity} { DTD_PARSE(TOKEN_ATT_TYPE); }
329 <DTD>{entities} { DTD_PARSE(TOKEN_ATT_TYPE); }
330 <DTD>{notation} { DTD_PARSE(TOKEN_ATT_TYPE); }
331 <DTD>{cdata_t} { DTD_PARSE(TOKEN_ATT_TYPE); }
332 <DTD>{defaulT} { DTD_PARSE(TOKEN_ATT_DEF_WITH_VALUE); }
333 <DTD>{fixed} { DTD_PARSE(TOKEN_ATT_DEF_WITH_VALUE); }
334 <DTD>{required} { DTD_PARSE(TOKEN_ATT_DEF); }
335 <DTD>{implied} { DTD_PARSE(TOKEN_ATT_DEF); }
337 <DTD>{star} { DTD_PARSE(TOKEN_STAR); }
338 <DTD>{question} { DTD_PARSE(TOKEN_QUESTION); }
339 <DTD>{plus} { DTD_PARSE(TOKEN_PLUS); }
340 <DTD>{comma} { DTD_PARSE(TOKEN_COMMA); }
341 <DTD>{open_parens} { DTD_PARSE(TOKEN_OPEN_PARENS); }
342 <DTD>{close_parens} { DTD_PARSE(TOKEN_CLOSE_PARENS); }
343 <DTD>{open_bracket} { DTD_PARSE(TOKEN_OPEN_BRACKET); }
344 <DTD>{close_bracket} { DTD_PARSE(TOKEN_CLOSE_BRACKET); }
345 <DTD>{pipe} { DTD_PARSE(TOKEN_PIPE); }
348 <DTD>{squoted} { DTD_PARSE(TOKEN_QUOTED); }
349 <DTD>{name} { DTD_PARSE(TOKEN_NAME); }
354 * Turn diagnostics back on, so we check the code that we've written.
358 static dtd_token_data_t* new_token(char* text, char* location) {
359 dtd_token_data_t* t = g_new(dtd_token_data_t,1);
361 t->text = g_strdup(text);
362 t->location = g_strdup(location);
368 static size_t my_yyinput(Dtd_Parse_scanner_state_t *state, char* buff, size_t size) {
370 if (state->offsetx >= state->len) {
372 } else if (state->offsetx + size <= state->len) {
373 memcpy(buff, state->input_string->str + state->offsetx, size);
374 state->offsetx += size;
377 size = state->len - state->offsetx;
378 memcpy(buff, state->input_string->str + state->offsetx, size);
379 state->offsetx = state->len;
384 extern dtd_build_data_t* dtd_parse(GString* s) {
386 Dtd_Parse_scanner_state_t state;
388 if (Dtd_Parse_lex_init(&scanner) != 0) {
389 #ifdef DEBUG_DTD_PARSER
390 fprintf(stderr, "Can't initialize scanner: %s\n",
396 state.input_string = s;
398 state.len = state.input_string->len;
400 state.pParser = DtdParseAlloc(g_malloc);
402 #ifdef DEBUG_DTD_PARSER
403 DtdParseTrace(stderr, ">>");
406 build_data = g_new(dtd_build_data_t,1);
408 build_data->proto_name = NULL;
409 build_data->media_type = NULL;
410 build_data->description = NULL;
411 build_data->proto_root = NULL;
412 build_data->recursion = false;
414 build_data->elements = g_ptr_array_new();
415 build_data->attributes = g_ptr_array_new();
417 build_data->error = g_string_new("");
419 state.location = NULL;
420 state.attr_name = NULL;
422 /* Associate the state with the scanner */
423 Dtd_Parse_set_extra(&state, scanner);
425 Dtd_Parse_lex(scanner);
427 DtdParse(state.pParser, 0, NULL, build_data);
429 Dtd_Parse_lex_destroy(scanner);
431 g_free(state.location);
433 DtdParseFree(state.pParser, g_free);