/[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.15 by wakaba, Sat Oct 18 08:05:29 2008 UTC revision 1.34 by wakaba, Sat Sep 5 11:31:58 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 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO Line 179  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO
179  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
180  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
181  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }  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 187  sub FOREIGN_EL () { 0b1_00000000000 } Line 206  sub FOREIGN_EL () { 0b1_00000000000 }
206  ## Character reference mappings  ## Character reference mappings
207    
208  my $charref_map = {  my $charref_map = {
209      0x00 => 0xFFFD, # REPLACEMENT CHARACTER
210    0x0D => 0x000A,    0x0D => 0x000A,
211    0x80 => 0x20AC,    0x80 => 0x20AC,
212    0x81 => 0xFFFD,    0x81 => 0x0081,
213    0x82 => 0x201A,    0x82 => 0x201A,
214    0x83 => 0x0192,    0x83 => 0x0192,
215    0x84 => 0x201E,    0x84 => 0x201E,
# Line 201  my $charref_map = { Line 221  my $charref_map = {
221    0x8A => 0x0160,    0x8A => 0x0160,
222    0x8B => 0x2039,    0x8B => 0x2039,
223    0x8C => 0x0152,    0x8C => 0x0152,
224    0x8D => 0xFFFD,    0x8D => 0x008D,
225    0x8E => 0x017D,    0x8E => 0x017D,
226    0x8F => 0xFFFD,    0x8F => 0x008F,
227    0x90 => 0xFFFD,    0x90 => 0x0090,
228    0x91 => 0x2018,    0x91 => 0x2018,
229    0x92 => 0x2019,    0x92 => 0x2019,
230    0x93 => 0x201C,    0x93 => 0x201C,
# Line 217  my $charref_map = { Line 237  my $charref_map = {
237    0x9A => 0x0161,    0x9A => 0x0161,
238    0x9B => 0x203A,    0x9B => 0x203A,
239    0x9C => 0x0153,    0x9C => 0x0153,
240    0x9D => 0xFFFD,    0x9D => 0x009D,
241    0x9E => 0x017E,    0x9E => 0x017E,
242    0x9F => 0x0178,    0x9F => 0x0178,
243  }; # $charref_map  }; # $charref_map
244  $charref_map->{$_} = 0xFFFD  $charref_map->{$_} = $_
245      for 0x0000..0x0008, 0x000B, 0x000E..0x001F, 0x007F,      for 0x0001..0x0008, 0x000B, 0x000E..0x001F, 0x007F,
246          0xD800..0xDFFF, 0xFDD0..0xFDDF, ## ISSUE: 0xFDEF          0xD800..0xDFFF, 0xFDD0..0xFDEF,
247          0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF,          0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF,
248          0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE,          0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE,
249          0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF,          0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF,
# Line 1083  sub _get_next_token ($) { Line 1103  sub _get_next_token ($) {
1103          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1104          # reconsume          # reconsume
1105    
1106          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1107            #return  ($self->{ct}); # start tag or end tag
1108    
1109          redo A;          redo A;
1110        } elsif ($self->{nc} == 0x002F) { # /        } elsif ($self->{nc} == 0x002F) { # /
# Line 1224  sub _get_next_token ($) { Line 1245  sub _get_next_token ($) {
1245          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1246          # reconsume          # reconsume
1247    
1248          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1249            #return  ($self->{ct}); # start tag or end tag
1250    
1251          redo A;          redo A;
1252        } else {        } else {
1253          if ({          if ({
1254               0x0022 => 1, # "               0x0022 => 1, # "
1255               0x0027 => 1, # '               0x0027 => 1, # '
1256                 0x003C => 1, # <
1257               0x003D => 1, # =               0x003D => 1, # =
1258              }->{$self->{nc}}) {              }->{$self->{nc}}) {
1259                        
# Line 1409  sub _get_next_token ($) { Line 1432  sub _get_next_token ($) {
1432          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1433          # reconsume          # reconsume
1434    
1435          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1436            #return  ($self->{ct}); # start tag or end tag
1437    
1438          redo A;          redo A;
1439        } else {        } else {
1440          if ($self->{nc} == 0x0022 or # "          if ({
1441              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1442                 0x0027 => 1, # '
1443                 0x003C => 1, # <
1444                }->{$self->{nc}}) {
1445                        
1446            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1447            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1573  sub _get_next_token ($) { Line 1600  sub _get_next_token ($) {
1600          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1601          # reconsume          # reconsume
1602    
1603          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1604            #return  ($self->{ct}); # start tag or end tag
1605    
1606          redo A;          redo A;
1607        } else {        } else {
# Line 1585  sub _get_next_token ($) { Line 1613  sub _get_next_token ($) {
1613                        
1614          }          }
1615    
1616          if ($self->{nc} == 0x0022 or # "          if ({
1617              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1618                 0x0027 => 1, # '
1619                 0x003C => 1, # <
1620                }->{$self->{nc}}) {
1621                        
1622            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1623            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1719  sub _get_next_token ($) { Line 1750  sub _get_next_token ($) {
1750          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1751          ## reconsume          ## reconsume
1752    
1753          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1754            #return  ($self->{ct}); # start tag or end tag
1755    
1756          redo A;          redo A;
1757        } else {        } else {
1758          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1759                        
1760            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1761            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute value');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute value');
# Line 1799  sub _get_next_token ($) { Line 1831  sub _get_next_token ($) {
1831      }      }
1832        
1833          redo A;          redo A;
1834          } elsif ($self->{is_xml} and
1835                   $is_space->{$self->{nc}}) {
1836            
1837            $self->{ca}->{value} .= ' ';
1838            ## Stay in the state.
1839            
1840        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1841          $self->{line_prev} = $self->{line};
1842          $self->{column_prev} = $self->{column};
1843          $self->{column}++;
1844          $self->{nc}
1845              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1846        } else {
1847          $self->{set_nc}->($self);
1848        }
1849      
1850            redo A;
1851        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1852          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1853          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1823  sub _get_next_token ($) { Line 1872  sub _get_next_token ($) {
1872            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1873            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1874            ## reconsume            ## reconsume
1875            return  ($self->{ct}); # end tag  
1876              ## Discard the token.
1877              #return  ($self->{ct}); # end tag
1878    
1879            redo A;            redo A;
1880          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1881            ## XML5: No parse error above; not defined yet.            ## XML5: No parse error above; not defined yet.
1882            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
1883            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1884            ## Reconsume.            ## Reconsume.
1885            return  ($self->{ct}); # ATTLIST  
1886              ## Discard the token.
1887              #return  ($self->{ct}); # ATTLIST
1888    
1889            redo A;            redo A;
1890          } else {          } else {
1891            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1846  sub _get_next_token ($) { Line 1901  sub _get_next_token ($) {
1901          }          }
1902          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1903          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1904                                q["&<],                                qq["&<\x09\x0C\x20],
1905                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1906    
1907          ## Stay in the state          ## Stay in the state
# Line 1913  sub _get_next_token ($) { Line 1968  sub _get_next_token ($) {
1968      }      }
1969        
1970          redo A;          redo A;
1971          } elsif ($self->{is_xml} and
1972                   $is_space->{$self->{nc}}) {
1973            
1974            $self->{ca}->{value} .= ' ';
1975            ## Stay in the state.
1976            
1977        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1978          $self->{line_prev} = $self->{line};
1979          $self->{column_prev} = $self->{column};
1980          $self->{column}++;
1981          $self->{nc}
1982              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1983        } else {
1984          $self->{set_nc}->($self);
1985        }
1986      
1987            redo A;
1988        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1989          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1990          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1922  sub _get_next_token ($) { Line 1994  sub _get_next_token ($) {
1994            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1995            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1996            ## reconsume            ## reconsume
1997            return  ($self->{ct}); # start tag  
1998              ## Discard the token.
1999              #return  ($self->{ct}); # start tag
2000    
2001            redo A;            redo A;
2002          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
2003            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1937  sub _get_next_token ($) { Line 2012  sub _get_next_token ($) {
2012            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2013            $self->{s_kwd} = '';            $self->{s_kwd} = '';
2014            ## reconsume            ## reconsume
2015            return  ($self->{ct}); # end tag  
2016              ## Discard the token.
2017              #return  ($self->{ct}); # end tag
2018    
2019            redo A;            redo A;
2020          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
2021            ## XML5: No parse error above; not defined yet.            ## XML5: No parse error above; not defined yet.
2022            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
2023            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2024            ## Reconsume.            ## Reconsume.
2025            return  ($self->{ct}); # ATTLIST  
2026              ## Discard the token.
2027              #return  ($self->{ct}); # ATTLIST
2028    
2029            redo A;            redo A;
2030          } else {          } else {
2031            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1960  sub _get_next_token ($) { Line 2041  sub _get_next_token ($) {
2041          }          }
2042          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2043          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2044                                q['&<],                                qq['&<\x09\x0C\x20],
2045                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2046    
2047          ## Stay in the state          ## Stay in the state
# Line 2099  sub _get_next_token ($) { Line 2180  sub _get_next_token ($) {
2180            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2181            $self->{s_kwd} = '';            $self->{s_kwd} = '';
2182            ## reconsume            ## reconsume
2183            return  ($self->{ct}); # start tag  
2184              ## Discard the token.
2185              #return  ($self->{ct}); # start tag
2186              
2187            redo A;            redo A;
2188          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
2189            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed tag');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed tag');
# Line 2115  sub _get_next_token ($) { Line 2199  sub _get_next_token ($) {
2199            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2200            $self->{s_kwd} = '';            $self->{s_kwd} = '';
2201            ## reconsume            ## reconsume
2202            return  ($self->{ct}); # end tag  
2203              ## Discard the token.
2204              #return  ($self->{ct}); # end tag
2205    
2206            redo A;            redo A;
2207          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
2208            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
2209            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
2210            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2211            ## Reconsume.            ## Reconsume.
2212            return  ($self->{ct}); # ATTLIST  
2213              ## Discard the token.
2214              #return  ($self->{ct}); # ATTLIST
2215    
2216            redo A;            redo A;
2217          } else {          } else {
2218            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 2132  sub _get_next_token ($) { Line 2222  sub _get_next_token ($) {
2222               0x0022 => 1, # "               0x0022 => 1, # "
2223               0x0027 => 1, # '               0x0027 => 1, # '
2224               0x003D => 1, # =               0x003D => 1, # =
2225                 0x003C => 1, # <
2226              }->{$self->{nc}}) {              }->{$self->{nc}}) {
2227                        
2228            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 2141  sub _get_next_token ($) { Line 2232  sub _get_next_token ($) {
2232          }          }
2233          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2234          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2235                                q["'=& >],                                qq["'=& \x09\x0C>],
2236                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2237    
2238          ## Stay in the state          ## Stay in the state
# Line 2241  sub _get_next_token ($) { Line 2332  sub _get_next_token ($) {
2332          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2333          $self->{s_kwd} = '';          $self->{s_kwd} = '';
2334          ## Reconsume.          ## Reconsume.
2335          return  ($self->{ct}); # start tag or end tag  
2336            ## Discard the token.
2337            #return  ($self->{ct}); # start tag or end tag
2338    
2339          redo A;          redo A;
2340        } else {        } else {
2341                    
# Line 2308  sub _get_next_token ($) { Line 2402  sub _get_next_token ($) {
2402          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2403          $self->{s_kwd} = '';          $self->{s_kwd} = '';
2404          ## Reconsume.          ## Reconsume.
2405          return  ($self->{ct}); # start tag or end tag  
2406            ## Discard the token.
2407            #return  ($self->{ct}); # start tag or end tag
2408    
2409          redo A;          redo A;
2410        } else {        } else {
2411                    
# Line 2883  sub _get_next_token ($) { Line 2980  sub _get_next_token ($) {
2980        
2981          redo A;          redo A;
2982        }        }
2983      } elsif ($self->{state} == COMMENT_END_STATE) {      } elsif ($self->{state} == COMMENT_END_STATE or
2984                 $self->{state} == COMMENT_END_BANG_STATE) {
2985        ## XML5: "Comment end state" and "DOCTYPE comment end state".        ## XML5: "Comment end state" and "DOCTYPE comment end state".
2986          ## (No comment end bang state.)
2987    
2988        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2989          if ($self->{in_subset}) {          if ($self->{in_subset}) {
# Line 2911  sub _get_next_token ($) { Line 3010  sub _get_next_token ($) {
3010    
3011          redo A;          redo A;
3012        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
3013            if ($self->{state} == COMMENT_END_BANG_STATE) {
3014              
3015              $self->{ct}->{data} .= '--!'; # comment
3016              $self->{state} = COMMENT_END_DASH_STATE;
3017            } else {
3018              
3019              ## XML5: Not a parse error.
3020              $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',
3021                              line => $self->{line_prev},
3022                              column => $self->{column_prev});
3023              $self->{ct}->{data} .= '-'; # comment
3024              ## Stay in the state
3025            }
3026                    
3027          ## XML5: Not a parse error.      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3028          $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',        $self->{line_prev} = $self->{line};
3029                          line => $self->{line_prev},        $self->{column_prev} = $self->{column};
3030                          column => $self->{column_prev});        $self->{column}++;
3031          $self->{ct}->{data} .= '-'; # comment        $self->{nc}
3032          ## Stay in the state            = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3033        } else {
3034          $self->{set_nc}->($self);
3035        }
3036      
3037            redo A;
3038          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
3039                   $is_space->{$self->{nc}}) {
3040            
3041            $self->{parse_error}->(level => $self->{level}->{must}, type => 'comment end space'); # XXX error type
3042            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3043            $self->{state} = COMMENT_END_SPACE_STATE;
3044            
3045        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3046          $self->{line_prev} = $self->{line};
3047          $self->{column_prev} = $self->{column};
3048          $self->{column}++;
3049          $self->{nc}
3050              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3051        } else {
3052          $self->{set_nc}->($self);
3053        }
3054      
3055            redo A;
3056          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
3057                   $self->{nc} == 0x0021) { # !
3058            
3059            $self->{parse_error}->(level => $self->{level}->{must}, type => 'comment end bang'); # XXX error type
3060            $self->{state} = COMMENT_END_BANG_STATE;
3061                    
3062      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3063        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 2940  sub _get_next_token ($) { Line 3080  sub _get_next_token ($) {
3080            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
3081            $self->{s_kwd} = '';            $self->{s_kwd} = '';
3082          }          }
3083          ## reconsume          ## Reconsume.
3084    
3085          return  ($self->{ct}); # comment          return  ($self->{ct}); # comment
3086    
3087          redo A;          redo A;
3088        } else {        } else {
3089                    
3090          ## XML5: Not a parse error.          if ($self->{state} == COMMENT_END_BANG_STATE) {
3091          $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',            $self->{ct}->{data} .= '--!' . chr ($self->{nc}); # comment
3092                          line => $self->{line_prev},          } else {
3093                          column => $self->{column_prev});            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3094          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          }
3095          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
3096                    
3097      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 2966  sub _get_next_token ($) { Line 3106  sub _get_next_token ($) {
3106        
3107          redo A;          redo A;
3108        }        }
3109        } elsif ($self->{state} == COMMENT_END_SPACE_STATE) {
3110          ## XML5: Not exist.
3111    
3112          if ($self->{nc} == 0x003E) { # >
3113            if ($self->{in_subset}) {
3114              
3115              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3116            } else {
3117              
3118              $self->{state} = DATA_STATE;
3119              $self->{s_kwd} = '';
3120            }
3121            
3122        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3123          $self->{line_prev} = $self->{line};
3124          $self->{column_prev} = $self->{column};
3125          $self->{column}++;
3126          $self->{nc}
3127              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3128        } else {
3129          $self->{set_nc}->($self);
3130        }
3131      
3132    
3133            return  ($self->{ct}); # comment
3134    
3135            redo A;
3136          } elsif ($is_space->{$self->{nc}}) {
3137            
3138            $self->{ct}->{data} .= chr ($self->{nc}); # comment
3139            ## Stay in the state.
3140            
3141        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3142          $self->{line_prev} = $self->{line};
3143          $self->{column_prev} = $self->{column};
3144          $self->{column}++;
3145          $self->{nc}
3146              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3147        } else {
3148          $self->{set_nc}->($self);
3149        }
3150      
3151            redo A;
3152          } elsif ($self->{nc} == -1) {
3153            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed comment');
3154            if ($self->{in_subset}) {
3155              
3156              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3157            } else {
3158              
3159              $self->{state} = DATA_STATE;
3160              $self->{s_kwd} = '';
3161            }
3162            ## Reconsume.
3163    
3164            return  ($self->{ct}); # comment
3165    
3166            redo A;
3167          } else {
3168            
3169            $self->{ct}->{data} .= chr ($self->{nc}); # comment
3170            $self->{state} = COMMENT_STATE;
3171            
3172        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3173          $self->{line_prev} = $self->{line};
3174          $self->{column_prev} = $self->{column};
3175          $self->{column}++;
3176          $self->{nc}
3177              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3178        } else {
3179          $self->{set_nc}->($self);
3180        }
3181      
3182            redo A;
3183          }
3184      } elsif ($self->{state} == DOCTYPE_STATE) {      } elsif ($self->{state} == DOCTYPE_STATE) {
3185        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
3186                    
# Line 2982  sub _get_next_token ($) { Line 3197  sub _get_next_token ($) {
3197      }      }
3198        
3199          redo A;          redo A;
3200          } elsif ($self->{nc} == -1) {
3201            
3202            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3203            $self->{ct}->{quirks} = 1;
3204    
3205            $self->{state} = DATA_STATE;
3206            ## Reconsume.
3207            return  ($self->{ct}); # DOCTYPE (quirks)
3208    
3209            redo A;
3210        } else {        } else {
3211                    
3212          ## XML5: Unless EOF, swith to the bogus comment state.          ## XML5: Swith to the bogus comment state.
3213          $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');
3214          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
3215          ## reconsume          ## reconsume
# Line 3029  sub _get_next_token ($) { Line 3254  sub _get_next_token ($) {
3254          return  ($self->{ct}); # DOCTYPE (quirks)          return  ($self->{ct}); # DOCTYPE (quirks)
3255    
3256          redo A;          redo A;
3257          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3258            
3259            $self->{ct}->{name} # DOCTYPE
3260                = chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3261            delete $self->{ct}->{quirks};
3262            $self->{state} = DOCTYPE_NAME_STATE;
3263            
3264        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3265          $self->{line_prev} = $self->{line};
3266          $self->{column_prev} = $self->{column};
3267          $self->{column}++;
3268          $self->{nc}
3269              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3270        } else {
3271          $self->{set_nc}->($self);
3272        }
3273      
3274            redo A;
3275        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3276                    
3277          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');
# Line 3115  sub _get_next_token ($) { Line 3358  sub _get_next_token ($) {
3358          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3359    
3360          redo A;          redo A;
3361          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3362            
3363            $self->{ct}->{name} # DOCTYPE
3364                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3365            delete $self->{ct}->{quirks};
3366            ## Stay in the state.
3367            
3368        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3369          $self->{line_prev} = $self->{line};
3370          $self->{column_prev} = $self->{column};
3371          $self->{column}++;
3372          $self->{nc}
3373              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3374        } else {
3375          $self->{set_nc}->($self);
3376        }
3377      
3378            redo A;
3379        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3380                    
3381          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
# Line 3146  sub _get_next_token ($) { Line 3407  sub _get_next_token ($) {
3407          redo A;          redo A;
3408        } else {        } else {
3409                    
3410          $self->{ct}->{name}          $self->{ct}->{name} .= chr ($self->{nc}); # DOCTYPE
3411            .= chr ($self->{nc}); # DOCTYPE          ## Stay in the state.
         ## Stay in the state  
3412                    
3413      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3414        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3182  sub _get_next_token ($) { Line 3442  sub _get_next_token ($) {
3442        
3443          redo A;          redo A;
3444        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3445            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3446              
3447              $self->{state} = DATA_STATE;
3448              $self->{s_kwd} = '';
3449            } else {
3450              
3451              $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
3452              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3453            }
3454                    
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3455                    
3456      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3457        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3196  sub _get_next_token ($) { Line 3463  sub _get_next_token ($) {
3463        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3464      }      }
3465        
3466            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3467          redo A;          redo A;
3468        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3469            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3470              
3471              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3472              $self->{state} = DATA_STATE;
3473              $self->{s_kwd} = '';
3474              $self->{ct}->{quirks} = 1;
3475            } else {
3476              
3477              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3478              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3479            }
3480                    
3481          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          ## Reconsume.
3482          $self->{state} = DATA_STATE;          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{s_kwd} = '';  
         ## reconsume  
   
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3483          redo A;          redo A;
3484        } elsif ($self->{nc} == 0x0050 or # P        } elsif ($self->{nc} == 0x0050 or # P
3485                 $self->{nc} == 0x0070) { # p                 $self->{nc} == 0x0070) { # p
# Line 3245  sub _get_next_token ($) { Line 3515  sub _get_next_token ($) {
3515      }      }
3516        
3517          redo A;          redo A;
3518        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{nc} == 0x0022 and # "
3519                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3520                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3521            
3522            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
3523            $self->{ct}->{value} = ''; # ENTITY
3524            
3525        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3526          $self->{line_prev} = $self->{line};
3527          $self->{column_prev} = $self->{column};
3528          $self->{column}++;
3529          $self->{nc}
3530              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3531        } else {
3532          $self->{set_nc}->($self);
3533        }
3534      
3535            redo A;
3536          } elsif ($self->{nc} == 0x0027 and # '
3537                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3538                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3539            
3540            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
3541            $self->{ct}->{value} = ''; # ENTITY
3542            
3543        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3544          $self->{line_prev} = $self->{line};
3545          $self->{column_prev} = $self->{column};
3546          $self->{column}++;
3547          $self->{nc}
3548              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3549        } else {
3550          $self->{set_nc}->($self);
3551        }
3552      
3553            redo A;
3554          } elsif ($self->{is_xml} and
3555                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3556                   $self->{nc} == 0x005B) { # [
3557                    
3558          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3559          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 3264  sub _get_next_token ($) { Line 3572  sub _get_next_token ($) {
3572          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3573          redo A;          redo A;
3574        } else {        } else {
3575                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name'); ## TODO: type
3576          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name');  
3577          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3578              
3579              $self->{ct}->{quirks} = 1;
3580              $self->{state} = BOGUS_DOCTYPE_STATE;
3581            } else {
3582              
3583              $self->{state} = BOGUS_MD_STATE;
3584            }
3585    
         $self->{state} = BOGUS_DOCTYPE_STATE;  
3586                    
3587      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3588        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3340  sub _get_next_token ($) { Line 3654  sub _get_next_token ($) {
3654        
3655          redo A;          redo A;
3656        } else {        } else {
3657                    $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',  
3658                          line => $self->{line_prev},                          line => $self->{line_prev},
3659                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3660          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3661              
3662          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3663              $self->{state} = BOGUS_DOCTYPE_STATE;
3664            } else {
3665              
3666              $self->{state} = BOGUS_MD_STATE;
3667            }
3668          ## Reconsume.          ## Reconsume.
3669          redo A;          redo A;
3670        }        }
# Line 3408  sub _get_next_token ($) { Line 3726  sub _get_next_token ($) {
3726        
3727          redo A;          redo A;
3728        } else {        } else {
3729                    $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',  
3730                          line => $self->{line_prev},                          line => $self->{line_prev},
3731                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3732          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3733              
3734          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3735              $self->{state} = BOGUS_DOCTYPE_STATE;
3736            } else {
3737              
3738              $self->{state} = BOGUS_MD_STATE;
3739            }
3740          ## Reconsume.          ## Reconsume.
3741          redo A;          redo A;
3742        }        }
# Line 3467  sub _get_next_token ($) { Line 3789  sub _get_next_token ($) {
3789        
3790          redo A;          redo A;
3791        } elsif ($self->{nc} eq 0x003E) { # >        } elsif ($self->{nc} eq 0x003E) { # >
           
3792          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3793            
3794          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3795          $self->{s_kwd} = '';            
3796              $self->{state} = DATA_STATE;
3797              $self->{s_kwd} = '';
3798              $self->{ct}->{quirks} = 1;
3799            } else {
3800              
3801              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3802            }
3803            
3804                    
3805      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3806        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3483  sub _get_next_token ($) { Line 3812  sub _get_next_token ($) {
3812        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3813      }      }
3814        
3815            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3816          redo A;          redo A;
3817        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3818            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3819              
3820              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3821              $self->{state} = DATA_STATE;
3822              $self->{s_kwd} = '';
3823              $self->{ct}->{quirks} = 1;
3824            } else {
3825              
3826              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3827              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3828            }
3829                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3830          ## reconsume          ## reconsume
   
         $self->{ct}->{quirks} = 1;  
