1%include { 2 3/* dtd_parser.lemon 4 * XML dissector for wireshark 5 * XML's DTD grammar 6 * 7 * Copyright 2005, Luis E. Garcia Ontanon <luis@ontanon.org> 8 * 9 * Wireshark - Network traffic analyzer 10 * By Gerald Combs <gerald@wireshark.org> 11 * Copyright 1998 Gerald Combs 12 * 13 * SPDX-License-Identifier: GPL-2.0-or-later 14 */ 15 16#include "config.h" 17 18#include <stdio.h> 19#include <glib.h> 20#include <assert.h> 21#include "dtd.h" 22#include "dtd_parse.h" 23 24static dtd_named_list_t* dtd_named_list_new(gchar* name, GPtrArray* list) { 25 dtd_named_list_t* nl = g_new(dtd_named_list_t,1); 26 27 nl->name = name; 28 nl->list = list; 29 30 return nl; 31} 32 33static GPtrArray* g_ptr_array_join(GPtrArray* a, GPtrArray* b){ 34 35 while(b->len > 0) { 36 g_ptr_array_add(a,g_ptr_array_remove_index_fast(b,0)); 37 } 38 39 g_ptr_array_free(b,TRUE); 40 41 return a; 42} 43 44} 45 46%name DtdParse 47 48%extra_argument { dtd_build_data_t *bd } 49 50%token_destructor { 51 (void) bd; /* Mark unused, similar to Q_UNUSED */ 52 if ($$) { 53 g_free($$->text); 54 g_free($$->location); 55 g_free($$); 56 } 57} 58 59%syntax_error { 60 if (!TOKEN) 61 g_string_append_printf(bd->error,"syntax error at end of file"); 62 else 63 g_string_append_printf(bd->error,"syntax error in %s at or before '%s': \n", TOKEN->location,TOKEN->text); 64} 65 66%parse_failure { 67 g_string_append_printf(bd->error,"DTD parsing failure\n"); 68} 69 70%token_prefix TOKEN_ 71 72%token_type { dtd_token_data_t* } 73 74dtd ::= doctype. 75dtd ::= dtd_parts. 76 77doctype ::= TAG_START DOCTYPE_KW NAME(Name) OPEN_BRACKET dtd_parts CLOSE_BRACKET TAG_STOP. { 78 dtd_named_list_t* root; 79 GPtrArray* root_elems = g_ptr_array_new(); 80 guint i; 81 gchar *name; 82 83 if(! bd->proto_name) { 84 bd->proto_name = Name->text; 85 } 86 87 g_free(bd->proto_root); 88 89 bd->proto_root = Name->text; 90 91 name = g_ascii_strdown(bd->proto_name, -1); 92 g_free(bd->proto_name); 93 bd->proto_name = name; 94 95 for( i = 0; i< bd->elements->len; i++) { 96 dtd_named_list_t* el = (dtd_named_list_t*)g_ptr_array_index(bd->elements,i); 97 98 g_ptr_array_add(root_elems,g_strdup(el->name)); 99 } 100 101 root = dtd_named_list_new(g_strdup(Name->text),root_elems); 102 103 g_ptr_array_add(bd->elements,root); 104 105 g_free(Name->location); 106 g_free(Name); 107 108} 109 110dtd_parts ::= dtd_parts element(Element). { g_ptr_array_add(bd->elements,Element); } 111dtd_parts ::= dtd_parts attlist(Attlist). { g_ptr_array_add(bd->attributes,Attlist); } 112dtd_parts ::= element(Element). { g_ptr_array_add(bd->elements,Element); } 113dtd_parts ::= attlist(Attlist). { g_ptr_array_add(bd->attributes,Attlist); } 114 115%type attlist { dtd_named_list_t* } 116attlist(A) ::= TAG_START ATTLIST_KW NAME(B) attrib_list(TheList) TAG_STOP. { 117 A = dtd_named_list_new(g_ascii_strdown(B->text, -1),TheList); 118 g_free(B->text); 119 g_free(B->location); 120 g_free(B); 121} 122 123%type element { dtd_named_list_t* } 124element(A) ::= TAG_START ELEMENT_KW NAME(B) sub_elements(C) TAG_STOP. { 125 A = dtd_named_list_new(g_ascii_strdown(B->text, -1),C); 126 g_free(B->text); 127 g_free(B->location); 128 g_free(B); 129} 130 131%type attrib_list { GPtrArray* } 132attrib_list(A) ::= attrib_list(B) attrib(C). { g_ptr_array_add(B,C); A = B; } 133attrib_list(A) ::= attrib(B). { A = g_ptr_array_new(); g_ptr_array_add(A,B); } 134 135%type attrib { gchar* } 136attrib(A) ::= NAME(B) att_type att_default. { 137 A = g_ascii_strdown(B->text, -1); 138 g_free(B->text); 139 g_free(B->location); 140 g_free(B); 141} 142 143att_type ::= ATT_TYPE. 144att_type ::= enumeration. 145 146att_default ::= ATT_DEF. 147att_default ::= ATT_DEF_WITH_VALUE QUOTED. 148att_default ::= QUOTED. 149att_default ::= IMPLIED_KW. 150att_default ::= REQUIRED_KW. 151 152enumeration ::= OPEN_PARENS enum_list CLOSE_PARENS. 153 154enum_list ::= enum_list PIPE enum_item. 155enum_list ::= enum_item. 156enum_list ::= enumeration. 157enum_list ::= enum_list PIPE enumeration. 158 159enum_item ::= NAME. 160enum_item ::= QUOTED. 161 162 163%type sub_elements { GPtrArray* } 164sub_elements(A) ::= sub_elements(B) STAR. {A=B;} 165sub_elements(A) ::= sub_elements(B) PLUS. {A=B;} 166sub_elements(A) ::= sub_elements(B) QUESTION. {A=B;} 167sub_elements(A) ::= OPEN_PARENS ELEM_DATA CLOSE_PARENS. { A = g_ptr_array_new(); } 168sub_elements(A) ::= OPEN_PARENS element_list(B) COMMA ELEM_DATA CLOSE_PARENS. { A = B; } 169sub_elements(A) ::= OPEN_PARENS element_list(B) PIPE ELEM_DATA CLOSE_PARENS. { A = B; } 170sub_elements(A) ::= OPEN_PARENS element_list(B) CLOSE_PARENS. { A = B; } 171sub_elements(A) ::= EMPTY_KW. { A = g_ptr_array_new(); } 172 173%type element_list { GPtrArray* } 174element_list(A) ::= element_list(B) COMMA element_child(C). { g_ptr_array_add(B,C); A = B; } 175element_list(A) ::= element_list(B) PIPE element_child(C). { g_ptr_array_add(B,C); A = B; } 176element_list(A) ::= element_child(B). { A = g_ptr_array_new(); g_ptr_array_add(A,B); } 177element_list(A) ::= sub_elements(B). { A = B; } 178element_list(A) ::= element_list(B) COMMA sub_elements(C). { A = g_ptr_array_join(B,C); } 179element_list(A) ::= element_list(B) PIPE sub_elements(C). { A = g_ptr_array_join(B,C); } 180 181%type element_child { gchar* } 182element_child(A) ::= NAME(B). { 183 A = g_ascii_strdown(B->text, -1); 184 g_free(B->text); 185 g_free(B->location); 186 g_free(B); 187} 188 189element_child(A) ::= NAME(B) STAR. { 190 A = g_ascii_strdown(B->text, -1); 191 g_free(B->text); 192 g_free(B->location); 193 g_free(B); 194} 195 196element_child(A) ::= NAME(B) QUESTION. { 197 A = g_ascii_strdown(B->text, -1); 198 g_free(B->text); 199 g_free(B->location); 200 g_free(B); 201} 202 203element_child(A) ::= NAME(B) PLUS. { 204 A = g_ascii_strdown(B->text, -1); 205 g_free(B->text); 206 g_free(B->location); 207 g_free(B); 208} 209 210