/[suikacvs]/markup/html/whatpm/Whatpm/HTML/Tokenizer.pm
Suika

Diff of /markup/html/whatpm/Whatpm/HTML/Tokenizer.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.14 by wakaba, Fri Oct 17 07:14:29 2008 UTC revision 1.33 by wakaba, Sat Sep 5 10:41:07 2009 UTC
# Line 105  sub COMMENT_START_STATE () { 14 } Line 105  sub COMMENT_START_STATE () { 14 }
105  sub COMMENT_START_DASH_STATE () { 15 }  sub COMMENT_START_DASH_STATE () { 15 }
106  sub COMMENT_STATE () { 16 }  sub COMMENT_STATE () { 16 }
107  sub COMMENT_END_STATE () { 17 }  sub COMMENT_END_STATE () { 17 }
108    sub COMMENT_END_BANG_STATE () { 102 }
109    sub COMMENT_END_SPACE_STATE () { 103 } ## LAST
110  sub COMMENT_END_DASH_STATE () { 18 }  sub COMMENT_END_DASH_STATE () { 18 }
111  sub BOGUS_COMMENT_STATE () { 19 }  sub BOGUS_COMMENT_STATE () { 19 }
112  sub DOCTYPE_STATE () { 20 }  sub DOCTYPE_STATE () { 20 }
# Line 164  sub BEFORE_MD_NAME_STATE () { 68 } Line 166  sub BEFORE_MD_NAME_STATE () { 68 }
166  sub MD_NAME_STATE () { 69 }  sub MD_NAME_STATE () { 69 }
167  sub DOCTYPE_ENTITY_PARAMETER_BEFORE_STATE () { 70 }  sub DOCTYPE_ENTITY_PARAMETER_BEFORE_STATE () { 70 }
168  sub DOCTYPE_ATTLIST_NAME_AFTER_STATE () { 71 }  sub DOCTYPE_ATTLIST_NAME_AFTER_STATE () { 71 }
169    sub DOCTYPE_ATTLIST_ATTRIBUTE_NAME_STATE () { 72 }
170    sub DOCTYPE_ATTLIST_ATTRIBUTE_NAME_AFTER_STATE () { 73 }
171    sub DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_STATE () { 74 }
172    sub DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_AFTER_STATE () { 75 }
173    sub BEFORE_ALLOWED_TOKEN_STATE () { 76 }
174    sub ALLOWED_TOKEN_STATE () { 77 }
175    sub AFTER_ALLOWED_TOKEN_STATE () { 78 }
176    sub AFTER_ALLOWED_TOKENS_STATE () { 79 }
177    sub BEFORE_ATTR_DEFAULT_STATE () { 80 }
178    sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE () { 81 }
179    sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
180    sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
181    sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }
182    sub BEFORE_NDATA_STATE () { 85 }
183    sub NDATA_STATE () { 86 }
184    sub AFTER_NDATA_STATE () { 87 }
185    sub BEFORE_NOTATION_NAME_STATE () { 88 }
186    sub NOTATION_NAME_STATE () { 89 }
187    sub DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE () { 90 }
188    sub DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE () { 91 }
189    sub ENTITY_VALUE_ENTITY_STATE () { 92 }
190    sub AFTER_ELEMENT_NAME_STATE () { 93 }
191    sub BEFORE_ELEMENT_CONTENT_STATE () { 94 }
192    sub CONTENT_KEYWORD_STATE () { 95 }
193    sub AFTER_CM_GROUP_OPEN_STATE () { 96 }
194    sub CM_ELEMENT_NAME_STATE () { 97 }
195    sub AFTER_CM_ELEMENT_NAME_STATE () { 98 }
196    sub AFTER_CM_GROUP_CLOSE_STATE () { 99 }
197    sub AFTER_MD_DEF_STATE () { 100 }
198    sub BOGUS_MD_STATE () { 101 }
199    
200  ## Tree constructor state constants (see Whatpm::HTML for the full  ## Tree constructor state constants (see Whatpm::HTML for the full
201  ## list and descriptions)  ## list and descriptions)
# Line 1070  sub _get_next_token ($) { Line 1102  sub _get_next_token ($) {
1102          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1103          # reconsume          # reconsume
1104    
1105          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1106            #return  ($self->{ct}); # start tag or end tag
1107    
1108          redo A;          redo A;
1109        } elsif ($self->{nc} == 0x002F) { # /        } elsif ($self->{nc} == 0x002F) { # /
# Line 1211  sub _get_next_token ($) { Line 1244  sub _get_next_token ($) {
1244          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1245          # reconsume          # reconsume
1246    
1247          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1248            #return  ($self->{ct}); # start tag or end tag
1249    
1250          redo A;          redo A;
1251        } else {        } else {
1252          if ({          if ({
1253               0x0022 => 1, # "               0x0022 => 1, # "
1254               0x0027 => 1, # '               0x0027 => 1, # '
1255                 0x003C => 1, # <
1256               0x003D => 1, # =               0x003D => 1, # =
1257              }->{$self->{nc}}) {              }->{$self->{nc}}) {
1258                        
# Line 1396  sub _get_next_token ($) { Line 1431  sub _get_next_token ($) {
1431          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1432          # reconsume          # reconsume
1433    
1434          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1435            #return  ($self->{ct}); # start tag or end tag
1436    
1437          redo A;          redo A;
1438        } else {        } else {
1439          if ($self->{nc} == 0x0022 or # "          if ({
1440              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1441                 0x0027 => 1, # '
1442                 0x003C => 1, # <
1443                }->{$self->{nc}}) {
1444                        
1445            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1446            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1560  sub _get_next_token ($) { Line 1599  sub _get_next_token ($) {
1599          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1600          # reconsume          # reconsume
1601    
1602          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1603            #return  ($self->{ct}); # start tag or end tag
1604    
1605          redo A;          redo A;
1606        } else {        } else {
# Line 1572  sub _get_next_token ($) { Line 1612  sub _get_next_token ($) {
1612                        
1613          }          }
1614    
1615          if ($self->{nc} == 0x0022 or # "          if ({
1616              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1617                 0x0027 => 1, # '
1618                 0x003C => 1, # <
1619                }->{$self->{nc}}) {
1620                        
1621            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1622            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1706  sub _get_next_token ($) { Line 1749  sub _get_next_token ($) {
1749          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1750          ## reconsume          ## reconsume
1751    
1752          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1753            #return  ($self->{ct}); # start tag or end tag
1754    
1755          redo A;          redo A;
1756        } else {        } else {
1757          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1758                        
1759            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1760            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute value');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute value');
# Line 1737  sub _get_next_token ($) { Line 1781  sub _get_next_token ($) {
1781          redo A;          redo A;
1782        }        }
1783      } elsif ($self->{state} == ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE) {      } elsif ($self->{state} == ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE) {
1784        ## XML5: "Tag attribute value double quoted state".        ## XML5: "Tag attribute value double quoted state" and "DOCTYPE
1785          ## ATTLIST attribute value double quoted state".
1786                
1787        if ($self->{nc} == 0x0022) { # "        if ($self->{nc} == 0x0022) { # "
1788                    if ($self->{ct}->{type} == ATTLIST_TOKEN) {
1789          ## XML5: "Tag attribute name before state".            
1790          $self->{state} = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;            ## XML5: "DOCTYPE ATTLIST name after state".
1791              push @{$self->{ct}->{attrdefs}}, $self->{ca};
1792              $self->{state} = AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE;
1793            } else {
1794              
1795              ## XML5: "Tag attribute name before state".
1796              $self->{state} = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;
1797            }
1798                    
1799      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1800        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 1778  sub _get_next_token ($) { Line 1830  sub _get_next_token ($) {
1830      }      }
1831        
1832          redo A;          redo A;
1833          } elsif ($self->{is_xml} and
1834                   $is_space->{$self->{nc}}) {
1835            
1836            $self->{ca}->{value} .= ' ';
1837            ## Stay in the state.
1838            
1839        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1840          $self->{line_prev} = $self->{line};
1841          $self->{column_prev} = $self->{column};
1842          $self->{column}++;
1843          $self->{nc}
1844              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1845        } else {
1846          $self->{set_nc}->($self);
1847        }
1848      
1849            redo A;
1850        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1851          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1852          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
1853                        
1854            $self->{last_stag_name} = $self->{ct}->{tag_name};            $self->{last_stag_name} = $self->{ct}->{tag_name};
1855    
1856              $self->{state} = DATA_STATE;
1857              $self->{s_kwd} = '';
1858              ## reconsume
1859              return  ($self->{ct}); # start tag
1860              redo A;
1861          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
1862            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
1863            if ($self->{ct}->{attributes}) {            if ($self->{ct}->{attributes}) {
# Line 1792  sub _get_next_token ($) { Line 1867  sub _get_next_token ($) {
1867              ## NOTE: This state should never be reached.              ## NOTE: This state should never be reached.
1868                            
1869            }            }
1870    
1871              $self->{state} = DATA_STATE;
1872              $self->{s_kwd} = '';
1873              ## reconsume
1874    
1875              ## Discard the token.
1876              #return  ($self->{ct}); # end tag
1877    
1878              redo A;
1879            } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1880              ## XML5: No parse error above; not defined yet.
1881              push @{$self->{ct}->{attrdefs}}, $self->{ca};
1882              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1883              ## Reconsume.
1884    
1885              ## Discard the token.
1886              #return  ($self->{ct}); # ATTLIST
1887    
1888              redo A;
1889          } else {          } else {
1890            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1891          }          }
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
         ## reconsume  
   
         return  ($self->{ct}); # start tag or end tag  
   
         redo A;  
1892        } else {        } else {
1893            ## XML5 [ATTLIST]: Not defined yet.
1894          if ($self->{is_xml} and $self->{nc} == 0x003C) { # <          if ($self->{is_xml} and $self->{nc} == 0x003C) { # <
1895                        
1896            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 1812  sub _get_next_token ($) { Line 1900  sub _get_next_token ($) {
1900          }          }
1901          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1902          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1903                                q["&<],                                qq["&<\x09\x0C\x20],
1904                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1905    
1906          ## Stay in the state          ## Stay in the state
# Line 1830  sub _get_next_token ($) { Line 1918  sub _get_next_token ($) {
1918          redo A;          redo A;
1919        }        }
1920      } elsif ($self->{state} == ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE) {      } elsif ($self->{state} == ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE) {
1921        ## XML5: "Tag attribute value single quoted state".        ## XML5: "Tag attribute value single quoted state" and "DOCTYPE
1922          ## ATTLIST attribute value single quoted state".
1923    
1924        if ($self->{nc} == 0x0027) { # '        if ($self->{nc} == 0x0027) { # '
1925                    if ($self->{ct}->{type} == ATTLIST_TOKEN) {
1926          ## XML5: "Before attribute name state" (sic).            
1927          $self->{state} = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;            ## XML5: "DOCTYPE ATTLIST name after state".
1928              push @{$self->{ct}->{attrdefs}}, $self->{ca};
1929              $self->{state} = AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE;
1930            } else {
1931              
1932              ## XML5: "Before attribute name state" (sic).
1933              $self->{state} = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;
1934            }
1935                    
1936      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1937        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 1871  sub _get_next_token ($) { Line 1967  sub _get_next_token ($) {
1967      }      }
1968        
1969          redo A;          redo A;
1970          } elsif ($self->{is_xml} and
1971                   $is_space->{$self->{nc}}) {
1972            
1973            $self->{ca}->{value} .= ' ';
1974            ## Stay in the state.
1975            
1976        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1977          $self->{line_prev} = $self->{line};
1978          $self->{column_prev} = $self->{column};
1979          $self->{column}++;
1980          $self->{nc}
1981              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1982        } else {
1983          $self->{set_nc}->($self);
1984        }
1985      
1986            redo A;
1987        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1988          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1989          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
1990                        
1991            $self->{last_stag_name} = $self->{ct}->{tag_name};            $self->{last_stag_name} = $self->{ct}->{tag_name};
1992    
1993              $self->{state} = DATA_STATE;
1994              $self->{s_kwd} = '';
1995              ## reconsume
1996    
1997              ## Discard the token.
1998              #return  ($self->{ct}); # start tag
1999    
2000              redo A;
2001          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
2002            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
2003            if ($self->{ct}->{attributes}) {            if ($self->{ct}->{attributes}) {
# Line 1885  sub _get_next_token ($) { Line 2007  sub _get_next_token ($) {
2007              ## NOTE: This state should never be reached.              ## NOTE: This state should never be reached.
2008                            
2009            }            }
2010    
2011              $self->{state} = DATA_STATE;
2012              $self->{s_kwd} = '';
2013              ## reconsume
2014    
2015              ## Discard the token.
2016              #return  ($self->{ct}); # end tag
2017    
2018              redo A;
2019            } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
2020              ## XML5: No parse error above; not defined yet.
2021              push @{$self->{ct}->{attrdefs}}, $self->{ca};
2022              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2023              ## Reconsume.
2024    
2025              ## Discard the token.
2026              #return  ($self->{ct}); # ATTLIST
2027    
2028              redo A;
2029          } else {          } else {
2030            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
2031          }          }
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
         ## reconsume  
   
         return  ($self->{ct}); # start tag or end tag  
   
         redo A;  