3831          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3832          redo A;          redo A;
3833        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3834                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3835                   $self->{nc} == 0x005B) { # [
3836                    
3837          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3838          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3520  sub _get_next_token ($) { Line 3852  sub _get_next_token ($) {
3852          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3853          redo A;          redo A;
3854        } else {        } else {
           
3855          $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;  
3856    
3857          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3858              
3859              $self->{ct}->{quirks} = 1;
3860              $self->{state} = BOGUS_DOCTYPE_STATE;
3861            } else {
3862              
3863              $self->{state} = BOGUS_MD_STATE;
3864            }
3865    
3866                    
3867      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3868        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3555  sub _get_next_token ($) { Line 3893  sub _get_next_token ($) {
3893        
3894          redo A;          redo A;
3895        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3896          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3897    
3898          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3899          $self->{s_kwd} = '';            
3900              $self->{state} = DATA_STATE;
3901              $self->{s_kwd} = '';
3902              $self->{ct}->{quirks} = 1;
3903            } else {
3904              
3905              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3906            }
3907    
3908                    
3909      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3910        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3571  sub _get_next_token ($) { Line 3916  sub _get_next_token ($) {
3916        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3917      }      }
3918        
3919            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3920          redo A;          redo A;
3921        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3922          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3923    
3924          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3925          $self->{s_kwd} = '';            
3926          ## reconsume            $self->{state} = DATA_STATE;
3927              $self->{s_kwd} = '';
3928          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
3929            } else {
3930              
3931              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3932            }
3933            
3934            ## Reconsume.
3935          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3936          redo A;          redo A;
3937        } else {        } else {
3938                    
3939          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3940          $self->{read_until}->($self->{ct}->{pubid}, q[">],          $self->{read_until}->($self->{ct}->{pubid}, q[">],
3941                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3942    
# Line 3626  sub _get_next_token ($) { Line 3971  sub _get_next_token ($) {
3971        
3972          redo A;          redo A;
3973        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3974          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3975    
3976          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3977          $self->{s_kwd} = '';            
3978              $self->{state} = DATA_STATE;
3979              $self->{s_kwd} = '';
3980              $self->{ct}->{quirks} = 1;
3981            } else {
3982              
3983              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3984            }
3985    
3986                    
3987      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3988        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3642  sub _get_next_token ($) { Line 3994  sub _get_next_token ($) {
3994        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3995      }      }
3996        
3997            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3998          redo A;          redo A;
3999        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4000          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
4001    
4002          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4003          $self->{s_kwd} = '';            
4004              $self->{state} = DATA_STATE;
4005              $self->{s_kwd} = '';
4006              $self->{ct}->{quirks} = 1;
4007            } else {
4008              
4009              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4010            }
4011          
4012          ## reconsume          ## reconsume
4013            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4014          redo A;          redo A;
4015        } else {        } else {
4016                    
4017          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4018          $self->{read_until}->($self->{ct}->{pubid}, q['>],          $self->{read_until}->($self->{ct}->{pubid}, q['>],
4019                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
4020    
# Line 3698  sub _get_next_token ($) { Line 4050  sub _get_next_token ($) {
4050          redo A;          redo A;
4051        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
4052                    
4053          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
4054          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
4055                    
4056      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 3714  sub _get_next_token ($) { Line 4066  sub _get_next_token ($) {
4066          redo A;          redo A;
4067        } elsif ($self->{nc} == 0x0027) { # '        } elsif ($self->{nc} == 0x0027) { # '
4068                    
4069          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
4070          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
4071                    
4072      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 3729  sub _get_next_token ($) { Line 4081  sub _get_next_token ($) {
4081        
4082          redo A;          redo A;
4083        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4084          if ($self->{is_xml}) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4085                        if ($self->{is_xml}) {
4086            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');              
4087                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4088              } else {
4089                
4090              }
4091              $self->{state} = DATA_STATE;
4092              $self->{s_kwd} = '';
4093          } else {          } else {
4094                        if ($self->{ct}->{type} == NOTATION_TOKEN) {
4095                
4096              } else {
4097                
4098                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');            
4099              }
4100              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4101          }          }
4102          $self->{state} = DATA_STATE;          
         $self->{s_kwd} = '';  
4103                    
4104      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4105        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3748  sub _get_next_token ($) { Line 4111  sub _get_next_token ($) {
4111        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4112      }      }
4113        
4114            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
4115          redo A;          redo A;
4116        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4117            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4118              
4119              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4120              
4121              $self->{state} = DATA_STATE;
4122              $self->{s_kwd} = '';
4123              $self->{ct}->{quirks} = 1;
4124            } else {
4125              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4126              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4127            }
4128                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4129          ## reconsume          ## reconsume
4130            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4131          redo A;          redo A;
4132        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4133                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4134                   $self->{nc} == 0x005B) { # [
4135                    
4136          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4137          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3784  sub _get_next_token ($) { Line 4151  sub _get_next_token ($) {
4151          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4152          redo A;          redo A;
4153        } else {        } else {
           
4154          $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;  
4155    
4156          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4157              
4158              $self->{ct}->{quirks} = 1;
4159              $self->{state} = BOGUS_DOCTYPE_STATE;
4160            } else {
4161              
4162              $self->{state} = BOGUS_MD_STATE;
4163            }
4164    
4165                    
4166      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4167        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3851  sub _get_next_token ($) { Line 4224  sub _get_next_token ($) {
4224        
4225          redo A;          redo A;
4226        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
4227          $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} = '';  
4228                    
4229      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4230        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3867  sub _get_next_token ($) { Line 4237  sub _get_next_token ($) {
4237      }      }
4238        
4239    
4240          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4241          return  ($self->{ct}); # DOCTYPE            
4242              $self->{state} = DATA_STATE;
4243              $self->{s_kwd} = '';
4244              $self->{ct}->{quirks} = 1;
4245            } else {
4246              
4247              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4248            }
4249    
4250            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4251          redo A;          redo A;
4252        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4253            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4254              
4255              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4256              $self->{state} = DATA_STATE;
4257              $self->{s_kwd} = '';
4258              $self->{ct}->{quirks} = 1;
4259            } else {
4260              
4261              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4262              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4263            }
4264                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4265          ## reconsume          ## reconsume
4266            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4267          redo A;          redo A;
4268        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4269                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4270                   $self->{nc} == 0x005B) { # [
4271                    
4272          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4273    
# Line 3904  sub _get_next_token ($) { Line 4288  sub _get_next_token ($) {
4288          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4289          redo A;          redo A;
4290        } else {        } else {
           
4291          $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;  
4292    
4293          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4294                        
4295              $self->{ct}->{quirks} = 1;
4296              $self->{state} = BOGUS_DOCTYPE_STATE;
4297            } else {
4298              
4299              $self->{state} = BOGUS_MD_STATE;
4300            }
4301    
4302                    
4303      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4304        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3939  sub _get_next_token ($) { Line 4329  sub _get_next_token ($) {
4329        
4330          redo A;          redo A;
4331        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >
           
4332          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4333    
4334          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4335          $self->{s_kwd} = '';            
4336              $self->{state} = DATA_STATE;
4337              $self->{s_kwd} = '';
4338              $self->{ct}->{quirks} = 1;
4339            } else {
4340              
4341              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4342            }
4343            
4344                    
4345      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4346        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3955  sub _get_next_token ($) { Line 4352  sub _get_next_token ($) {
4352        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4353      }      }
4354        
4355            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4356          redo A;          redo A;
4357        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4358          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4359    
4360          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4361          $self->{s_kwd} = '';            
4362              $self->{state} = DATA_STATE;
4363              $self->{s_kwd} = '';
4364              $self->{ct}->{quirks} = 1;
4365            } else {
4366              
4367              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4368            }
4369            
4370          ## reconsume          ## reconsume
4371            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4372          redo A;          redo A;
4373        } else {        } else {
4374                    
4375          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4376          $self->{read_until}->($self->{ct}->{sysid}, q[">],          $self->{read_until}->($self->{ct}->{sysid}, q[">],
4377                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4378    
# Line 4032  sub _get_next_token ($) { Line 4429  sub _get_next_token ($) {
4429    
4430          redo A;          redo A;
4431        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4432          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4433    
4434          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4435          $self->{s_kwd} = '';            
4436          ## reconsume            $self->{state} = DATA_STATE;
4437              $self->{s_kwd} = '';
4438          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
4439          return  ($self->{ct}); # DOCTYPE          } else {
4440              
4441              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4442            }
4443    
4444            ## reconsume
4445            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4446          redo A;          redo A;
4447        } else {        } else {
4448                    
4449          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4450          $self->{read_until}->($self->{ct}->{sysid}, q['>],          $self->{read_until}->($self->{ct}->{sysid}, q['>],
4451                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4452    
# Line 4066  sub _get_next_token ($) { Line 4466  sub _get_next_token ($) {
4466        }        }
4467      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
4468        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4469                    if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
4470          ## Stay in the state            
4471              $self->{state} = BEFORE_NDATA_STATE;
4472            } else {
4473              
4474              ## Stay in the state
4475            }
4476                    
4477      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4478        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4081  sub _get_next_token ($) { Line 4486  sub _get_next_token ($) {
4486        
4487          redo A;          redo A;
4488        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4489            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4490              
4491              $self->{state} = DATA_STATE;
4492              $self->{s_kwd} = '';
4493            } else {
4494              
4495              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4496            }
4497    
4498                    
4499          $self->{state} = DATA_STATE;      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4500          $self->{s_kwd} = '';        $self->{line_prev} = $self->{line};
4501          $self->{column_prev} = $self->{column};
4502          $self->{column}++;
4503          $self->{nc}
4504              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4505        } else {
4506          $self->{set_nc}->($self);
4507        }
4508      
4509            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4510            redo A;
4511          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4512                   ($self->{nc} == 0x004E or # N
4513                    $self->{nc} == 0x006E)) { # n
4514            
4515            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before NDATA'); ## TODO: type
4516            $self->{state} = NDATA_STATE;
4517            $self->{kwd} = chr $self->{nc};
4518                    
4519      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4520        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4095  sub _get_next_token ($) { Line 4526  sub _get_next_token ($) {
4526        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4527      }      }
4528        
   
         return  ($self->{ct}); # DOCTYPE  
   
4529          redo A;          redo A;
4530        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4531                    if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4532          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');            
4533          $self->{state} = DATA_STATE;            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4534          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
4535          ## reconsume            $self->{s_kwd} = '';
4536              $self->{ct}->{quirks} = 1;
4537          $self->{ct}->{quirks} = 1;          } else {
4538          return  ($self->{ct}); # DOCTYPE            
4539              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4540              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4541            }
4542    
4543            ## reconsume
4544            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4545          redo A;          redo A;
4546        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4547                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4548                   $self->{nc} == 0x005B) { # [
4549                    
4550          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4551          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 4129  sub _get_next_token ($) { Line 4564  sub _get_next_token ($) {
4564          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4565          redo A;          redo A;
4566        } else {        } else {
           
4567          $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;  
4568    
4569          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4570              
4571              #$self->{ct}->{quirks} = 1;
4572              $self->{state} = BOGUS_DOCTYPE_STATE;
4573            } else {
4574              
4575              $self->{state} = BOGUS_MD_STATE;
4576            }
4577    
4578            
4579        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4580          $self->{line_prev} = $self->{line};
4581          $self->{column_prev} = $self->{column};
4582          $self->{column}++;
4583          $self->{nc}
4584              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4585        } else {
4586          $self->{set_nc}->($self);
4587        }
4588      
4589            redo A;
4590          }
4591        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
4592          if ($is_space->{$self->{nc}}) {
4593            
4594            ## Stay in the state.
4595            
4596        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4597          $self->{line_prev} = $self->{line};
4598          $self->{column_prev} = $self->{column};
4599          $self->{column}++;
4600          $self->{nc}
4601              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4602        } else {
4603          $self->{set_nc}->($self);
4604        }
4605      
4606            redo A;
4607          } elsif ($self->{nc} == 0x003E) { # >
4608            
4609            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4610            
4611        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4612          $self->{line_prev} = $self->{line};
4613          $self->{column_prev} = $self->{column};
4614          $self->{column}++;
4615          $self->{nc}
4616              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4617        } else {
4618          $self->{set_nc}->($self);
4619        }
4620      
4621            return  ($self->{ct}); # ENTITY
4622            redo A;
4623          } elsif ($self->{nc} == 0x004E or # N
4624                   $self->{nc} == 0x006E) { # n
4625            
4626            $self->{state} = NDATA_STATE;
4627            $self->{kwd} = chr $self->{nc};
4628            
4629        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4630          $self->{line_prev} = $self->{line};
4631          $self->{column_prev} = $self->{column};
4632          $self->{column}++;
4633          $self->{nc}
4634              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4635        } else {
4636          $self->{set_nc}->($self);
4637        }
4638      
4639            redo A;
4640          } elsif ($self->{nc} == -1) {
4641            
4642            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4643            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4644            ## reconsume
4645            return  ($self->{ct}); # ENTITY
4646            redo A;
4647          } else {
4648            
4649            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
4650            $self->{state} = BOGUS_MD_STATE;
4651                    
4652      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4653        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4357  sub _get_next_token ($) { Line 4871  sub _get_next_token ($) {
4871              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4872              $self->{entity_add} => 1,              $self->{entity_add} => 1,
4873            }->{$self->{nc}}) {            }->{$self->{nc}}) {
4874                    if ($self->{is_xml}) {
4875              
4876              $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
4877                              line => $self->{line_prev},
4878                              column => $self->{column_prev}
4879                                  + ($self->{nc} == -1 ? 1 : 0));
4880            } else {
4881              
4882              ## No error
4883            }
4884          ## Don't consume          ## Don't consume
         ## No error  
