/[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.26 by wakaba, Thu Jul 2 21:42:43 2009 UTC
# Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO
177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
178  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
179  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }
180    sub BEFORE_NDATA_STATE () { 85 }
181    sub NDATA_STATE () { 86 }
182    sub AFTER_NDATA_STATE () { 87 }
183    sub BEFORE_NOTATION_NAME_STATE () { 88 }
184    sub NOTATION_NAME_STATE () { 89 }
185    sub DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE () { 90 }
186    sub DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE () { 91 }
187    sub ENTITY_VALUE_ENTITY_STATE () { 92 }
188    sub AFTER_ELEMENT_NAME_STATE () { 93 }
189    sub BEFORE_ELEMENT_CONTENT_STATE () { 94 }
190    sub CONTENT_KEYWORD_STATE () { 95 }
191    sub AFTER_CM_GROUP_OPEN_STATE () { 96 }
192    sub CM_ELEMENT_NAME_STATE () { 97 }
193    sub AFTER_CM_ELEMENT_NAME_STATE () { 98 }
194    sub AFTER_CM_GROUP_CLOSE_STATE () { 99 }
195    sub AFTER_MD_DEF_STATE () { 100 }
196    sub BOGUS_MD_STATE () { 101 }
197    
198  ## Tree constructor state constants (see Whatpm::HTML for the full  ## Tree constructor state constants (see Whatpm::HTML for the full
199  ## list and descriptions)  ## list and descriptions)
# Line 1723  sub _get_next_token ($) { Line 1740  sub _get_next_token ($) {
1740    
1741          redo A;          redo A;
1742        } else {        } else {
1743          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1744                        
1745            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1746            $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 1816  sub _get_next_token ($) {
1816      }      }
1817        
1818          redo A;          redo A;
1819          } elsif ($self->{is_xml} and
1820                   $is_space->{$self->{nc}}) {
1821            
1822            $self->{ca}->{value} .= ' ';
1823            ## Stay in the state.
1824            
1825        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1826          $self->{line_prev} = $self->{line};
1827          $self->{column_prev} = $self->{column};
1828          $self->{column}++;
1829          $self->{nc}
1830              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1831        } else {
1832          $self->{set_nc}->($self);
1833        }
1834      
1835            redo A;
1836        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1837          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1838          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1846  sub _get_next_token ($) { Line 1880  sub _get_next_token ($) {
1880          }          }
1881          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1882          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1883                                q["&<],                                qq["&<\x09\x0C\x20],
1884                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1885    
1886          ## Stay in the state          ## Stay in the state
# Line 1913  sub _get_next_token ($) { Line 1947  sub _get_next_token ($) {
1947      }      }
1948        
1949          redo A;          redo A;
1950          } elsif ($self->{is_xml} and
1951                   $is_space->{$self->{nc}}) {
1952            
1953            $self->{ca}->{value} .= ' ';
1954            ## Stay in the state.
1955            
1956        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1957          $self->{line_prev} = $self->{line};
1958          $self->{column_prev} = $self->{column};
1959          $self->{column}++;
1960          $self->{nc}
1961              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1962        } else {
1963          $self->{set_nc}->($self);
1964        }
1965      
1966            redo A;
1967        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1968          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1969          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1960  sub _get_next_token ($) { Line 2011  sub _get_next_token ($) {
2011          }          }
2012          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2013          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2014                                q['&<],                                qq['&<\x09\x0C\x20],
2015                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2016    
2017          ## Stay in the state          ## Stay in the state
# Line 2132  sub _get_next_token ($) { Line 2183  sub _get_next_token ($) {
2183               0x0022 => 1, # "               0x0022 => 1, # "
2184               0x0027 => 1, # '               0x0027 => 1, # '
2185               0x003D => 1, # =               0x003D => 1, # =
2186                 0x003C => 1, # <
2187              }->{$self->{nc}}) {              }->{$self->{nc}}) {
2188                        
2189            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 2141  sub _get_next_token ($) { Line 2193  sub _get_next_token ($) {
2193          }          }
2194          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2195          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2196                                q["'=& >],                                qq["'=& \x09\x0C>],
2197                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2198    
2199          ## Stay in the state          ## Stay in the state
# Line 3182  sub _get_next_token ($) { Line 3234  sub _get_next_token ($) {
3234        
3235          redo A;          redo A;
3236        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3237            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3238              
3239              $self->{state} = DATA_STATE;
3240              $self->{s_kwd} = '';
3241            } else {
3242              
3243              $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
3244              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3245            }
3246                    
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3247                    
3248      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3249        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3196  sub _get_next_token ($) { Line 3255  sub _get_next_token ($) {
3255        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3256      }      }
3257        
3258            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3259          redo A;          redo A;
3260        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3261            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3262              
3263              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3264              $self->{state} = DATA_STATE;
3265              $self->{s_kwd} = '';
3266              $self->{ct}->{quirks} = 1;
3267            } else {
3268              
3269              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3270              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3271            }
3272                    
3273          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          ## Reconsume.
3274          $self->{state} = DATA_STATE;          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{s_kwd} = '';  
         ## reconsume  
   
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3275          redo A;          redo A;
3276        } elsif ($self->{nc} == 0x0050 or # P        } elsif ($self->{nc} == 0x0050 or # P
3277                 $self->{nc} == 0x0070) { # p                 $self->{nc} == 0x0070) { # p
# Line 3245  sub _get_next_token ($) { Line 3307  sub _get_next_token ($) {
3307      }      }
3308        
3309          redo A;          redo A;
3310        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{nc} == 0x0022 and # "
3311                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3312                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3313            
3314            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
3315            $self->{ct}->{value} = ''; # ENTITY
3316            
3317        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3318          $self->{line_prev} = $self->{line};
3319          $self->{column_prev} = $self->{column};
3320          $self->{column}++;
3321          $self->{nc}
3322              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3323        } else {
3324          $self->{set_nc}->($self);
3325        }
3326      
3327            redo A;
3328          } elsif ($self->{nc} == 0x0027 and # '
3329                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3330                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3331            
3332            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
3333            $self->{ct}->{value} = ''; # ENTITY
3334            
3335        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3336          $self->{line_prev} = $self->{line};
3337          $self->{column_prev} = $self->{column};
3338          $self->{column}++;
3339          $self->{nc}
3340              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3341        } else {
3342          $self->{set_nc}->($self);
3343        }
3344      
3345            redo A;
3346          } elsif ($self->{is_xml} and
3347                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3348                   $self->{nc} == 0x005B) { # [
3349                    
3350          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3351          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 3264  sub _get_next_token ($) { Line 3364  sub _get_next_token ($) {
3364          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3365          redo A;          redo A;
3366        } else {        } else {
3367                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name'); ## TODO: type
3368          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name');  
3369          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3370              
3371              $self->{ct}->{quirks} = 1;
3372              $self->{state} = BOGUS_DOCTYPE_STATE;
3373            } else {
3374              
3375              $self->{state} = BOGUS_MD_STATE;
3376            }
3377    
         $self->{state} = BOGUS_DOCTYPE_STATE;  
3378                    
3379      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3380        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3340  sub _get_next_token ($) { Line 3446  sub _get_next_token ($) {
3446        
3447          redo A;          redo A;
3448        } else {        } else {
3449                    $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',  
3450                          line => $self->{line_prev},                          line => $self->{line_prev},
3451                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3452          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3453              
3454          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3455              $self->{state} = BOGUS_DOCTYPE_STATE;
3456            } else {
3457              
3458              $self->{state} = BOGUS_MD_STATE;
3459            }
3460          ## Reconsume.          ## Reconsume.
3461          redo A;          redo A;
3462        }        }
# Line 3408  sub _get_next_token ($) { Line 3518  sub _get_next_token ($) {
3518        
3519          redo A;          redo A;
3520        } else {        } else {
3521                    $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',  
3522                          line => $self->{line_prev},                          line => $self->{line_prev},
3523                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3524          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3525              
3526          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3527              $self->{state} = BOGUS_DOCTYPE_STATE;
3528            } else {
3529              
3530              $self->{state} = BOGUS_MD_STATE;
3531            }
3532          ## Reconsume.          ## Reconsume.
3533          redo A;          redo A;
3534        }        }
# Line 3467  sub _get_next_token ($) { Line 3581  sub _get_next_token ($) {
3581        
3582          redo A;          redo A;
3583        } elsif ($self->{nc} eq 0x003E) { # >        } elsif ($self->{nc} eq 0x003E) { # >
           
3584          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3585            
3586          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3587          $self->{s_kwd} = '';            
3588              $self->{state} = DATA_STATE;
3589              $self->{s_kwd} = '';
3590              $self->{ct}->{quirks} = 1;
3591            } else {
3592              
3593              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3594            }
3595            
3596                    
3597      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3598        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3483  sub _get_next_token ($) { Line 3604  sub _get_next_token ($) {
3604        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3605      }      }
3606        
3607            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3608          redo A;          redo A;
3609        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3610            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3611              
3612              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3613              $self->{state} = DATA_STATE;
3614              $self->{s_kwd} = '';
3615              $self->{ct}->{quirks} = 1;
3616            } else {
3617              
3618              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3619              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3620            }
3621                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3622          ## reconsume          ## reconsume
   
         $self->{ct}->{quirks} = 1;  