2032        } else {        } else {
2033            ## XML5 [ATTLIST]: Not defined yet.
2034          if ($self->{is_xml} and $self->{nc} == 0x003C) { # <          if ($self->{is_xml} and $self->{nc} == 0x003C) { # <
2035                        
2036            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 1905  sub _get_next_token ($) { Line 2040  sub _get_next_token ($) {
2040          }          }
2041          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2042          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2043                                q['&<],                                qq['&<\x09\x0C\x20],
2044                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2045    
2046          ## Stay in the state          ## Stay in the state
# Line 1926  sub _get_next_token ($) { Line 2061  sub _get_next_token ($) {
2061        ## XML5: "Tag attribute value unquoted state".        ## XML5: "Tag attribute value unquoted state".
2062    
2063        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
2064                    if ($self->{ct}->{type} == ATTLIST_TOKEN) {
2065          ## XML5: "Tag attribute name before state".            
2066          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;            push @{$self->{ct}->{attrdefs}}, $self->{ca};
2067              $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
2068            } else {
2069              
2070              ## XML5: "Tag attribute name before state".
2071              $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
2072            }
2073                    
2074      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
2075        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 1969  sub _get_next_token ($) { Line 2110  sub _get_next_token ($) {
2110          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
2111                        
2112            $self->{last_stag_name} = $self->{ct}->{tag_name};            $self->{last_stag_name} = $self->{ct}->{tag_name};
2113    
2114              $self->{state} = DATA_STATE;
2115              $self->{s_kwd} = '';
2116              
2117        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
2118          $self->{line_prev} = $self->{line};
2119          $self->{column_prev} = $self->{column};
2120          $self->{column}++;
2121          $self->{nc}
2122              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
2123        } else {
2124          $self->{set_nc}->($self);
2125        }
2126      
2127              return  ($self->{ct}); # start tag
2128              redo A;
2129          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
2130            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
2131            if ($self->{ct}->{attributes}) {            if ($self->{ct}->{attributes}) {
# Line 1978  sub _get_next_token ($) { Line 2135  sub _get_next_token ($) {
2135              ## NOTE: This state should never be reached.              ## NOTE: This state should never be reached.
2136                            
2137            }            }
2138          } else {  
2139            die "$0: $self->{ct}->{type}: Unknown token type";            $self->{state} = DATA_STATE;
2140          }            $self->{s_kwd} = '';
2141          $self->{state} = DATA_STATE;            
         $self->{s_kwd} = '';  
           
2142      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
2143        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
2144        $self->{column_prev} = $self->{column};        $self->{column_prev} = $self->{column};
# Line 1994  sub _get_next_token ($) { Line 2149  sub _get_next_token ($) {
2149        $self->{set_nc}->($self);        $self->{set_nc}->($self);
2150      }      }
2151        
2152              return  ($self->{ct}); # end tag
2153          return  ($self->{ct}); # start tag or end tag            redo A;
2154            } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
2155          redo A;            push @{$self->{ct}->{attrdefs}}, $self->{ca};
2156              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2157              
2158        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
2159          $self->{line_prev} = $self->{line};
2160          $self->{column_prev} = $self->{column};
2161          $self->{column}++;
2162          $self->{nc}
2163              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
2164        } else {
2165          $self->{set_nc}->($self);
2166        }
2167      
2168              return  ($self->{ct}); # ATTLIST
2169              redo A;
2170            } else {
2171              die "$0: $self->{ct}->{type}: Unknown token type";
2172            }
2173        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed tag');  
2174          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
2175                        
2176              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed tag');
2177            $self->{last_stag_name} = $self->{ct}->{tag_name};            $self->{last_stag_name} = $self->{ct}->{tag_name};
2178    
2179              $self->{state} = DATA_STATE;
2180              $self->{s_kwd} = '';
2181              ## reconsume
2182    
2183              ## Discard the token.
2184              #return  ($self->{ct}); # start tag
2185              
2186              redo A;
2187          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
2188              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed tag');
2189            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
2190            if ($self->{ct}->{attributes}) {            if ($self->{ct}->{attributes}) {
2191                            
# Line 2012  sub _get_next_token ($) { Line 2194  sub _get_next_token ($) {
2194              ## NOTE: This state should never be reached.              ## NOTE: This state should never be reached.
2195                            
2196            }            }
2197    
2198              $self->{state} = DATA_STATE;
2199              $self->{s_kwd} = '';
2200              ## reconsume
2201    
2202              ## Discard the token.
2203              #return  ($self->{ct}); # end tag
2204    
2205              redo A;
2206            } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
2207              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
2208              push @{$self->{ct}->{attrdefs}}, $self->{ca};
2209              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2210              ## Reconsume.
2211    
2212              ## Discard the token.
2213              #return  ($self->{ct}); # ATTLIST
2214    
2215              redo A;
2216          } else {          } else {
2217            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
2218          }          }
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
         ## reconsume  
   
         return  ($self->{ct}); # start tag or end tag  
   
         redo A;  
2219        } else {        } else {
2220          if ({          if ({
2221               0x0022 => 1, # "               0x0022 => 1, # "
2222               0x0027 => 1, # '               0x0027 => 1, # '
2223               0x003D => 1, # =               0x003D => 1, # =
2224                 0x003C => 1, # <
2225              }->{$self->{nc}}) {              }->{$self->{nc}}) {
2226                        
2227            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 2036  sub _get_next_token ($) { Line 2231  sub _get_next_token ($) {
2231          }          }
2232          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2233          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2234                                q["'=& >],                                qq["'=& \x09\x0C>],
2235                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2236    
2237          ## Stay in the state          ## Stay in the state
# Line 2136  sub _get_next_token ($) { Line 2331  sub _get_next_token ($) {
2331          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2332          $self->{s_kwd} = '';          $self->{s_kwd} = '';
2333          ## Reconsume.          ## Reconsume.
2334          return  ($self->{ct}); # start tag or end tag  
2335            ## Discard the token.
2336            #return  ($self->{ct}); # start tag or end tag
2337    
2338          redo A;          redo A;
2339        } else {        } else {
2340                    
# Line 2203  sub _get_next_token ($) { Line 2401  sub _get_next_token ($) {
2401          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2402          $self->{s_kwd} = '';          $self->{s_kwd} = '';
2403          ## Reconsume.          ## Reconsume.
2404          return  ($self->{ct}); # start tag or end tag  
2405            ## Discard the token.
2406            #return  ($self->{ct}); # start tag or end tag
2407    
2408          redo A;          redo A;
2409        } else {        } else {
2410                    
# Line 2778  sub _get_next_token ($) { Line 2979  sub _get_next_token ($) {
2979        
2980          redo A;          redo A;
2981        }        }
2982      } elsif ($self->{state} == COMMENT_END_STATE) {      } elsif ($self->{state} == COMMENT_END_STATE or
2983                 $self->{state} == COMMENT_END_BANG_STATE) {
2984        ## XML5: "Comment end state" and "DOCTYPE comment end state".        ## XML5: "Comment end state" and "DOCTYPE comment end state".
2985          ## (No comment end bang state.)
2986    
2987        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2988          if ($self->{in_subset}) {          if ($self->{in_subset}) {
# Line 2806  sub _get_next_token ($) { Line 3009  sub _get_next_token ($) {
3009    
3010          redo A;          redo A;
3011        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
3012            if ($self->{state} == COMMENT_END_BANG_STATE) {
3013              
3014              $self->{ct}->{data} .= '--!'; # comment
3015              $self->{state} = COMMENT_END_DASH_STATE;
3016            } else {
3017              
3018              ## XML5: Not a parse error.
3019              $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',
3020                              line => $self->{line_prev},
3021                              column => $self->{column_prev});
3022              $self->{ct}->{data} .= '-'; # comment
3023              ## Stay in the state
3024            }
3025                    
3026          ## XML5: Not a parse error.      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3027          $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',        $self->{line_prev} = $self->{line};
3028                          line => $self->{line_prev},        $self->{column_prev} = $self->{column};
3029                          column => $self->{column_prev});        $self->{column}++;
3030          $self->{ct}->{data} .= '-'; # comment        $self->{nc}
3031          ## Stay in the state            = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3032        } else {
3033          $self->{set_nc}->($self);
3034        }
3035      
3036            redo A;
3037          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
3038                   $is_space->{$self->{nc}}) {
3039            
3040            $self->{parse_error}->(level => $self->{level}->{must}, type => 'comment end space'); # XXX error type
3041            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3042            $self->{state} = COMMENT_END_SPACE_STATE;
3043            
3044        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3045          $self->{line_prev} = $self->{line};
3046          $self->{column_prev} = $self->{column};
3047          $self->{column}++;
3048          $self->{nc}
3049              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3050        } else {
3051          $self->{set_nc}->($self);
3052        }
3053      
3054            redo A;
3055          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
3056                   $self->{nc} == 0x0021) { # !
3057            
3058            $self->{parse_error}->(level => $self->{level}->{must}, type => 'comment end bang'); # XXX error type
3059            $self->{state} = COMMENT_END_BANG_STATE;
3060                    
3061      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3062        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 2835  sub _get_next_token ($) { Line 3079  sub _get_next_token ($) {
3079            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
3080            $self->{s_kwd} = '';            $self->{s_kwd} = '';
3081          }          }
3082          ## reconsume          ## Reconsume.
3083    
3084          return  ($self->{ct}); # comment          return  ($self->{ct}); # comment
3085    
3086          redo A;          redo A;
3087        } else {        } else {
3088                    
3089          ## XML5: Not a parse error.          if ($self->{state} == COMMENT_END_BANG_STATE) {
3090          $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',            $self->{ct}->{data} .= '--!' . chr ($self->{nc}); # comment
3091                          line => $self->{line_prev},          } else {
3092                          column => $self->{column_prev});            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3093          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          }
3094          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
3095                    
3096      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 2861  sub _get_next_token ($) { Line 3105  sub _get_next_token ($) {
3105        
3106          redo A;          redo A;
3107        }        }
3108        } elsif ($self->{state} == COMMENT_END_SPACE_STATE) {
3109          ## XML5: Not exist.
3110    
3111          if ($self->{nc} == 0x003E) { # >
3112            if ($self->{in_subset}) {
3113              
3114              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3115            } else {
3116              
3117              $self->{state} = DATA_STATE;
3118              $self->{s_kwd} = '';
3119            }
3120            
3121        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3122          $self->{line_prev} = $self->{line};
3123          $self->{column_prev} = $self->{column};
3124          $self->{column}++;
3125          $self->{nc}
3126              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3127        } else {
3128          $self->{set_nc}->($self);
3129        }
3130      
3131    
3132            return  ($self->{ct}); # comment
3133    
3134            redo A;
3135          } elsif ($is_space->{$self->{nc}}) {
3136            
3137            $self->{ct}->{data} .= chr ($self->{nc}); # comment
3138            ## Stay in the state.
3139            
3140        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3141          $self->{line_prev} = $self->{line};
3142          $self->{column_prev} = $self->{column};
3143          $self->{column}++;
3144          $self->{nc}
3145              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3146        } else {
3147          $self->{set_nc}->($self);
3148        }
3149      
3150            redo A;
3151          } elsif ($self->{nc} == -1) {
3152            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed comment');
3153            if ($self->{in_subset}) {
3154              
3155              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3156            } else {
3157              
3158              $self->{state} = DATA_STATE;
3159              $self->{s_kwd} = '';
3160            }
3161            ## Reconsume.
3162    
3163            return  ($self->{ct}); # comment
3164    
3165            redo A;
3166          } else {
3167            
3168            $self->{ct}->{data} .= chr ($self->{nc}); # comment
3169            $self->{state} = COMMENT_STATE;
3170            
3171        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3172          $self->{line_prev} = $self->{line};
3173          $self->{column_prev} = $self->{column};
3174          $self->{column}++;
3175          $self->{nc}
3176              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3177        } else {
3178          $self->{set_nc}->($self);
3179        }
3180      
3181            redo A;
3182          }
3183      } elsif ($self->{state} == DOCTYPE_STATE) {      } elsif ($self->{state} == DOCTYPE_STATE) {
3184        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
3185                    
# Line 2877  sub _get_next_token ($) { Line 3196  sub _get_next_token ($) {
3196      }      }
3197        
3198          redo A;          redo A;
3199          } elsif ($self->{nc} == -1) {
3200            
3201            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3202            $self->{ct}->{quirks} = 1;
3203    
3204            $self->{state} = DATA_STATE;
3205            ## Reconsume.
3206            return  ($self->{ct}); # DOCTYPE (quirks)
3207    
3208            redo A;
3209        } else {        } else {
3210                    
3211          ## XML5: Unless EOF, swith to the bogus comment state.          ## XML5: Swith to the bogus comment state.
3212          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before DOCTYPE name');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before DOCTYPE name');
3213          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
3214          ## reconsume          ## reconsume
# Line 2924  sub _get_next_token ($) { Line 3253  sub _get_next_token ($) {
3253          return  ($self->{ct}); # DOCTYPE (quirks)          return  ($self->{ct}); # DOCTYPE (quirks)
3254    
3255          redo A;          redo A;
3256          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3257            
3258            $self->{ct}->{name} # DOCTYPE
3259                = chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3260            delete $self->{ct}->{quirks};
3261            $self->{state} = DOCTYPE_NAME_STATE;
3262            
3263        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3264          $self->{line_prev} = $self->{line};
3265          $self->{column_prev} = $self->{column};
3266          $self->{column}++;
3267          $self->{nc}
3268              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3269        } else {
3270          $self->{set_nc}->($self);
3271        }
3272      
3273            redo A;
3274        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3275                    
3276          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');
# Line 3010  sub _get_next_token ($) { Line 3357  sub _get_next_token ($) {
3357          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3358    
3359          redo A;          redo A;
3360          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3361            
3362            $self->{ct}->{name} # DOCTYPE
3363                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3364            delete $self->{ct}->{quirks};
3365            ## Stay in the state.
3366            
3367        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3368          $self->{line_prev} = $self->{line};
3369          $self->{column_prev} = $self->{column};
3370          $self->{column}++;
3371          $self->{nc}
3372              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3373        } else {
3374          $self->{set_nc}->($self);
3375        }
3376      
3377            redo A;
3378        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3379                    
3380          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
# Line 3041  sub _get_next_token ($) { Line 3406  sub _get_next_token ($) {
3406          redo A;          redo A;
3407        } else {        } else {
3408                    
3409          $self->{ct}->{name}          $self->{ct}->{name} .= chr ($self->{nc}); # DOCTYPE
3410            .= chr ($self->{nc}); # DOCTYPE          ## Stay in the state.
         ## Stay in the state  
3411                    
3412      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3413        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3077  sub _get_next_token ($) { Line 3441  sub _get_next_token ($) {
3441        
3442          redo A;          redo A;
3443        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3444            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3445              
3446              $self->{state} = DATA_STATE;
3447              $self->{s_kwd} = '';
3448            } else {
3449              
3450              $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
3451              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3452            }
3453                    
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3454                    
3455      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3456        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3091  sub _get_next_token ($) { Line 3462  sub _get_next_token ($) {
3462        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3463      }      }
3464        
3465            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3466          redo A;          redo A;
3467        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3468            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3469              
3470              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3471              $self->{state} = DATA_STATE;
3472              $self->{s_kwd} = '';
3473              $self->{ct}->{quirks} = 1;
3474            } else {
3475              
3476              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3477              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3478            }
3479                    
3480          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          ## Reconsume.
3481          $self->{state} = DATA_STATE;          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{s_kwd} = '';  
         ## reconsume  
   
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3482          redo A;          redo A;
3483        } elsif ($self->{nc} == 0x0050 or # P        } elsif ($self->{nc} == 0x0050 or # P
3484                 $self->{nc} == 0x0070) { # p                 $self->{nc} == 0x0070) { # p
# Line 3140  sub _get_next_token ($) { Line 3514  sub _get_next_token ($) {
3514      }      }
3515        
3516          redo A;          redo A;
3517        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{nc} == 0x0022 and # "
3518                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3519                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3520            
3521            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
3522            $self->{ct}->{value} = ''; # ENTITY
3523            
3524        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3525          $self->{line_prev} = $self->{line};
3526          $self->{column_prev} = $self->{column};
3527          $self->{column}++;
3528          $self->{nc}
3529              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3530        } else {
3531          $self->{set_nc}->($self);
3532        }
3533      
3534            redo A;
3535          } elsif ($self->{nc} == 0x0027 and # '
3536                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3537                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3538            
3539            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
3540            $self->{ct}->{value} = ''; # ENTITY
3541            
3542        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3543          $self->{line_prev} = $self->{line};
3544          $self->{column_prev} = $self->{column};
3545          $self->{column}++;
3546          $self->{nc}
3547              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3548        } else {
3549          $self->{set_nc}->($self);
3550        }
3551      
3552            redo A;
3553          } elsif ($self->{is_xml} and
3554                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3555                   $self->{nc} == 0x005B) { # [
3556                    
3557          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3558          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 3159  sub _get_next_token ($) { Line 3571  sub _get_next_token ($) {
3571          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3572          redo A;          redo A;
3573        } else {        } else {
3574                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name'); ## TODO: type
3575          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name');  
3576          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3577              
3578              $self->{ct}->{quirks} = 1;
3579              $self->{state} = BOGUS_DOCTYPE_STATE;
3580            } else {
3581              
3582              $self->{state} = BOGUS_MD_STATE;
3583            }
3584    
         $self->{state} = BOGUS_DOCTYPE_STATE;  
3585                    
3586      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3587        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3235  sub _get_next_token ($) { Line 3653  sub _get_next_token ($) {
3653        
3654          redo A;          redo A;
3655        } else {        } else {
3656                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name', ## TODO: type
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name',  
3657                          line => $self->{line_prev},                          line => $self->{line_prev},
3658                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3659          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3660              
3661          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3662              $self->{state} = BOGUS_DOCTYPE_STATE;
3663            } else {
3664              
3665              $self->{state} = BOGUS_MD_STATE;
3666            }
3667          ## Reconsume.          ## Reconsume.
3668          redo A;          redo A;
3669        }        }
# Line 3303  sub _get_next_token ($) { Line 3725  sub _get_next_token ($) {
3725        
3726          redo A;          redo A;
3727        } else {        } else {
3728                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name', ## TODO: type
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name',  
3729                          line => $self->{line_prev},                          line => $self->{line_prev},
3730                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3731          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3732              
3733          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3734              $self->{state} = BOGUS_DOCTYPE_STATE;
3735            } else {
3736              
3737              $self->{state} = BOGUS_MD_STATE;
3738            }
3739          ## Reconsume.          ## Reconsume.
3740          redo A;          redo A;
3741        }        }
# Line 3362  sub _get_next_token ($) { Line 3788  sub _get_next_token ($) {
3788        
3789          redo A;          redo A;
3790        } elsif ($self->{nc} eq 0x003E) { # >        } elsif ($self->{nc} eq 0x003E) { # >
           
3791          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3792            
3793          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3794          $self->{s_kwd} = '';            
3795              $self->{state} = DATA_STATE;
3796              $self->{s_kwd} = '';
3797              $self->{ct}->{quirks} = 1;
3798            } else {
3799              
3800              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3801            }
3802            
3803                    
3804      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3805        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3378  sub _get_next_token ($) { Line 3811  sub _get_next_token ($) {
3811        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3812      }      }
3813        
3814            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3815          redo A;          redo A;
3816        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3817            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3818              
3819              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3820              $self->{state} = DATA_STATE;
3821              $self->{s_kwd} = '';
3822              $self->{ct}->{quirks} = 1;
3823            } else {
3824              
3825              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3826              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3827            }
3828                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3829          ## reconsume          ## reconsume
   
         $self->{ct}->{quirks} = 1;  