4885          ## Return nothing.          ## Return nothing.
4886          #          #
4887        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 4378  sub _get_next_token ($) { Line 4900  sub _get_next_token ($) {
4900      }      }
4901        
4902          redo A;          redo A;
4903        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
4904                   (0x0041 <= $self->{nc} and
4905                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
4906                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
4907                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 4432  sub _get_next_token ($) { Line 4955  sub _get_next_token ($) {
4955          redo A;          redo A;
4956        }        }
4957      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
4958        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
4959            $self->{nc} == 0x0058) { # X          
4960            $self->{state} = HEXREF_X_STATE;
4961            $self->{kwd} .= chr $self->{nc};
4962            
4963        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4964          $self->{line_prev} = $self->{line};
4965          $self->{column_prev} = $self->{column};
4966          $self->{column}++;
4967          $self->{nc}
4968              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4969        } else {
4970          $self->{set_nc}->($self);
4971        }
4972      
4973            redo A;
4974          } elsif ($self->{nc} == 0x0058) { # X
4975                    
4976            if ($self->{is_xml}) {
4977              $self->{parse_error}->(level => $self->{level}->{must}, type => 'uppercase hcro'); ## TODO: type
4978            }
4979          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
4980          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4981                    
# Line 4539  sub _get_next_token ($) { Line 5080  sub _get_next_token ($) {
5080        my $code = $self->{kwd};        my $code = $self->{kwd};
5081        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5082        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5083        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5084              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5085              ($self->{is_xml} and $code == 0x0000)) {
5086                    
5087          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5088                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4692  sub _get_next_token ($) { Line 5235  sub _get_next_token ($) {
5235        my $code = $self->{kwd};        my $code = $self->{kwd};
5236        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5237        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5238        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5239              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5240              ($self->{is_xml} and $code == 0x0000)) {
5241                    
5242          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5243                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4726  sub _get_next_token ($) { Line 5271  sub _get_next_token ($) {
5271          redo A;          redo A;
5272        }        }
5273      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
5274        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
5275            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
5276            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
5277              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
5278             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
5279              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
5280             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
5281              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
5282             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
5283                    {
5284                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
5285                      $self->{entity_add} => 1,
5286                    }->{$self->{nc}}))) {
5287          our $EntityChar;          our $EntityChar;
5288          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5289          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
5290                $self->{ge}->{$self->{kwd}}) {
5291            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
5292                            if (defined $self->{ge}->{$self->{kwd}}) {
5293              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
5294                    
5295                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
5296                  } else {
5297                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
5298                      
5299                      $self->{parse_error}->(level => $self->{level}->{must}, type => 'unparsed entity', ## TODO: type
5300                                      value => $self->{kwd});
5301                    } else {
5302                      
5303                    }
5304                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
5305                  }
5306                } else {
5307                  if ($self->{is_xml}) {
5308                    
5309                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'entity not declared', ## TODO: type
5310                                    value => $self->{kwd},
5311                                    level => {
5312                                              'amp;' => $self->{level}->{warn},
5313                                              'quot;' => $self->{level}->{warn},
5314                                              'lt;' => $self->{level}->{warn},
5315                                              'gt;' => $self->{level}->{warn},
5316                                              'apos;' => $self->{level}->{warn},
5317                                             }->{$self->{kwd}} ||
5318                                             $self->{level}->{must});
5319                  } else {
5320                    
5321                  }
5322                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
5323                }
5324              $self->{entity__match} = 1;              $self->{entity__match} = 1;
5325                            
5326      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5136  sub _get_next_token ($) { Line 5716  sub _get_next_token ($) {
5716          ## XML5: Not defined yet.          ## XML5: Not defined yet.
5717    
5718          ## TODO:          ## TODO:
5719    
5720            if (not $self->{stop_processing} and
5721                not $self->{document}->xml_standalone) {
5722              $self->{parse_error}->(level => $self->{level}->{must}, type => 'stop processing', ## TODO: type
5723                              level => $self->{level}->{info});
5724              $self->{stop_processing} = 1;
5725            }
5726    
5727                    
5728      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
5729        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5358  sub _get_next_token ($) { Line 5946  sub _get_next_token ($) {
5946      }      }
5947        
5948          redo A;          redo A;
5949        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
5950                   $self->{nc} == 0x0065) { # e
5951          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
5952          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5953                    
# Line 5373  sub _get_next_token ($) { Line 5962  sub _get_next_token ($) {
5962      }      }
5963        
5964          redo A;          redo A;
5965        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
5966                   $self->{nc} == 0x0061) { # a
5967          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
5968          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5969                    
# Line 5388  sub _get_next_token ($) { Line 5978  sub _get_next_token ($) {
5978      }      }
5979        
5980          redo A;          redo A;
5981        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
5982                   $self->{nc} == 0x006E) { # n
5983          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
5984          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5985                    
# Line 5416  sub _get_next_token ($) { Line 6007  sub _get_next_token ($) {
6007        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
6008        redo A;        redo A;
6009      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
6010        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
6011              $self->{nc} == 0x006E) { # n
6012          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
6013          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6014                    
# Line 5431  sub _get_next_token ($) { Line 6023  sub _get_next_token ($) {
6023      }      }
6024        
6025          redo A;          redo A;
6026        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
6027                   $self->{nc} == 0x006C) { # l
6028          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
6029          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
6030          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 5459  sub _get_next_token ($) { Line 6052  sub _get_next_token ($) {
6052          redo A;          redo A;
6053        }        }
6054      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
6055        if ($self->{nc} == {        if ($self->{nc} == [
6056              'EN' => 0x0054, # T              undef,
6057              'ENT' => 0x0049, # I              undef,
6058              'ENTI' => 0x0054, # T              0x0054, # T
6059            }->{$self->{kwd}}) {              0x0049, # I
6060                0x0054, # T
6061              ]->[length $self->{kwd}] or
6062              $self->{nc} == [
6063                undef,
6064                undef,
6065                0x0074, # t
6066                0x0069, # i
6067                0x0074, # t
6068              ]->[length $self->{kwd}]) {
6069          ## Stay in the state.          ## Stay in the state.
6070          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6071                    
# Line 5478  sub _get_next_token ($) { Line 6080  sub _get_next_token ($) {
6080      }      }
6081        
6082          redo A;          redo A;
6083        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
6084                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
6085          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
6086            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
6087              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6088                              text => 'ENTITY',
6089                              line => $self->{line_prev},
6090                              column => $self->{column_prev} - 4);
6091            }
6092            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
6093                         line => $self->{line_prev},                         line => $self->{line_prev},
6094                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
6095          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 5508  sub _get_next_token ($) { Line 6117  sub _get_next_token ($) {
6117          redo A;          redo A;
6118        }        }
6119      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
6120        if ($self->{nc} == {        if ($self->{nc} == [
6121              'EL' => 0x0045, # E             undef,
6122              'ELE' => 0x004D, # M             undef,
6123              'ELEM' => 0x0045, # E             0x0045, # E
6124              'ELEME' => 0x004E, # N             0x004D, # M
6125            }->{$self->{kwd}}) {             0x0045, # E
6126               0x004E, # N
6127              ]->[length $self->{kwd}] or
6128              $self->{nc} == [
6129               undef,
6130               undef,
6131               0x0065, # e
6132               0x006D, # m
6133               0x0065, # e
6134               0x006E, # n
6135              ]->[length $self->{kwd}]) {
6136          ## Stay in the state.          ## Stay in the state.
6137          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6138                    
# Line 5528  sub _get_next_token ($) { Line 6147  sub _get_next_token ($) {
6147      }      }
6148        
6149          redo A;          redo A;
6150        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
6151                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6152                    $self->{nc} == 0x0074)) { # t
6153            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
6154              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6155                              text => 'ELEMENT',
6156                              line => $self->{line_prev},
6157                              column => $self->{column_prev} - 5);
6158            }
6159          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
6160                         line => $self->{line_prev},                         line => $self->{line_prev},
6161                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6162          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6163                    
6164      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5558  sub _get_next_token ($) { Line 6184  sub _get_next_token ($) {
6184          redo A;          redo A;
6185        }        }
6186      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
6187        if ($self->{nc} == {        if ($self->{nc} == [
6188              'A' => 0x0054, # T             undef,
6189              'AT' => 0x0054, # T             0x0054, # T
6190              'ATT' => 0x004C, # L             0x0054, # T
6191              'ATTL' => 0x0049, # I             0x004C, # L
6192              'ATTLI' => 0x0053, # S             0x0049, # I
6193            }->{$self->{kwd}}) {             0x0053, # S
6194              ]->[length $self->{kwd}] or
6195              $self->{nc} == [
6196               undef,
6197               0x0074, # t
6198               0x0074, # t
6199               0x006C, # l
6200               0x0069, # i
6201               0x0073, # s
6202              ]->[length $self->{kwd}]) {
6203          ## Stay in the state.          ## Stay in the state.
6204          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6205                    
# Line 5579  sub _get_next_token ($) { Line 6214  sub _get_next_token ($) {
6214      }      }
6215        
6216          redo A;          redo A;
6217        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
6218                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6219                    $self->{nc} == 0x0074)) { # t
6220            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
6221              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6222                              text => 'ATTLIST',
6223                              line => $self->{line_prev},
6224                              column => $self->{column_prev} - 5);
6225            }
6226          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
6227                         attrdefs => [],                         attrdefs => [],
6228                         line => $self->{line_prev},                         line => $self->{line_prev},
6229                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6230          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6231                    
6232      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5610  sub _get_next_token ($) { Line 6252  sub _get_next_token ($) {
6252          redo A;          redo A;
6253        }        }
6254      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
6255        if ($self->{nc} == {        if ($self->{nc} == [
6256              'N' => 0x004F, # O             undef,
6257              'NO' => 0x0054, # T             0x004F, # O
6258              'NOT' => 0x0041, # A             0x0054, # T
6259              'NOTA' => 0x0054, # T             0x0041, # A
6260              'NOTAT' => 0x0049, # I             0x0054, # T
6261              'NOTATI' => 0x004F, # O             0x0049, # I
6262            }->{$self->{kwd}}) {             0x004F, # O
6263              ]->[length $self->{kwd}] or
6264              $self->{nc} == [
6265               undef,
6266               0x006F, # o
6267               0x0074, # t
6268               0x0061, # a
6269               0x0074, # t
6270               0x0069, # i
6271               0x006F, # o
6272              ]->[length $self->{kwd}]) {
6273          ## Stay in the state.          ## Stay in the state.
6274          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6275                    
# Line 5632  sub _get_next_token ($) { Line 6284  sub _get_next_token ($) {
6284      }      }
6285        
6286          redo A;          redo A;
6287        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
6288                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
6289                    $self->{nc} == 0x006E)) { # n
6290            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
6291              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6292                              text => 'NOTATION',
6293                              line => $self->{line_prev},
6294                              column => $self->{column_prev} - 6);
6295            }
6296          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
6297                         line => $self->{line_prev},                         line => $self->{line_prev},
6298                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
6299          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6300                    
6301      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5845  sub _get_next_token ($) { Line 6504  sub _get_next_token ($) {
6504        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".
6505                
6506        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
6507          ## TODO:          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6508          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
6509            } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6510              $self->{state} = AFTER_ELEMENT_NAME_STATE;
6511            } else { # ENTITY/NOTATION
6512              $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6513            }
6514                    
6515      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6516        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5863  sub _get_next_token ($) { Line 6527  sub _get_next_token ($) {
6527          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6528            #            #
6529          } else {          } else {
6530            $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
6531          }          }
6532          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6533                    
# Line 6853  sub _get_next_token ($) { Line 7517  sub _get_next_token ($) {
7517        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
7518          ## XML5: No parse error.          ## XML5: No parse error.
7519          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no default type'); ## TODO: type          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no default type'); ## TODO: type
7520          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = BOGUS_MD_STATE;
         $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded  
