forked from osmocom/wireshark
2e1fa634c6
Change-Id: I6fa38d5d85b25ac6c55fcfa67d6c8dba8482cc8c Reviewed-on: https://code.wireshark.org/review/10266 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
223 lines
5.9 KiB
Text
223 lines
5.9 KiB
Text
%include {
|
|
|
|
/* dtd_parser.lemon
|
|
* XML dissector for wireshark
|
|
* XML's DTD grammar
|
|
*
|
|
* Copyright 2005, 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 "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <glib.h>
|
|
#include <assert.h>
|
|
#include "dtd.h"
|
|
#include "dtd_parse.h"
|
|
|
|
static dtd_named_list_t* dtd_named_list_new(gchar* name, GPtrArray* list) {
|
|
dtd_named_list_t* nl = g_new(dtd_named_list_t,1);
|
|
|
|
nl->name = name;
|
|
nl->list = list;
|
|
|
|
return nl;
|
|
}
|
|
|
|
static GPtrArray* g_ptr_array_join(GPtrArray* a, GPtrArray* b){
|
|
|
|
while(b->len > 0) {
|
|
g_ptr_array_add(a,g_ptr_array_remove_index_fast(b,0));
|
|
}
|
|
|
|
g_ptr_array_free(b,TRUE);
|
|
|
|
return a;
|
|
}
|
|
|
|
}
|
|
|
|
%name DtdParse
|
|
|
|
%extra_argument { dtd_build_data_t *bd }
|
|
|
|
%token_destructor {
|
|
(void) bd; /* Mark unused, similar to Q_UNUSED */
|
|
if ($$) {
|
|
if ($$->text) g_free($$->text);
|
|
if ($$->location) g_free($$->location);
|
|
g_free($$);
|
|
}
|
|
}
|
|
|
|
%syntax_error {
|
|
if (!TOKEN)
|
|
g_string_append_printf(bd->error,"syntax error at end of file");
|
|
else
|
|
g_string_append_printf(bd->error,"syntax error in %s at or before '%s': \n", TOKEN->location,TOKEN->text);
|
|
}
|
|
|
|
%parse_failure {
|
|
g_string_append_printf(bd->error,"DTD parsing failure\n");
|
|
}
|
|
|
|
%token_prefix TOKEN_
|
|
|
|
%token_type { dtd_token_data_t* }
|
|
|
|
dtd ::= doctype.
|
|
dtd ::= dtd_parts.
|
|
|
|
doctype ::= TAG_START DOCTYPE_KW NAME(Name) OPEN_BRACKET dtd_parts CLOSE_BRACKET TAG_STOP. {
|
|
dtd_named_list_t* root;
|
|
GPtrArray* root_elems = g_ptr_array_new();
|
|
guint i;
|
|
gchar *name;
|
|
|
|
if(! bd->proto_name) {
|
|
bd->proto_name = Name->text;
|
|
}
|
|
|
|
if(bd->proto_root)
|
|
g_free(bd->proto_root);
|
|
|
|
bd->proto_root = Name->text;
|
|
|
|
name = g_ascii_strdown(bd->proto_name, -1);
|
|
g_free(bd->proto_name);
|
|
bd->proto_name = name;
|
|
|
|
for( i = 0; i< bd->elements->len; i++) {
|
|
dtd_named_list_t* el = (dtd_named_list_t*)g_ptr_array_index(bd->elements,i);
|
|
|
|
g_ptr_array_add(root_elems,g_strdup(el->name));
|
|
}
|
|
|
|
root = dtd_named_list_new(g_strdup(Name->text),root_elems);
|
|
|
|
g_ptr_array_add(bd->elements,root);
|
|
|
|
g_free(Name->location);
|
|
g_free(Name);
|
|
|
|
}
|
|
|
|
dtd_parts ::= dtd_parts element(Element). { g_ptr_array_add(bd->elements,Element); }
|
|
dtd_parts ::= dtd_parts attlist(Attlist). { g_ptr_array_add(bd->attributes,Attlist); }
|
|
dtd_parts ::= element(Element). { g_ptr_array_add(bd->elements,Element); }
|
|
dtd_parts ::= attlist(Attlist). { g_ptr_array_add(bd->attributes,Attlist); }
|
|
|
|
%type attlist { dtd_named_list_t* }
|
|
attlist(A) ::= TAG_START ATTLIST_KW NAME(B) attrib_list(TheList) TAG_STOP. {
|
|
A = dtd_named_list_new(g_ascii_strdown(B->text, -1),TheList);
|
|
g_free(B->text);
|
|
g_free(B->location);
|
|
g_free(B);
|
|
}
|
|
|
|
%type element { dtd_named_list_t* }
|
|
element(A) ::= TAG_START ELEMENT_KW NAME(B) sub_elements(C) TAG_STOP. {
|
|
A = dtd_named_list_new(g_ascii_strdown(B->text, -1),C);
|
|
g_free(B->text);
|
|
g_free(B->location);
|
|
g_free(B);
|
|
}
|
|
|
|
%type attrib_list { GPtrArray* }
|
|
attrib_list(A) ::= attrib_list(B) attrib(C). { g_ptr_array_add(B,C); A = B; }
|
|
attrib_list(A) ::= attrib(B). { A = g_ptr_array_new(); g_ptr_array_add(A,B); }
|
|
|
|
%type attrib { gchar* }
|
|
attrib(A) ::= NAME(B) att_type att_default. {
|
|
A = g_ascii_strdown(B->text, -1);
|
|
g_free(B->text);
|
|
g_free(B->location);
|
|
g_free(B);
|
|
}
|
|
|
|
att_type ::= ATT_TYPE.
|
|
att_type ::= enumeration.
|
|
|
|
att_default ::= ATT_DEF.
|
|
att_default ::= ATT_DEF_WITH_VALUE QUOTED.
|
|
att_default ::= QUOTED.
|
|
att_default ::= IMPLIED_KW.
|
|
att_default ::= REQUIRED_KW.
|
|
|
|
enumeration ::= OPEN_PARENS enum_list CLOSE_PARENS.
|
|
|
|
enum_list ::= enum_list PIPE enum_item.
|
|
enum_list ::= enum_item.
|
|
enum_list ::= enumeration.
|
|
enum_list ::= enum_list PIPE enumeration.
|
|
|
|
enum_item ::= NAME.
|
|
enum_item ::= QUOTED.
|
|
|
|
|
|
%type sub_elements { GPtrArray* }
|
|
sub_elements(A) ::= sub_elements(B) STAR. {A=B;}
|
|
sub_elements(A) ::= sub_elements(B) PLUS. {A=B;}
|
|
sub_elements(A) ::= sub_elements(B) QUESTION. {A=B;}
|
|
sub_elements(A) ::= OPEN_PARENS ELEM_DATA CLOSE_PARENS. { A = g_ptr_array_new(); }
|
|
sub_elements(A) ::= OPEN_PARENS element_list(B) COMMA ELEM_DATA CLOSE_PARENS. { A = B; }
|
|
sub_elements(A) ::= OPEN_PARENS element_list(B) PIPE ELEM_DATA CLOSE_PARENS. { A = B; }
|
|
sub_elements(A) ::= OPEN_PARENS element_list(B) CLOSE_PARENS. { A = B; }
|
|
sub_elements(A) ::= EMPTY_KW. { A = g_ptr_array_new(); }
|
|
|
|
%type element_list { GPtrArray* }
|
|
element_list(A) ::= element_list(B) COMMA element_child(C). { g_ptr_array_add(B,C); A = B; }
|
|
element_list(A) ::= element_list(B) PIPE element_child(C). { g_ptr_array_add(B,C); A = B; }
|
|
element_list(A) ::= element_child(B). { A = g_ptr_array_new(); g_ptr_array_add(A,B); }
|
|
element_list(A) ::= sub_elements(B). { A = B; }
|
|
element_list(A) ::= element_list(B) COMMA sub_elements(C). { A = g_ptr_array_join(B,C); }
|
|
element_list(A) ::= element_list(B) PIPE sub_elements(C). { A = g_ptr_array_join(B,C); }
|
|
|
|
%type element_child { gchar* }
|
|
element_child(A) ::= NAME(B). {
|
|
A = g_ascii_strdown(B->text, -1);
|
|
g_free(B->text);
|
|
g_free(B->location);
|
|
g_free(B);
|
|
}
|
|
|
|
element_child(A) ::= NAME(B) STAR. {
|
|
A = g_ascii_strdown(B->text, -1);
|
|
g_free(B->text);
|
|
g_free(B->location);
|
|
g_free(B);
|
|
}
|
|
|
|
element_child(A) ::= NAME(B) QUESTION. {
|
|
A = g_ascii_strdown(B->text, -1);
|
|
g_free(B->text);
|
|
g_free(B->location);
|
|
g_free(B);
|
|
}
|
|
|
|
element_child(A) ::= NAME(B) PLUS. {
|
|
A = g_ascii_strdown(B->text, -1);
|
|
g_free(B->text);
|
|
g_free(B->location);
|
|
g_free(B);
|
|
}
|
|
|