3623          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3624          redo A;          redo A;
3625        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3626                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3627                   $self->{nc} == 0x005B) { # [
3628                    
3629          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3630          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3520  sub _get_next_token ($) { Line 3644  sub _get_next_token ($) {
3644          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3645          redo A;          redo A;
3646        } else {        } else {
           
3647          $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;  
3648    
3649          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3650              
3651              $self->{ct}->{quirks} = 1;
3652              $self->{state} = BOGUS_DOCTYPE_STATE;
3653            } else {
3654              
3655              $self->{state} = BOGUS_MD_STATE;
3656            }
3657    
3658                    
3659      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3660        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3555  sub _get_next_token ($) { Line 3685  sub _get_next_token ($) {
3685        
3686          redo A;          redo A;
3687        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3688          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3689    
3690          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3691          $self->{s_kwd} = '';            
3692              $self->{state} = DATA_STATE;
3693              $self->{s_kwd} = '';
3694              $self->{ct}->{quirks} = 1;
3695            } else {
3696              
3697              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3698            }
3699    
3700                    
3701      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3702        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3571  sub _get_next_token ($) { Line 3708  sub _get_next_token ($) {
3708        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3709      }      }
3710        
3711            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3712          redo A;          redo A;
3713        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3714          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3715    
3716          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3717          $self->{s_kwd} = '';            
3718          ## reconsume            $self->{state} = DATA_STATE;
3719              $self->{s_kwd} = '';
3720          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
3721            } else {
3722              
3723              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3724            }
3725            
3726            ## Reconsume.
3727          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3728          redo A;          redo A;
3729        } else {        } else {
3730                    
3731          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3732          $self->{read_until}->($self->{ct}->{pubid}, q[">],          $self->{read_until}->($self->{ct}->{pubid}, q[">],
3733                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3734    
# Line 3626  sub _get_next_token ($) { Line 3763  sub _get_next_token ($) {
3763        
3764          redo A;          redo A;
3765        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3766          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3767    
3768          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3769          $self->{s_kwd} = '';            
3770              $self->{state} = DATA_STATE;
3771              $self->{s_kwd} = '';
3772              $self->{ct}->{quirks} = 1;
3773            } else {
3774              
3775              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3776            }
3777    
3778                    
3779      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3780        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3642  sub _get_next_token ($) { Line 3786  sub _get_next_token ($) {
3786        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3787      }      }
3788        
3789            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3790          redo A;          redo A;
3791        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3792          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed 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          ## reconsume          ## reconsume
3805            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3806          redo A;          redo A;
3807        } else {        } else {
3808                    
3809          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3810          $self->{read_until}->($self->{ct}->{pubid}, q['>],          $self->{read_until}->($self->{ct}->{pubid}, q['>],
3811                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3812    
# Line 3698  sub _get_next_token ($) { Line 3842  sub _get_next_token ($) {
3842          redo A;          redo A;
3843        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
3844                    
3845          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
3846          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
3847                    
3848      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 3858  sub _get_next_token ($) {
3858          redo A;          redo A;
3859        } elsif ($self->{nc} == 0x0027) { # '        } elsif ($self->{nc} == 0x0027) { # '
3860                    
3861          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
3862          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
3863                    
3864      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 3873  sub _get_next_token ($) {
3873        
3874          redo A;          redo A;
3875        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3876          if ($self->{is_xml}) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3877                        if ($self->{is_xml}) {
3878            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');              
3879                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
3880              } else {
3881                
3882              }
3883              $self->{state} = DATA_STATE;
3884              $self->{s_kwd} = '';
3885          } else {          } else {
3886                        if ($self->{ct}->{type} == NOTATION_TOKEN) {
3887                
3888              } else {
3889                
3890                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');            
3891              }
3892              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3893          }          }
3894          $self->{state} = DATA_STATE;          
         $self->{s_kwd} = '';  
3895                    
3896      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3897        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3748  sub _get_next_token ($) { Line 3903  sub _get_next_token ($) {
3903        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3904      }      }
3905        
3906            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3907          redo A;          redo A;
3908        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3909            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3910              
3911              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3912              
3913              $self->{state} = DATA_STATE;
3914              $self->{s_kwd} = '';
3915              $self->{ct}->{quirks} = 1;
3916            } else {
3917              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3918              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3919            }
3920                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3921          ## reconsume          ## reconsume
3922            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3923          redo A;          redo A;
3924        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3925                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3926                   $self->{nc} == 0x005B) { # [
3927                    
3928          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
3929          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3784  sub _get_next_token ($) { Line 3943  sub _get_next_token ($) {
3943          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3944          redo A;          redo A;
3945        } else {        } else {
           
3946          $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;  
3947    
3948          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3949              
3950              $self->{ct}->{quirks} = 1;
3951              $self->{state} = BOGUS_DOCTYPE_STATE;
3952            } else {
3953              
3954              $self->{state} = BOGUS_MD_STATE;
3955            }
3956    
3957                    
3958      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3959        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3851  sub _get_next_token ($) { Line 4016  sub _get_next_token ($) {
4016        
4017          redo A;          redo A;
4018        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
4019          $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} = '';  
4020                    
4021      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4022        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3867  sub _get_next_token ($) { Line 4029  sub _get_next_token ($) {
4029      }      }
4030        
4031    
4032          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4033          return  ($self->{ct}); # DOCTYPE            
4034              $self->{state} = DATA_STATE;
4035              $self->{s_kwd} = '';
4036              $self->{ct}->{quirks} = 1;
4037            } else {
4038              
4039              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4040            }
4041    
4042            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4043          redo A;          redo A;
4044        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4045            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4046              
4047              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4048              $self->{state} = DATA_STATE;
4049              $self->{s_kwd} = '';
4050              $self->{ct}->{quirks} = 1;
4051            } else {
4052              
4053              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4054              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4055            }
4056                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4057          ## reconsume          ## reconsume
4058            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4059          redo A;          redo A;
4060        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4061                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4062                   $self->{nc} == 0x005B) { # [
4063                    
4064          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4065    
# Line 3904  sub _get_next_token ($) { Line 4080  sub _get_next_token ($) {
4080          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4081          redo A;          redo A;
4082        } else {        } else {
           
4083          $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;  
4084    
4085          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4086                        
4087              $self->{ct}->{quirks} = 1;
4088              $self->{state} = BOGUS_DOCTYPE_STATE;
4089            } else {
4090              
4091              $self->{state} = BOGUS_MD_STATE;
4092            }
4093    
4094                    
4095      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4096        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3939  sub _get_next_token ($) { Line 4121  sub _get_next_token ($) {
4121        
4122          redo A;          redo A;
4123        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >
           
4124          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4125    
4126          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4127          $self->{s_kwd} = '';            
4128              $self->{state} = DATA_STATE;
4129              $self->{s_kwd} = '';
4130              $self->{ct}->{quirks} = 1;
4131            } else {
4132              
4133              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4134            }
4135            
4136                    
4137      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4138        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3955  sub _get_next_token ($) { Line 4144  sub _get_next_token ($) {
4144        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4145      }      }
4146        
4147            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4148          redo A;          redo A;
4149        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4150          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4151    
4152          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4153          $self->{s_kwd} = '';            
4154              $self->{state} = DATA_STATE;
4155              $self->{s_kwd} = '';
4156              $self->{ct}->{quirks} = 1;
4157            } else {
4158              
4159              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4160            }
4161            
4162          ## reconsume          ## reconsume
4163            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4164          redo A;          redo A;
4165        } else {        } else {
4166                    
4167          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4168          $self->{read_until}->($self->{ct}->{sysid}, q[">],          $self->{read_until}->($self->{ct}->{sysid}, q[">],
4169                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4170    
# Line 4032  sub _get_next_token ($) { Line 4221  sub _get_next_token ($) {
4221    
4222          redo A;          redo A;
4223        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4224          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4225    
4226          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4227          $self->{s_kwd} = '';            
4228          ## reconsume            $self->{state} = DATA_STATE;
4229              $self->{s_kwd} = '';
4230          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
4231          return  ($self->{ct}); # DOCTYPE          } else {
4232              
4233              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4234            }
4235    
4236            ## reconsume
4237            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4238          redo A;          redo A;
4239        } else {        } else {
4240                    
4241          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4242          $self->{read_until}->($self->{ct}->{sysid}, q['>],          $self->{read_until}->($self->{ct}->{sysid}, q['>],
4243                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4244    
# Line 4066  sub _get_next_token ($) { Line 4258  sub _get_next_token ($) {
4258        }        }
4259      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
4260        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4261                    if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
4262          ## Stay in the state            
4263              $self->{state} = BEFORE_NDATA_STATE;
4264            } else {
4265              
4266              ## Stay in the state
4267            }
4268                    
4269      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4270        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4081  sub _get_next_token ($) { Line 4278  sub _get_next_token ($) {
4278        
4279          redo A;          redo A;
4280        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4281            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4282              
4283              $self->{state} = DATA_STATE;
4284              $self->{s_kwd} = '';
4285            } else {
4286              
4287              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4288            }
4289    
4290                    
4291          $self->{state} = DATA_STATE;      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4292          $self->{s_kwd} = '';        $self->{line_prev} = $self->{line};
4293          $self->{column_prev} = $self->{column};
4294          $self->{column}++;
4295          $self->{nc}
4296              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4297        } else {
4298          $self->{set_nc}->($self);
4299        }
4300      
4301            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4302            redo A;
4303          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4304                   ($self->{nc} == 0x004E or # N
4305                    $self->{nc} == 0x006E)) { # n
4306            
4307            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before NDATA'); ## TODO: type
4308            $self->{state} = NDATA_STATE;
4309            $self->{kwd} = chr $self->{nc};
4310                    
4311      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4312        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4095  sub _get_next_token ($) { Line 4318  sub _get_next_token ($) {
4318        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4319      }      }
4320        
   
         return  ($self->{ct}); # DOCTYPE  
   
4321          redo A;          redo A;
4322        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4323                    if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4324          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');            
4325          $self->{state} = DATA_STATE;            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4326          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
4327          ## reconsume            $self->{s_kwd} = '';
4328              $self->{ct}->{quirks} = 1;
4329          $self->{ct}->{quirks} = 1;          } else {
4330          return  ($self->{ct}); # DOCTYPE            
4331              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4332              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4333            }
4334    
4335            ## reconsume
4336            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4337          redo A;          redo A;
4338        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4339                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4340                   $self->{nc} == 0x005B) { # [
4341                    
4342          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4343          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 4129  sub _get_next_token ($) { Line 4356  sub _get_next_token ($) {
4356          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4357          redo A;          redo A;
4358        } else {        } else {
           
4359          $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;  
4360    
4361          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4362              
4363              #$self->{ct}->{quirks} = 1;
4364              $self->{state} = BOGUS_DOCTYPE_STATE;
4365            } else {
4366              
4367              $self->{state} = BOGUS_MD_STATE;
4368            }
4369    
4370            
4371        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4372          $self->{line_prev} = $self->{line};
4373          $self->{column_prev} = $self->{column};
4374          $self->{column}++;
4375          $self->{nc}
4376              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4377        } else {
4378          $self->{set_nc}->($self);
4379        }
4380      
4381            redo A;
4382          }
4383        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
4384          if ($is_space->{$self->{nc}}) {
4385            
4386            ## Stay in the state.
4387            
4388        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4389          $self->{line_prev} = $self->{line};
4390          $self->{column_prev} = $self->{column};
4391          $self->{column}++;
4392          $self->{nc}
4393              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4394        } else {
4395          $self->{set_nc}->($self);
4396        }
4397      
4398            redo A;
4399          } elsif ($self->{nc} == 0x003E) { # >
4400            
4401            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4402            
4403        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4404          $self->{line_prev} = $self->{line};
4405          $self->{column_prev} = $self->{column};
4406          $self->{column}++;
4407          $self->{nc}
4408              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4409        } else {
4410          $self->{set_nc}->($self);
4411        }
4412      
4413            return  ($self->{ct}); # ENTITY
4414            redo A;
4415          } elsif ($self->{nc} == 0x004E or # N
4416                   $self->{nc} == 0x006E) { # n
4417            
4418            $self->{state} = NDATA_STATE;
4419            $self->{kwd} = chr $self->{nc};
4420            
4421        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4422          $self->{line_prev} = $self->{line};
4423          $self->{column_prev} = $self->{column};
4424          $self->{column}++;
4425          $self->{nc}
4426              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4427        } else {
4428          $self->{set_nc}->($self);
4429        }
4430      
4431            redo A;
4432          } elsif ($self->{nc} == -1) {
4433            
4434            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4435            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4436            ## reconsume
4437            return  ($self->{ct}); # ENTITY
4438            redo A;
4439          } else {
4440            
4441            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
4442            $self->{state} = BOGUS_MD_STATE;
4443                    
4444      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4445        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4357  sub _get_next_token ($) { Line 4663  sub _get_next_token ($) {
4663              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4664              $self->{entity_add} => 1,              $self->{entity_add} => 1,
4665            }->{$self->{nc}}) {            }->{$self->{nc}}) {
4666                    if ($self->{is_xml}) {
4667              
4668              $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
4669                              line => $self->{line_prev},
4670                              column => $self->{column_prev}
4671                                  + ($self->{nc} == -1 ? 1 : 0));
4672            } else {
4673              
4674              ## No error
4675            }
4676          ## Don't consume          ## Don't consume
         ## No error  