7521          ## Reconsume.          ## Reconsume.
7522          redo A;          redo A;
7523        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
# Line 7141  sub _get_next_token ($) { Line 7804  sub _get_next_token ($) {
7804          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
7805          ## Reconsume.          ## Reconsume.
7806          redo A;          redo A;
7807        }              }
7808        } elsif ($self->{state} == NDATA_STATE) {
7809          ## ASCII case-insensitive
7810          if ($self->{nc} == [
7811                undef,
7812                0x0044, # D
7813                0x0041, # A
7814                0x0054, # T
7815              ]->[length $self->{kwd}] or
7816              $self->{nc} == [
7817                undef,
7818                0x0064, # d
7819                0x0061, # a
7820                0x0074, # t
7821              ]->[length $self->{kwd}]) {
7822            
7823            ## Stay in the state.
7824            $self->{kwd} .= chr $self->{nc};
7825            
7826        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7827          $self->{line_prev} = $self->{line};
7828          $self->{column_prev} = $self->{column};
7829          $self->{column}++;
7830          $self->{nc}
7831              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7832        } else {
7833          $self->{set_nc}->($self);
7834        }
7835      
7836            redo A;
7837          } elsif ((length $self->{kwd}) == 4 and
7838                   ($self->{nc} == 0x0041 or # A
7839                    $self->{nc} == 0x0061)) { # a
7840            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
7841              
7842              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
7843                              text => 'NDATA',
7844                              line => $self->{line_prev},
7845                              column => $self->{column_prev} - 4);
7846            } else {
7847              
7848            }
7849            $self->{state} = AFTER_NDATA_STATE;
7850            
7851        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7852          $self->{line_prev} = $self->{line};
7853          $self->{column_prev} = $self->{column};
7854          $self->{column}++;
7855          $self->{nc}
7856              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7857        } else {
7858          $self->{set_nc}->($self);
7859        }
7860      
7861            redo A;
7862          } else {
7863            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7864                            line => $self->{line_prev},
7865                            column => $self->{column_prev} + 1
7866                                - length $self->{kwd});
7867            
7868            $self->{state} = BOGUS_MD_STATE;
7869            ## Reconsume.
7870            redo A;
7871          }
7872        } elsif ($self->{state} == AFTER_NDATA_STATE) {
7873          if ($is_space->{$self->{nc}}) {
7874            $self->{state} = BEFORE_NOTATION_NAME_STATE;
7875            
7876        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7877          $self->{line_prev} = $self->{line};
7878          $self->{column_prev} = $self->{column};
7879          $self->{column}++;
7880          $self->{nc}
7881              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7882        } else {
7883          $self->{set_nc}->($self);
7884        }
7885      
7886            redo A;
7887          } elsif ($self->{nc} == 0x003E) { # >
7888            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7889            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7890            
7891        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7892          $self->{line_prev} = $self->{line};
7893          $self->{column_prev} = $self->{column};
7894          $self->{column}++;
7895          $self->{nc}
7896              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7897        } else {
7898          $self->{set_nc}->($self);
7899        }
7900      
7901            return  ($self->{ct}); # ENTITY
7902            redo A;
7903          } elsif ($self->{nc} == -1) {
7904            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7905            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7906            
7907        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7908          $self->{line_prev} = $self->{line};
7909          $self->{column_prev} = $self->{column};
7910          $self->{column}++;
7911          $self->{nc}
7912              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7913        } else {
7914          $self->{set_nc}->($self);
7915        }
7916      
7917            return  ($self->{ct}); # ENTITY
7918            redo A;
7919          } else {
7920            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7921                            line => $self->{line_prev},
7922                            column => $self->{column_prev} + 1
7923                                - length $self->{kwd});
7924            $self->{state} = BOGUS_MD_STATE;
7925            ## Reconsume.
7926            redo A;
7927          }
7928        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
7929          if ($is_space->{$self->{nc}}) {
7930            ## Stay in the state.
7931            
7932        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7933          $self->{line_prev} = $self->{line};
7934          $self->{column_prev} = $self->{column};
7935          $self->{column}++;
7936          $self->{nc}
7937              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7938        } else {
7939          $self->{set_nc}->($self);
7940        }
7941      
7942            redo A;
7943          } elsif ($self->{nc} == 0x003E) { # >
7944            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7945            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7946            
7947        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7948          $self->{line_prev} = $self->{line};
7949          $self->{column_prev} = $self->{column};
7950          $self->{column}++;
7951          $self->{nc}
7952              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7953        } else {
7954          $self->{set_nc}->($self);
7955        }
7956      
7957            return  ($self->{ct}); # ENTITY
7958            redo A;
7959          } elsif ($self->{nc} == -1) {
7960            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7961            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7962            
7963        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7964          $self->{line_prev} = $self->{line};
7965          $self->{column_prev} = $self->{column};
7966          $self->{column}++;
7967          $self->{nc}
7968              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7969        } else {
7970          $self->{set_nc}->($self);
7971        }
7972      
7973            return  ($self->{ct}); # ENTITY
7974            redo A;
7975          } else {
7976            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
7977            $self->{state} = NOTATION_NAME_STATE;
7978            
7979        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7980          $self->{line_prev} = $self->{line};
7981          $self->{column_prev} = $self->{column};
7982          $self->{column}++;
7983          $self->{nc}
7984              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7985        } else {
7986          $self->{set_nc}->($self);
7987        }
7988      
7989            redo A;
7990          }
7991        } elsif ($self->{state} == NOTATION_NAME_STATE) {
7992          if ($is_space->{$self->{nc}}) {
7993            $self->{state} = AFTER_MD_DEF_STATE;
7994            
7995        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7996          $self->{line_prev} = $self->{line};
7997          $self->{column_prev} = $self->{column};
7998          $self->{column}++;
7999          $self->{nc}
8000              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8001        } else {
8002          $self->{set_nc}->($self);
8003        }
8004      
8005            redo A;
8006          } elsif ($self->{nc} == 0x003E) { # >
8007            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8008            
8009        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8010          $self->{line_prev} = $self->{line};
8011          $self->{column_prev} = $self->{column};
8012          $self->{column}++;
8013          $self->{nc}
8014              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8015        } else {
8016          $self->{set_nc}->($self);
8017        }
8018      
8019            return  ($self->{ct}); # ENTITY
8020            redo A;
8021          } elsif ($self->{nc} == -1) {
8022            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8023            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8024            
8025        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8026          $self->{line_prev} = $self->{line};
8027          $self->{column_prev} = $self->{column};
8028          $self->{column}++;
8029          $self->{nc}
8030              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8031        } else {
8032          $self->{set_nc}->($self);
8033        }
8034      
8035            return  ($self->{ct}); # ENTITY
8036            redo A;
8037          } else {
8038            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
8039            ## Stay in the state.
8040            
8041        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8042          $self->{line_prev} = $self->{line};
8043          $self->{column_prev} = $self->{column};
8044          $self->{column}++;
8045          $self->{nc}
8046              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8047        } else {
8048          $self->{set_nc}->($self);
8049        }
8050      
8051            redo A;
8052          }
8053        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
8054          if ($self->{nc} == 0x0022) { # "
8055            $self->{state} = AFTER_MD_DEF_STATE;
8056            
8057        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8058          $self->{line_prev} = $self->{line};
8059          $self->{column_prev} = $self->{column};
8060          $self->{column}++;
8061          $self->{nc}
8062              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8063        } else {
8064          $self->{set_nc}->($self);
8065        }
8066      
8067            redo A;
8068          } elsif ($self->{nc} == 0x0026) { # &
8069            $self->{prev_state} = $self->{state};
8070            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
8071            $self->{entity_add} = 0x0022; # "
8072            
8073        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8074          $self->{line_prev} = $self->{line};
8075          $self->{column_prev} = $self->{column};
8076          $self->{column}++;
8077          $self->{nc}
8078              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8079        } else {
8080          $self->{set_nc}->($self);
8081        }
8082      
8083            redo A;
8084    ## TODO: %
8085          } elsif ($self->{nc} == -1) {
8086            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
8087            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8088            ## Reconsume.
8089            return  ($self->{ct}); # ENTITY
8090            redo A;
8091          } else {
8092            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
8093            
8094        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8095          $self->{line_prev} = $self->{line};
8096          $self->{column_prev} = $self->{column};
8097          $self->{column}++;
8098          $self->{nc}
8099              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8100        } else {
8101          $self->{set_nc}->($self);
8102        }
8103      
8104            redo A;
8105          }
8106        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
8107          if ($self->{nc} == 0x0027) { # '
8108            $self->{state} = AFTER_MD_DEF_STATE;
8109            
8110        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8111          $self->{line_prev} = $self->{line};
8112          $self->{column_prev} = $self->{column};
8113          $self->{column}++;
8114          $self->{nc}
8115              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8116        } else {
8117          $self->{set_nc}->($self);
8118        }
8119      
8120            redo A;
8121          } elsif ($self->{nc} == 0x0026) { # &
8122            $self->{prev_state} = $self->{state};
8123            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
8124            $self->{entity_add} = 0x0027; # '
8125            
8126        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8127          $self->{line_prev} = $self->{line};
8128          $self->{column_prev} = $self->{column};
8129          $self->{column}++;
8130          $self->{nc}
8131              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8132        } else {
8133          $self->{set_nc}->($self);
8134        }
8135      
8136            redo A;
8137    ## TODO: %
8138          } elsif ($self->{nc} == -1) {
8139            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
8140            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8141            ## Reconsume.
8142            return  ($self->{ct}); # ENTITY
8143            redo A;
8144          } else {
8145            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
8146            
8147        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8148          $self->{line_prev} = $self->{line};
8149          $self->{column_prev} = $self->{column};
8150          $self->{column}++;
8151          $self->{nc}
8152              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8153        } else {
8154          $self->{set_nc}->($self);
8155        }
8156      
8157            redo A;
8158          }
8159        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
8160          if ($is_space->{$self->{nc}} or
8161              {
8162                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
8163                $self->{entity_add} => 1,
8164              }->{$self->{nc}}) {
8165            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
8166                            line => $self->{line_prev},
8167                            column => $self->{column_prev}
8168                                + ($self->{nc} == -1 ? 1 : 0));
8169            ## Don't consume
8170            ## Return nothing.
8171            #
8172          } elsif ($self->{nc} == 0x0023) { # #
8173            $self->{ca} = $self->{ct};
8174            $self->{state} = ENTITY_HASH_STATE;
8175            $self->{kwd} = '#';
8176            
8177        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8178          $self->{line_prev} = $self->{line};
8179          $self->{column_prev} = $self->{column};
8180          $self->{column}++;
8181          $self->{nc}
8182              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8183        } else {
8184          $self->{set_nc}->($self);
8185        }
8186      
8187            redo A;
8188          } else {
8189            #
8190          }
8191    
8192          $self->{ct}->{value} .= '&';
8193          $self->{state} = $self->{prev_state};
8194          ## Reconsume.
8195          redo A;
8196        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
8197          if ($is_space->{$self->{nc}}) {
8198            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
8199            
8200        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8201          $self->{line_prev} = $self->{line};
8202          $self->{column_prev} = $self->{column};
8203          $self->{column}++;
8204          $self->{nc}
8205              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8206        } else {
8207          $self->{set_nc}->($self);
8208        }
8209      
8210            redo A;
8211          } elsif ($self->{nc} == 0x0028) { # (
8212            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8213            $self->{ct}->{content} = ['('];
8214            $self->{group_depth} = 1;
8215            
8216        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8217          $self->{line_prev} = $self->{line};
8218          $self->{column_prev} = $self->{column};
8219          $self->{column}++;
8220          $self->{nc}
8221              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8222        } else {
8223          $self->{set_nc}->($self);
8224        }
8225      
8226            redo A;
8227          } elsif ($self->{nc} == 0x003E) { # >
8228            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
8229            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8230            
8231        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8232          $self->{line_prev} = $self->{line};
8233          $self->{column_prev} = $self->{column};
8234          $self->{column}++;
8235          $self->{nc}
8236              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8237        } else {
8238          $self->{set_nc}->($self);
8239        }
8240      
8241            return  ($self->{ct}); # ELEMENT
8242            redo A;
8243          } elsif ($self->{nc} == -1) {
8244            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8245            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8246            
8247        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8248          $self->{line_prev} = $self->{line};
8249          $self->{column_prev} = $self->{column};
8250          $self->{column}++;
8251          $self->{nc}
8252              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8253        } else {
8254          $self->{set_nc}->($self);
8255        }
8256      
8257            return  ($self->{ct}); # ELEMENT
8258            redo A;
8259          } else {
8260            $self->{ct}->{content} = [chr $self->{nc}];
8261            $self->{state} = CONTENT_KEYWORD_STATE;
8262            
8263        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8264          $self->{line_prev} = $self->{line};
8265          $self->{column_prev} = $self->{column};
8266          $self->{column}++;
8267          $self->{nc}
8268              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8269        } else {
8270          $self->{set_nc}->($self);
8271        }
8272      
8273            redo A;
8274          }
8275        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
8276          if ($is_space->{$self->{nc}}) {
8277            $self->{state} = AFTER_MD_DEF_STATE;
8278            
8279        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8280          $self->{line_prev} = $self->{line};
8281          $self->{column_prev} = $self->{column};
8282          $self->{column}++;
8283          $self->{nc}
8284              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8285        } else {
8286          $self->{set_nc}->($self);
8287        }
8288      
8289            redo A;
8290          } elsif ($self->{nc} == 0x003E) { # >
8291            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8292            
8293        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8294          $self->{line_prev} = $self->{line};
8295          $self->{column_prev} = $self->{column};
8296          $self->{column}++;
8297          $self->{nc}
8298              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8299        } else {
8300          $self->{set_nc}->($self);
8301        }
8302      
8303            return  ($self->{ct}); # ELEMENT
8304            redo A;
8305          } elsif ($self->{nc} == -1) {
8306            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8307            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8308            
8309        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8310          $self->{line_prev} = $self->{line};
8311          $self->{column_prev} = $self->{column};
8312          $self->{column}++;
8313          $self->{nc}
8314              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8315        } else {
8316          $self->{set_nc}->($self);
8317        }
8318      
8319            return  ($self->{ct}); # ELEMENT
8320            redo A;
8321          } else {
8322            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
8323            ## Stay in the state.
8324            
8325        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8326          $self->{line_prev} = $self->{line};
8327          $self->{column_prev} = $self->{column};
8328          $self->{column}++;
8329          $self->{nc}
8330              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8331        } else {
8332          $self->{set_nc}->($self);
8333        }
8334      
8335            redo A;
8336          }
8337        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
8338          if ($is_space->{$self->{nc}}) {
8339            ## Stay in the state.
8340            
8341        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8342          $self->{line_prev} = $self->{line};
8343          $self->{column_prev} = $self->{column};
8344          $self->{column}++;
8345          $self->{nc}
8346              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8347        } else {
8348          $self->{set_nc}->($self);
8349        }
8350      
8351            redo A;
8352          } elsif ($self->{nc} == 0x0028) { # (
8353            $self->{group_depth}++;
8354            push @{$self->{ct}->{content}}, chr $self->{nc};
8355            ## Stay in the state.
8356            
8357        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8358          $self->{line_prev} = $self->{line};
8359          $self->{column_prev} = $self->{column};
8360          $self->{column}++;
8361          $self->{nc}
8362              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8363        } else {
8364          $self->{set_nc}->($self);
8365        }
8366      
8367            redo A;
8368          } elsif ($self->{nc} == 0x007C or # |
8369                   $self->{nc} == 0x002C) { # ,
8370            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8371            ## Stay in the state.
8372            
8373        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8374          $self->{line_prev} = $self->{line};
8375          $self->{column_prev} = $self->{column};
8376          $self->{column}++;
8377          $self->{nc}
8378              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8379        } else {
8380          $self->{set_nc}->($self);
8381        }
8382      
8383            redo A;
8384          } elsif ($self->{nc} == 0x0029) { # )
8385            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8386            push @{$self->{ct}->{content}}, chr $self->{nc};
8387            $self->{group_depth}--;
8388            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8389            
8390        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8391          $self->{line_prev} = $self->{line};
8392          $self->{column_prev} = $self->{column};
8393          $self->{column}++;
8394          $self->{nc}
8395              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8396        } else {
8397          $self->{set_nc}->($self);
8398        }
8399      
8400            redo A;
8401          } elsif ($self->{nc} == 0x003E) { # >
8402            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8403            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8404            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8405            
8406        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8407          $self->{line_prev} = $self->{line};
8408          $self->{column_prev} = $self->{column};
8409          $self->{column}++;
8410          $self->{nc}
8411              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8412        } else {
8413          $self->{set_nc}->($self);
8414        }
8415      
8416            return  ($self->{ct}); # ELEMENT
8417            redo A;
8418          } elsif ($self->{nc} == -1) {
8419            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8420            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8421            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8422            
8423        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8424          $self->{line_prev} = $self->{line};
8425          $self->{column_prev} = $self->{column};
8426          $self->{column}++;
8427          $self->{nc}
8428              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8429        } else {
8430          $self->{set_nc}->($self);
8431        }
8432      
8433            return  ($self->{ct}); # ELEMENT
8434            redo A;
8435          } else {
8436            push @{$self->{ct}->{content}}, chr $self->{nc};
8437            $self->{state} = CM_ELEMENT_NAME_STATE;
8438            
8439        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8440          $self->{line_prev} = $self->{line};
8441          $self->{column_prev} = $self->{column};
8442          $self->{column}++;
8443          $self->{nc}
8444              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8445        } else {
8446          $self->{set_nc}->($self);
8447        }
8448      
8449            redo A;
8450          }
8451        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
8452          if ($is_space->{$self->{nc}}) {
8453            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8454            
8455        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8456          $self->{line_prev} = $self->{line};
8457          $self->{column_prev} = $self->{column};
8458          $self->{column}++;
8459          $self->{nc}
8460              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8461        } else {
8462          $self->{set_nc}->($self);
8463        }
8464      
8465            redo A;
8466          } elsif ($self->{nc} == 0x002A or # *
8467                   $self->{nc} == 0x002B or # +
8468                   $self->{nc} == 0x003F) { # ?
8469            push @{$self->{ct}->{content}}, chr $self->{nc};
8470            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8471            
8472        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8473          $self->{line_prev} = $self->{line};
8474          $self->{column_prev} = $self->{column};
8475          $self->{column}++;
8476          $self->{nc}
8477              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8478        } else {
8479          $self->{set_nc}->($self);
8480        }
8481      
8482            redo A;
8483          } elsif ($self->{nc} == 0x007C or # |
8484                   $self->{nc} == 0x002C) { # ,
8485            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8486            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8487            
8488        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8489          $self->{line_prev} = $self->{line};
8490          $self->{column_prev} = $self->{column};
8491          $self->{column}++;
8492          $self->{nc}
8493              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8494        } else {
8495          $self->{set_nc}->($self);
8496        }
8497      
8498            redo A;
8499          } elsif ($self->{nc} == 0x0029) { # )
8500            $self->{group_depth}--;
8501            push @{$self->{ct}->{content}}, chr $self->{nc};
8502            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8503            
8504        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8505          $self->{line_prev} = $self->{line};
8506          $self->{column_prev} = $self->{column};
8507          $self->{column}++;
8508          $self->{nc}
8509              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8510        } else {
8511          $self->{set_nc}->($self);
8512        }
8513      
8514            redo A;
8515          } elsif ($self->{nc} == 0x003E) { # >
8516            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8517            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8518            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8519            
8520        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8521          $self->{line_prev} = $self->{line};
8522          $self->{column_prev} = $self->{column};
8523          $self->{column}++;
8524          $self->{nc}
8525              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8526        } else {
8527          $self->{set_nc}->($self);
8528        }
8529      
8530            return  ($self->{ct}); # ELEMENT
8531            redo A;
8532          } elsif ($self->{nc} == -1) {
8533            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8534            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8535            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8536            
8537        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8538          $self->{line_prev} = $self->{line};
8539          $self->{column_prev} = $self->{column};
8540          $self->{column}++;
8541          $self->{nc}
8542              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8543        } else {
8544          $self->{set_nc}->($self);
8545        }
8546      
8547            return  ($self->{ct}); # ELEMENT
8548            redo A;
8549          } else {
8550            $self->{ct}->{content}->[-1] .= chr $self->{nc};
8551            ## Stay in the state.
8552            
8553        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8554          $self->{line_prev} = $self->{line};
8555          $self->{column_prev} = $self->{column};
8556          $self->{column}++;
8557          $self->{nc}
8558              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8559        } else {
8560          $self->{set_nc}->($self);
8561        }
8562      
8563            redo A;
8564          }
8565        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
8566          if ($is_space->{$self->{nc}}) {
8567            ## Stay in the state.
8568            
8569        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8570          $self->{line_prev} = $self->{line};
8571          $self->{column_prev} = $self->{column};
8572          $self->{column}++;
8573          $self->{nc}
8574              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8575        } else {
8576          $self->{set_nc}->($self);
8577        }
8578      
8579            redo A;
8580          } elsif ($self->{nc} == 0x007C or # |
8581                   $self->{nc} == 0x002C) { # ,
8582            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8583            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8584            
8585        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8586          $self->{line_prev} = $self->{line};
8587          $self->{column_prev} = $self->{column};
8588          $self->{column}++;
8589          $self->{nc}
8590              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8591        } else {
8592          $self->{set_nc}->($self);
8593        }
8594      
8595            redo A;
8596          } elsif ($self->{nc} == 0x0029) { # )
8597            $self->{group_depth}--;
8598            push @{$self->{ct}->{content}}, chr $self->{nc};
8599            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8600            
8601        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8602          $self->{line_prev} = $self->{line};
8603          $self->{column_prev} = $self->{column};
8604          $self->{column}++;
8605          $self->{nc}
8606              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8607        } else {
8608          $self->{set_nc}->($self);
8609        }
8610      
8611            redo A;
8612          } elsif ($self->{nc} == 0x003E) { # >
8613            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8614            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8615            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8616            
8617        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8618          $self->{line_prev} = $self->{line};
8619          $self->{column_prev} = $self->{column};
8620          $self->{column}++;
8621          $self->{nc}
8622              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8623        } else {
8624          $self->{set_nc}->($self);
8625        }
8626      
8627            return  ($self->{ct}); # ELEMENT
8628            redo A;
8629          } elsif ($self->{nc} == -1) {
8630            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8631            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8632            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8633            
8634        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8635          $self->{line_prev} = $self->{line};
8636          $self->{column_prev} = $self->{column};
8637          $self->{column}++;
8638          $self->{nc}
8639              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8640        } else {
8641          $self->{set_nc}->($self);
8642        }
8643      
8644            return  ($self->{ct}); # ELEMENT
8645            redo A;
8646          } else {
8647            $self->{parse_error}->(level => $self->{level}->{must}, type => 'after element name'); ## TODO: type
8648            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8649            $self->{state} = BOGUS_MD_STATE;
8650            
8651        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8652          $self->{line_prev} = $self->{line};
8653          $self->{column_prev} = $self->{column};
8654          $self->{column}++;
8655          $self->{nc}
8656              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8657        } else {
8658          $self->{set_nc}->($self);
8659        }
8660      
8661            redo A;
8662          }
8663        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
8664          if ($is_space->{$self->{nc}}) {
8665            if ($self->{group_depth}) {
8666              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8667            } else {
8668              $self->{state} = AFTER_MD_DEF_STATE;
8669            }
8670            
8671        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8672          $self->{line_prev} = $self->{line};
8673          $self->{column_prev} = $self->{column};
8674          $self->{column}++;
8675          $self->{nc}
8676              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8677        } else {
8678          $self->{set_nc}->($self);
8679        }
8680      
8681            redo A;
8682          } elsif ($self->{nc} == 0x002A or # *
8683                   $self->{nc} == 0x002B or # +
8684                   $self->{nc} == 0x003F) { # ?
8685            push @{$self->{ct}->{content}}, chr $self->{nc};
8686            if ($self->{group_depth}) {
8687              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8688            } else {
8689              $self->{state} = AFTER_MD_DEF_STATE;
8690            }
8691            
8692        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8693          $self->{line_prev} = $self->{line};
8694          $self->{column_prev} = $self->{column};
8695          $self->{column}++;
8696          $self->{nc}
8697              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8698        } else {
8699          $self->{set_nc}->($self);
8700        }
8701      
8702            redo A;
8703          } elsif ($self->{nc} == 0x0029) { # )
8704            if ($self->{group_depth}) {
8705              $self->{group_depth}--;
8706              push @{$self->{ct}->{content}}, chr $self->{nc};
8707              ## Stay in the state.
8708              
8709        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8710          $self->{line_prev} = $self->{line};
8711          $self->{column_prev} = $self->{column};
8712          $self->{column}++;
8713          $self->{nc}
8714              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8715        } else {
8716          $self->{set_nc}->($self);
8717        }
8718      
8719              redo A;
8720            } else {
8721              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8722              $self->{state} = BOGUS_MD_STATE;
8723              ## Reconsume.
8724              redo A;
8725            }
8726          } elsif ($self->{nc} == 0x003E) { # >
8727            if ($self->{group_depth}) {
8728              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8729              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8730            }
8731            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8732            
8733        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8734          $self->{line_prev} = $self->{line};
8735          $self->{column_prev} = $self->{column};
8736          $self->{column}++;
8737          $self->{nc}
8738              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8739        } else {
8740          $self->{set_nc}->($self);
8741        }
8742      
8743            return  ($self->{ct}); # ELEMENT
8744            redo A;
8745          } elsif ($self->{nc} == -1) {
8746            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8747            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8748            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8749            
8750        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8751          $self->{line_prev} = $self->{line};
8752          $self->{column_prev} = $self->{column};
8753          $self->{column}++;
8754          $self->{nc}
8755              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8756        } else {
8757          $self->{set_nc}->($self);
8758        }
8759      
8760            return  ($self->{ct}); # ELEMENT
8761            redo A;
8762          } else {
8763            if ($self->{group_depth}) {
8764              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8765            } else {
8766              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8767              $self->{state} = BOGUS_MD_STATE;
8768            }
8769            ## Reconsume.
8770            redo A;
8771          }
8772        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
8773          if ($is_space->{$self->{nc}}) {
8774            ## Stay in the state.
8775            
8776        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8777          $self->{line_prev} = $self->{line};
8778          $self->{column_prev} = $self->{column};
8779          $self->{column}++;
8780          $self->{nc}
8781              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8782        } else {
8783          $self->{set_nc}->($self);
8784        }
8785      
8786            redo A;
8787          } elsif ($self->{nc} == 0x003E) { # >
8788            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8789            
8790        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8791          $self->{line_prev} = $self->{line};
8792          $self->{column_prev} = $self->{column};
8793          $self->{column}++;
8794          $self->{nc}
8795              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8796        } else {
8797          $self->{set_nc}->($self);
8798        }
8799      
8800            return  ($self->{ct}); # ENTITY/ELEMENT
8801            redo A;
8802          } elsif ($self->{nc} == -1) {
8803            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8804            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8805            
8806        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8807          $self->{line_prev} = $self->{line};
8808          $self->{column_prev} = $self->{column};
8809          $self->{column}++;
8810          $self->{nc}
8811              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8812        } else {
8813          $self->{set_nc}->($self);
8814        }
8815      
8816            return  ($self->{ct}); # ENTITY/ELEMENT
8817            redo A;
8818          } else {
8819            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8820            $self->{state} = BOGUS_MD_STATE;
8821            ## Reconsume.
8822            redo A;
8823          }
8824        } elsif ($self->{state} == BOGUS_MD_STATE) {
8825          if ($self->{nc} == 0x003E) { # >
8826            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8827            
8828        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8829          $self->{line_prev} = $self->{line};
8830          $self->{column_prev} = $self->{column};
8831          $self->{column}++;
8832          $self->{nc}
8833              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8834        } else {
8835          $self->{set_nc}->($self);
8836        }
8837      
8838            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8839            redo A;
8840          } elsif ($self->{nc} == -1) {
8841            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8842            ## Reconsume.
8843            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8844            redo A;
8845          } else {
8846            ## Stay in the state.
8847            
8848        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8849          $self->{line_prev} = $self->{line};
8850          $self->{column_prev} = $self->{column};
8851          $self->{column}++;
8852          $self->{nc}
8853              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8854        } else {
8855          $self->{set_nc}->($self);
8856        }
8857      
8858            redo A;
8859          }
8860      } else {      } else {
8861        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
8862      }      }

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.34

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24