forked from osmocom/wireshark
436 lines
11 KiB
Plaintext
436 lines
11 KiB
Plaintext
%top {
|
|
/* Include this before everything else, for various large-file definitions */
|
|
#include "config.h"
|
|
}
|
|
|
|
/*
|
|
* We want a reentrant scanner.
|
|
*/
|
|
%option reentrant
|
|
|
|
/*
|
|
* We don't use input, so don't generate code for it.
|
|
*/
|
|
%option noinput
|
|
|
|
/*
|
|
* We don't use unput, so don't generate code for it.
|
|
*/
|
|
%option nounput
|
|
|
|
/*
|
|
* We don't read interactively from the terminal.
|
|
*/
|
|
%option never-interactive
|
|
|
|
/*
|
|
* We want to stop processing when we get to the end of the input.
|
|
*/
|
|
%option noyywrap
|
|
|
|
/*
|
|
* The type for the state we keep for a scanner.
|
|
*/
|
|
%option extra-type="Dtd_Parse_scanner_state_t *"
|
|
|
|
/*
|
|
* Prefix scanner routines with "Dtd_Parse_" rather than "yy", so this scanner
|
|
* can coexist with other scanners.
|
|
*/
|
|
%option prefix="Dtd_Parse_"
|
|
|
|
%option outfile="dtd_parse.c"
|
|
|
|
/*
|
|
* We have to override the memory allocators so that we don't get
|
|
* "unused argument" warnings from the yyscanner argument (which
|
|
* we don't use, as we have a global memory allocator).
|
|
*
|
|
* We provide, as macros, our own versions of the routines generated by Flex,
|
|
* which just call malloc()/realloc()/free() (as the Flex versions do),
|
|
* discarding the extra argument.
|
|
*/
|
|
%option noyyalloc
|
|
%option noyyrealloc
|
|
%option noyyfree
|
|
|
|
%{
|
|
|
|
/* dtd_parse.l
|
|
* an XML dissector for Wireshark
|
|
* lexical analyzer for DTDs
|
|
*
|
|
* Copyright 2004, Luis E. Garcia Ontanon <luis@ontanon.org>
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <glib.h>
|
|
#include <string.h>
|
|
|
|
#include "dtd.h"
|
|
#include "dtd_grammar.h"
|
|
#include "dtd_parse.h"
|
|
|
|
/*
|
|
* Disable diagnostics in the code generated by Flex.
|
|
*/
|
|
DIAG_OFF_FLEX
|
|
|
|
struct _proto_xmlpi_attr {
|
|
const gchar* name;
|
|
void (*act)(gchar*);
|
|
};
|
|
|
|
typedef struct {
|
|
GString* input_string;
|
|
size_t offsetx;
|
|
size_t len;
|
|
void* pParser;
|
|
gchar* location;
|
|
gchar* attr_name;
|
|
} Dtd_Parse_scanner_state_t;
|
|
|
|
static size_t my_yyinput(Dtd_Parse_scanner_state_t *state,char* buff,size_t size);
|
|
|
|
static dtd_token_data_t* new_token(gchar*,gchar*);
|
|
|
|
static dtd_build_data_t* build_data;
|
|
|
|
static void set_proto_name (gchar* val) { g_free(build_data->proto_name); build_data->proto_name = g_strdup(val); }
|
|
static void set_media_type (gchar* val) { g_free(build_data->media_type); build_data->media_type = g_strdup(val); }
|
|
static void set_proto_root (gchar* val) { g_free(build_data->proto_root); build_data->proto_root = g_strdup(val); }
|
|
static void set_description (gchar* val) { g_free(build_data->description); build_data->description = g_strdup(val); }
|
|
static void set_recursive (gchar* val) { build_data->recursion = ( g_ascii_strcasecmp(val,"yes") == 0 ) ? TRUE : FALSE; }
|
|
|
|
#ifdef DEBUG_DTD_PARSER
|
|
#define DEBUG_DTD_TOKEN fprintf(stderr,"->%s (%i)%s\n",location,token_type,yytext)
|
|
#else
|
|
#define DEBUG_DTD_TOKEN
|
|
#endif
|
|
|
|
#define DTD_PARSE(token_type) \
|
|
{ DEBUG_DTD_TOKEN; \
|
|
DtdParse(yyextra->pParser, (token_type), new_token(yytext, yyextra->location), build_data); \
|
|
if(build_data->error->len > 0) yyterminate(); \
|
|
}
|
|
|
|
|
|
#define YY_INPUT(buff,result,max_size) ( (result) = my_yyinput(yyextra,(buff),(max_size)) )
|
|
#define YY_USER_INIT BEGIN DTD;
|
|
|
|
/*
|
|
* Flex (v 2.5.35) uses this symbol to "exclude" unistd.h
|
|
*/
|
|
#ifdef _WIN32
|
|
#define YY_NO_UNISTD_H
|
|
#endif
|
|
|
|
/*
|
|
* Sleazy hack to suppress compiler warnings in yy_fatal_error().
|
|
*/
|
|
#define YY_EXIT_FAILURE ((void)yyscanner, 2)
|
|
|
|
/*
|
|
* Macros for the allocators, to discard the extra argument.
|
|
*/
|
|
#define Dtd_Parse_alloc(size, yyscanner) (void *)malloc(size)
|
|
#define Dtd_Parse_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
|
|
#define Dtd_Parse_free(ptr, yyscanner) free((char *)ptr)
|
|
|
|
%}
|
|
|
|
comment_start "<!--"
|
|
comment_stop "-->"
|
|
|
|
start_xmlpi "<?"
|
|
|
|
location_xmlpi "wireshark:location"
|
|
protocol_xmlpi "wireshark:protocol"
|
|
|
|
get_attr_quote =[:blank:]*["]
|
|
avoid_editor_bug ["]
|
|
|
|
get_location_xmlpi [^[:blank:]]+
|
|
|
|
stop_xmlpi "?>"
|
|
|
|
notation_tag "<!"[:blank:]*NOTATION
|
|
|
|
special_start "<!"
|
|
special_stop ">"
|
|
whitespace [[:blank:]\r\n]+
|
|
newline \n
|
|
attlist_kw ATTLIST
|
|
doctype_kw DOCTYPE
|
|
element_kw ELEMENT
|
|
|
|
pcdata #PCDATA
|
|
any ANY
|
|
cdata #CDATA
|
|
|
|
iD ID
|
|
idref IDREF
|
|
idrefs IDREFS
|
|
nmtoken NMTOKEN
|
|
nmtokens NMTOKENS
|
|
entity ENTITY
|
|
entities ENTITIES
|
|
notation NOTATION
|
|
cdata_t CDATA
|
|
|
|
empty EMPTY
|
|
defaulT #DEFAULT
|
|
fixed #FIXED
|
|
required #REQUIRED
|
|
implied #IMPLIED
|
|
|
|
star "*"
|
|
question "?"
|
|
plus "+"
|
|
open_parens "("
|
|
close_parens ")"
|
|
open_bracket "["
|
|
close_bracket "]"
|
|
comma ","
|
|
pipe "|"
|
|
dquote ["]
|
|
|
|
name [A-Za-z0-9][-a-zA-Z0-9_]*
|
|
dquoted ["][^\"]*["]
|
|
squoted ['][^\']*[']
|
|
|
|
%START DTD XMLPI LOCATION DONE PROTOCOL GET_ATTR_QUOTE GET_ATTR_VAL GET_ATTR_CLOSE_QUOTE IN_COMMENT IN_NOTATION
|
|
%%
|
|
|
|
{whitespace} ;
|
|
|
|
|
|
<DTD>{comment_start} { BEGIN IN_COMMENT; }
|
|
<IN_COMMENT>[^-]? |
|
|
<IN_COMMENT>[-] ;
|
|
<IN_COMMENT>{comment_stop} { BEGIN DTD; }
|
|
|
|
<DTD>{notation_tag} { BEGIN IN_NOTATION; }
|
|
<IN_NOTATION>[^>] ;
|
|
<IN_NOTATION>{special_stop} { BEGIN DTD; }
|
|
|
|
<DTD>{start_xmlpi} {
|
|
BEGIN XMLPI;
|
|
}
|
|
|
|
<XMLPI>{location_xmlpi} {
|
|
BEGIN LOCATION;
|
|
}
|
|
|
|
<XMLPI>{protocol_xmlpi} {
|
|
BEGIN PROTOCOL;
|
|
}
|
|
|
|
<XMLPI><.> ;
|
|
<XMLPI>{stop_xmlpi} BEGIN DTD;
|
|
|
|
<LOCATION>{get_location_xmlpi} {
|
|
g_free(yyextra->location);
|
|
yyextra->location = g_strdup(yytext);
|
|
BEGIN DONE;
|
|
}
|
|
|
|
<DONE>{stop_xmlpi} BEGIN DTD;
|
|
|
|
<PROTOCOL>{name} {
|
|
yyextra->attr_name = g_ascii_strdown(yytext, -1);
|
|
BEGIN GET_ATTR_QUOTE;
|
|
}
|
|
|
|
<GET_ATTR_QUOTE>{get_attr_quote} { BEGIN GET_ATTR_VAL; }
|
|
|
|
<GET_ATTR_QUOTE>. {
|
|
g_string_append_printf(build_data->error,
|
|
"error in wireshark:protocol xmpli at %s : could not find attribute value!",
|
|
yyextra->location);
|
|
yyterminate();
|
|
}
|
|
|
|
<GET_ATTR_VAL>[^"]+ {
|
|
/*"*/
|
|
struct _proto_xmlpi_attr* pa;
|
|
gboolean got_it = FALSE;
|
|
static struct _proto_xmlpi_attr proto_attrs[] =
|
|
{
|
|
{ "proto_name", set_proto_name },
|
|
{ "media", set_media_type },
|
|
{ "root", set_proto_root },
|
|
{ "description", set_description },
|
|
{ "hierarchy", set_recursive },
|
|
{NULL,NULL}
|
|
};
|
|
|
|
for(pa = proto_attrs; pa->name; pa++) {
|
|
if (g_ascii_strcasecmp(yyextra->attr_name,pa->name) == 0) {
|
|
pa->act(yytext);
|
|
got_it = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (! got_it) {
|
|
g_string_append_printf(build_data->error,
|
|
"error in wireshark:protocol xmpli at %s : no such parameter %s!",
|
|
yyextra->location, yyextra->attr_name);
|
|
g_free(yyextra->attr_name);
|
|
yyterminate();
|
|
}
|
|
|
|
g_free(yyextra->attr_name);
|
|
|
|
BEGIN GET_ATTR_CLOSE_QUOTE;
|
|
}
|
|
|
|
<GET_ATTR_CLOSE_QUOTE>{dquote} { BEGIN PROTOCOL;}
|
|
|
|
<PROTOCOL>{stop_xmlpi} BEGIN DTD;
|
|
|
|
<DTD>{special_start} { DTD_PARSE(TOKEN_TAG_START); }
|
|
<DTD>{special_stop} { DTD_PARSE(TOKEN_TAG_STOP); }
|
|
|
|
<DTD>{attlist_kw} { DTD_PARSE(TOKEN_ATTLIST_KW); }
|
|
<DTD>{element_kw} { DTD_PARSE(TOKEN_ELEMENT_KW); }
|
|
<DTD>{doctype_kw} { DTD_PARSE(TOKEN_DOCTYPE_KW); }
|
|
|
|
<DTD>{pcdata} { DTD_PARSE(TOKEN_ELEM_DATA); }
|
|
<DTD>{any} { DTD_PARSE(TOKEN_ELEM_DATA); }
|
|
<DTD>{cdata} { DTD_PARSE(TOKEN_ELEM_DATA); }
|
|
<DTD>{empty} { DTD_PARSE(TOKEN_EMPTY_KW); }
|
|
|
|
<DTD>{iD} { DTD_PARSE(TOKEN_ATT_TYPE); }
|
|
<DTD>{idref} { DTD_PARSE(TOKEN_ATT_TYPE); }
|
|
<DTD>{idrefs} { DTD_PARSE(TOKEN_ATT_TYPE); }
|
|
<DTD>{nmtoken} { DTD_PARSE(TOKEN_ATT_TYPE); }
|
|
<DTD>{nmtokens} { DTD_PARSE(TOKEN_ATT_TYPE); }
|
|
<DTD>{entity} { DTD_PARSE(TOKEN_ATT_TYPE); }
|
|
<DTD>{entities} { DTD_PARSE(TOKEN_ATT_TYPE); }
|
|
<DTD>{notation} { DTD_PARSE(TOKEN_ATT_TYPE); }
|
|
<DTD>{cdata_t} { DTD_PARSE(TOKEN_ATT_TYPE); }
|
|
<DTD>{defaulT} { DTD_PARSE(TOKEN_ATT_DEF_WITH_VALUE); }
|
|
<DTD>{fixed} { DTD_PARSE(TOKEN_ATT_DEF_WITH_VALUE); }
|
|
<DTD>{required} { DTD_PARSE(TOKEN_ATT_DEF); }
|
|
<DTD>{implied} { DTD_PARSE(TOKEN_ATT_DEF); }
|
|
|
|
<DTD>{star} { DTD_PARSE(TOKEN_STAR); }
|
|
<DTD>{question} { DTD_PARSE(TOKEN_QUESTION); }
|
|
<DTD>{plus} { DTD_PARSE(TOKEN_PLUS); }
|
|
<DTD>{comma} { DTD_PARSE(TOKEN_COMMA); }
|
|
<DTD>{open_parens} { DTD_PARSE(TOKEN_OPEN_PARENS); }
|
|
<DTD>{close_parens} { DTD_PARSE(TOKEN_CLOSE_PARENS); }
|
|
<DTD>{open_bracket} { DTD_PARSE(TOKEN_OPEN_BRACKET); }
|
|
<DTD>{close_bracket} { DTD_PARSE(TOKEN_CLOSE_BRACKET); }
|
|
<DTD>{pipe} { DTD_PARSE(TOKEN_PIPE); }
|
|
|
|
<DTD>{dquoted} |
|
|
<DTD>{squoted} { DTD_PARSE(TOKEN_QUOTED); }
|
|
<DTD>{name} { DTD_PARSE(TOKEN_NAME); }
|
|
|
|
%%
|
|
|
|
/*
|
|
* Turn diagnostics back on, so we check the code that we've written.
|
|
*/
|
|
DIAG_ON_FLEX
|
|
|
|
static dtd_token_data_t* new_token(gchar* text, gchar* location) {
|
|
dtd_token_data_t* t = g_new(dtd_token_data_t,1);
|
|
|
|
t->text = g_strdup(text);
|
|
t->location = g_strdup(location);
|
|
|
|
return t;
|
|
}
|
|
|
|
|
|
static size_t my_yyinput(Dtd_Parse_scanner_state_t *state, char* buff, size_t size) {
|
|
|
|
if (state->offsetx >= state->len) {
|
|
return YY_NULL;
|
|
} else if (state->offsetx + size <= state->len) {
|
|
memcpy(buff, state->input_string->str + state->offsetx, size);
|
|
state->offsetx += size;
|
|
return size;
|
|
} else {
|
|
size = state->len - state->offsetx;
|
|
memcpy(buff, state->input_string->str + state->offsetx, size);
|
|
state->offsetx = state->len;
|
|
return size;
|
|
}
|
|
}
|
|
|
|
extern dtd_build_data_t* dtd_parse(GString* s) {
|
|
yyscan_t scanner;
|
|
Dtd_Parse_scanner_state_t state;
|
|
|
|
if (Dtd_Parse_lex_init(&scanner) != 0) {
|
|
#ifdef DEBUG_DTD_PARSER
|
|
fprintf(stderr, "Can't initialize scanner: %s\n",
|
|
strerror(errno));
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
state.input_string = s;
|
|
state.offsetx = 0;
|
|
state.len = state.input_string->len;
|
|
|
|
state.pParser = DtdParseAlloc(g_malloc);
|
|
|
|
#ifdef DEBUG_DTD_PARSER
|
|
DtdParseTrace(stderr, ">>");
|
|
#endif
|
|
|
|
build_data = g_new(dtd_build_data_t,1);
|
|
|
|
build_data->proto_name = NULL;
|
|
build_data->media_type = NULL;
|
|
build_data->description = NULL;
|
|
build_data->proto_root = NULL;
|
|
build_data->recursion = FALSE;
|
|
|
|
build_data->elements = g_ptr_array_new();
|
|
build_data->attributes = g_ptr_array_new();
|
|
|
|
build_data->error = g_string_new("");
|
|
|
|
state.location = NULL;
|
|
state.attr_name = NULL;
|
|
|
|
/* Associate the state with the scanner */
|
|
Dtd_Parse_set_extra(&state, scanner);
|
|
|
|
Dtd_Parse_lex(scanner);
|
|
|
|
DtdParse(state.pParser, 0, NULL, build_data);
|
|
|
|
Dtd_Parse_lex_destroy(scanner);
|
|
|
|
g_free(state.location);
|
|
|
|
DtdParseFree(state.pParser, g_free);
|
|
|
|
return build_data;
|
|
}
|