3830          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3831          redo A;          redo A;
3832        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3833                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3834                   $self->{nc} == 0x005B) { # [
3835                    
3836          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3837          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3415  sub _get_next_token ($) { Line 3851  sub _get_next_token ($) {
3851          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3852          redo A;          redo A;
3853        } else {        } else {
           
3854          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after PUBLIC');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after PUBLIC');
         $self->{ct}->{quirks} = 1;  
3855    
3856          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3857              
3858              $self->{ct}->{quirks} = 1;
3859              $self->{state} = BOGUS_DOCTYPE_STATE;
3860            } else {
3861              
3862              $self->{state} = BOGUS_MD_STATE;
3863            }
3864    
3865                    
3866      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3867        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3450  sub _get_next_token ($) { Line 3892  sub _get_next_token ($) {
3892        
3893          redo A;          redo A;
3894        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3895          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3896    
3897          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3898          $self->{s_kwd} = '';            
3899              $self->{state} = DATA_STATE;
3900              $self->{s_kwd} = '';
3901              $self->{ct}->{quirks} = 1;
3902            } else {
3903              
3904              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3905            }
3906    
3907                    
3908      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3909        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3466  sub _get_next_token ($) { Line 3915  sub _get_next_token ($) {
3915        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3916      }      }
3917        
3918            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3919          redo A;          redo A;
3920        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3921          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3922    
3923          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3924          $self->{s_kwd} = '';            
3925          ## reconsume            $self->{state} = DATA_STATE;
3926              $self->{s_kwd} = '';
3927          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
3928            } else {
3929              
3930              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3931            }
3932            
3933            ## Reconsume.
3934          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3935          redo A;          redo A;
3936        } else {        } else {
3937                    
3938          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3939          $self->{read_until}->($self->{ct}->{pubid}, q[">],          $self->{read_until}->($self->{ct}->{pubid}, q[">],
3940                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3941    
# Line 3521  sub _get_next_token ($) { Line 3970  sub _get_next_token ($) {
3970        
3971          redo A;          redo A;
3972        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3973          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3974    
3975          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3976          $self->{s_kwd} = '';            
3977              $self->{state} = DATA_STATE;
3978              $self->{s_kwd} = '';
3979              $self->{ct}->{quirks} = 1;
3980            } else {
3981              
3982              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3983            }
3984    
3985                    
3986      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3987        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3537  sub _get_next_token ($) { Line 3993  sub _get_next_token ($) {
3993        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3994      }      }
3995        
3996            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3997          redo A;          redo A;
3998        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3999          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
4000    
4001          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4002          $self->{s_kwd} = '';            
4003              $self->{state} = DATA_STATE;
4004              $self->{s_kwd} = '';
4005              $self->{ct}->{quirks} = 1;
4006            } else {
4007              
4008              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4009            }
4010          
4011          ## reconsume          ## reconsume
4012            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4013          redo A;          redo A;
4014        } else {        } else {
4015                    
4016          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4017          $self->{read_until}->($self->{ct}->{pubid}, q['>],          $self->{read_until}->($self->{ct}->{pubid}, q['>],
4018                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
4019    
# Line 3593  sub _get_next_token ($) { Line 4049  sub _get_next_token ($) {
4049          redo A;          redo A;
4050        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
4051                    
4052          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
4053          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
4054                    
4055      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 3609  sub _get_next_token ($) { Line 4065  sub _get_next_token ($) {
4065          redo A;          redo A;
4066        } elsif ($self->{nc} == 0x0027) { # '        } elsif ($self->{nc} == 0x0027) { # '
4067                    
4068          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
4069          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
4070                    
4071      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 3624  sub _get_next_token ($) { Line 4080  sub _get_next_token ($) {
4080        
4081          redo A;          redo A;
4082        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4083          if ($self->{is_xml}) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4084                        if ($self->{is_xml}) {
4085            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');              
4086                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4087              } else {
4088                
4089              }
4090              $self->{state} = DATA_STATE;
4091              $self->{s_kwd} = '';
4092          } else {          } else {
4093                        if ($self->{ct}->{type} == NOTATION_TOKEN) {
4094                
4095              } else {
4096                
4097                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');            
4098              }
4099              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4100          }          }
4101          $self->{state} = DATA_STATE;          
         $self->{s_kwd} = '';  
4102                    
4103      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4104        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3643  sub _get_next_token ($) { Line 4110  sub _get_next_token ($) {
4110        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4111      }      }
4112        
4113            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
4114          redo A;          redo A;
4115        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4116            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4117              
4118              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4119              
4120              $self->{state} = DATA_STATE;
4121              $self->{s_kwd} = '';
4122              $self->{ct}->{quirks} = 1;
4123            } else {
4124              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4125              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4126            }
4127                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4128          ## reconsume          ## reconsume
4129            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4130          redo A;          redo A;
4131        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4132                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4133                   $self->{nc} == 0x005B) { # [
4134                    
4135          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4136          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3679  sub _get_next_token ($) { Line 4150  sub _get_next_token ($) {
4150          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4151          redo A;          redo A;
4152        } else {        } else {
           
4153          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after PUBLIC literal');
         $self->{ct}->{quirks} = 1;  
4154    
4155          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4156              
4157              $self->{ct}->{quirks} = 1;
4158              $self->{state} = BOGUS_DOCTYPE_STATE;
4159            } else {
4160              
4161              $self->{state} = BOGUS_MD_STATE;
4162            }
4163    
4164                    
4165      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4166        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3746  sub _get_next_token ($) { Line 4223  sub _get_next_token ($) {
4223        
4224          redo A;          redo A;
4225        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
4226          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4227                    
4228      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4229        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3762  sub _get_next_token ($) { Line 4236  sub _get_next_token ($) {
4236      }      }
4237        
4238    
4239          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4240          return  ($self->{ct}); # DOCTYPE            
4241              $self->{state} = DATA_STATE;
4242              $self->{s_kwd} = '';
4243              $self->{ct}->{quirks} = 1;
4244            } else {
4245              
4246              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4247            }
4248    
4249            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4250          redo A;          redo A;
4251        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4252            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4253              
4254              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4255              $self->{state} = DATA_STATE;
4256              $self->{s_kwd} = '';
4257              $self->{ct}->{quirks} = 1;
4258            } else {
4259              
4260              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4261              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4262            }
4263                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4264          ## reconsume          ## reconsume
4265            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4266          redo A;          redo A;
4267        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4268                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4269                   $self->{nc} == 0x005B) { # [
4270                    
4271          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4272    
# Line 3799  sub _get_next_token ($) { Line 4287  sub _get_next_token ($) {
4287          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4288          redo A;          redo A;
4289        } else {        } else {
           
4290          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM');
         $self->{ct}->{quirks} = 1;  
4291    
4292          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4293                        
4294              $self->{ct}->{quirks} = 1;
4295              $self->{state} = BOGUS_DOCTYPE_STATE;
4296            } else {
4297              
4298              $self->{state} = BOGUS_MD_STATE;
4299            }
4300    
4301                    
4302      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4303        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3834  sub _get_next_token ($) { Line 4328  sub _get_next_token ($) {
4328        
4329          redo A;          redo A;
4330        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >
           
4331          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4332    
4333          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4334          $self->{s_kwd} = '';            
4335              $self->{state} = DATA_STATE;
4336              $self->{s_kwd} = '';
4337              $self->{ct}->{quirks} = 1;
4338            } else {
4339              
4340              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4341            }
4342            
4343                    
4344      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4345        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3850  sub _get_next_token ($) { Line 4351  sub _get_next_token ($) {
4351        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4352      }      }
4353        
4354            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4355          redo A;          redo A;
4356        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4357          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4358    
4359          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4360          $self->{s_kwd} = '';            
4361              $self->{state} = DATA_STATE;
4362              $self->{s_kwd} = '';
4363              $self->{ct}->{quirks} = 1;
4364            } else {
4365              
4366              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4367            }
4368            
4369          ## reconsume          ## reconsume
4370            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4371          redo A;          redo A;
4372        } else {        } else {
4373                    
4374          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4375          $self->{read_until}->($self->{ct}->{sysid}, q[">],          $self->{read_until}->($self->{ct}->{sysid}, q[">],
4376                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4377    
# Line 3927  sub _get_next_token ($) { Line 4428  sub _get_next_token ($) {
4428    
4429          redo A;          redo A;
4430        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4431          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4432    
4433          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4434          $self->{s_kwd} = '';            
4435          ## reconsume            $self->{state} = DATA_STATE;
4436              $self->{s_kwd} = '';
4437          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
4438          return  ($self->{ct}); # DOCTYPE          } else {
4439              
4440              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4441            }
4442    
4443            ## reconsume
4444            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4445          redo A;          redo A;
4446        } else {        } else {
4447                    
4448          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4449          $self->{read_until}->($self->{ct}->{sysid}, q['>],          $self->{read_until}->($self->{ct}->{sysid}, q['>],
4450                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4451    
# Line 3961  sub _get_next_token ($) { Line 4465  sub _get_next_token ($) {
4465        }        }
4466      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
4467        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4468                    if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
4469          ## Stay in the state            
4470              $self->{state} = BEFORE_NDATA_STATE;
4471            } else {
4472              
4473              ## Stay in the state
4474            }
4475                    
4476      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4477        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3976  sub _get_next_token ($) { Line 4485  sub _get_next_token ($) {
4485        
4486          redo A;          redo A;
4487        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4488            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4489              
4490              $self->{state} = DATA_STATE;
4491              $self->{s_kwd} = '';
4492            } else {
4493              
4494              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4495            }
4496    
4497                    
4498          $self->{state} = DATA_STATE;      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4499          $self->{s_kwd} = '';        $self->{line_prev} = $self->{line};
4500          $self->{column_prev} = $self->{column};
4501          $self->{column}++;
4502          $self->{nc}
4503              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4504        } else {
4505          $self->{set_nc}->($self);
4506        }
4507      
4508            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4509            redo A;
4510          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4511                   ($self->{nc} == 0x004E or # N
4512                    $self->{nc} == 0x006E)) { # n
4513            
4514            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before NDATA'); ## TODO: type
4515            $self->{state} = NDATA_STATE;
4516            $self->{kwd} = chr $self->{nc};
4517                    
4518      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4519        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3990  sub _get_next_token ($) { Line 4525  sub _get_next_token ($) {
4525        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4526      }      }
4527        
   
         return  ($self->{ct}); # DOCTYPE  
   
4528          redo A;          redo A;
4529        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4530                    if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4531          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');            
4532          $self->{state} = DATA_STATE;            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4533          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
4534          ## reconsume            $self->{s_kwd} = '';
4535              $self->{ct}->{quirks} = 1;
4536          $self->{ct}->{quirks} = 1;          } else {
4537          return  ($self->{ct}); # DOCTYPE            
4538              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4539              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4540            }
4541    
4542            ## reconsume
4543            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4544          redo A;          redo A;
4545        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4546                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4547                   $self->{nc} == 0x005B) { # [
4548                    
4549          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4550          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 4024  sub _get_next_token ($) { Line 4563  sub _get_next_token ($) {
4563          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4564          redo A;          redo A;
4565        } else {        } else {
           
4566          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
         #$self->{ct}->{quirks} = 1;  
4567    
4568          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4569              
4570              #$self->{ct}->{quirks} = 1;
4571              $self->{state} = BOGUS_DOCTYPE_STATE;
4572            } else {
4573              
4574              $self->{state} = BOGUS_MD_STATE;
4575            }
4576    
4577            
4578        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4579          $self->{line_prev} = $self->{line};
4580          $self->{column_prev} = $self->{column};
4581          $self->{column}++;
4582          $self->{nc}
4583              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4584        } else {
4585          $self->{set_nc}->($self);
4586        }
4587      
4588            redo A;
4589          }
4590        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
4591          if ($is_space->{$self->{nc}}) {
4592            
4593            ## Stay in the state.
4594            
4595        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4596          $self->{line_prev} = $self->{line};
4597          $self->{column_prev} = $self->{column};
4598          $self->{column}++;
4599          $self->{nc}
4600              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4601        } else {
4602          $self->{set_nc}->($self);
4603        }
4604      
4605            redo A;
4606          } elsif ($self->{nc} == 0x003E) { # >
4607            
4608            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4609            
4610        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4611          $self->{line_prev} = $self->{line};
4612          $self->{column_prev} = $self->{column};
4613          $self->{column}++;
4614          $self->{nc}
4615              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4616        } else {
4617          $self->{set_nc}->($self);
4618        }
4619      
4620            return  ($self->{ct}); # ENTITY
4621            redo A;
4622          } elsif ($self->{nc} == 0x004E or # N
4623                   $self->{nc} == 0x006E) { # n
4624            
4625            $self->{state} = NDATA_STATE;
4626            $self->{kwd} = chr $self->{nc};
4627            
4628        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4629          $self->{line_prev} = $self->{line};
4630          $self->{column_prev} = $self->{column};
4631          $self->{column}++;
4632          $self->{nc}
4633              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4634        } else {
4635          $self->{set_nc}->($self);
4636        }
4637      
4638            redo A;
4639          } elsif ($self->{nc} == -1) {
4640            
4641            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4642            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4643            ## reconsume
4644            return  ($self->{ct}); # ENTITY
4645            redo A;
4646          } else {
4647            
4648            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
4649            $self->{state} = BOGUS_MD_STATE;
4650                    
4651      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4652        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4252  sub _get_next_token ($) { Line 4870  sub _get_next_token ($) {
4870              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4871              $self->{entity_add} => 1,              $self->{entity_add} => 1,
4872            }->{$self->{nc}}) {            }->{$self->{nc}}) {
4873                    if ($self->{is_xml}) {
4874              
4875              $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
4876                              line => $self->{line_prev},
4877                              column => $self->{column_prev}
4878                                  + ($self->{nc} == -1 ? 1 : 0));
4879            } else {
4880              
4881              ## No error
4882            }
4883          ## Don't consume          ## Don't consume
         ## No error  