4677          ## Return nothing.          ## Return nothing.
4678          #          #
4679        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 4378  sub _get_next_token ($) { Line 4692  sub _get_next_token ($) {
4692      }      }
4693        
4694          redo A;          redo A;
4695        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
4696                   (0x0041 <= $self->{nc} and
4697                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
4698                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
4699                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 4432  sub _get_next_token ($) { Line 4747  sub _get_next_token ($) {
4747          redo A;          redo A;
4748        }        }
4749      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
4750        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
4751            $self->{nc} == 0x0058) { # X          
4752            $self->{state} = HEXREF_X_STATE;
4753            $self->{kwd} .= chr $self->{nc};
4754            
4755        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4756          $self->{line_prev} = $self->{line};
4757          $self->{column_prev} = $self->{column};
4758          $self->{column}++;
4759          $self->{nc}
4760              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4761        } else {
4762          $self->{set_nc}->($self);
4763        }
4764      
4765            redo A;
4766          } elsif ($self->{nc} == 0x0058) { # X
4767                    
4768            if ($self->{is_xml}) {
4769              $self->{parse_error}->(level => $self->{level}->{must}, type => 'uppercase hcro'); ## TODO: type
4770            }
4771          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
4772          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4773                    
# Line 4539  sub _get_next_token ($) { Line 4872  sub _get_next_token ($) {
4872        my $code = $self->{kwd};        my $code = $self->{kwd};
4873        my $l = $self->{line_prev};        my $l = $self->{line_prev};
4874        my $c = $self->{column_prev};        my $c = $self->{column_prev};
4875        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
4876              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
4877              ($self->{is_xml} and $code == 0x0000)) {
4878                    
4879          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
4880                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4692  sub _get_next_token ($) { Line 5027  sub _get_next_token ($) {
5027        my $code = $self->{kwd};        my $code = $self->{kwd};
5028        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5029        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5030        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5031              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5032              ($self->{is_xml} and $code == 0x0000)) {
5033                    
5034          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5035                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4726  sub _get_next_token ($) { Line 5063  sub _get_next_token ($) {
5063          redo A;          redo A;
5064        }        }
5065      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
5066        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
5067            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
5068            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
5069              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
5070             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
5071              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
5072             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
5073              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
5074             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
5075                    {
5076                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
5077                      $self->{entity_add} => 1,
5078                    }->{$self->{nc}}))) {
5079          our $EntityChar;          our $EntityChar;
5080          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5081          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
5082                $self->{ge}->{$self->{kwd}}) {
5083            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
5084                            if (defined $self->{ge}->{$self->{kwd}}) {
5085              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
5086                    
5087                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
5088                  } else {
5089                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
5090                      
5091                      $self->{parse_error}->(level => $self->{level}->{must}, type => 'unparsed entity', ## TODO: type
5092                                      value => $self->{kwd});
5093                    } else {
5094                      
5095                    }
5096                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
5097                  }
5098                } else {
5099                  if ($self->{is_xml}) {
5100                    
5101                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'entity not declared', ## TODO: type
5102                                    value => $self->{kwd},
5103                                    level => {
5104                                              'amp;' => $self->{level}->{warn},
5105                                              'quot;' => $self->{level}->{warn},
5106                                              'lt;' => $self->{level}->{warn},
5107                                              'gt;' => $self->{level}->{warn},
5108                                              'apos;' => $self->{level}->{warn},
5109                                             }->{$self->{kwd}} ||
5110                                             $self->{level}->{must});
5111                  } else {
5112                    
5113                  }
5114                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
5115                }
5116              $self->{entity__match} = 1;              $self->{entity__match} = 1;
5117                            
5118      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 5508  sub _get_next_token ($) {
5508          ## XML5: Not defined yet.          ## XML5: Not defined yet.
5509    
5510          ## TODO:          ## TODO:
5511    
5512            if (not $self->{stop_processing} and
5513                not $self->{document}->xml_standalone) {
5514              $self->{parse_error}->(level => $self->{level}->{must}, type => 'stop processing', ## TODO: type
5515                              level => $self->{level}->{info});
5516              $self->{stop_processing} = 1;
5517            }
5518    
5519                    
5520      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
5521        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5358  sub _get_next_token ($) { Line 5738  sub _get_next_token ($) {
5738      }      }
5739        
5740          redo A;          redo A;
5741        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
5742                   $self->{nc} == 0x0065) { # e
5743          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
5744          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5745                    
# Line 5373  sub _get_next_token ($) { Line 5754  sub _get_next_token ($) {
5754      }      }
5755        
5756          redo A;          redo A;
5757        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
5758                   $self->{nc} == 0x0061) { # a
5759          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
5760          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5761                    
# Line 5388  sub _get_next_token ($) { Line 5770  sub _get_next_token ($) {
5770      }      }
5771        
5772          redo A;          redo A;
5773        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
5774                   $self->{nc} == 0x006E) { # n
5775          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
5776          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5777                    
# Line 5416  sub _get_next_token ($) { Line 5799  sub _get_next_token ($) {
5799        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
5800        redo A;        redo A;
5801      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
5802        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
5803              $self->{nc} == 0x006E) { # n
5804          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
5805          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5806                    
# Line 5431  sub _get_next_token ($) { Line 5815  sub _get_next_token ($) {
5815      }      }
5816        
5817          redo A;          redo A;
5818        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
5819                   $self->{nc} == 0x006C) { # l
5820          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
5821          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
5822          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 5459  sub _get_next_token ($) { Line 5844  sub _get_next_token ($) {
5844          redo A;          redo A;
5845        }        }
5846      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
5847        if ($self->{nc} == {        if ($self->{nc} == [
5848              'EN' => 0x0054, # T              undef,
5849              'ENT' => 0x0049, # I              undef,
5850              'ENTI' => 0x0054, # T              0x0054, # T
5851            }->{$self->{kwd}}) {              0x0049, # I
5852                0x0054, # T
5853              ]->[length $self->{kwd}] or
5854              $self->{nc} == [
5855                undef,
5856                undef,
5857                0x0074, # t
5858                0x0069, # i
5859                0x0074, # t
5860              ]->[length $self->{kwd}]) {
5861          ## Stay in the state.          ## Stay in the state.
5862          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5863                    
# Line 5478  sub _get_next_token ($) { Line 5872  sub _get_next_token ($) {
5872      }      }
5873        
5874          redo A;          redo A;
5875        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
5876                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
5877          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
5878            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
5879              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5880                              text => 'ENTITY',
5881                              line => $self->{line_prev},
5882                              column => $self->{column_prev} - 4);
5883            }
5884            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
5885                         line => $self->{line_prev},                         line => $self->{line_prev},
5886                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
5887          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 5508  sub _get_next_token ($) { Line 5909  sub _get_next_token ($) {
5909          redo A;          redo A;
5910        }        }
5911      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
5912        if ($self->{nc} == {        if ($self->{nc} == [
5913              'EL' => 0x0045, # E             undef,
5914              'ELE' => 0x004D, # M             undef,
5915              'ELEM' => 0x0045, # E             0x0045, # E
5916              'ELEME' => 0x004E, # N             0x004D, # M
5917            }->{$self->{kwd}}) {             0x0045, # E
5918               0x004E, # N
5919              ]->[length $self->{kwd}] or
5920              $self->{nc} == [
5921               undef,
5922               undef,
5923               0x0065, # e
5924               0x006D, # m
5925               0x0065, # e
5926               0x006E, # n
5927              ]->[length $self->{kwd}]) {
5928          ## Stay in the state.          ## Stay in the state.
5929          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5930                    
# Line 5528  sub _get_next_token ($) { Line 5939  sub _get_next_token ($) {
5939      }      }
5940        
5941          redo A;          redo A;
5942        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
5943                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
5944                    $self->{nc} == 0x0074)) { # t
5945            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
5946              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5947                              text => 'ELEMENT',
5948                              line => $self->{line_prev},
5949                              column => $self->{column_prev} - 5);
5950            }
5951          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
5952                         line => $self->{line_prev},                         line => $self->{line_prev},
5953                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
5954          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
5955                    
5956      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 5976  sub _get_next_token ($) {
5976          redo A;          redo A;
5977        }        }
5978      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
5979        if ($self->{nc} == {        if ($self->{nc} == [
5980              'A' => 0x0054, # T             undef,
5981              'AT' => 0x0054, # T             0x0054, # T
5982              'ATT' => 0x004C, # L             0x0054, # T
5983              'ATTL' => 0x0049, # I             0x004C, # L
5984              'ATTLI' => 0x0053, # S             0x0049, # I
5985            }->{$self->{kwd}}) {             0x0053, # S
5986              ]->[length $self->{kwd}] or
5987              $self->{nc} == [
5988               undef,
5989               0x0074, # t
5990               0x0074, # t
5991               0x006C, # l
5992               0x0069, # i
5993               0x0073, # s
5994              ]->[length $self->{kwd}]) {
5995          ## Stay in the state.          ## Stay in the state.
5996          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5997                    
# Line 5579  sub _get_next_token ($) { Line 6006  sub _get_next_token ($) {
6006      }      }
6007        
6008          redo A;          redo A;
6009        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
6010                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6011                    $self->{nc} == 0x0074)) { # t
6012            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
6013              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6014                              text => 'ATTLIST',
6015                              line => $self->{line_prev},
6016                              column => $self->{column_prev} - 5);
6017            }
6018          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
6019                         attrdefs => [],                         attrdefs => [],
6020                         line => $self->{line_prev},                         line => $self->{line_prev},
6021                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6022          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6023                    
6024      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 6044  sub _get_next_token ($) {
6044          redo A;          redo A;
6045        }        }
6046      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
6047        if ($self->{nc} == {        if ($self->{nc} == [
6048              'N' => 0x004F, # O             undef,
6049              'NO' => 0x0054, # T             0x004F, # O
6050              'NOT' => 0x0041, # A             0x0054, # T
6051              'NOTA' => 0x0054, # T             0x0041, # A
6052              'NOTAT' => 0x0049, # I             0x0054, # T
6053              'NOTATI' => 0x004F, # O             0x0049, # I
6054            }->{$self->{kwd}}) {             0x004F, # O
6055              ]->[length $self->{kwd}] or
6056              $self->{nc} == [
6057               undef,
6058               0x006F, # o
6059               0x0074, # t
6060               0x0061, # a
6061               0x0074, # t
6062               0x0069, # i
6063               0x006F, # o
6064              ]->[length $self->{kwd}]) {
6065          ## Stay in the state.          ## Stay in the state.
6066          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6067                    
# Line 5632  sub _get_next_token ($) { Line 6076  sub _get_next_token ($) {
6076      }      }
6077        
6078          redo A;          redo A;
6079        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
6080                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
6081                    $self->{nc} == 0x006E)) { # n
6082            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
6083              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6084                              text => 'NOTATION',
6085                              line => $self->{line_prev},
6086                              column => $self->{column_prev} - 6);
6087            }
6088          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
6089                         line => $self->{line_prev},                         line => $self->{line_prev},
6090                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
6091          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6092                    
6093      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 6296  sub _get_next_token ($) {
6296        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".
6297                
6298        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
6299          ## TODO:          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6300          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
6301            } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6302              $self->{state} = AFTER_ELEMENT_NAME_STATE;
6303            } else { # ENTITY/NOTATION
6304              $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6305            }
6306                    
6307      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6308        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5863  sub _get_next_token ($) { Line 6319  sub _get_next_token ($) {
6319          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6320            #            #
6321          } else {          } else {
6322            $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
6323          }          }
6324          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6325                    
# Line 6853  sub _get_next_token ($) { Line 7309  sub _get_next_token ($) {
7309        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
7310          ## XML5: No parse error.          ## XML5: No parse error.
7311          $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
7312          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = BOGUS_MD_STATE;
         $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded  
