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

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24