4884          ## Return nothing.          ## Return nothing.
4885          #          #
4886        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 4273  sub _get_next_token ($) { Line 4899  sub _get_next_token ($) {
4899      }      }
4900        
4901          redo A;          redo A;
4902        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
4903                   (0x0041 <= $self->{nc} and
4904                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
4905                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
4906                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 4327  sub _get_next_token ($) { Line 4954  sub _get_next_token ($) {
4954          redo A;          redo A;
4955        }        }
4956      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
4957        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
           $self->{nc} == 0x0058) { # X  
4958                    
4959          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
4960          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 4344  sub _get_next_token ($) { Line 4970  sub _get_next_token ($) {
4970      }      }
4971        
4972          redo A;          redo A;
4973          } elsif ($self->{nc} == 0x0058) { # X
4974            
4975            if ($self->{is_xml}) {
4976              $self->{parse_error}->(level => $self->{level}->{must}, type => 'uppercase hcro'); ## TODO: type
4977            }
4978            $self->{state} = HEXREF_X_STATE;
4979            $self->{kwd} .= chr $self->{nc};
4980            
4981        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4982          $self->{line_prev} = $self->{line};
4983          $self->{column_prev} = $self->{column};
4984          $self->{column}++;
4985          $self->{nc}
4986              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4987        } else {
4988          $self->{set_nc}->($self);
4989        }
4990      
4991            redo A;
4992        } elsif (0x0030 <= $self->{nc} and        } elsif (0x0030 <= $self->{nc} and
4993                 $self->{nc} <= 0x0039) { # 0..9                 $self->{nc} <= 0x0039) { # 0..9
4994                    
# Line 4434  sub _get_next_token ($) { Line 5079  sub _get_next_token ($) {
5079        my $code = $self->{kwd};        my $code = $self->{kwd};
5080        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5081        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5082        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5083              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5084              ($self->{is_xml} and $code == 0x0000)) {
5085                    
5086          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5087                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4587  sub _get_next_token ($) { Line 5234  sub _get_next_token ($) {
5234        my $code = $self->{kwd};        my $code = $self->{kwd};
5235        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5236        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5237        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5238              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5239              ($self->{is_xml} and $code == 0x0000)) {
5240                    
5241          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5242                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4621  sub _get_next_token ($) { Line 5270  sub _get_next_token ($) {
5270          redo A;          redo A;
5271        }        }
5272      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
5273        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
5274            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
5275            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
5276              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
5277             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
5278              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
5279             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
5280              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
5281             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
5282                    {
5283                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
5284                      $self->{entity_add} => 1,
5285                    }->{$self->{nc}}))) {
5286          our $EntityChar;          our $EntityChar;
5287          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5288          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
5289                $self->{ge}->{$self->{kwd}}) {
5290            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
5291                            if (defined $self->{ge}->{$self->{kwd}}) {
5292              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
5293                    
5294                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
5295                  } else {
5296                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
5297                      
5298                      $self->{parse_error}->(level => $self->{level}->{must}, type => 'unparsed entity', ## TODO: type
5299                                      value => $self->{kwd});
5300                    } else {
5301                      
5302                    }
5303                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
5304                  }
5305                } else {
5306                  if ($self->{is_xml}) {
5307                    
5308                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'entity not declared', ## TODO: type
5309                                    value => $self->{kwd},
5310                                    level => {
5311                                              'amp;' => $self->{level}->{warn},
5312                                              'quot;' => $self->{level}->{warn},
5313                                              'lt;' => $self->{level}->{warn},
5314                                              'gt;' => $self->{level}->{warn},
5315                                              'apos;' => $self->{level}->{warn},
5316                                             }->{$self->{kwd}} ||
5317                                             $self->{level}->{must});
5318                  } else {
5319                    
5320                  }
5321                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
5322                }
5323              $self->{entity__match} = 1;              $self->{entity__match} = 1;
5324                            
5325      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5031  sub _get_next_token ($) { Line 5715  sub _get_next_token ($) {
5715          ## XML5: Not defined yet.          ## XML5: Not defined yet.
5716    
5717          ## TODO:          ## TODO:
5718    
5719            if (not $self->{stop_processing} and
5720                not $self->{document}->xml_standalone) {
5721              $self->{parse_error}->(level => $self->{level}->{must}, type => 'stop processing', ## TODO: type
5722                              level => $self->{level}->{info});
5723              $self->{stop_processing} = 1;
5724            }
5725    
5726                    
5727      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
5728        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5253  sub _get_next_token ($) { Line 5945  sub _get_next_token ($) {
5945      }      }
5946        
5947          redo A;          redo A;
5948        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
5949                   $self->{nc} == 0x0065) { # e
5950          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
5951          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5952                    
# Line 5268  sub _get_next_token ($) { Line 5961  sub _get_next_token ($) {
5961      }      }
5962        
5963          redo A;          redo A;
5964        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
5965                   $self->{nc} == 0x0061) { # a
5966          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
5967          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5968                    
# Line 5283  sub _get_next_token ($) { Line 5977  sub _get_next_token ($) {
5977      }      }
5978        
5979          redo A;          redo A;
5980        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
5981                   $self->{nc} == 0x006E) { # n
5982          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
5983          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5984                    
# Line 5311  sub _get_next_token ($) { Line 6006  sub _get_next_token ($) {
6006        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
6007        redo A;        redo A;
6008      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
6009        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
6010              $self->{nc} == 0x006E) { # n
6011          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
6012          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6013                    
# Line 5326  sub _get_next_token ($) { Line 6022  sub _get_next_token ($) {
6022      }      }
6023        
6024          redo A;          redo A;
6025        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
6026                   $self->{nc} == 0x006C) { # l
6027          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
6028          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
6029          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 5354  sub _get_next_token ($) { Line 6051  sub _get_next_token ($) {
6051          redo A;          redo A;
6052        }        }
6053      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
6054        if ($self->{nc} == {        if ($self->{nc} == [
6055              'EN' => 0x0054, # T              undef,
6056              'ENT' => 0x0049, # I              undef,
6057              'ENTI' => 0x0054, # T              0x0054, # T
6058            }->{$self->{kwd}}) {              0x0049, # I
6059                0x0054, # T
6060              ]->[length $self->{kwd}] or
6061              $self->{nc} == [
6062                undef,
6063                undef,
6064                0x0074, # t
6065                0x0069, # i
6066                0x0074, # t
6067              ]->[length $self->{kwd}]) {
6068          ## Stay in the state.          ## Stay in the state.
6069          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6070                    
# Line 5373  sub _get_next_token ($) { Line 6079  sub _get_next_token ($) {
6079      }      }
6080        
6081          redo A;          redo A;
6082        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
6083                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
6084          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
6085            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
6086              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6087                              text => 'ENTITY',
6088                              line => $self->{line_prev},
6089                              column => $self->{column_prev} - 4);
6090            }
6091            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
6092                         line => $self->{line_prev},                         line => $self->{line_prev},
6093                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
6094          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 5403  sub _get_next_token ($) { Line 6116  sub _get_next_token ($) {
6116          redo A;          redo A;
6117        }        }
6118      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
6119        if ($self->{nc} == {        if ($self->{nc} == [
6120              'EL' => 0x0045, # E             undef,
6121              'ELE' => 0x004D, # M             undef,
6122              'ELEM' => 0x0045, # E             0x0045, # E
6123              'ELEME' => 0x004E, # N             0x004D, # M
6124            }->{$self->{kwd}}) {             0x0045, # E
6125               0x004E, # N
6126              ]->[length $self->{kwd}] or
6127              $self->{nc} == [
6128               undef,
6129               undef,
6130               0x0065, # e
6131               0x006D, # m
6132               0x0065, # e
6133               0x006E, # n
6134              ]->[length $self->{kwd}]) {
6135          ## Stay in the state.          ## Stay in the state.
6136          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6137                    
# Line 5423  sub _get_next_token ($) { Line 6146  sub _get_next_token ($) {
6146      }      }
6147        
6148          redo A;          redo A;
6149        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
6150                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6151                    $self->{nc} == 0x0074)) { # t
6152            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
6153              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6154                              text => 'ELEMENT',
6155                              line => $self->{line_prev},
6156                              column => $self->{column_prev} - 5);
6157            }
6158          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
6159                         line => $self->{line_prev},                         line => $self->{line_prev},
6160                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6161          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6162                    
6163      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5453  sub _get_next_token ($) { Line 6183  sub _get_next_token ($) {
6183          redo A;          redo A;
6184        }        }
6185      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
6186        if ($self->{nc} == {        if ($self->{nc} == [
6187              'A' => 0x0054, # T             undef,
6188              'AT' => 0x0054, # T             0x0054, # T
6189              'ATT' => 0x004C, # L             0x0054, # T
6190              'ATTL' => 0x0049, # I             0x004C, # L
6191              'ATTLI' => 0x0053, # S             0x0049, # I
6192            }->{$self->{kwd}}) {             0x0053, # S
6193              ]->[length $self->{kwd}] or
6194              $self->{nc} == [
6195               undef,
6196               0x0074, # t
6197               0x0074, # t
6198               0x006C, # l
6199               0x0069, # i
6200               0x0073, # s
6201              ]->[length $self->{kwd}]) {
6202          ## Stay in the state.          ## Stay in the state.
6203          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6204                    
# Line 5474  sub _get_next_token ($) { Line 6213  sub _get_next_token ($) {
6213      }      }
6214        
6215          redo A;          redo A;
6216        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
6217                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6218                    $self->{nc} == 0x0074)) { # t
6219            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
6220              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6221                              text => 'ATTLIST',
6222                              line => $self->{line_prev},
6223                              column => $self->{column_prev} - 5);
6224            }
6225          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
6226                           attrdefs => [],
6227                         line => $self->{line_prev},                         line => $self->{line_prev},
6228                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6229          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6230                    
6231      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5504  sub _get_next_token ($) { Line 6251  sub _get_next_token ($) {
6251          redo A;          redo A;
6252        }        }
6253      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
6254        if ($self->{nc} == {        if ($self->{nc} == [
6255              'N' => 0x004F, # O             undef,
6256              'NO' => 0x0054, # T             0x004F, # O
6257              'NOT' => 0x0041, # A             0x0054, # T
6258              'NOTA' => 0x0054, # T             0x0041, # A
6259              'NOTAT' => 0x0049, # I             0x0054, # T
6260              'NOTATI' => 0x004F, # O             0x0049, # I
6261            }->{$self->{kwd}}) {             0x004F, # O
6262              ]->[length $self->{kwd}] or
6263              $self->{nc} == [
6264               undef,
6265               0x006F, # o
6266               0x0074, # t
6267               0x0061, # a
6268               0x0074, # t
6269               0x0069, # i
6270               0x006F, # o
6271              ]->[length $self->{kwd}]) {
6272          ## Stay in the state.          ## Stay in the state.
6273          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6274                    
# Line 5526  sub _get_next_token ($) { Line 6283  sub _get_next_token ($) {
6283      }      }
6284        
6285          redo A;          redo A;
6286        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
6287                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
6288                    $self->{nc} == 0x006E)) { # n
6289            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
6290              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6291                              text => 'NOTATION',
6292                              line => $self->{line_prev},
6293                              column => $self->{column_prev} - 6);
6294            }
6295          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
6296                         line => $self->{line_prev},                         line => $self->{line_prev},
6297                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
6298          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6299                    
6300      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5739  sub _get_next_token ($) { Line 6503  sub _get_next_token ($) {
6503        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".
6504                
6505        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
6506          ## TODO:          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6507          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
6508            } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6509              $self->{state} = AFTER_ELEMENT_NAME_STATE;
6510            } else { # ENTITY/NOTATION
6511              $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6512            }
6513                    
6514      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6515        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5757  sub _get_next_token ($) { Line 6526  sub _get_next_token ($) {
6526          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6527            #            #
6528          } else {          } else {
6529            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md body'); ## TODO: type            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
6530          }          }
6531          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6532                    
# Line 5831  sub _get_next_token ($) { Line 6600  sub _get_next_token ($) {
6600          ## XML5: No parse error.          ## XML5: No parse error.
6601          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
6602          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
6603            return  ($self->{ct});
6604          redo A;          redo A;
6605        } else {        } else {
6606          ## XML5: Not defined yet.          ## XML5: Not defined yet.
6607            $self->{ca} = {name => chr ($self->{nc}), # attrdef
6608          ## TODO: ...                         tokens => [],
6609                           line => $self->{line}, column => $self->{column}};
6610          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_NAME_STATE;
6611          $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded          
6612        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6613          $self->{line_prev} = $self->{line};
6614          $self->{column_prev} = $self->{column};
6615          $self->{column}++;
6616          $self->{nc}
6617              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6618        } else {
6619          $self->{set_nc}->($self);
6620        }
6621      
6622            redo A;
6623          }
6624        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_NAME_STATE) {
6625          if ($is_space->{$self->{nc}}) {
6626            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_NAME_AFTER_STATE;
6627            
6628        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6629          $self->{line_prev} = $self->{line};
6630          $self->{column_prev} = $self->{column};
6631          $self->{column}++;
6632          $self->{nc}
6633              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6634        } else {
6635          $self->{set_nc}->($self);
6636        }
6637      
6638            redo A;
6639          } elsif ($self->{nc} == 0x003E) { # >
6640            ## XML5: Same as "anything else".
6641            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no attr type'); ## TODO: type
6642            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6643            
6644        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6645          $self->{line_prev} = $self->{line};
6646          $self->{column_prev} = $self->{column};
6647          $self->{column}++;
6648          $self->{nc}
6649              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6650        } else {
6651          $self->{set_nc}->($self);
6652        }
6653      
6654            return  ($self->{ct}); # ATTLIST
6655            redo A;
6656          } elsif ($self->{nc} == 0x0028) { # (
6657            ## XML5: Same as "anything else".
6658            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before paren'); ## TODO: type
6659            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
6660            
6661        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6662          $self->{line_prev} = $self->{line};
6663          $self->{column_prev} = $self->{column};
6664          $self->{column}++;
6665          $self->{nc}
6666              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6667        } else {
6668          $self->{set_nc}->($self);
6669        }
6670      
6671            redo A;
6672          } elsif ($self->{nc} == -1) {
6673            ## XML5: No parse error.
6674            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
6675            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
6676            
6677        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6678          $self->{line_prev} = $self->{line};
6679          $self->{column_prev} = $self->{column};
6680          $self->{column}++;
6681          $self->{nc}
6682              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6683        } else {
6684          $self->{set_nc}->($self);
6685        }
6686      
6687            return  ($self->{ct}); # ATTLIST
6688            redo A;
6689          } else {
6690            ## XML5: Not defined yet.
6691            $self->{ca}->{name} .= chr $self->{nc};
6692            ## Stay in the state.
6693            
6694        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6695          $self->{line_prev} = $self->{line};
6696          $self->{column_prev} = $self->{column};
6697          $self->{column}++;
6698          $self->{nc}
6699              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6700        } else {
6701          $self->{set_nc}->($self);
6702        }
6703      
6704            redo A;
6705          }
6706        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_NAME_AFTER_STATE) {
6707          if ($is_space->{$self->{nc}}) {
6708            ## Stay in the state.
6709            
6710        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6711          $self->{line_prev} = $self->{line};
6712          $self->{column_prev} = $self->{column};
6713          $self->{column}++;
6714          $self->{nc}
6715              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6716        } else {
6717          $self->{set_nc}->($self);
6718        }
6719      
6720            redo A;
6721          } elsif ($self->{nc} == 0x003E) { # >
6722            ## XML5: Same as "anything else".
6723            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no attr type'); ## TODO: type
6724            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6725            
6726        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6727          $self->{line_prev} = $self->{line};
6728          $self->{column_prev} = $self->{column};
6729          $self->{column}++;
6730          $self->{nc}
6731              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6732        } else {
6733          $self->{set_nc}->($self);
6734        }
6735      
6736            return  ($self->{ct}); # ATTLIST
6737            redo A;
6738          } elsif ($self->{nc} == 0x0028) { # (
6739            ## XML5: Same as "anything else".
6740            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
6741            
6742        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6743          $self->{line_prev} = $self->{line};
6744          $self->{column_prev} = $self->{column};
6745          $self->{column}++;
6746          $self->{nc}
6747              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6748        } else {
6749          $self->{set_nc}->($self);
6750        }
6751      
6752            redo A;
6753          } elsif ($self->{nc} == -1) {
6754            ## XML5: No parse error.
6755            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
6756            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
6757            
6758        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6759          $self->{line_prev} = $self->{line};
6760          $self->{column_prev} = $self->{column};
6761          $self->{column}++;
6762          $self->{nc}
6763              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6764        } else {
6765          $self->{set_nc}->($self);
6766        }
6767      
6768            return  ($self->{ct});
6769            redo A;
6770          } else {
6771            ## XML5: Not defined yet.
6772            $self->{ca}->{type} = chr $self->{nc};
6773            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_STATE;
6774            
6775        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6776          $self->{line_prev} = $self->{line};
6777          $self->{column_prev} = $self->{column};
6778          $self->{column}++;
6779          $self->{nc}
6780              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6781        } else {
6782          $self->{set_nc}->($self);
6783        }
6784      
6785            redo A;
6786          }
6787        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_STATE) {
6788          if ($is_space->{$self->{nc}}) {
6789            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_AFTER_STATE;
6790            
6791        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6792          $self->{line_prev} = $self->{line};
6793          $self->{column_prev} = $self->{column};
6794          $self->{column}++;
6795          $self->{nc}
6796              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6797        } else {
6798          $self->{set_nc}->($self);
6799        }
6800      
6801            redo A;
6802          } elsif ($self->{nc} == 0x0023) { # #
6803            ## XML5: Same as "anything else".
6804            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before default value'); ## TODO: type
6805            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE;
6806            
6807        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6808          $self->{line_prev} = $self->{line};
6809          $self->{column_prev} = $self->{column};
6810          $self->{column}++;
6811          $self->{nc}
6812              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6813        } else {
6814          $self->{set_nc}->($self);
6815        }
6816      
6817            redo A;
6818          } elsif ($self->{nc} == 0x0022) { # "
6819            ## XML5: Same as "anything else".
6820            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before default value'); ## TODO: type
6821            $self->{ca}->{value} = '';
6822            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
6823            
6824        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6825          $self->{line_prev} = $self->{line};
6826          $self->{column_prev} = $self->{column};
6827          $self->{column}++;
6828          $self->{nc}
6829              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6830        } else {
6831          $self->{set_nc}->($self);
6832        }
6833      
6834            redo A;
6835          } elsif ($self->{nc} == 0x0027) { # '
6836            ## XML5: Same as "anything else".
6837            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before default value'); ## TODO: type
6838            $self->{ca}->{value} = '';
6839            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
6840            
6841        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6842          $self->{line_prev} = $self->{line};
6843          $self->{column_prev} = $self->{column};
6844          $self->{column}++;
6845          $self->{nc}
6846              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6847        } else {
6848          $self->{set_nc}->($self);
6849        }
6850      
6851            redo A;
6852          } elsif ($self->{nc} == 0x003E) { # >
6853            ## XML5: Same as "anything else".
6854            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no attr default'); ## TODO: type
6855            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6856            
6857        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6858          $self->{line_prev} = $self->{line};
6859          $self->{column_prev} = $self->{column};
6860          $self->{column}++;
6861          $self->{nc}
6862              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6863        } else {
6864          $self->{set_nc}->($self);
6865        }
6866      
6867            return  ($self->{ct}); # ATTLIST
6868            redo A;
6869          } elsif ($self->{nc} == 0x0028) { # (
6870            ## XML5: Same as "anything else".
6871            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before paren'); ## TODO: type
6872            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
6873            
6874        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6875          $self->{line_prev} = $self->{line};
6876          $self->{column_prev} = $self->{column};
6877          $self->{column}++;
6878          $self->{nc}
6879              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6880        } else {
6881          $self->{set_nc}->($self);
6882        }
6883      
6884            redo A;
6885          } elsif ($self->{nc} == -1) {
6886            ## XML5: No parse error.
6887            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
6888            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
6889            
6890        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6891          $self->{line_prev} = $self->{line};
6892          $self->{column_prev} = $self->{column};
6893          $self->{column}++;
6894          $self->{nc}
6895              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6896        } else {
6897          $self->{set_nc}->($self);
6898        }
6899      
6900            return  ($self->{ct});
6901            redo A;
6902          } else {
6903            ## XML5: Not defined yet.
6904            $self->{ca}->{type} .= chr $self->{nc};
6905            ## Stay in the state.
6906            
6907        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6908          $self->{line_prev} = $self->{line};
6909          $self->{column_prev} = $self->{column};
6910          $self->{column}++;
6911          $self->{nc}
6912              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6913        } else {
6914          $self->{set_nc}->($self);
6915        }
6916      
6917            redo A;
6918          }
6919        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_AFTER_STATE) {
6920          if ($is_space->{$self->{nc}}) {
6921            ## Stay in the state.
6922            
6923        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6924          $self->{line_prev} = $self->{line};
6925          $self->{column_prev} = $self->{column};
6926          $self->{column}++;
6927          $self->{nc}
6928              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6929        } else {
6930          $self->{set_nc}->($self);
6931        }
6932      
6933            redo A;
6934          } elsif ($self->{nc} == 0x0028) { # (
6935            ## XML5: Same as "anything else".
6936            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
6937            
6938        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6939          $self->{line_prev} = $self->{line};
6940          $self->{column_prev} = $self->{column};
6941          $self->{column}++;
6942          $self->{nc}
6943              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6944        } else {
6945          $self->{set_nc}->($self);
6946        }
6947      
6948            redo A;
6949          } elsif ($self->{nc} == 0x0023) { # #
6950            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE;
6951            
6952        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6953          $self->{line_prev} = $self->{line};
6954          $self->{column_prev} = $self->{column};
6955          $self->{column}++;
6956          $self->{nc}
6957              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6958        } else {
6959          $self->{set_nc}->($self);
6960        }
6961      
6962            redo A;
6963          } elsif ($self->{nc} == 0x0022) { # "
6964            ## XML5: Same as "anything else".
6965            $self->{ca}->{value} = '';
6966            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
6967            
6968        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6969          $self->{line_prev} = $self->{line};
6970          $self->{column_prev} = $self->{column};
6971          $self->{column}++;
6972          $self->{nc}
6973              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6974        } else {
6975          $self->{set_nc}->($self);
6976        }
6977      
6978            redo A;
6979          } elsif ($self->{nc} == 0x0027) { # '
6980            ## XML5: Same as "anything else".
6981            $self->{ca}->{value} = '';
6982            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
6983            
6984        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6985          $self->{line_prev} = $self->{line};
6986          $self->{column_prev} = $self->{column};
6987          $self->{column}++;
6988          $self->{nc}
6989              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
6990        } else {
6991          $self->{set_nc}->($self);
6992        }
6993      
6994            redo A;
6995          } elsif ($self->{nc} == 0x003E) { # >
6996            ## XML5: Same as "anything else".
6997            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no attr default'); ## TODO: type
6998            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6999            
7000        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7001          $self->{line_prev} = $self->{line};
7002          $self->{column_prev} = $self->{column};
7003          $self->{column}++;
7004          $self->{nc}
7005              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7006        } else {
7007          $self->{set_nc}->($self);
7008        }
7009      
7010            return  ($self->{ct}); # ATTLIST
7011            redo A;
7012          } elsif ($self->{nc} == -1) {
7013            ## XML5: No parse error.
7014            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7015            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
7016            
7017        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7018          $self->{line_prev} = $self->{line};
7019          $self->{column_prev} = $self->{column};
7020          $self->{column}++;
7021          $self->{nc}
7022              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7023        } else {
7024          $self->{set_nc}->($self);
7025        }
7026      
7027            return  ($self->{ct});
7028            redo A;
7029          } else {
7030            ## XML5: Switch to the "DOCTYPE bogus comment state".
7031            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unquoted attr value'); ## TODO: type
7032            $self->{ca}->{value} = '';
7033            $self->{state} = ATTRIBUTE_VALUE_UNQUOTED_STATE;
7034            ## Reconsume.
7035            redo A;
7036          }
7037        } elsif ($self->{state} == BEFORE_ALLOWED_TOKEN_STATE) {
7038          if ($is_space->{$self->{nc}}) {
7039            ## Stay in the state.
7040            
7041        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7042          $self->{line_prev} = $self->{line};
7043          $self->{column_prev} = $self->{column};
7044          $self->{column}++;
7045          $self->{nc}
7046              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7047        } else {
7048          $self->{set_nc}->($self);
7049        }
7050      
7051            redo A;
7052          } elsif ($self->{nc} == 0x007C) { # |
7053            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty allowed token'); ## TODO: type
7054            ## Stay in the state.
7055            
7056        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7057          $self->{line_prev} = $self->{line};
7058          $self->{column_prev} = $self->{column};
7059          $self->{column}++;
7060          $self->{nc}
7061              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7062        } else {
7063          $self->{set_nc}->($self);
7064        }
7065      
7066            redo A;
7067          } elsif ($self->{nc} == 0x0029) { # )
7068            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty allowed token'); ## TODO: type
7069            $self->{state} = AFTER_ALLOWED_TOKENS_STATE;
7070            
7071        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7072          $self->{line_prev} = $self->{line};
7073          $self->{column_prev} = $self->{column};
7074          $self->{column}++;
7075          $self->{nc}
7076              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7077        } else {
7078          $self->{set_nc}->($self);
7079        }
7080      
7081            redo A;
7082          } elsif ($self->{nc} == 0x003E) { # >
7083            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed allowed tokens'); ## TODO: type
7084            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7085            
7086        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7087          $self->{line_prev} = $self->{line};
7088          $self->{column_prev} = $self->{column};
7089          $self->{column}++;
7090          $self->{nc}
7091              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7092        } else {
7093          $self->{set_nc}->($self);
7094        }
7095      
7096            return  ($self->{ct}); # ATTLIST
7097            redo A;
7098          } elsif ($self->{nc} == -1) {
7099            ## XML5: No parse error.
7100            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7101            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
7102            
7103        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7104          $self->{line_prev} = $self->{line};
7105          $self->{column_prev} = $self->{column};
7106          $self->{column}++;
7107          $self->{nc}
7108              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7109        } else {
7110          $self->{set_nc}->($self);
7111        }
7112      
7113            return  ($self->{ct});
7114            redo A;
7115          } else {
7116            push @{$self->{ca}->{tokens}}, chr $self->{nc};
7117            $self->{state} = ALLOWED_TOKEN_STATE;
7118            
7119        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7120          $self->{line_prev} = $self->{line};
7121          $self->{column_prev} = $self->{column};
7122          $self->{column}++;
7123          $self->{nc}
7124              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7125        } else {
7126          $self->{set_nc}->($self);
7127        }
7128      
7129            redo A;
7130          }
7131        } elsif ($self->{state} == ALLOWED_TOKEN_STATE) {
7132          if ($is_space->{$self->{nc}}) {
7133            $self->{state} = AFTER_ALLOWED_TOKEN_STATE;
7134            
7135        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7136          $self->{line_prev} = $self->{line};
7137          $self->{column_prev} = $self->{column};
7138          $self->{column}++;
7139          $self->{nc}
7140              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7141        } else {
7142          $self->{set_nc}->($self);
7143        }
7144      
7145            redo A;
7146          } elsif ($self->{nc} == 0x007C) { # |
7147            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
7148            
7149        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7150          $self->{line_prev} = $self->{line};
7151          $self->{column_prev} = $self->{column};
7152          $self->{column}++;
7153          $self->{nc}
7154              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7155        } else {
7156          $self->{set_nc}->($self);
7157        }
7158      
7159            redo A;
7160          } elsif ($self->{nc} == 0x0029) { # )
7161            $self->{state} = AFTER_ALLOWED_TOKENS_STATE;
7162            
7163        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7164          $self->{line_prev} = $self->{line};
7165          $self->{column_prev} = $self->{column};
7166          $self->{column}++;
7167          $self->{nc}
7168              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7169        } else {
7170          $self->{set_nc}->($self);
7171        }
7172      
7173            redo A;
7174          } elsif ($self->{nc} == 0x003E) { # >
7175            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed allowed tokens'); ## TODO: type
7176            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7177            
7178        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7179          $self->{line_prev} = $self->{line};
7180          $self->{column_prev} = $self->{column};
7181          $self->{column}++;
7182          $self->{nc}
7183              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7184        } else {
7185          $self->{set_nc}->($self);
7186        }
7187      
7188            return  ($self->{ct}); # ATTLIST
7189            redo A;
7190          } elsif ($self->{nc} == -1) {
7191            ## XML5: No parse error.
7192            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7193            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
7194            
7195        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7196          $self->{line_prev} = $self->{line};
7197          $self->{column_prev} = $self->{column};
7198          $self->{column}++;
7199          $self->{nc}
7200              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7201        } else {
7202          $self->{set_nc}->($self);
7203        }
7204      
7205            return  ($self->{ct});
7206            redo A;
7207          } else {
7208            $self->{ca}->{tokens}->[-1] .= chr $self->{nc};
7209            ## Stay in the state.
7210            
7211        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7212          $self->{line_prev} = $self->{line};
7213          $self->{column_prev} = $self->{column};
7214          $self->{column}++;
7215          $self->{nc}
7216              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7217        } else {
7218          $self->{set_nc}->($self);
7219        }
7220      
7221            redo A;
7222          }
7223        } elsif ($self->{state} == AFTER_ALLOWED_TOKEN_STATE) {
7224          if ($is_space->{$self->{nc}}) {
7225            ## Stay in the state.
7226            
7227        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7228          $self->{line_prev} = $self->{line};
7229          $self->{column_prev} = $self->{column};
7230          $self->{column}++;
7231          $self->{nc}
7232              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7233        } else {
7234          $self->{set_nc}->($self);
7235        }
7236      
7237            redo A;
7238          } elsif ($self->{nc} == 0x007C) { # |
7239            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
7240            
7241        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7242          $self->{line_prev} = $self->{line};
7243          $self->{column_prev} = $self->{column};
7244          $self->{column}++;
7245          $self->{nc}
7246              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7247        } else {
7248          $self->{set_nc}->($self);
7249        }
7250      
7251            redo A;
7252          } elsif ($self->{nc} == 0x0029) { # )
7253            $self->{state} = AFTER_ALLOWED_TOKENS_STATE;
7254            
7255        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7256          $self->{line_prev} = $self->{line};
7257          $self->{column_prev} = $self->{column};
7258          $self->{column}++;
7259          $self->{nc}
7260              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7261        } else {
7262          $self->{set_nc}->($self);
7263        }
7264      
7265            redo A;
7266          } elsif ($self->{nc} == 0x003E) { # >
7267            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed allowed tokens'); ## TODO: type
7268            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7269            
7270        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7271          $self->{line_prev} = $self->{line};
7272          $self->{column_prev} = $self->{column};
7273          $self->{column}++;
7274          $self->{nc}
7275              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7276        } else {
7277          $self->{set_nc}->($self);
7278        }
7279      
7280            return  ($self->{ct}); # ATTLIST
7281            redo A;
7282          } elsif ($self->{nc} == -1) {
7283            ## XML5: No parse error.
7284            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7285            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
7286            
7287        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7288          $self->{line_prev} = $self->{line};
7289          $self->{column_prev} = $self->{column};
7290          $self->{column}++;
7291          $self->{nc}
7292              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7293        } else {
7294          $self->{set_nc}->($self);
7295        }
7296      
7297            return  ($self->{ct});
7298            redo A;
7299          } else {
7300            $self->{parse_error}->(level => $self->{level}->{must}, type => 'space in allowed token', ## TODO: type
7301                            line => $self->{line_prev},
7302                            column => $self->{column_prev});
7303            $self->{ca}->{tokens}->[-1] .= ' ' . chr $self->{nc};
7304            $self->{state} = ALLOWED_TOKEN_STATE;
7305            
7306        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7307          $self->{line_prev} = $self->{line};
7308          $self->{column_prev} = $self->{column};
7309          $self->{column}++;
7310          $self->{nc}
7311              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7312        } else {
7313          $self->{set_nc}->($self);
7314        }
7315      
7316            redo A;
7317          }
7318        } elsif ($self->{state} == AFTER_ALLOWED_TOKENS_STATE) {
7319          if ($is_space->{$self->{nc}}) {
7320            $self->{state} = BEFORE_ATTR_DEFAULT_STATE;
7321            
7322        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7323          $self->{line_prev} = $self->{line};
7324          $self->{column_prev} = $self->{column};
7325          $self->{column}++;
7326          $self->{nc}
7327              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7328        } else {
7329          $self->{set_nc}->($self);
7330        }
7331      
7332            redo A;
7333          } elsif ($self->{nc} == 0x0023) { # #
7334            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before default value'); ## TODO: type
7335            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE;
7336            
7337        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7338          $self->{line_prev} = $self->{line};
7339          $self->{column_prev} = $self->{column};
7340          $self->{column}++;
7341          $self->{nc}
7342              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7343        } else {
7344          $self->{set_nc}->($self);
7345        }
7346      
7347            redo A;
7348          } elsif ($self->{nc} == 0x0022) { # "
7349            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before default value'); ## TODO: type
7350            $self->{ca}->{value} = '';
7351            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
7352            
7353        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7354          $self->{line_prev} = $self->{line};
7355          $self->{column_prev} = $self->{column};
7356          $self->{column}++;
7357          $self->{nc}
7358              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7359        } else {
7360          $self->{set_nc}->($self);
7361        }
7362      
7363            redo A;
7364          } elsif ($self->{nc} == 0x0027) { # '
7365            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before default value'); ## TODO: type
7366            $self->{ca}->{value} = '';
7367            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
7368            
7369        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7370          $self->{line_prev} = $self->{line};
7371          $self->{column_prev} = $self->{column};
7372          $self->{column}++;
7373          $self->{nc}
7374              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7375        } else {
7376          $self->{set_nc}->($self);
7377        }
7378      
7379            redo A;
7380          } elsif ($self->{nc} == 0x003E) { # >
7381            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no attr default'); ## TODO: type
7382            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7383            
7384        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7385          $self->{line_prev} = $self->{line};
7386          $self->{column_prev} = $self->{column};
7387          $self->{column}++;
7388          $self->{nc}
7389              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7390        } else {
7391          $self->{set_nc}->($self);
7392        }
7393      
7394            return  ($self->{ct}); # ATTLIST
7395            redo A;
7396          } elsif ($self->{nc} == -1) {
7397            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7398            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7399            
7400        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7401          $self->{line_prev} = $self->{line};
7402          $self->{column_prev} = $self->{column};
7403          $self->{column}++;
7404          $self->{nc}
7405              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7406        } else {
7407          $self->{set_nc}->($self);
7408        }
7409      
7410            return  ($self->{ct});
7411            redo A;
7412          } else {
7413            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unquoted attr value'); ## TODO: type
7414            $self->{state} = ATTRIBUTE_VALUE_UNQUOTED_STATE;
7415            ## Reconsume.
7416            redo A;
7417          }
7418        } elsif ($self->{state} == BEFORE_ATTR_DEFAULT_STATE) {
7419          if ($is_space->{$self->{nc}}) {
7420            ## Stay in the state.
7421            
7422        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7423          $self->{line_prev} = $self->{line};
7424          $self->{column_prev} = $self->{column};
7425          $self->{column}++;
7426          $self->{nc}
7427              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7428        } else {
7429          $self->{set_nc}->($self);
7430        }
7431      
7432            redo A;
7433          } elsif ($self->{nc} == 0x0023) { # #
7434            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE;
7435            
7436        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7437          $self->{line_prev} = $self->{line};
7438          $self->{column_prev} = $self->{column};
7439          $self->{column}++;
7440          $self->{nc}
7441              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7442        } else {
7443          $self->{set_nc}->($self);
7444        }
7445      
7446            redo A;
7447          } elsif ($self->{nc} == 0x0022) { # "
7448            $self->{ca}->{value} = '';
7449            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
7450            
7451        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7452          $self->{line_prev} = $self->{line};
7453          $self->{column_prev} = $self->{column};
7454          $self->{column}++;
7455          $self->{nc}
7456              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7457        } else {
7458          $self->{set_nc}->($self);
7459        }
7460      
7461            redo A;
7462          } elsif ($self->{nc} == 0x0027) { # '
7463            $self->{ca}->{value} = '';
7464            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
7465            
7466        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7467          $self->{line_prev} = $self->{line};
7468          $self->{column_prev} = $self->{column};
7469          $self->{column}++;
7470          $self->{nc}
7471              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7472        } else {
7473          $self->{set_nc}->($self);
7474        }
7475      
7476            redo A;
7477          } elsif ($self->{nc} == 0x003E) { # >
7478            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no attr default'); ## TODO: type
7479            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7480            
7481        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7482          $self->{line_prev} = $self->{line};
7483          $self->{column_prev} = $self->{column};
7484          $self->{column}++;
7485          $self->{nc}
7486              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7487        } else {
7488          $self->{set_nc}->($self);
7489        }
7490      
7491            return  ($self->{ct}); # ATTLIST
7492            redo A;
7493          } elsif ($self->{nc} == -1) {
7494            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7495            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7496            
7497        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7498          $self->{line_prev} = $self->{line};
7499          $self->{column_prev} = $self->{column};
7500          $self->{column}++;
7501          $self->{nc}
7502              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7503        } else {
7504          $self->{set_nc}->($self);
7505        }
7506      
7507            return  ($self->{ct});
7508            redo A;
7509          } else {
7510            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unquoted attr value'); ## TODO: type
7511            $self->{state} = ATTRIBUTE_VALUE_UNQUOTED_STATE;
7512            ## Reconsume.
7513            redo A;
7514          }
7515        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE) {
7516          if ($is_space->{$self->{nc}}) {
7517            ## XML5: No parse error.
7518            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no default type'); ## TODO: type
7519            $self->{state} = BOGUS_MD_STATE;
7520            ## Reconsume.
7521            redo A;
7522          } elsif ($self->{nc} == 0x0022) { # "
7523            ## XML5: Same as "anything else".
7524            $self->{ca}->{value} = '';
7525            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
7526            
7527        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7528          $self->{line_prev} = $self->{line};
7529          $self->{column_prev} = $self->{column};
7530          $self->{column}++;
7531          $self->{nc}
7532              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7533        } else {
7534          $self->{set_nc}->($self);
7535        }
7536      
7537            redo A;
7538          } elsif ($self->{nc} == 0x0027) { # '
7539            ## XML5: Same as "anything else".
7540            $self->{ca}->{value} = '';
7541            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
7542            
7543        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7544          $self->{line_prev} = $self->{line};
7545          $self->{column_prev} = $self->{column};
7546          $self->{column}++;
7547          $self->{nc}
7548              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7549        } else {
7550          $self->{set_nc}->($self);
7551        }
7552      
7553            redo A;
7554          } elsif ($self->{nc} == 0x003E) { # >
7555            ## XML5: Same as "anything else".
7556            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no attr default'); ## TODO: type
7557            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7558            
7559        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7560          $self->{line_prev} = $self->{line};
7561          $self->{column_prev} = $self->{column};
7562          $self->{column}++;
7563          $self->{nc}
7564              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7565        } else {
7566          $self->{set_nc}->($self);
7567        }
7568      
7569            return  ($self->{ct}); # ATTLIST
7570            redo A;
7571          } elsif ($self->{nc} == -1) {
7572            ## XML5: No parse error.
7573            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7574            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
7575            
7576        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7577          $self->{line_prev} = $self->{line};
7578          $self->{column_prev} = $self->{column};
7579          $self->{column}++;
7580          $self->{nc}
7581              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7582        } else {
7583          $self->{set_nc}->($self);
7584        }
7585      
7586            return  ($self->{ct});
7587            redo A;
7588          } else {
7589            $self->{ca}->{default} = chr $self->{nc};
7590            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE;
7591            
7592        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7593          $self->{line_prev} = $self->{line};
7594          $self->{column_prev} = $self->{column};
7595          $self->{column}++;
7596          $self->{nc}
7597              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7598        } else {
7599          $self->{set_nc}->($self);
7600        }
7601      
7602            redo A;
7603          }
7604        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE) {
7605          if ($is_space->{$self->{nc}}) {
7606            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE;
7607            
7608        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7609          $self->{line_prev} = $self->{line};
7610          $self->{column_prev} = $self->{column};
7611          $self->{column}++;
7612          $self->{nc}
7613              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7614        } else {
7615          $self->{set_nc}->($self);
7616        }
7617      
7618            redo A;
7619          } elsif ($self->{nc} == 0x0022) { # "
7620            ## XML5: Same as "anything else".
7621            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before default value'); ## TODO: type
7622            $self->{ca}->{value} = '';
7623            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
7624            
7625        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7626          $self->{line_prev} = $self->{line};
7627          $self->{column_prev} = $self->{column};
7628          $self->{column}++;
7629          $self->{nc}
7630              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7631        } else {
7632          $self->{set_nc}->($self);
7633        }
7634      
7635            redo A;
7636          } elsif ($self->{nc} == 0x0027) { # '
7637            ## XML5: Same as "anything else".
7638            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before default value'); ## TODO: type
7639            $self->{ca}->{value} = '';
7640            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
7641            
7642        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7643          $self->{line_prev} = $self->{line};
7644          $self->{column_prev} = $self->{column};
7645          $self->{column}++;
7646          $self->{nc}
7647              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7648        } else {
7649          $self->{set_nc}->($self);
7650        }
7651      
7652            redo A;
7653          } elsif ($self->{nc} == 0x003E) { # >
7654            ## XML5: Same as "anything else".
7655            push @{$self->{ct}->{attrdefs}}, $self->{ca};
7656            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7657            
7658        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7659          $self->{line_prev} = $self->{line};
7660          $self->{column_prev} = $self->{column};
7661          $self->{column}++;
7662          $self->{nc}
7663              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7664        } else {
7665          $self->{set_nc}->($self);
7666        }
7667      
7668            return  ($self->{ct}); # ATTLIST
7669            redo A;
7670          } elsif ($self->{nc} == -1) {
7671            ## XML5: No parse error.
7672            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7673            push @{$self->{ct}->{attrdefs}}, $self->{ca};
7674            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
7675            
7676        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7677          $self->{line_prev} = $self->{line};
7678          $self->{column_prev} = $self->{column};
7679          $self->{column}++;
7680          $self->{nc}
7681              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7682        } else {
7683          $self->{set_nc}->($self);
7684        }
7685      
7686            return  ($self->{ct});
7687            redo A;
7688          } else {
7689            $self->{ca}->{default} .= chr $self->{nc};
7690            ## Stay in the state.
7691            
7692        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7693          $self->{line_prev} = $self->{line};
7694          $self->{column_prev} = $self->{column};
7695          $self->{column}++;
7696          $self->{nc}
7697              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7698        } else {
7699          $self->{set_nc}->($self);
7700        }
7701      
7702            redo A;
7703          }
7704        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE) {
7705          if ($is_space->{$self->{nc}}) {
7706            ## Stay in the state.
7707            
7708        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7709          $self->{line_prev} = $self->{line};
7710          $self->{column_prev} = $self->{column};
7711          $self->{column}++;
7712          $self->{nc}
7713              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7714        } else {
7715          $self->{set_nc}->($self);
7716        }
7717      
7718            redo A;
7719          } elsif ($self->{nc} == 0x0022) { # "
7720            $self->{ca}->{value} = '';
7721            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
7722            
7723        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7724          $self->{line_prev} = $self->{line};
7725          $self->{column_prev} = $self->{column};
7726          $self->{column}++;
7727          $self->{nc}
7728              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7729        } else {
7730          $self->{set_nc}->($self);
7731        }
7732      
7733            redo A;
7734          } elsif ($self->{nc} == 0x0027) { # '
7735            $self->{ca}->{value} = '';
7736            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
7737            
7738        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7739          $self->{line_prev} = $self->{line};
7740          $self->{column_prev} = $self->{column};
7741          $self->{column}++;
7742          $self->{nc}
7743              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7744        } else {
7745          $self->{set_nc}->($self);
7746        }
7747      
7748            redo A;
7749          } elsif ($self->{nc} == 0x003E) { # >
7750            push @{$self->{ct}->{attrdefs}}, $self->{ca};
7751            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7752            
7753        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7754          $self->{line_prev} = $self->{line};
7755          $self->{column_prev} = $self->{column};
7756          $self->{column}++;
7757          $self->{nc}
7758              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7759        } else {
7760          $self->{set_nc}->($self);
7761        }
7762      
7763            return  ($self->{ct}); # ATTLIST
7764            redo A;
7765          } elsif ($self->{nc} == -1) {
7766            ## XML5: No parse error.
7767            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7768            push @{$self->{ct}->{attrdefs}}, $self->{ca};
7769            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
7770            
7771        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7772          $self->{line_prev} = $self->{line};
7773          $self->{column_prev} = $self->{column};
7774          $self->{column}++;
7775          $self->{nc}
7776              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7777        } else {
7778          $self->{set_nc}->($self);
7779        }
7780      
7781            return  ($self->{ct});
7782            redo A;
7783          } else {
7784            ## XML5: Not defined yet.
7785            if ($self->{ca}->{default} eq 'FIXED') {
7786              $self->{state} = ATTRIBUTE_VALUE_UNQUOTED_STATE;
7787            } else {
7788              push @{$self->{ct}->{attrdefs}}, $self->{ca};
7789              $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
7790            }
7791            ## Reconsume.
7792            redo A;
7793          }
7794        } elsif ($self->{state} == AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE) {
7795          if ($is_space->{$self->{nc}} or
7796              $self->{nc} == -1 or
7797              $self->{nc} == 0x003E) { # >
7798            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
7799            ## Reconsume.
7800            redo A;
7801          } else {
7802            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before attr name'); ## TODO: type
7803            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
7804            ## Reconsume.
7805            redo A;
7806          }
7807        } elsif ($self->{state} == NDATA_STATE) {
7808          ## ASCII case-insensitive
7809          if ($self->{nc} == [
7810                undef,
7811                0x0044, # D
7812                0x0041, # A
7813                0x0054, # T
7814              ]->[length $self->{kwd}] or
7815              $self->{nc} == [
7816                undef,
7817                0x0064, # d
7818                0x0061, # a
7819                0x0074, # t
7820              ]->[length $self->{kwd}]) {
7821            
7822            ## Stay in the state.
7823            $self->{kwd} .= chr $self->{nc};
7824            
7825        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7826          $self->{line_prev} = $self->{line};
7827          $self->{column_prev} = $self->{column};
7828          $self->{column}++;
7829          $self->{nc}
7830              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7831        } else {
7832          $self->{set_nc}->($self);
7833        }
7834      
7835            redo A;
7836          } elsif ((length $self->{kwd}) == 4 and
7837                   ($self->{nc} == 0x0041 or # A
7838                    $self->{nc} == 0x0061)) { # a
7839            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
7840              
7841              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
7842                              text => 'NDATA',
7843                              line => $self->{line_prev},
7844                              column => $self->{column_prev} - 4);
7845            } else {
7846              
7847            }
7848            $self->{state} = AFTER_NDATA_STATE;
7849            
7850        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7851          $self->{line_prev} = $self->{line};
7852          $self->{column_prev} = $self->{column};
7853          $self->{column}++;
7854          $self->{nc}
7855              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7856        } else {
7857          $self->{set_nc}->($self);
7858        }
7859      
7860            redo A;
7861          } else {
7862            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7863                            line => $self->{line_prev},
7864                            column => $self->{column_prev} + 1
7865                                - length $self->{kwd});
7866            
7867            $self->{state} = BOGUS_MD_STATE;
7868            ## Reconsume.
7869            redo A;
7870          }
7871        } elsif ($self->{state} == AFTER_NDATA_STATE) {
7872          if ($is_space->{$self->{nc}}) {
7873            $self->{state} = BEFORE_NOTATION_NAME_STATE;
7874            
7875        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7876          $self->{line_prev} = $self->{line};
7877          $self->{column_prev} = $self->{column};
7878          $self->{column}++;
7879          $self->{nc}
7880              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7881        } else {
7882          $self->{set_nc}->($self);
7883        }
7884      
7885            redo A;
7886          } elsif ($self->{nc} == 0x003E) { # >
7887            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7888            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7889            
7890        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7891          $self->{line_prev} = $self->{line};
7892          $self->{column_prev} = $self->{column};
7893          $self->{column}++;
7894          $self->{nc}
7895              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7896        } else {
7897          $self->{set_nc}->($self);
7898        }
7899      
7900            return  ($self->{ct}); # ENTITY
7901            redo A;
7902          } elsif ($self->{nc} == -1) {
7903            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7904            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7905            
7906        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7907          $self->{line_prev} = $self->{line};
7908          $self->{column_prev} = $self->{column};
7909          $self->{column}++;
7910          $self->{nc}
7911              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7912        } else {
7913          $self->{set_nc}->($self);
7914        }
7915      
7916            return  ($self->{ct}); # ENTITY
7917            redo A;
7918          } else {
7919            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7920                            line => $self->{line_prev},
7921                            column => $self->{column_prev} + 1
7922                                - length $self->{kwd});
7923            $self->{state} = BOGUS_MD_STATE;
7924            ## Reconsume.
7925            redo A;
7926          }
7927        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
7928          if ($is_space->{$self->{nc}}) {
7929            ## Stay in the state.
7930            
7931        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7932          $self->{line_prev} = $self->{line};
7933          $self->{column_prev} = $self->{column};
7934          $self->{column}++;
7935          $self->{nc}
7936              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7937        } else {
7938          $self->{set_nc}->($self);
7939        }
7940      
7941            redo A;
7942          } elsif ($self->{nc} == 0x003E) { # >
7943            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7944            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7945            
7946        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7947          $self->{line_prev} = $self->{line};
7948          $self->{column_prev} = $self->{column};
7949          $self->{column}++;
7950          $self->{nc}
7951              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7952        } else {
7953          $self->{set_nc}->($self);
7954        }
7955      
7956            return  ($self->{ct}); # ENTITY
7957            redo A;
7958          } elsif ($self->{nc} == -1) {
7959            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7960            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7961            
7962        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7963          $self->{line_prev} = $self->{line};
7964          $self->{column_prev} = $self->{column};
7965          $self->{column}++;
7966          $self->{nc}
7967              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7968        } else {
7969          $self->{set_nc}->($self);
7970        }
7971      
7972            return  ($self->{ct}); # ENTITY
7973            redo A;
7974          } else {
7975            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
7976            $self->{state} = NOTATION_NAME_STATE;
7977            
7978        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7979          $self->{line_prev} = $self->{line};
7980          $self->{column_prev} = $self->{column};
7981          $self->{column}++;
7982          $self->{nc}
7983              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7984        } else {
7985          $self->{set_nc}->($self);
7986        }
7987      
7988            redo A;
7989          }
7990        } elsif ($self->{state} == NOTATION_NAME_STATE) {
7991          if ($is_space->{$self->{nc}}) {
7992            $self->{state} = AFTER_MD_DEF_STATE;
7993            
7994        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7995          $self->{line_prev} = $self->{line};
7996          $self->{column_prev} = $self->{column};
7997          $self->{column}++;
7998          $self->{nc}
7999              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8000        } else {
8001          $self->{set_nc}->($self);
8002        }
8003      
8004            redo A;
8005          } elsif ($self->{nc} == 0x003E) { # >
8006            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8007            
8008        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8009          $self->{line_prev} = $self->{line};
8010          $self->{column_prev} = $self->{column};
8011          $self->{column}++;
8012          $self->{nc}
8013              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8014        } else {
8015          $self->{set_nc}->($self);
8016        }
8017      
8018            return  ($self->{ct}); # ENTITY
8019            redo A;
8020          } elsif ($self->{nc} == -1) {
8021            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8022            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8023            
8024        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8025          $self->{line_prev} = $self->{line};
8026          $self->{column_prev} = $self->{column};
8027          $self->{column}++;
8028          $self->{nc}
8029              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8030        } else {
8031          $self->{set_nc}->($self);
8032        }
8033      
8034            return  ($self->{ct}); # ENTITY
8035            redo A;
8036          } else {
8037            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
8038            ## Stay in the state.
8039            
8040        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8041          $self->{line_prev} = $self->{line};
8042          $self->{column_prev} = $self->{column};
8043          $self->{column}++;
8044          $self->{nc}
8045              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8046        } else {
8047          $self->{set_nc}->($self);
8048        }
8049      
8050            redo A;
8051          }
8052        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
8053          if ($self->{nc} == 0x0022) { # "
8054            $self->{state} = AFTER_MD_DEF_STATE;
8055            
8056        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8057          $self->{line_prev} = $self->{line};
8058          $self->{column_prev} = $self->{column};
8059          $self->{column}++;
8060          $self->{nc}
8061              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8062        } else {
8063          $self->{set_nc}->($self);
8064        }
8065      
8066            redo A;
8067          } elsif ($self->{nc} == 0x0026) { # &
8068            $self->{prev_state} = $self->{state};
8069            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
8070            $self->{entity_add} = 0x0022; # "
8071            
8072        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8073          $self->{line_prev} = $self->{line};
8074          $self->{column_prev} = $self->{column};
8075          $self->{column}++;
8076          $self->{nc}
8077              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8078        } else {
8079          $self->{set_nc}->($self);
8080        }
8081      
8082            redo A;
8083    ## TODO: %
8084          } elsif ($self->{nc} == -1) {
8085            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
8086            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8087          ## Reconsume.          ## Reconsume.
8088            return  ($self->{ct}); # ENTITY
8089            redo A;
8090          } else {
8091            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
8092            
8093        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8094          $self->{line_prev} = $self->{line};
8095          $self->{column_prev} = $self->{column};
8096          $self->{column}++;
8097          $self->{nc}
8098              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8099        } else {
8100          $self->{set_nc}->($self);
8101        }
8102      
8103          redo A;          redo A;
8104        }        }
8105        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
8106          if ($self->{nc} == 0x0027) { # '
8107            $self->{state} = AFTER_MD_DEF_STATE;
8108            
8109        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8110          $self->{line_prev} = $self->{line};
8111          $self->{column_prev} = $self->{column};
8112          $self->{column}++;
8113          $self->{nc}
8114              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8115        } else {
8116          $self->{set_nc}->($self);
8117        }
8118      
8119            redo A;
8120          } elsif ($self->{nc} == 0x0026) { # &
8121            $self->{prev_state} = $self->{state};
8122            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
8123            $self->{entity_add} = 0x0027; # '
8124            
8125        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8126          $self->{line_prev} = $self->{line};
8127          $self->{column_prev} = $self->{column};
8128          $self->{column}++;
8129          $self->{nc}
8130              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8131        } else {
8132          $self->{set_nc}->($self);
8133        }
8134      
8135            redo A;
8136    ## TODO: %
8137          } elsif ($self->{nc} == -1) {
8138            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
8139            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8140            ## Reconsume.
8141            return  ($self->{ct}); # ENTITY
8142            redo A;
8143          } else {
8144            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
8145            
8146        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8147          $self->{line_prev} = $self->{line};
8148          $self->{column_prev} = $self->{column};
8149          $self->{column}++;
8150          $self->{nc}
8151              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8152        } else {
8153          $self->{set_nc}->($self);
8154        }
8155      
8156            redo A;
8157          }
8158        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
8159          if ($is_space->{$self->{nc}} or
8160              {
8161                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
8162                $self->{entity_add} => 1,
8163              }->{$self->{nc}}) {
8164            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
8165                            line => $self->{line_prev},
8166                            column => $self->{column_prev}
8167                                + ($self->{nc} == -1 ? 1 : 0));
8168            ## Don't consume
8169            ## Return nothing.
8170            #
8171          } elsif ($self->{nc} == 0x0023) { # #
8172            $self->{ca} = $self->{ct};
8173            $self->{state} = ENTITY_HASH_STATE;
8174            $self->{kwd} = '#';
8175            
8176        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8177          $self->{line_prev} = $self->{line};
8178          $self->{column_prev} = $self->{column};
8179          $self->{column}++;
8180          $self->{nc}
8181              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8182        } else {
8183          $self->{set_nc}->($self);
8184        }
8185      
8186            redo A;
8187          } else {
8188            #
8189          }
8190    
8191          $self->{ct}->{value} .= '&';
8192          $self->{state} = $self->{prev_state};
8193          ## Reconsume.
8194          redo A;
8195        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
8196          if ($is_space->{$self->{nc}}) {
8197            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
8198            
8199        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8200          $self->{line_prev} = $self->{line};
8201          $self->{column_prev} = $self->{column};
8202          $self->{column}++;
8203          $self->{nc}
8204              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8205        } else {
8206          $self->{set_nc}->($self);
8207        }
8208      
8209            redo A;
8210          } elsif ($self->{nc} == 0x0028) { # (
8211            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8212            $self->{ct}->{content} = ['('];
8213            $self->{group_depth} = 1;
8214            
8215        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8216          $self->{line_prev} = $self->{line};
8217          $self->{column_prev} = $self->{column};
8218          $self->{column}++;
8219          $self->{nc}
8220              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8221        } else {
8222          $self->{set_nc}->($self);
8223        }
8224      
8225            redo A;
8226          } elsif ($self->{nc} == 0x003E) { # >
8227            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
8228            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8229            
8230        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8231          $self->{line_prev} = $self->{line};
8232          $self->{column_prev} = $self->{column};
8233          $self->{column}++;
8234          $self->{nc}
8235              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8236        } else {
8237          $self->{set_nc}->($self);
8238        }
8239      
8240            return  ($self->{ct}); # ELEMENT
8241            redo A;
8242          } elsif ($self->{nc} == -1) {
8243            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8244            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8245            
8246        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8247          $self->{line_prev} = $self->{line};
8248          $self->{column_prev} = $self->{column};
8249          $self->{column}++;
8250          $self->{nc}
8251              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8252        } else {
8253          $self->{set_nc}->($self);
8254        }
8255      
8256            return  ($self->{ct}); # ELEMENT
8257            redo A;
8258          } else {
8259            $self->{ct}->{content} = [chr $self->{nc}];
8260            $self->{state} = CONTENT_KEYWORD_STATE;
8261            
8262        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8263          $self->{line_prev} = $self->{line};
8264          $self->{column_prev} = $self->{column};
8265          $self->{column}++;
8266          $self->{nc}
8267              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8268        } else {
8269          $self->{set_nc}->($self);
8270        }
8271      
8272            redo A;
8273          }
8274        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
8275          if ($is_space->{$self->{nc}}) {
8276            $self->{state} = AFTER_MD_DEF_STATE;
8277            
8278        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8279          $self->{line_prev} = $self->{line};
8280          $self->{column_prev} = $self->{column};
8281          $self->{column}++;
8282          $self->{nc}
8283              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8284        } else {
8285          $self->{set_nc}->($self);
8286        }
8287      
8288            redo A;
8289          } elsif ($self->{nc} == 0x003E) { # >
8290            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8291            
8292        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8293          $self->{line_prev} = $self->{line};
8294          $self->{column_prev} = $self->{column};
8295          $self->{column}++;
8296          $self->{nc}
8297              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8298        } else {
8299          $self->{set_nc}->($self);
8300        }
8301      
8302            return  ($self->{ct}); # ELEMENT
8303            redo A;
8304          } elsif ($self->{nc} == -1) {
8305            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8306            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8307            
8308        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8309          $self->{line_prev} = $self->{line};
8310          $self->{column_prev} = $self->{column};
8311          $self->{column}++;
8312          $self->{nc}
8313              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8314        } else {
8315          $self->{set_nc}->($self);
8316        }
8317      
8318            return  ($self->{ct}); # ELEMENT
8319            redo A;
8320          } else {
8321            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
8322            ## Stay in the state.
8323            
8324        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8325          $self->{line_prev} = $self->{line};
8326          $self->{column_prev} = $self->{column};
8327          $self->{column}++;
8328          $self->{nc}
8329              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8330        } else {
8331          $self->{set_nc}->($self);
8332        }
8333      
8334            redo A;
8335          }
8336        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
8337          if ($is_space->{$self->{nc}}) {
8338            ## Stay in the state.
8339            
8340        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8341          $self->{line_prev} = $self->{line};
8342          $self->{column_prev} = $self->{column};
8343          $self->{column}++;
8344          $self->{nc}
8345              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8346        } else {
8347          $self->{set_nc}->($self);
8348        }
8349      
8350            redo A;
8351          } elsif ($self->{nc} == 0x0028) { # (
8352            $self->{group_depth}++;
8353            push @{$self->{ct}->{content}}, chr $self->{nc};
8354            ## Stay in the state.
8355            
8356        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8357          $self->{line_prev} = $self->{line};
8358          $self->{column_prev} = $self->{column};
8359          $self->{column}++;
8360          $self->{nc}
8361              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8362        } else {
8363          $self->{set_nc}->($self);
8364        }
8365      
8366            redo A;
8367          } elsif ($self->{nc} == 0x007C or # |
8368                   $self->{nc} == 0x002C) { # ,
8369            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8370            ## Stay in the state.
8371            
8372        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8373          $self->{line_prev} = $self->{line};
8374          $self->{column_prev} = $self->{column};
8375          $self->{column}++;
8376          $self->{nc}
8377              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8378        } else {
8379          $self->{set_nc}->($self);
8380        }
8381      
8382            redo A;
8383          } elsif ($self->{nc} == 0x0029) { # )
8384            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8385            push @{$self->{ct}->{content}}, chr $self->{nc};
8386            $self->{group_depth}--;
8387            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8388            
8389        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8390          $self->{line_prev} = $self->{line};
8391          $self->{column_prev} = $self->{column};
8392          $self->{column}++;
8393          $self->{nc}
8394              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8395        } else {
8396          $self->{set_nc}->($self);
8397        }
8398      
8399            redo A;
8400          } elsif ($self->{nc} == 0x003E) { # >
8401            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8402            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8403            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8404            
8405        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8406          $self->{line_prev} = $self->{line};
8407          $self->{column_prev} = $self->{column};
8408          $self->{column}++;
8409          $self->{nc}
8410              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8411        } else {
8412          $self->{set_nc}->($self);
8413        }
8414      
8415            return  ($self->{ct}); # ELEMENT
8416            redo A;
8417          } elsif ($self->{nc} == -1) {
8418            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8419            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8420            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8421            
8422        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8423          $self->{line_prev} = $self->{line};
8424          $self->{column_prev} = $self->{column};
8425          $self->{column}++;
8426          $self->{nc}
8427              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8428        } else {
8429          $self->{set_nc}->($self);
8430        }
8431      
8432            return  ($self->{ct}); # ELEMENT
8433            redo A;
8434          } else {
8435            push @{$self->{ct}->{content}}, chr $self->{nc};
8436            $self->{state} = CM_ELEMENT_NAME_STATE;
8437            
8438        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8439          $self->{line_prev} = $self->{line};
8440          $self->{column_prev} = $self->{column};
8441          $self->{column}++;
8442          $self->{nc}
8443              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8444        } else {
8445          $self->{set_nc}->($self);
8446        }
8447      
8448            redo A;
8449          }
8450        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
8451          if ($is_space->{$self->{nc}}) {
8452            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8453            
8454        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8455          $self->{line_prev} = $self->{line};
8456          $self->{column_prev} = $self->{column};
8457          $self->{column}++;
8458          $self->{nc}
8459              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8460        } else {
8461          $self->{set_nc}->($self);
8462        }
8463      
8464            redo A;
8465          } elsif ($self->{nc} == 0x002A or # *
8466                   $self->{nc} == 0x002B or # +
8467                   $self->{nc} == 0x003F) { # ?
8468            push @{$self->{ct}->{content}}, chr $self->{nc};
8469            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8470            
8471        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8472          $self->{line_prev} = $self->{line};
8473          $self->{column_prev} = $self->{column};
8474          $self->{column}++;
8475          $self->{nc}
8476              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8477        } else {
8478          $self->{set_nc}->($self);
8479        }
8480      
8481            redo A;
8482          } elsif ($self->{nc} == 0x007C or # |
8483                   $self->{nc} == 0x002C) { # ,
8484            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8485            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8486            
8487        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8488          $self->{line_prev} = $self->{line};
8489          $self->{column_prev} = $self->{column};
8490          $self->{column}++;
8491          $self->{nc}
8492              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8493        } else {
8494          $self->{set_nc}->($self);
8495        }
8496      
8497            redo A;
8498          } elsif ($self->{nc} == 0x0029) { # )
8499            $self->{group_depth}--;
8500            push @{$self->{ct}->{content}}, chr $self->{nc};
8501            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8502            
8503        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8504          $self->{line_prev} = $self->{line};
8505          $self->{column_prev} = $self->{column};
8506          $self->{column}++;
8507          $self->{nc}
8508              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8509        } else {
8510          $self->{set_nc}->($self);
8511        }
8512      
8513            redo A;
8514          } elsif ($self->{nc} == 0x003E) { # >
8515            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8516            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8517            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8518            
8519        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8520          $self->{line_prev} = $self->{line};
8521          $self->{column_prev} = $self->{column};
8522          $self->{column}++;
8523          $self->{nc}
8524              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8525        } else {
8526          $self->{set_nc}->($self);
8527        }
8528      
8529            return  ($self->{ct}); # ELEMENT
8530            redo A;
8531          } elsif ($self->{nc} == -1) {
8532            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8533            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8534            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8535            
8536        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8537          $self->{line_prev} = $self->{line};
8538          $self->{column_prev} = $self->{column};
8539          $self->{column}++;
8540          $self->{nc}
8541              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8542        } else {
8543          $self->{set_nc}->($self);
8544        }
8545      
8546            return  ($self->{ct}); # ELEMENT
8547            redo A;
8548          } else {
8549            $self->{ct}->{content}->[-1] .= chr $self->{nc};
8550            ## Stay in the state.
8551            
8552        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8553          $self->{line_prev} = $self->{line};
8554          $self->{column_prev} = $self->{column};
8555          $self->{column}++;
8556          $self->{nc}
8557              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8558        } else {
8559          $self->{set_nc}->($self);
8560        }
8561      
8562            redo A;
8563          }
8564        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
8565          if ($is_space->{$self->{nc}}) {
8566            ## Stay in the state.
8567            
8568        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8569          $self->{line_prev} = $self->{line};
8570          $self->{column_prev} = $self->{column};
8571          $self->{column}++;
8572          $self->{nc}
8573              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8574        } else {
8575          $self->{set_nc}->($self);
8576        }
8577      
8578            redo A;
8579          } elsif ($self->{nc} == 0x007C or # |
8580                   $self->{nc} == 0x002C) { # ,
8581            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8582            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8583            
8584        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8585          $self->{line_prev} = $self->{line};
8586          $self->{column_prev} = $self->{column};
8587          $self->{column}++;
8588          $self->{nc}
8589              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8590        } else {
8591          $self->{set_nc}->($self);
8592        }
8593      
8594            redo A;
8595          } elsif ($self->{nc} == 0x0029) { # )
8596            $self->{group_depth}--;
8597            push @{$self->{ct}->{content}}, chr $self->{nc};
8598            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8599            
8600        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8601          $self->{line_prev} = $self->{line};
8602          $self->{column_prev} = $self->{column};
8603          $self->{column}++;
8604          $self->{nc}
8605              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8606        } else {
8607          $self->{set_nc}->($self);
8608        }
8609      
8610            redo A;
8611          } elsif ($self->{nc} == 0x003E) { # >
8612            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8613            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8614            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8615            
8616        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8617          $self->{line_prev} = $self->{line};
8618          $self->{column_prev} = $self->{column};
8619          $self->{column}++;
8620          $self->{nc}
8621              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8622        } else {
8623          $self->{set_nc}->($self);
8624        }
8625      
8626            return  ($self->{ct}); # ELEMENT
8627            redo A;
8628          } elsif ($self->{nc} == -1) {
8629            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8630            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8631            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8632            
8633        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8634          $self->{line_prev} = $self->{line};
8635          $self->{column_prev} = $self->{column};
8636          $self->{column}++;
8637          $self->{nc}
8638              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8639        } else {
8640          $self->{set_nc}->($self);
8641        }
8642      
8643            return  ($self->{ct}); # ELEMENT
8644            redo A;
8645          } else {
8646            $self->{parse_error}->(level => $self->{level}->{must}, type => 'after element name'); ## TODO: type
8647            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8648            $self->{state} = BOGUS_MD_STATE;
8649            
8650        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8651          $self->{line_prev} = $self->{line};
8652          $self->{column_prev} = $self->{column};
8653          $self->{column}++;
8654          $self->{nc}
8655              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8656        } else {
8657          $self->{set_nc}->($self);
8658        }
8659      
8660            redo A;
8661          }
8662        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
8663          if ($is_space->{$self->{nc}}) {
8664            if ($self->{group_depth}) {
8665              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8666            } else {
8667              $self->{state} = AFTER_MD_DEF_STATE;
8668            }
8669            
8670        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8671          $self->{line_prev} = $self->{line};
8672          $self->{column_prev} = $self->{column};
8673          $self->{column}++;
8674          $self->{nc}
8675              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8676        } else {
8677          $self->{set_nc}->($self);
8678        }
8679      
8680            redo A;
8681          } elsif ($self->{nc} == 0x002A or # *
8682                   $self->{nc} == 0x002B or # +
8683                   $self->{nc} == 0x003F) { # ?
8684            push @{$self->{ct}->{content}}, chr $self->{nc};
8685            if ($self->{group_depth}) {
8686              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8687            } else {
8688              $self->{state} = AFTER_MD_DEF_STATE;
8689            }
8690            
8691        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8692          $self->{line_prev} = $self->{line};
8693          $self->{column_prev} = $self->{column};
8694          $self->{column}++;
8695          $self->{nc}
8696              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8697        } else {
8698          $self->{set_nc}->($self);
8699        }
8700      
8701            redo A;
8702          } elsif ($self->{nc} == 0x0029) { # )
8703            if ($self->{group_depth}) {
8704              $self->{group_depth}--;
8705              push @{$self->{ct}->{content}}, chr $self->{nc};
8706              ## Stay in the state.
8707              
8708        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8709          $self->{line_prev} = $self->{line};
8710          $self->{column_prev} = $self->{column};
8711          $self->{column}++;
8712          $self->{nc}
8713              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8714        } else {
8715          $self->{set_nc}->($self);
8716        }
8717      
8718              redo A;
8719            } else {
8720              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8721              $self->{state} = BOGUS_MD_STATE;
8722              ## Reconsume.
8723              redo A;
8724            }
8725          } elsif ($self->{nc} == 0x003E) { # >
8726            if ($self->{group_depth}) {
8727              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8728              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8729            }
8730            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8731            
8732        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8733          $self->{line_prev} = $self->{line};
8734          $self->{column_prev} = $self->{column};
8735          $self->{column}++;
8736          $self->{nc}
8737              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8738        } else {
8739          $self->{set_nc}->($self);
8740        }
8741      
8742            return  ($self->{ct}); # ELEMENT
8743            redo A;
8744          } elsif ($self->{nc} == -1) {
8745            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8746            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8747            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8748            
8749        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8750          $self->{line_prev} = $self->{line};
8751          $self->{column_prev} = $self->{column};
8752          $self->{column}++;
8753          $self->{nc}
8754              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8755        } else {
8756          $self->{set_nc}->($self);
8757        }
8758      
8759            return  ($self->{ct}); # ELEMENT
8760            redo A;
8761          } else {
8762            if ($self->{group_depth}) {
8763              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8764            } else {
8765              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8766              $self->{state} = BOGUS_MD_STATE;
8767            }
8768            ## Reconsume.
8769            redo A;
8770          }
8771        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
8772          if ($is_space->{$self->{nc}}) {
8773            ## Stay in the state.
8774            
8775        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8776          $self->{line_prev} = $self->{line};
8777          $self->{column_prev} = $self->{column};
8778          $self->{column}++;
8779          $self->{nc}
8780              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8781        } else {
8782          $self->{set_nc}->($self);
8783        }
8784      
8785            redo A;
8786          } elsif ($self->{nc} == 0x003E) { # >
8787            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8788            
8789        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8790          $self->{line_prev} = $self->{line};
8791          $self->{column_prev} = $self->{column};
8792          $self->{column}++;
8793          $self->{nc}
8794              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8795        } else {
8796          $self->{set_nc}->($self);
8797        }
8798      
8799            return  ($self->{ct}); # ENTITY/ELEMENT
8800            redo A;
8801          } elsif ($self->{nc} == -1) {
8802            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8803            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8804            
8805        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8806          $self->{line_prev} = $self->{line};
8807          $self->{column_prev} = $self->{column};
8808          $self->{column}++;
8809          $self->{nc}
8810              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8811        } else {
8812          $self->{set_nc}->($self);
8813        }
8814      
8815            return  ($self->{ct}); # ENTITY/ELEMENT
8816            redo A;
8817          } else {
8818            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8819            $self->{state} = BOGUS_MD_STATE;
8820            ## Reconsume.
8821            redo A;
8822          }
8823        } elsif ($self->{state} == BOGUS_MD_STATE) {
8824          if ($self->{nc} == 0x003E) { # >
8825            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8826            
8827        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8828          $self->{line_prev} = $self->{line};
8829          $self->{column_prev} = $self->{column};
8830          $self->{column}++;
8831          $self->{nc}
8832              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8833        } else {
8834          $self->{set_nc}->($self);
8835        }
8836      
8837            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8838            redo A;
8839          } elsif ($self->{nc} == -1) {
8840            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8841            ## Reconsume.
8842            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8843            redo A;
8844          } else {
8845            ## Stay in the state.
8846            
8847        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8848          $self->{line_prev} = $self->{line};
8849          $self->{column_prev} = $self->{column};
8850          $self->{column}++;
8851          $self->{nc}
8852              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8853        } else {
8854          $self->{set_nc}->($self);
8855        }
8856      
8857            redo A;
8858          }
8859      } else {      } else {
8860        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
8861      }      }
# Line 5853  sub _get_next_token ($) { Line 8866  sub _get_next_token ($) {
8866    
8867  1;  1;
8868  ## $Date$  ## $Date$
8869                                    

Legend:
Removed from v.1.14  
changed lines
  Added in v.1.33

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24