7313          ## Reconsume.          ## Reconsume.
7314          redo A;          redo A;
7315        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
# Line 7141  sub _get_next_token ($) { Line 7596  sub _get_next_token ($) {
7596          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
7597          ## Reconsume.          ## Reconsume.
7598          redo A;          redo A;
7599        }              }
7600        } elsif ($self->{state} == NDATA_STATE) {
7601          ## ASCII case-insensitive
7602          if ($self->{nc} == [
7603                undef,
7604                0x0044, # D
7605                0x0041, # A
7606                0x0054, # T
7607              ]->[length $self->{kwd}] or
7608              $self->{nc} == [
7609                undef,
7610                0x0064, # d
7611                0x0061, # a
7612                0x0074, # t
7613              ]->[length $self->{kwd}]) {
7614            
7615            ## Stay in the state.
7616            $self->{kwd} .= chr $self->{nc};
7617            
7618        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7619          $self->{line_prev} = $self->{line};
7620          $self->{column_prev} = $self->{column};
7621          $self->{column}++;
7622          $self->{nc}
7623              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7624        } else {
7625          $self->{set_nc}->($self);
7626        }
7627      
7628            redo A;
7629          } elsif ((length $self->{kwd}) == 4 and
7630                   ($self->{nc} == 0x0041 or # A
7631                    $self->{nc} == 0x0061)) { # a
7632            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
7633              
7634              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
7635                              text => 'NDATA',
7636                              line => $self->{line_prev},
7637                              column => $self->{column_prev} - 4);
7638            } else {
7639              
7640            }
7641            $self->{state} = AFTER_NDATA_STATE;
7642            
7643        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7644          $self->{line_prev} = $self->{line};
7645          $self->{column_prev} = $self->{column};
7646          $self->{column}++;
7647          $self->{nc}
7648              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7649        } else {
7650          $self->{set_nc}->($self);
7651        }
7652      
7653            redo A;
7654          } else {
7655            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7656                            line => $self->{line_prev},
7657                            column => $self->{column_prev} + 1
7658                                - length $self->{kwd});
7659            
7660            $self->{state} = BOGUS_MD_STATE;
7661            ## Reconsume.
7662            redo A;
7663          }
7664        } elsif ($self->{state} == AFTER_NDATA_STATE) {
7665          if ($is_space->{$self->{nc}}) {
7666            $self->{state} = BEFORE_NOTATION_NAME_STATE;
7667            
7668        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7669          $self->{line_prev} = $self->{line};
7670          $self->{column_prev} = $self->{column};
7671          $self->{column}++;
7672          $self->{nc}
7673              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7674        } else {
7675          $self->{set_nc}->($self);
7676        }
7677      
7678            redo A;
7679          } elsif ($self->{nc} == 0x003E) { # >
7680            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7681            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7682            
7683        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7684          $self->{line_prev} = $self->{line};
7685          $self->{column_prev} = $self->{column};
7686          $self->{column}++;
7687          $self->{nc}
7688              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7689        } else {
7690          $self->{set_nc}->($self);
7691        }
7692      
7693            return  ($self->{ct}); # ENTITY
7694            redo A;
7695          } elsif ($self->{nc} == -1) {
7696            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7697            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7698            
7699        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7700          $self->{line_prev} = $self->{line};
7701          $self->{column_prev} = $self->{column};
7702          $self->{column}++;
7703          $self->{nc}
7704              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7705        } else {
7706          $self->{set_nc}->($self);
7707        }
7708      
7709            return  ($self->{ct}); # ENTITY
7710            redo A;
7711          } else {
7712            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7713                            line => $self->{line_prev},
7714                            column => $self->{column_prev} + 1
7715                                - length $self->{kwd});
7716            $self->{state} = BOGUS_MD_STATE;
7717            ## Reconsume.
7718            redo A;
7719          }
7720        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
7721          if ($is_space->{$self->{nc}}) {
7722            ## Stay in the state.
7723            
7724        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7725          $self->{line_prev} = $self->{line};
7726          $self->{column_prev} = $self->{column};
7727          $self->{column}++;
7728          $self->{nc}
7729              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7730        } else {
7731          $self->{set_nc}->($self);
7732        }
7733      
7734            redo A;
7735          } elsif ($self->{nc} == 0x003E) { # >
7736            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7737            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7738            
7739        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7740          $self->{line_prev} = $self->{line};
7741          $self->{column_prev} = $self->{column};
7742          $self->{column}++;
7743          $self->{nc}
7744              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7745        } else {
7746          $self->{set_nc}->($self);
7747        }
7748      
7749            return  ($self->{ct}); # ENTITY
7750            redo A;
7751          } elsif ($self->{nc} == -1) {
7752            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7753            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7754            
7755        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7756          $self->{line_prev} = $self->{line};
7757          $self->{column_prev} = $self->{column};
7758          $self->{column}++;
7759          $self->{nc}
7760              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7761        } else {
7762          $self->{set_nc}->($self);
7763        }
7764      
7765            return  ($self->{ct}); # ENTITY
7766            redo A;
7767          } else {
7768            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
7769            $self->{state} = NOTATION_NAME_STATE;
7770            
7771        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7772          $self->{line_prev} = $self->{line};
7773          $self->{column_prev} = $self->{column};
7774          $self->{column}++;
7775          $self->{nc}
7776              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7777        } else {
7778          $self->{set_nc}->($self);
7779        }
7780      
7781            redo A;
7782          }
7783        } elsif ($self->{state} == NOTATION_NAME_STATE) {
7784          if ($is_space->{$self->{nc}}) {
7785            $self->{state} = AFTER_MD_DEF_STATE;
7786            
7787        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7788          $self->{line_prev} = $self->{line};
7789          $self->{column_prev} = $self->{column};
7790          $self->{column}++;
7791          $self->{nc}
7792              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7793        } else {
7794          $self->{set_nc}->($self);
7795        }
7796      
7797            redo A;
7798          } elsif ($self->{nc} == 0x003E) { # >
7799            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7800            
7801        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7802          $self->{line_prev} = $self->{line};
7803          $self->{column_prev} = $self->{column};
7804          $self->{column}++;
7805          $self->{nc}
7806              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7807        } else {
7808          $self->{set_nc}->($self);
7809        }
7810      
7811            return  ($self->{ct}); # ENTITY
7812            redo A;
7813          } elsif ($self->{nc} == -1) {
7814            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7815            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7816            
7817        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7818          $self->{line_prev} = $self->{line};
7819          $self->{column_prev} = $self->{column};
7820          $self->{column}++;
7821          $self->{nc}
7822              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7823        } else {
7824          $self->{set_nc}->($self);
7825        }
7826      
7827            return  ($self->{ct}); # ENTITY
7828            redo A;
7829          } else {
7830            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
7831            ## Stay in the state.
7832            
7833        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7834          $self->{line_prev} = $self->{line};
7835          $self->{column_prev} = $self->{column};
7836          $self->{column}++;
7837          $self->{nc}
7838              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7839        } else {
7840          $self->{set_nc}->($self);
7841        }
7842      
7843            redo A;
7844          }
7845        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
7846          if ($self->{nc} == 0x0022) { # "
7847            $self->{state} = AFTER_MD_DEF_STATE;
7848            
7849        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7850          $self->{line_prev} = $self->{line};
7851          $self->{column_prev} = $self->{column};
7852          $self->{column}++;
7853          $self->{nc}
7854              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7855        } else {
7856          $self->{set_nc}->($self);
7857        }
7858      
7859            redo A;
7860          } elsif ($self->{nc} == 0x0026) { # &
7861            $self->{prev_state} = $self->{state};
7862            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7863            $self->{entity_add} = 0x0022; # "
7864            
7865        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7866          $self->{line_prev} = $self->{line};
7867          $self->{column_prev} = $self->{column};
7868          $self->{column}++;
7869          $self->{nc}
7870              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7871        } else {
7872          $self->{set_nc}->($self);
7873        }
7874      
7875            redo A;
7876    ## TODO: %
7877          } elsif ($self->{nc} == -1) {
7878            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7879            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7880            ## Reconsume.
7881            return  ($self->{ct}); # ENTITY
7882            redo A;
7883          } else {
7884            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7885            
7886        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7887          $self->{line_prev} = $self->{line};
7888          $self->{column_prev} = $self->{column};
7889          $self->{column}++;
7890          $self->{nc}
7891              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7892        } else {
7893          $self->{set_nc}->($self);
7894        }
7895      
7896            redo A;
7897          }
7898        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
7899          if ($self->{nc} == 0x0027) { # '
7900            $self->{state} = AFTER_MD_DEF_STATE;
7901            
7902        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7903          $self->{line_prev} = $self->{line};
7904          $self->{column_prev} = $self->{column};
7905          $self->{column}++;
7906          $self->{nc}
7907              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7908        } else {
7909          $self->{set_nc}->($self);
7910        }
7911      
7912            redo A;
7913          } elsif ($self->{nc} == 0x0026) { # &
7914            $self->{prev_state} = $self->{state};
7915            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7916            $self->{entity_add} = 0x0027; # '
7917            
7918        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7919          $self->{line_prev} = $self->{line};
7920          $self->{column_prev} = $self->{column};
7921          $self->{column}++;
7922          $self->{nc}
7923              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7924        } else {
7925          $self->{set_nc}->($self);
7926        }
7927      
7928            redo A;
7929    ## TODO: %
7930          } elsif ($self->{nc} == -1) {
7931            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7932            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7933            ## Reconsume.
7934            return  ($self->{ct}); # ENTITY
7935            redo A;
7936          } else {
7937            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7938            
7939        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7940          $self->{line_prev} = $self->{line};
7941          $self->{column_prev} = $self->{column};
7942          $self->{column}++;
7943          $self->{nc}
7944              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7945        } else {
7946          $self->{set_nc}->($self);
7947        }
7948      
7949            redo A;
7950          }
7951        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
7952          if ($is_space->{$self->{nc}} or
7953              {
7954                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
7955                $self->{entity_add} => 1,
7956              }->{$self->{nc}}) {
7957            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
7958                            line => $self->{line_prev},
7959                            column => $self->{column_prev}
7960                                + ($self->{nc} == -1 ? 1 : 0));
7961            ## Don't consume
7962            ## Return nothing.
7963            #
7964          } elsif ($self->{nc} == 0x0023) { # #
7965            $self->{ca} = $self->{ct};
7966            $self->{state} = ENTITY_HASH_STATE;
7967            $self->{kwd} = '#';
7968            
7969        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7970          $self->{line_prev} = $self->{line};
7971          $self->{column_prev} = $self->{column};
7972          $self->{column}++;
7973          $self->{nc}
7974              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7975        } else {
7976          $self->{set_nc}->($self);
7977        }
7978      
7979            redo A;
7980          } else {
7981            #
7982          }
7983    
7984          $self->{ct}->{value} .= '&';
7985          $self->{state} = $self->{prev_state};
7986          ## Reconsume.
7987          redo A;
7988        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
7989          if ($is_space->{$self->{nc}}) {
7990            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
7991            
7992        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7993          $self->{line_prev} = $self->{line};
7994          $self->{column_prev} = $self->{column};
7995          $self->{column}++;
7996          $self->{nc}
7997              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7998        } else {
7999          $self->{set_nc}->($self);
8000        }
8001      
8002            redo A;
8003          } elsif ($self->{nc} == 0x0028) { # (
8004            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8005            $self->{ct}->{content} = ['('];
8006            $self->{group_depth} = 1;
8007            
8008        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8009          $self->{line_prev} = $self->{line};
8010          $self->{column_prev} = $self->{column};
8011          $self->{column}++;
8012          $self->{nc}
8013              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8014        } else {
8015          $self->{set_nc}->($self);
8016        }
8017      
8018            redo A;
8019          } elsif ($self->{nc} == 0x003E) { # >
8020            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
8021            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8022            
8023        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8024          $self->{line_prev} = $self->{line};
8025          $self->{column_prev} = $self->{column};
8026          $self->{column}++;
8027          $self->{nc}
8028              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8029        } else {
8030          $self->{set_nc}->($self);
8031        }
8032      
8033            return  ($self->{ct}); # ELEMENT
8034            redo A;
8035          } elsif ($self->{nc} == -1) {
8036            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8037            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8038            
8039        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8040          $self->{line_prev} = $self->{line};
8041          $self->{column_prev} = $self->{column};
8042          $self->{column}++;
8043          $self->{nc}
8044              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8045        } else {
8046          $self->{set_nc}->($self);
8047        }
8048      
8049            return  ($self->{ct}); # ELEMENT
8050            redo A;
8051          } else {
8052            $self->{ct}->{content} = [chr $self->{nc}];
8053            $self->{state} = CONTENT_KEYWORD_STATE;
8054            
8055        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8056          $self->{line_prev} = $self->{line};
8057          $self->{column_prev} = $self->{column};
8058          $self->{column}++;
8059          $self->{nc}
8060              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8061        } else {
8062          $self->{set_nc}->($self);
8063        }
8064      
8065            redo A;
8066          }
8067        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
8068          if ($is_space->{$self->{nc}}) {
8069            $self->{state} = AFTER_MD_DEF_STATE;
8070            
8071        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8072          $self->{line_prev} = $self->{line};
8073          $self->{column_prev} = $self->{column};
8074          $self->{column}++;
8075          $self->{nc}
8076              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8077        } else {
8078          $self->{set_nc}->($self);
8079        }
8080      
8081            redo A;
8082          } elsif ($self->{nc} == 0x003E) { # >
8083            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8084            
8085        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8086          $self->{line_prev} = $self->{line};
8087          $self->{column_prev} = $self->{column};
8088          $self->{column}++;
8089          $self->{nc}
8090              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8091        } else {
8092          $self->{set_nc}->($self);
8093        }
8094      
8095            return  ($self->{ct}); # ELEMENT
8096            redo A;
8097          } elsif ($self->{nc} == -1) {
8098            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8099            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8100            
8101        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8102          $self->{line_prev} = $self->{line};
8103          $self->{column_prev} = $self->{column};
8104          $self->{column}++;
8105          $self->{nc}
8106              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8107        } else {
8108          $self->{set_nc}->($self);
8109        }
8110      
8111            return  ($self->{ct}); # ELEMENT
8112            redo A;
8113          } else {
8114            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
8115            ## Stay in the state.
8116            
8117        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8118          $self->{line_prev} = $self->{line};
8119          $self->{column_prev} = $self->{column};
8120          $self->{column}++;
8121          $self->{nc}
8122              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8123        } else {
8124          $self->{set_nc}->($self);
8125        }
8126      
8127            redo A;
8128          }
8129        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
8130          if ($is_space->{$self->{nc}}) {
8131            ## Stay in the state.
8132            
8133        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8134          $self->{line_prev} = $self->{line};
8135          $self->{column_prev} = $self->{column};
8136          $self->{column}++;
8137          $self->{nc}
8138              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8139        } else {
8140          $self->{set_nc}->($self);
8141        }
8142      
8143            redo A;
8144          } elsif ($self->{nc} == 0x0028) { # (
8145            $self->{group_depth}++;
8146            push @{$self->{ct}->{content}}, chr $self->{nc};
8147            ## Stay in the state.
8148            
8149        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8150          $self->{line_prev} = $self->{line};
8151          $self->{column_prev} = $self->{column};
8152          $self->{column}++;
8153          $self->{nc}
8154              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8155        } else {
8156          $self->{set_nc}->($self);
8157        }
8158      
8159            redo A;
8160          } elsif ($self->{nc} == 0x007C or # |
8161                   $self->{nc} == 0x002C) { # ,
8162            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8163            ## Stay in the state.
8164            
8165        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8166          $self->{line_prev} = $self->{line};
8167          $self->{column_prev} = $self->{column};
8168          $self->{column}++;
8169          $self->{nc}
8170              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8171        } else {
8172          $self->{set_nc}->($self);
8173        }
8174      
8175            redo A;
8176          } elsif ($self->{nc} == 0x0029) { # )
8177            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8178            push @{$self->{ct}->{content}}, chr $self->{nc};
8179            $self->{group_depth}--;
8180            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8181            
8182        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8183          $self->{line_prev} = $self->{line};
8184          $self->{column_prev} = $self->{column};
8185          $self->{column}++;
8186          $self->{nc}
8187              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8188        } else {
8189          $self->{set_nc}->($self);
8190        }
8191      
8192            redo A;
8193          } elsif ($self->{nc} == 0x003E) { # >
8194            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8195            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8196            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8197            
8198        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8199          $self->{line_prev} = $self->{line};
8200          $self->{column_prev} = $self->{column};
8201          $self->{column}++;
8202          $self->{nc}
8203              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8204        } else {
8205          $self->{set_nc}->($self);
8206        }
8207      
8208            return  ($self->{ct}); # ELEMENT
8209            redo A;
8210          } elsif ($self->{nc} == -1) {
8211            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8212            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8213            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8214            
8215        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8216          $self->{line_prev} = $self->{line};
8217          $self->{column_prev} = $self->{column};
8218          $self->{column}++;
8219          $self->{nc}
8220              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8221        } else {
8222          $self->{set_nc}->($self);
8223        }
8224      
8225            return  ($self->{ct}); # ELEMENT
8226            redo A;
8227          } else {
8228            push @{$self->{ct}->{content}}, chr $self->{nc};
8229            $self->{state} = CM_ELEMENT_NAME_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            redo A;
8242          }
8243        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
8244          if ($is_space->{$self->{nc}}) {
8245            $self->{state} = AFTER_CM_ELEMENT_NAME_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            redo A;
8258          } elsif ($self->{nc} == 0x002A or # *
8259                   $self->{nc} == 0x002B or # +
8260                   $self->{nc} == 0x003F) { # ?
8261            push @{$self->{ct}->{content}}, chr $self->{nc};
8262            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8263            
8264        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8265          $self->{line_prev} = $self->{line};
8266          $self->{column_prev} = $self->{column};
8267          $self->{column}++;
8268          $self->{nc}
8269              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8270        } else {
8271          $self->{set_nc}->($self);
8272        }
8273      
8274            redo A;
8275          } elsif ($self->{nc} == 0x007C or # |
8276                   $self->{nc} == 0x002C) { # ,
8277            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8278            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8279            
8280        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8281          $self->{line_prev} = $self->{line};
8282          $self->{column_prev} = $self->{column};
8283          $self->{column}++;
8284          $self->{nc}
8285              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8286        } else {
8287          $self->{set_nc}->($self);
8288        }
8289      
8290            redo A;
8291          } elsif ($self->{nc} == 0x0029) { # )
8292            $self->{group_depth}--;
8293            push @{$self->{ct}->{content}}, chr $self->{nc};
8294            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8295            
8296        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8297          $self->{line_prev} = $self->{line};
8298          $self->{column_prev} = $self->{column};
8299          $self->{column}++;
8300          $self->{nc}
8301              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8302        } else {
8303          $self->{set_nc}->($self);
8304        }
8305      
8306            redo A;
8307          } elsif ($self->{nc} == 0x003E) { # >
8308            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8309            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8310            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8311            
8312        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8313          $self->{line_prev} = $self->{line};
8314          $self->{column_prev} = $self->{column};
8315          $self->{column}++;
8316          $self->{nc}
8317              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8318        } else {
8319          $self->{set_nc}->($self);
8320        }
8321      
8322            return  ($self->{ct}); # ELEMENT
8323            redo A;
8324          } elsif ($self->{nc} == -1) {
8325            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8326            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8327            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8328            
8329        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8330          $self->{line_prev} = $self->{line};
8331          $self->{column_prev} = $self->{column};
8332          $self->{column}++;
8333          $self->{nc}
8334              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8335        } else {
8336          $self->{set_nc}->($self);
8337        }
8338      
8339            return  ($self->{ct}); # ELEMENT
8340            redo A;
8341          } else {
8342            $self->{ct}->{content}->[-1] .= chr $self->{nc};
8343            ## Stay in the state.
8344            
8345        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8346          $self->{line_prev} = $self->{line};
8347          $self->{column_prev} = $self->{column};
8348          $self->{column}++;
8349          $self->{nc}
8350              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8351        } else {
8352          $self->{set_nc}->($self);
8353        }
8354      
8355            redo A;
8356          }
8357        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
8358          if ($is_space->{$self->{nc}}) {
8359            ## Stay in the state.
8360            
8361        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8362          $self->{line_prev} = $self->{line};
8363          $self->{column_prev} = $self->{column};
8364          $self->{column}++;
8365          $self->{nc}
8366              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8367        } else {
8368          $self->{set_nc}->($self);
8369        }
8370      
8371            redo A;
8372          } elsif ($self->{nc} == 0x007C or # |
8373                   $self->{nc} == 0x002C) { # ,
8374            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8375            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8376            
8377        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8378          $self->{line_prev} = $self->{line};
8379          $self->{column_prev} = $self->{column};
8380          $self->{column}++;
8381          $self->{nc}
8382              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8383        } else {
8384          $self->{set_nc}->($self);
8385        }
8386      
8387            redo A;
8388          } elsif ($self->{nc} == 0x0029) { # )
8389            $self->{group_depth}--;
8390            push @{$self->{ct}->{content}}, chr $self->{nc};
8391            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8392            
8393        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8394          $self->{line_prev} = $self->{line};
8395          $self->{column_prev} = $self->{column};
8396          $self->{column}++;
8397          $self->{nc}
8398              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8399        } else {
8400          $self->{set_nc}->($self);
8401        }
8402      
8403            redo A;
8404          } elsif ($self->{nc} == 0x003E) { # >
8405            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8406            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8407            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8408            
8409        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8410          $self->{line_prev} = $self->{line};
8411          $self->{column_prev} = $self->{column};
8412          $self->{column}++;
8413          $self->{nc}
8414              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8415        } else {
8416          $self->{set_nc}->($self);
8417        }
8418      
8419            return  ($self->{ct}); # ELEMENT
8420            redo A;
8421          } elsif ($self->{nc} == -1) {
8422            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8423            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8424            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8425            
8426        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8427          $self->{line_prev} = $self->{line};
8428          $self->{column_prev} = $self->{column};
8429          $self->{column}++;
8430          $self->{nc}
8431              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8432        } else {
8433          $self->{set_nc}->($self);
8434        }
8435      
8436            return  ($self->{ct}); # ELEMENT
8437            redo A;
8438          } else {
8439            $self->{parse_error}->(level => $self->{level}->{must}, type => 'after element name'); ## TODO: type
8440            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8441            $self->{state} = BOGUS_MD_STATE;
8442            
8443        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8444          $self->{line_prev} = $self->{line};
8445          $self->{column_prev} = $self->{column};
8446          $self->{column}++;
8447          $self->{nc}
8448              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8449        } else {
8450          $self->{set_nc}->($self);
8451        }
8452      
8453            redo A;
8454          }
8455        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
8456          if ($is_space->{$self->{nc}}) {
8457            if ($self->{group_depth}) {
8458              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8459            } else {
8460              $self->{state} = AFTER_MD_DEF_STATE;
8461            }
8462            
8463        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8464          $self->{line_prev} = $self->{line};
8465          $self->{column_prev} = $self->{column};
8466          $self->{column}++;
8467          $self->{nc}
8468              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8469        } else {
8470          $self->{set_nc}->($self);
8471        }
8472      
8473            redo A;
8474          } elsif ($self->{nc} == 0x002A or # *
8475                   $self->{nc} == 0x002B or # +
8476                   $self->{nc} == 0x003F) { # ?
8477            push @{$self->{ct}->{content}}, chr $self->{nc};
8478            if ($self->{group_depth}) {
8479              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8480            } else {
8481              $self->{state} = AFTER_MD_DEF_STATE;
8482            }
8483            
8484        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8485          $self->{line_prev} = $self->{line};
8486          $self->{column_prev} = $self->{column};
8487          $self->{column}++;
8488          $self->{nc}
8489              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8490        } else {
8491          $self->{set_nc}->($self);
8492        }
8493      
8494            redo A;
8495          } elsif ($self->{nc} == 0x0029) { # )
8496            if ($self->{group_depth}) {
8497              $self->{group_depth}--;
8498              push @{$self->{ct}->{content}}, chr $self->{nc};
8499              ## Stay in the state.
8500              
8501        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8502          $self->{line_prev} = $self->{line};
8503          $self->{column_prev} = $self->{column};
8504          $self->{column}++;
8505          $self->{nc}
8506              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8507        } else {
8508          $self->{set_nc}->($self);
8509        }
8510      
8511              redo A;
8512            } else {
8513              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8514              $self->{state} = BOGUS_MD_STATE;
8515              ## Reconsume.
8516              redo A;
8517            }
8518          } elsif ($self->{nc} == 0x003E) { # >
8519            if ($self->{group_depth}) {
8520              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8521              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8522            }
8523            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8524            
8525        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8526          $self->{line_prev} = $self->{line};
8527          $self->{column_prev} = $self->{column};
8528          $self->{column}++;
8529          $self->{nc}
8530              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8531        } else {
8532          $self->{set_nc}->($self);
8533        }
8534      
8535            return  ($self->{ct}); # ELEMENT
8536            redo A;
8537          } elsif ($self->{nc} == -1) {
8538            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8539            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8540            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8541            
8542        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8543          $self->{line_prev} = $self->{line};
8544          $self->{column_prev} = $self->{column};
8545          $self->{column}++;
8546          $self->{nc}
8547              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8548        } else {
8549          $self->{set_nc}->($self);
8550        }
8551      
8552            return  ($self->{ct}); # ELEMENT
8553            redo A;
8554          } else {
8555            if ($self->{group_depth}) {
8556              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8557            } else {
8558              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8559              $self->{state} = BOGUS_MD_STATE;
8560            }
8561            ## Reconsume.
8562            redo A;
8563          }
8564        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
8565          if ($is_space->{$self->{nc}}) {
8566            ## Stay in the state.
8567            
8568        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8569          $self->{line_prev} = $self->{line};
8570          $self->{column_prev} = $self->{column};
8571          $self->{column}++;
8572          $self->{nc}
8573              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8574        } else {
8575          $self->{set_nc}->($self);
8576        }
8577      
8578            redo A;
8579          } elsif ($self->{nc} == 0x003E) { # >
8580            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8581            
8582        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8583          $self->{line_prev} = $self->{line};
8584          $self->{column_prev} = $self->{column};
8585          $self->{column}++;
8586          $self->{nc}
8587              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8588        } else {
8589          $self->{set_nc}->($self);
8590        }
8591      
8592            return  ($self->{ct}); # ENTITY/ELEMENT
8593            redo A;
8594          } elsif ($self->{nc} == -1) {
8595            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8596            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8597            
8598        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8599          $self->{line_prev} = $self->{line};
8600          $self->{column_prev} = $self->{column};
8601          $self->{column}++;
8602          $self->{nc}
8603              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8604        } else {
8605          $self->{set_nc}->($self);
8606        }
8607      
8608            return  ($self->{ct}); # ENTITY/ELEMENT
8609            redo A;
8610          } else {
8611            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8612            $self->{state} = BOGUS_MD_STATE;
8613            ## Reconsume.
8614            redo A;
8615          }
8616        } elsif ($self->{state} == BOGUS_MD_STATE) {
8617          if ($self->{nc} == 0x003E) { # >
8618            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8619            
8620        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8621          $self->{line_prev} = $self->{line};
8622          $self->{column_prev} = $self->{column};
8623          $self->{column}++;
8624          $self->{nc}
8625              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8626        } else {
8627          $self->{set_nc}->($self);
8628        }
8629      
8630            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8631            redo A;
8632          } elsif ($self->{nc} == -1) {
8633            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8634            ## Reconsume.
8635            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8636            redo A;
8637          } else {
8638            ## Stay in the state.
8639            
8640        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8641          $self->{line_prev} = $self->{line};
8642          $self->{column_prev} = $self->{column};
8643          $self->{column}++;
8644          $self->{nc}
8645              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8646        } else {
8647          $self->{set_nc}->($self);
8648        }
8649      
8650            redo A;
8651          }
8652      } else {      } else {
8653        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
8654      }      }

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24