/[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.24 by wakaba, Sun Oct 19 14:05:20 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 3182  sub _get_next_token ($) { Line 3199  sub _get_next_token ($) {
3199        
3200          redo A;          redo A;
3201        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3202            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3203              
3204              $self->{state} = DATA_STATE;
3205              $self->{s_kwd} = '';
3206            } else {
3207              
3208              $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
3209              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3210            }
3211                    
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3212                    
3213      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3214        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3196  sub _get_next_token ($) { Line 3220  sub _get_next_token ($) {
3220        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3221      }      }
3222        
3223            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3224          redo A;          redo A;
3225        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3226            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3227              
3228              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3229              $self->{state} = DATA_STATE;
3230              $self->{s_kwd} = '';
3231              $self->{ct}->{quirks} = 1;
3232            } else {
3233              
3234              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3235              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3236            }
3237                    
3238          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          ## Reconsume.
3239          $self->{state} = DATA_STATE;          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{s_kwd} = '';  
         ## reconsume  
   
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3240          redo A;          redo A;
3241        } elsif ($self->{nc} == 0x0050 or # P        } elsif ($self->{nc} == 0x0050 or # P
3242                 $self->{nc} == 0x0070) { # p                 $self->{nc} == 0x0070) { # p
# Line 3245  sub _get_next_token ($) { Line 3272  sub _get_next_token ($) {
3272      }      }
3273        
3274          redo A;          redo A;
3275        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{nc} == 0x0022 and # "
3276                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3277                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3278            
3279            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
3280            $self->{ct}->{value} = ''; # ENTITY
3281            
3282        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3283          $self->{line_prev} = $self->{line};
3284          $self->{column_prev} = $self->{column};
3285          $self->{column}++;
3286          $self->{nc}
3287              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3288        } else {
3289          $self->{set_nc}->($self);
3290        }
3291      
3292            redo A;
3293          } elsif ($self->{nc} == 0x0027 and # '
3294                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3295                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3296            
3297            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
3298            $self->{ct}->{value} = ''; # ENTITY
3299            
3300        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3301          $self->{line_prev} = $self->{line};
3302          $self->{column_prev} = $self->{column};
3303          $self->{column}++;
3304          $self->{nc}
3305              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3306        } else {
3307          $self->{set_nc}->($self);
3308        }
3309      
3310            redo A;
3311          } elsif ($self->{is_xml} and
3312                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3313                   $self->{nc} == 0x005B) { # [
3314                    
3315          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3316          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 3264  sub _get_next_token ($) { Line 3329  sub _get_next_token ($) {
3329          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3330          redo A;          redo A;
3331        } else {        } else {
3332                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name'); ## TODO: type
3333          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name');  
3334          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3335              
3336              $self->{ct}->{quirks} = 1;
3337              $self->{state} = BOGUS_DOCTYPE_STATE;
3338            } else {
3339              
3340              $self->{state} = BOGUS_MD_STATE;
3341            }
3342    
         $self->{state} = BOGUS_DOCTYPE_STATE;  
3343                    
3344      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3345        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3340  sub _get_next_token ($) { Line 3411  sub _get_next_token ($) {
3411        
3412          redo A;          redo A;
3413        } else {        } else {
3414                    $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',  
3415                          line => $self->{line_prev},                          line => $self->{line_prev},
3416                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3417          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3418              
3419          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3420              $self->{state} = BOGUS_DOCTYPE_STATE;
3421            } else {
3422              
3423              $self->{state} = BOGUS_MD_STATE;
3424            }
3425          ## Reconsume.          ## Reconsume.
3426          redo A;          redo A;
3427        }        }
# Line 3408  sub _get_next_token ($) { Line 3483  sub _get_next_token ($) {
3483        
3484          redo A;          redo A;
3485        } else {        } else {
3486                    $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',  
3487                          line => $self->{line_prev},                          line => $self->{line_prev},
3488                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3489          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3490              
3491          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3492              $self->{state} = BOGUS_DOCTYPE_STATE;
3493            } else {
3494              
3495              $self->{state} = BOGUS_MD_STATE;
3496            }
3497          ## Reconsume.          ## Reconsume.
3498          redo A;          redo A;
3499        }        }
# Line 3467  sub _get_next_token ($) { Line 3546  sub _get_next_token ($) {
3546        
3547          redo A;          redo A;
3548        } elsif ($self->{nc} eq 0x003E) { # >        } elsif ($self->{nc} eq 0x003E) { # >
           
3549          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3550            
3551          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3552          $self->{s_kwd} = '';            
3553              $self->{state} = DATA_STATE;
3554              $self->{s_kwd} = '';
3555              $self->{ct}->{quirks} = 1;
3556            } else {
3557              
3558              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3559            }
3560            
3561                    
3562      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3563        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3483  sub _get_next_token ($) { Line 3569  sub _get_next_token ($) {
3569        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3570      }      }
3571        
3572            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3573          redo A;          redo A;
3574        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3575            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3576              
3577              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3578              $self->{state} = DATA_STATE;
3579              $self->{s_kwd} = '';
3580              $self->{ct}->{quirks} = 1;
3581            } else {
3582              
3583              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3584              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3585            }
3586                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3587          ## reconsume          ## reconsume
   
         $self->{ct}->{quirks} = 1;  
3588          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3589          redo A;          redo A;
3590        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3591                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3592                   $self->{nc} == 0x005B) { # [
3593                    
3594          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3595          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3520  sub _get_next_token ($) { Line 3609  sub _get_next_token ($) {
3609          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3610          redo A;          redo A;
3611        } else {        } else {
           
3612          $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;  
3613    
3614          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3615              
3616              $self->{ct}->{quirks} = 1;
3617              $self->{state} = BOGUS_DOCTYPE_STATE;
3618            } else {
3619              
3620              $self->{state} = BOGUS_MD_STATE;
3621            }
3622    
3623                    
3624      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3625        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3555  sub _get_next_token ($) { Line 3650  sub _get_next_token ($) {
3650        
3651          redo A;          redo A;
3652        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3653          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3654    
3655          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3656          $self->{s_kwd} = '';            
3657              $self->{state} = DATA_STATE;
3658              $self->{s_kwd} = '';
3659              $self->{ct}->{quirks} = 1;
3660            } else {
3661              
3662              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3663            }
3664    
3665                    
3666      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3667        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3571  sub _get_next_token ($) { Line 3673  sub _get_next_token ($) {
3673        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3674      }      }
3675        
3676            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3677          redo A;          redo A;
3678        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3679          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3680    
3681          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3682          $self->{s_kwd} = '';            
3683          ## reconsume            $self->{state} = DATA_STATE;
3684              $self->{s_kwd} = '';
3685          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
3686            } else {
3687              
3688              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3689            }
3690            
3691            ## Reconsume.
3692          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3693          redo A;          redo A;
3694        } else {        } else {
3695                    
3696          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3697          $self->{read_until}->($self->{ct}->{pubid}, q[">],          $self->{read_until}->($self->{ct}->{pubid}, q[">],
3698                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3699    
# Line 3626  sub _get_next_token ($) { Line 3728  sub _get_next_token ($) {
3728        
3729          redo A;          redo A;
3730        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3731          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3732    
3733          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3734          $self->{s_kwd} = '';            
3735              $self->{state} = DATA_STATE;
3736              $self->{s_kwd} = '';
3737              $self->{ct}->{quirks} = 1;
3738            } else {
3739              
3740              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3741            }
3742    
3743                    
3744      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3745        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3642  sub _get_next_token ($) { Line 3751  sub _get_next_token ($) {
3751        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3752      }      }
3753        
3754            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3755          redo A;          redo A;
3756        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3757          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3758    
3759          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3760          $self->{s_kwd} = '';            
3761              $self->{state} = DATA_STATE;
3762              $self->{s_kwd} = '';
3763              $self->{ct}->{quirks} = 1;
3764            } else {
3765              
3766              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3767            }
3768          
3769          ## reconsume          ## reconsume
3770            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3771          redo A;          redo A;
3772        } else {        } else {
3773                    
3774          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3775          $self->{read_until}->($self->{ct}->{pubid}, q['>],          $self->{read_until}->($self->{ct}->{pubid}, q['>],
3776                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3777    
# Line 3698  sub _get_next_token ($) { Line 3807  sub _get_next_token ($) {
3807          redo A;          redo A;
3808        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
3809                    
3810          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
3811          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
3812                    
3813      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 3823  sub _get_next_token ($) {
3823          redo A;          redo A;
3824        } elsif ($self->{nc} == 0x0027) { # '        } elsif ($self->{nc} == 0x0027) { # '
3825                    
3826          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
3827          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
3828                    
3829      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 3838  sub _get_next_token ($) {
3838        
3839          redo A;          redo A;
3840        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3841          if ($self->{is_xml}) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3842                        if ($self->{is_xml}) {
3843            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');              
3844                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
3845              } else {
3846                
3847              }
3848              $self->{state} = DATA_STATE;
3849              $self->{s_kwd} = '';
3850          } else {          } else {
3851                        if ($self->{ct}->{type} == NOTATION_TOKEN) {
3852                
3853              } else {
3854                
3855                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');            
3856              }
3857              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3858          }          }
3859          $self->{state} = DATA_STATE;          
         $self->{s_kwd} = '';  
3860                    
3861      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3862        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3748  sub _get_next_token ($) { Line 3868  sub _get_next_token ($) {
3868        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3869      }      }
3870        
3871            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3872          redo A;          redo A;
3873        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3874            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3875              
3876              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3877              
3878              $self->{state} = DATA_STATE;
3879              $self->{s_kwd} = '';
3880              $self->{ct}->{quirks} = 1;
3881            } else {
3882              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3883              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3884            }
3885                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3886          ## reconsume          ## reconsume
3887            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3888          redo A;          redo A;
3889        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3890                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3891                   $self->{nc} == 0x005B) { # [
3892                    
3893          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
3894          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3784  sub _get_next_token ($) { Line 3908  sub _get_next_token ($) {
3908          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3909          redo A;          redo A;
3910        } else {        } else {
           
3911          $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;  
3912    
3913          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3914              
3915              $self->{ct}->{quirks} = 1;
3916              $self->{state} = BOGUS_DOCTYPE_STATE;
3917            } else {
3918              
3919              $self->{state} = BOGUS_MD_STATE;
3920            }
3921    
3922                    
3923      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3924        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3851  sub _get_next_token ($) { Line 3981  sub _get_next_token ($) {
3981        
3982          redo A;          redo A;
3983        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3984          $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} = '';  
3985                    
3986      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3987        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3867  sub _get_next_token ($) { Line 3994  sub _get_next_token ($) {
3994      }      }
3995        
3996    
3997          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3998          return  ($self->{ct}); # DOCTYPE            
3999              $self->{state} = DATA_STATE;
4000              $self->{s_kwd} = '';
4001              $self->{ct}->{quirks} = 1;
4002            } else {
4003              
4004              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4005            }
4006    
4007            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4008          redo A;          redo A;
4009        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4010            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4011              
4012              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4013              $self->{state} = DATA_STATE;
4014              $self->{s_kwd} = '';
4015              $self->{ct}->{quirks} = 1;
4016            } else {
4017              
4018              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4019              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4020            }
4021                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4022          ## reconsume          ## reconsume
4023            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4024          redo A;          redo A;
4025        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4026                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4027                   $self->{nc} == 0x005B) { # [
4028                    
4029          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4030    
# Line 3904  sub _get_next_token ($) { Line 4045  sub _get_next_token ($) {
4045          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4046          redo A;          redo A;
4047        } else {        } else {
           
4048          $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;  
4049    
4050          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4051                        
4052              $self->{ct}->{quirks} = 1;
4053              $self->{state} = BOGUS_DOCTYPE_STATE;
4054            } else {
4055              
4056              $self->{state} = BOGUS_MD_STATE;
4057            }
4058    
4059                    
4060      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4061        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3939  sub _get_next_token ($) { Line 4086  sub _get_next_token ($) {
4086        
4087          redo A;          redo A;
4088        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >
           
4089          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4090    
4091          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4092          $self->{s_kwd} = '';            
4093              $self->{state} = DATA_STATE;
4094              $self->{s_kwd} = '';
4095              $self->{ct}->{quirks} = 1;
4096            } else {
4097              
4098              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4099            }
4100            
4101                    
4102      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4103        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3955  sub _get_next_token ($) { Line 4109  sub _get_next_token ($) {
4109        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4110      }      }
4111        
4112            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4113          redo A;          redo A;
4114        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4115          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4116    
4117          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4118          $self->{s_kwd} = '';            
4119              $self->{state} = DATA_STATE;
4120              $self->{s_kwd} = '';
4121              $self->{ct}->{quirks} = 1;
4122            } else {
4123              
4124              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4125            }
4126            
4127          ## reconsume          ## reconsume
4128            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4129          redo A;          redo A;
4130        } else {        } else {
4131                    
4132          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4133          $self->{read_until}->($self->{ct}->{sysid}, q[">],          $self->{read_until}->($self->{ct}->{sysid}, q[">],
4134                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4135    
# Line 4032  sub _get_next_token ($) { Line 4186  sub _get_next_token ($) {
4186    
4187          redo A;          redo A;
4188        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4189          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4190    
4191          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4192          $self->{s_kwd} = '';            
4193          ## reconsume            $self->{state} = DATA_STATE;
4194              $self->{s_kwd} = '';
4195          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
4196          return  ($self->{ct}); # DOCTYPE          } else {
4197              
4198              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4199            }
4200    
4201            ## reconsume
4202            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4203          redo A;          redo A;
4204        } else {        } else {
4205                    
4206          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4207          $self->{read_until}->($self->{ct}->{sysid}, q['>],          $self->{read_until}->($self->{ct}->{sysid}, q['>],
4208                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4209    
# Line 4066  sub _get_next_token ($) { Line 4223  sub _get_next_token ($) {
4223        }        }
4224      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
4225        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4226                    if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
4227          ## Stay in the state            
4228              $self->{state} = BEFORE_NDATA_STATE;
4229            } else {
4230              
4231              ## Stay in the state
4232            }
4233                    
4234      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4235        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4081  sub _get_next_token ($) { Line 4243  sub _get_next_token ($) {
4243        
4244          redo A;          redo A;
4245        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4246            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4247              
4248              $self->{state} = DATA_STATE;
4249              $self->{s_kwd} = '';
4250            } else {
4251              
4252              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4253            }
4254    
4255                    
4256          $self->{state} = DATA_STATE;      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4257          $self->{s_kwd} = '';        $self->{line_prev} = $self->{line};
4258          $self->{column_prev} = $self->{column};
4259          $self->{column}++;
4260          $self->{nc}
4261              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4262        } else {
4263          $self->{set_nc}->($self);
4264        }
4265      
4266            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4267            redo A;
4268          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4269                   ($self->{nc} == 0x004E or # N
4270                    $self->{nc} == 0x006E)) { # n
4271            
4272            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before NDATA'); ## TODO: type
4273            $self->{state} = NDATA_STATE;
4274            $self->{kwd} = chr $self->{nc};
4275                    
4276      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4277        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4095  sub _get_next_token ($) { Line 4283  sub _get_next_token ($) {
4283        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4284      }      }
4285        
   
         return  ($self->{ct}); # DOCTYPE  
   
4286          redo A;          redo A;
4287        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4288                    if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4289          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');            
4290          $self->{state} = DATA_STATE;            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4291          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
4292          ## reconsume            $self->{s_kwd} = '';
4293              $self->{ct}->{quirks} = 1;
4294          $self->{ct}->{quirks} = 1;          } else {
4295          return  ($self->{ct}); # DOCTYPE            
4296              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4297              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4298            }
4299    
4300            ## reconsume
4301            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4302          redo A;          redo A;
4303        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4304                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4305                   $self->{nc} == 0x005B) { # [
4306                    
4307          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4308          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 4129  sub _get_next_token ($) { Line 4321  sub _get_next_token ($) {
4321          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4322          redo A;          redo A;
4323        } else {        } else {
           
4324          $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;  
4325    
4326          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4327              
4328              #$self->{ct}->{quirks} = 1;
4329              $self->{state} = BOGUS_DOCTYPE_STATE;
4330            } else {
4331              
4332              $self->{state} = BOGUS_MD_STATE;
4333            }
4334    
4335            
4336        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4337          $self->{line_prev} = $self->{line};
4338          $self->{column_prev} = $self->{column};
4339          $self->{column}++;
4340          $self->{nc}
4341              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4342        } else {
4343          $self->{set_nc}->($self);
4344        }
4345      
4346            redo A;
4347          }
4348        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
4349          if ($is_space->{$self->{nc}}) {
4350            
4351            ## Stay in the state.
4352            
4353        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4354          $self->{line_prev} = $self->{line};
4355          $self->{column_prev} = $self->{column};
4356          $self->{column}++;
4357          $self->{nc}
4358              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4359        } else {
4360          $self->{set_nc}->($self);
4361        }
4362      
4363            redo A;
4364          } elsif ($self->{nc} == 0x003E) { # >
4365            
4366            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4367            
4368        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4369          $self->{line_prev} = $self->{line};
4370          $self->{column_prev} = $self->{column};
4371          $self->{column}++;
4372          $self->{nc}
4373              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4374        } else {
4375          $self->{set_nc}->($self);
4376        }
4377      
4378            return  ($self->{ct}); # ENTITY
4379            redo A;
4380          } elsif ($self->{nc} == 0x004E or # N
4381                   $self->{nc} == 0x006E) { # n
4382            
4383            $self->{state} = NDATA_STATE;
4384            $self->{kwd} = chr $self->{nc};
4385            
4386        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4387          $self->{line_prev} = $self->{line};
4388          $self->{column_prev} = $self->{column};
4389          $self->{column}++;
4390          $self->{nc}
4391              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4392        } else {
4393          $self->{set_nc}->($self);
4394        }
4395      
4396            redo A;
4397          } elsif ($self->{nc} == -1) {
4398            
4399            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4400            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4401            ## reconsume
4402            return  ($self->{ct}); # ENTITY
4403            redo A;
4404          } else {
4405            
4406            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
4407            $self->{state} = BOGUS_MD_STATE;
4408                    
4409      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4410        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4357  sub _get_next_token ($) { Line 4628  sub _get_next_token ($) {
4628              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4629              $self->{entity_add} => 1,              $self->{entity_add} => 1,
4630            }->{$self->{nc}}) {            }->{$self->{nc}}) {
4631                    if ($self->{is_xml}) {
4632              
4633              $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
4634                              line => $self->{line_prev},
4635                              column => $self->{column_prev}
4636                                  + ($self->{nc} == -1 ? 1 : 0));
4637            } else {
4638              
4639              ## No error
4640            }
4641          ## Don't consume          ## Don't consume
         ## No error  
4642          ## Return nothing.          ## Return nothing.
4643          #          #
4644        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 4378  sub _get_next_token ($) { Line 4657  sub _get_next_token ($) {
4657      }      }
4658        
4659          redo A;          redo A;
4660        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
4661                   (0x0041 <= $self->{nc} and
4662                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
4663                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
4664                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 4432  sub _get_next_token ($) { Line 4712  sub _get_next_token ($) {
4712          redo A;          redo A;
4713        }        }
4714      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
4715        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
4716            $self->{nc} == 0x0058) { # X          
4717            $self->{state} = HEXREF_X_STATE;
4718            $self->{kwd} .= chr $self->{nc};
4719            
4720        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4721          $self->{line_prev} = $self->{line};
4722          $self->{column_prev} = $self->{column};
4723          $self->{column}++;
4724          $self->{nc}
4725              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4726        } else {
4727          $self->{set_nc}->($self);
4728        }
4729      
4730            redo A;
4731          } elsif ($self->{nc} == 0x0058) { # X
4732                    
4733            if ($self->{is_xml}) {
4734              $self->{parse_error}->(level => $self->{level}->{must}, type => 'uppercase hcro'); ## TODO: type
4735            }
4736          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
4737          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4738                    
# Line 4726  sub _get_next_token ($) { Line 5024  sub _get_next_token ($) {
5024          redo A;          redo A;
5025        }        }
5026      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
5027        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
5028            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
5029            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
5030              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
5031             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
5032              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
5033             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
5034              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
5035             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
5036                    {
5037                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
5038                      $self->{entity_add} => 1,
5039                    }->{$self->{nc}}))) {
5040          our $EntityChar;          our $EntityChar;
5041          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5042          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
5043                $self->{ge}->{$self->{kwd}}) {
5044            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
5045                            if (defined $self->{ge}->{$self->{kwd}}) {
5046              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
5047                    
5048                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
5049                  } else {
5050                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
5051                      
5052                      $self->{parse_error}->(level => $self->{level}->{must}, type => 'unparsed entity', ## TODO: type
5053                                      value => $self->{kwd});
5054                    } else {
5055                      
5056                    }
5057                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
5058                  }
5059                } else {
5060                  if ($self->{is_xml}) {
5061                    
5062                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'entity not declared', ## TODO: type
5063                                    value => $self->{kwd},
5064                                    level => {
5065                                              'amp;' => $self->{level}->{warn},
5066                                              'quot;' => $self->{level}->{warn},
5067                                              'lt;' => $self->{level}->{warn},
5068                                              'gt;' => $self->{level}->{warn},
5069                                              'apos;' => $self->{level}->{warn},
5070                                             }->{$self->{kwd}} ||
5071                                             $self->{level}->{must});
5072                  } else {
5073                    
5074                  }
5075                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
5076                }
5077              $self->{entity__match} = 1;              $self->{entity__match} = 1;
5078                            
5079      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 5469  sub _get_next_token ($) {
5469          ## XML5: Not defined yet.          ## XML5: Not defined yet.
5470    
5471          ## TODO:          ## TODO:
5472    
5473            if (not $self->{stop_processing} and
5474                not $self->{document}->xml_standalone) {
5475              $self->{parse_error}->(level => $self->{level}->{must}, type => 'stop processing', ## TODO: type
5476                              level => $self->{level}->{info});
5477              $self->{stop_processing} = 1;
5478            }
5479    
5480                    
5481      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
5482        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5358  sub _get_next_token ($) { Line 5699  sub _get_next_token ($) {
5699      }      }
5700        
5701          redo A;          redo A;
5702        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
5703                   $self->{nc} == 0x0065) { # e
5704          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
5705          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5706                    
# Line 5373  sub _get_next_token ($) { Line 5715  sub _get_next_token ($) {
5715      }      }
5716        
5717          redo A;          redo A;
5718        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
5719                   $self->{nc} == 0x0061) { # a
5720          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
5721          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5722                    
# Line 5388  sub _get_next_token ($) { Line 5731  sub _get_next_token ($) {
5731      }      }
5732        
5733          redo A;          redo A;
5734        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
5735                   $self->{nc} == 0x006E) { # n
5736          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
5737          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5738                    
# Line 5416  sub _get_next_token ($) { Line 5760  sub _get_next_token ($) {
5760        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
5761        redo A;        redo A;
5762      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
5763        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
5764              $self->{nc} == 0x006E) { # n
5765          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
5766          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5767                    
# Line 5431  sub _get_next_token ($) { Line 5776  sub _get_next_token ($) {
5776      }      }
5777        
5778          redo A;          redo A;
5779        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
5780                   $self->{nc} == 0x006C) { # l
5781          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
5782          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
5783          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 5459  sub _get_next_token ($) { Line 5805  sub _get_next_token ($) {
5805          redo A;          redo A;
5806        }        }
5807      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
5808        if ($self->{nc} == {        if ($self->{nc} == [
5809              'EN' => 0x0054, # T              undef,
5810              'ENT' => 0x0049, # I              undef,
5811              'ENTI' => 0x0054, # T              0x0054, # T
5812            }->{$self->{kwd}}) {              0x0049, # I
5813                0x0054, # T
5814              ]->[length $self->{kwd}] or
5815              $self->{nc} == [
5816                undef,
5817                undef,
5818                0x0074, # t
5819                0x0069, # i
5820                0x0074, # t
5821              ]->[length $self->{kwd}]) {
5822          ## Stay in the state.          ## Stay in the state.
5823          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5824                    
# Line 5478  sub _get_next_token ($) { Line 5833  sub _get_next_token ($) {
5833      }      }
5834        
5835          redo A;          redo A;
5836        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
5837                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
5838          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
5839            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
5840              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5841                              text => 'ENTITY',
5842                              line => $self->{line_prev},
5843                              column => $self->{column_prev} - 4);
5844            }
5845            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
5846                         line => $self->{line_prev},                         line => $self->{line_prev},
5847                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
5848          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 5508  sub _get_next_token ($) { Line 5870  sub _get_next_token ($) {
5870          redo A;          redo A;
5871        }        }
5872      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
5873        if ($self->{nc} == {        if ($self->{nc} == [
5874              'EL' => 0x0045, # E             undef,
5875              'ELE' => 0x004D, # M             undef,
5876              'ELEM' => 0x0045, # E             0x0045, # E
5877              'ELEME' => 0x004E, # N             0x004D, # M
5878            }->{$self->{kwd}}) {             0x0045, # E
5879               0x004E, # N
5880              ]->[length $self->{kwd}] or
5881              $self->{nc} == [
5882               undef,
5883               undef,
5884               0x0065, # e
5885               0x006D, # m
5886               0x0065, # e
5887               0x006E, # n
5888              ]->[length $self->{kwd}]) {
5889          ## Stay in the state.          ## Stay in the state.
5890          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5891                    
# Line 5528  sub _get_next_token ($) { Line 5900  sub _get_next_token ($) {
5900      }      }
5901        
5902          redo A;          redo A;
5903        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
5904                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
5905                    $self->{nc} == 0x0074)) { # t
5906            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
5907              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5908                              text => 'ELEMENT',
5909                              line => $self->{line_prev},
5910                              column => $self->{column_prev} - 5);
5911            }
5912          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
5913                         line => $self->{line_prev},                         line => $self->{line_prev},
5914                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
5915          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
5916                    
5917      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 5937  sub _get_next_token ($) {
5937          redo A;          redo A;
5938        }        }
5939      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
5940        if ($self->{nc} == {        if ($self->{nc} == [
5941              'A' => 0x0054, # T             undef,
5942              'AT' => 0x0054, # T             0x0054, # T
5943              'ATT' => 0x004C, # L             0x0054, # T
5944              'ATTL' => 0x0049, # I             0x004C, # L
5945              'ATTLI' => 0x0053, # S             0x0049, # I
5946            }->{$self->{kwd}}) {             0x0053, # S
5947              ]->[length $self->{kwd}] or
5948              $self->{nc} == [
5949               undef,
5950               0x0074, # t
5951               0x0074, # t
5952               0x006C, # l
5953               0x0069, # i
5954               0x0073, # s
5955              ]->[length $self->{kwd}]) {
5956          ## Stay in the state.          ## Stay in the state.
5957          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5958                    
# Line 5579  sub _get_next_token ($) { Line 5967  sub _get_next_token ($) {
5967      }      }
5968        
5969          redo A;          redo A;
5970        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
5971                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
5972                    $self->{nc} == 0x0074)) { # t
5973            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
5974              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5975                              text => 'ATTLIST',
5976                              line => $self->{line_prev},
5977                              column => $self->{column_prev} - 5);
5978            }
5979          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
5980                         attrdefs => [],                         attrdefs => [],
5981                         line => $self->{line_prev},                         line => $self->{line_prev},
5982                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
5983          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
5984                    
5985      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 6005  sub _get_next_token ($) {
6005          redo A;          redo A;
6006        }        }
6007      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
6008        if ($self->{nc} == {        if ($self->{nc} == [
6009              'N' => 0x004F, # O             undef,
6010              'NO' => 0x0054, # T             0x004F, # O
6011              'NOT' => 0x0041, # A             0x0054, # T
6012              'NOTA' => 0x0054, # T             0x0041, # A
6013              'NOTAT' => 0x0049, # I             0x0054, # T
6014              'NOTATI' => 0x004F, # O             0x0049, # I
6015            }->{$self->{kwd}}) {             0x004F, # O
6016              ]->[length $self->{kwd}] or
6017              $self->{nc} == [
6018               undef,
6019               0x006F, # o
6020               0x0074, # t
6021               0x0061, # a
6022               0x0074, # t
6023               0x0069, # i
6024               0x006F, # o
6025              ]->[length $self->{kwd}]) {
6026          ## Stay in the state.          ## Stay in the state.
6027          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6028                    
# Line 5632  sub _get_next_token ($) { Line 6037  sub _get_next_token ($) {
6037      }      }
6038        
6039          redo A;          redo A;
6040        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
6041                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
6042                    $self->{nc} == 0x006E)) { # n
6043            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
6044              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6045                              text => 'NOTATION',
6046                              line => $self->{line_prev},
6047                              column => $self->{column_prev} - 6);
6048            }
6049          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
6050                         line => $self->{line_prev},                         line => $self->{line_prev},
6051                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
6052          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6053                    
6054      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 6257  sub _get_next_token ($) {
6257        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".
6258                
6259        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
6260          ## TODO:          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6261          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
6262            } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6263              $self->{state} = AFTER_ELEMENT_NAME_STATE;
6264            } else { # ENTITY/NOTATION
6265              $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6266            }
6267                    
6268      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6269        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5863  sub _get_next_token ($) { Line 6280  sub _get_next_token ($) {
6280          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6281            #            #
6282          } else {          } else {
6283            $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
6284          }          }
6285          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6286                    
# Line 6853  sub _get_next_token ($) { Line 7270  sub _get_next_token ($) {
7270        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
7271          ## XML5: No parse error.          ## XML5: No parse error.
7272          $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
7273          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = BOGUS_MD_STATE;
         $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded  
7274          ## Reconsume.          ## Reconsume.
7275          redo A;          redo A;
7276        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
# Line 7141  sub _get_next_token ($) { Line 7557  sub _get_next_token ($) {
7557          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
7558          ## Reconsume.          ## Reconsume.
7559          redo A;          redo A;
7560        }              }
7561        } elsif ($self->{state} == NDATA_STATE) {
7562          ## ASCII case-insensitive
7563          if ($self->{nc} == [
7564                undef,
7565                0x0044, # D
7566                0x0041, # A
7567                0x0054, # T
7568              ]->[length $self->{kwd}] or
7569              $self->{nc} == [
7570                undef,
7571                0x0064, # d
7572                0x0061, # a
7573                0x0074, # t
7574              ]->[length $self->{kwd}]) {
7575            
7576            ## Stay in the state.
7577            $self->{kwd} .= chr $self->{nc};
7578            
7579        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7580          $self->{line_prev} = $self->{line};
7581          $self->{column_prev} = $self->{column};
7582          $self->{column}++;
7583          $self->{nc}
7584              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7585        } else {
7586          $self->{set_nc}->($self);
7587        }
7588      
7589            redo A;
7590          } elsif ((length $self->{kwd}) == 4 and
7591                   ($self->{nc} == 0x0041 or # A
7592                    $self->{nc} == 0x0061)) { # a
7593            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
7594              
7595              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
7596                              text => 'NDATA',
7597                              line => $self->{line_prev},
7598                              column => $self->{column_prev} - 4);
7599            } else {
7600              
7601            }
7602            $self->{state} = AFTER_NDATA_STATE;
7603            
7604        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7605          $self->{line_prev} = $self->{line};
7606          $self->{column_prev} = $self->{column};
7607          $self->{column}++;
7608          $self->{nc}
7609              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7610        } else {
7611          $self->{set_nc}->($self);
7612        }
7613      
7614            redo A;
7615          } else {
7616            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7617                            line => $self->{line_prev},
7618                            column => $self->{column_prev} + 1
7619                                - length $self->{kwd});
7620            
7621            $self->{state} = BOGUS_MD_STATE;
7622            ## Reconsume.
7623            redo A;
7624          }
7625        } elsif ($self->{state} == AFTER_NDATA_STATE) {
7626          if ($is_space->{$self->{nc}}) {
7627            $self->{state} = BEFORE_NOTATION_NAME_STATE;
7628            
7629        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7630          $self->{line_prev} = $self->{line};
7631          $self->{column_prev} = $self->{column};
7632          $self->{column}++;
7633          $self->{nc}
7634              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7635        } else {
7636          $self->{set_nc}->($self);
7637        }
7638      
7639            redo A;
7640          } elsif ($self->{nc} == 0x003E) { # >
7641            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7642            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7643            
7644        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7645          $self->{line_prev} = $self->{line};
7646          $self->{column_prev} = $self->{column};
7647          $self->{column}++;
7648          $self->{nc}
7649              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7650        } else {
7651          $self->{set_nc}->($self);
7652        }
7653      
7654            return  ($self->{ct}); # ENTITY
7655            redo A;
7656          } elsif ($self->{nc} == -1) {
7657            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7658            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7659            
7660        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7661          $self->{line_prev} = $self->{line};
7662          $self->{column_prev} = $self->{column};
7663          $self->{column}++;
7664          $self->{nc}
7665              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7666        } else {
7667          $self->{set_nc}->($self);
7668        }
7669      
7670            return  ($self->{ct}); # ENTITY
7671            redo A;
7672          } else {
7673            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7674                            line => $self->{line_prev},
7675                            column => $self->{column_prev} + 1
7676                                - length $self->{kwd});
7677            $self->{state} = BOGUS_MD_STATE;
7678            ## Reconsume.
7679            redo A;
7680          }
7681        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
7682          if ($is_space->{$self->{nc}}) {
7683            ## Stay in the state.
7684            
7685        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7686          $self->{line_prev} = $self->{line};
7687          $self->{column_prev} = $self->{column};
7688          $self->{column}++;
7689          $self->{nc}
7690              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7691        } else {
7692          $self->{set_nc}->($self);
7693        }
7694      
7695            redo A;
7696          } elsif ($self->{nc} == 0x003E) { # >
7697            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7698            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7699            
7700        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7701          $self->{line_prev} = $self->{line};
7702          $self->{column_prev} = $self->{column};
7703          $self->{column}++;
7704          $self->{nc}
7705              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7706        } else {
7707          $self->{set_nc}->($self);
7708        }
7709      
7710            return  ($self->{ct}); # ENTITY
7711            redo A;
7712          } elsif ($self->{nc} == -1) {
7713            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7714            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7715            
7716        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7717          $self->{line_prev} = $self->{line};
7718          $self->{column_prev} = $self->{column};
7719          $self->{column}++;
7720          $self->{nc}
7721              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7722        } else {
7723          $self->{set_nc}->($self);
7724        }
7725      
7726            return  ($self->{ct}); # ENTITY
7727            redo A;
7728          } else {
7729            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
7730            $self->{state} = NOTATION_NAME_STATE;
7731            
7732        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7733          $self->{line_prev} = $self->{line};
7734          $self->{column_prev} = $self->{column};
7735          $self->{column}++;
7736          $self->{nc}
7737              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7738        } else {
7739          $self->{set_nc}->($self);
7740        }
7741      
7742            redo A;
7743          }
7744        } elsif ($self->{state} == NOTATION_NAME_STATE) {
7745          if ($is_space->{$self->{nc}}) {
7746            $self->{state} = AFTER_MD_DEF_STATE;
7747            
7748        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7749          $self->{line_prev} = $self->{line};
7750          $self->{column_prev} = $self->{column};
7751          $self->{column}++;
7752          $self->{nc}
7753              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7754        } else {
7755          $self->{set_nc}->($self);
7756        }
7757      
7758            redo A;
7759          } elsif ($self->{nc} == 0x003E) { # >
7760            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7761            
7762        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7763          $self->{line_prev} = $self->{line};
7764          $self->{column_prev} = $self->{column};
7765          $self->{column}++;
7766          $self->{nc}
7767              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7768        } else {
7769          $self->{set_nc}->($self);
7770        }
7771      
7772            return  ($self->{ct}); # ENTITY
7773            redo A;
7774          } elsif ($self->{nc} == -1) {
7775            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7776            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7777            
7778        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7779          $self->{line_prev} = $self->{line};
7780          $self->{column_prev} = $self->{column};
7781          $self->{column}++;
7782          $self->{nc}
7783              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7784        } else {
7785          $self->{set_nc}->($self);
7786        }
7787      
7788            return  ($self->{ct}); # ENTITY
7789            redo A;
7790          } else {
7791            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
7792            ## Stay in the state.
7793            
7794        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7795          $self->{line_prev} = $self->{line};
7796          $self->{column_prev} = $self->{column};
7797          $self->{column}++;
7798          $self->{nc}
7799              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7800        } else {
7801          $self->{set_nc}->($self);
7802        }
7803      
7804            redo A;
7805          }
7806        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
7807          if ($self->{nc} == 0x0022) { # "
7808            $self->{state} = AFTER_MD_DEF_STATE;
7809            
7810        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7811          $self->{line_prev} = $self->{line};
7812          $self->{column_prev} = $self->{column};
7813          $self->{column}++;
7814          $self->{nc}
7815              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7816        } else {
7817          $self->{set_nc}->($self);
7818        }
7819      
7820            redo A;
7821          } elsif ($self->{nc} == 0x0026) { # &
7822            $self->{prev_state} = $self->{state};
7823            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7824            $self->{entity_add} = 0x0022; # "
7825            
7826        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7827          $self->{line_prev} = $self->{line};
7828          $self->{column_prev} = $self->{column};
7829          $self->{column}++;
7830          $self->{nc}
7831              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7832        } else {
7833          $self->{set_nc}->($self);
7834        }
7835      
7836            redo A;
7837    ## TODO: %
7838          } elsif ($self->{nc} == -1) {
7839            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7840            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7841            ## Reconsume.
7842            return  ($self->{ct}); # ENTITY
7843            redo A;
7844          } else {
7845            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7846            
7847        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7848          $self->{line_prev} = $self->{line};
7849          $self->{column_prev} = $self->{column};
7850          $self->{column}++;
7851          $self->{nc}
7852              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7853        } else {
7854          $self->{set_nc}->($self);
7855        }
7856      
7857            redo A;
7858          }
7859        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
7860          if ($self->{nc} == 0x0027) { # '
7861            $self->{state} = AFTER_MD_DEF_STATE;
7862            
7863        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7864          $self->{line_prev} = $self->{line};
7865          $self->{column_prev} = $self->{column};
7866          $self->{column}++;
7867          $self->{nc}
7868              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7869        } else {
7870          $self->{set_nc}->($self);
7871        }
7872      
7873            redo A;
7874          } elsif ($self->{nc} == 0x0026) { # &
7875            $self->{prev_state} = $self->{state};
7876            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7877            $self->{entity_add} = 0x0027; # '
7878            
7879        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7880          $self->{line_prev} = $self->{line};
7881          $self->{column_prev} = $self->{column};
7882          $self->{column}++;
7883          $self->{nc}
7884              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7885        } else {
7886          $self->{set_nc}->($self);
7887        }
7888      
7889            redo A;
7890    ## TODO: %
7891          } elsif ($self->{nc} == -1) {
7892            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7893            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7894            ## Reconsume.
7895            return  ($self->{ct}); # ENTITY
7896            redo A;
7897          } else {
7898            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7899            
7900        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7901          $self->{line_prev} = $self->{line};
7902          $self->{column_prev} = $self->{column};
7903          $self->{column}++;
7904          $self->{nc}
7905              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7906        } else {
7907          $self->{set_nc}->($self);
7908        }
7909      
7910            redo A;
7911          }
7912        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
7913          if ($is_space->{$self->{nc}} or
7914              {
7915                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
7916                $self->{entity_add} => 1,
7917              }->{$self->{nc}}) {
7918            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
7919                            line => $self->{line_prev},
7920                            column => $self->{column_prev}
7921                                + ($self->{nc} == -1 ? 1 : 0));
7922            ## Don't consume
7923            ## Return nothing.
7924            #
7925          } elsif ($self->{nc} == 0x0023) { # #
7926            $self->{ca} = $self->{ct};
7927            $self->{state} = ENTITY_HASH_STATE;
7928            $self->{kwd} = '#';
7929            
7930        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7931          $self->{line_prev} = $self->{line};
7932          $self->{column_prev} = $self->{column};
7933          $self->{column}++;
7934          $self->{nc}
7935              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7936        } else {
7937          $self->{set_nc}->($self);
7938        }
7939      
7940            redo A;
7941          } else {
7942            #
7943          }
7944    
7945          $self->{ct}->{value} .= '&';
7946          $self->{state} = $self->{prev_state};
7947          ## Reconsume.
7948          redo A;
7949        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
7950          if ($is_space->{$self->{nc}}) {
7951            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
7952            
7953        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7954          $self->{line_prev} = $self->{line};
7955          $self->{column_prev} = $self->{column};
7956          $self->{column}++;
7957          $self->{nc}
7958              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7959        } else {
7960          $self->{set_nc}->($self);
7961        }
7962      
7963            redo A;
7964          } elsif ($self->{nc} == 0x0028) { # (
7965            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
7966            $self->{ct}->{content} = ['('];
7967            $self->{group_depth} = 1;
7968            
7969        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7970          $self->{line_prev} = $self->{line};
7971          $self->{column_prev} = $self->{column};
7972          $self->{column}++;
7973          $self->{nc}
7974              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7975        } else {
7976          $self->{set_nc}->($self);
7977        }
7978      
7979            redo A;
7980          } elsif ($self->{nc} == 0x003E) { # >
7981            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
7982            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7983            
7984        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7985          $self->{line_prev} = $self->{line};
7986          $self->{column_prev} = $self->{column};
7987          $self->{column}++;
7988          $self->{nc}
7989              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7990        } else {
7991          $self->{set_nc}->($self);
7992        }
7993      
7994            return  ($self->{ct}); # ELEMENT
7995            redo A;
7996          } elsif ($self->{nc} == -1) {
7997            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7998            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7999            
8000        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8001          $self->{line_prev} = $self->{line};
8002          $self->{column_prev} = $self->{column};
8003          $self->{column}++;
8004          $self->{nc}
8005              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8006        } else {
8007          $self->{set_nc}->($self);
8008        }
8009      
8010            return  ($self->{ct}); # ELEMENT
8011            redo A;
8012          } else {
8013            $self->{ct}->{content} = [chr $self->{nc}];
8014            $self->{state} = CONTENT_KEYWORD_STATE;
8015            
8016        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8017          $self->{line_prev} = $self->{line};
8018          $self->{column_prev} = $self->{column};
8019          $self->{column}++;
8020          $self->{nc}
8021              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8022        } else {
8023          $self->{set_nc}->($self);
8024        }
8025      
8026            redo A;
8027          }
8028        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
8029          if ($is_space->{$self->{nc}}) {
8030            $self->{state} = AFTER_MD_DEF_STATE;
8031            
8032        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8033          $self->{line_prev} = $self->{line};
8034          $self->{column_prev} = $self->{column};
8035          $self->{column}++;
8036          $self->{nc}
8037              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8038        } else {
8039          $self->{set_nc}->($self);
8040        }
8041      
8042            redo A;
8043          } elsif ($self->{nc} == 0x003E) { # >
8044            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8045            
8046        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8047          $self->{line_prev} = $self->{line};
8048          $self->{column_prev} = $self->{column};
8049          $self->{column}++;
8050          $self->{nc}
8051              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8052        } else {
8053          $self->{set_nc}->($self);
8054        }
8055      
8056            return  ($self->{ct}); # ELEMENT
8057            redo A;
8058          } elsif ($self->{nc} == -1) {
8059            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8060            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8061            
8062        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8063          $self->{line_prev} = $self->{line};
8064          $self->{column_prev} = $self->{column};
8065          $self->{column}++;
8066          $self->{nc}
8067              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8068        } else {
8069          $self->{set_nc}->($self);
8070        }
8071      
8072            return  ($self->{ct}); # ELEMENT
8073            redo A;
8074          } else {
8075            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
8076            ## Stay in the state.
8077            
8078        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8079          $self->{line_prev} = $self->{line};
8080          $self->{column_prev} = $self->{column};
8081          $self->{column}++;
8082          $self->{nc}
8083              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8084        } else {
8085          $self->{set_nc}->($self);
8086        }
8087      
8088            redo A;
8089          }
8090        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
8091          if ($is_space->{$self->{nc}}) {
8092            ## Stay in the state.
8093            
8094        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8095          $self->{line_prev} = $self->{line};
8096          $self->{column_prev} = $self->{column};
8097          $self->{column}++;
8098          $self->{nc}
8099              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8100        } else {
8101          $self->{set_nc}->($self);
8102        }
8103      
8104            redo A;
8105          } elsif ($self->{nc} == 0x0028) { # (
8106            $self->{group_depth}++;
8107            push @{$self->{ct}->{content}}, chr $self->{nc};
8108            ## Stay in the state.
8109            
8110        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8111          $self->{line_prev} = $self->{line};
8112          $self->{column_prev} = $self->{column};
8113          $self->{column}++;
8114          $self->{nc}
8115              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8116        } else {
8117          $self->{set_nc}->($self);
8118        }
8119      
8120            redo A;
8121          } elsif ($self->{nc} == 0x007C or # |
8122                   $self->{nc} == 0x002C) { # ,
8123            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8124            ## Stay in the state.
8125            
8126        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8127          $self->{line_prev} = $self->{line};
8128          $self->{column_prev} = $self->{column};
8129          $self->{column}++;
8130          $self->{nc}
8131              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8132        } else {
8133          $self->{set_nc}->($self);
8134        }
8135      
8136            redo A;
8137          } elsif ($self->{nc} == 0x0029) { # )
8138            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8139            push @{$self->{ct}->{content}}, chr $self->{nc};
8140            $self->{group_depth}--;
8141            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8142            
8143        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8144          $self->{line_prev} = $self->{line};
8145          $self->{column_prev} = $self->{column};
8146          $self->{column}++;
8147          $self->{nc}
8148              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8149        } else {
8150          $self->{set_nc}->($self);
8151        }
8152      
8153            redo A;
8154          } elsif ($self->{nc} == 0x003E) { # >
8155            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8156            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8157            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8158            
8159        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8160          $self->{line_prev} = $self->{line};
8161          $self->{column_prev} = $self->{column};
8162          $self->{column}++;
8163          $self->{nc}
8164              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8165        } else {
8166          $self->{set_nc}->($self);
8167        }
8168      
8169            return  ($self->{ct}); # ELEMENT
8170            redo A;
8171          } elsif ($self->{nc} == -1) {
8172            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8173            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8174            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8175            
8176        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8177          $self->{line_prev} = $self->{line};
8178          $self->{column_prev} = $self->{column};
8179          $self->{column}++;
8180          $self->{nc}
8181              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8182        } else {
8183          $self->{set_nc}->($self);
8184        }
8185      
8186            return  ($self->{ct}); # ELEMENT
8187            redo A;
8188          } else {
8189            push @{$self->{ct}->{content}}, chr $self->{nc};
8190            $self->{state} = CM_ELEMENT_NAME_STATE;
8191            
8192        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8193          $self->{line_prev} = $self->{line};
8194          $self->{column_prev} = $self->{column};
8195          $self->{column}++;
8196          $self->{nc}
8197              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8198        } else {
8199          $self->{set_nc}->($self);
8200        }
8201      
8202            redo A;
8203          }
8204        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
8205          if ($is_space->{$self->{nc}}) {
8206            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8207            
8208        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8209          $self->{line_prev} = $self->{line};
8210          $self->{column_prev} = $self->{column};
8211          $self->{column}++;
8212          $self->{nc}
8213              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8214        } else {
8215          $self->{set_nc}->($self);
8216        }
8217      
8218            redo A;
8219          } elsif ($self->{nc} == 0x002A or # *
8220                   $self->{nc} == 0x002B or # +
8221                   $self->{nc} == 0x003F) { # ?
8222            push @{$self->{ct}->{content}}, chr $self->{nc};
8223            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8224            
8225        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8226          $self->{line_prev} = $self->{line};
8227          $self->{column_prev} = $self->{column};
8228          $self->{column}++;
8229          $self->{nc}
8230              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8231        } else {
8232          $self->{set_nc}->($self);
8233        }
8234      
8235            redo A;
8236          } elsif ($self->{nc} == 0x007C or # |
8237                   $self->{nc} == 0x002C) { # ,
8238            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8239            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8240            
8241        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8242          $self->{line_prev} = $self->{line};
8243          $self->{column_prev} = $self->{column};
8244          $self->{column}++;
8245          $self->{nc}
8246              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8247        } else {
8248          $self->{set_nc}->($self);
8249        }
8250      
8251            redo A;
8252          } elsif ($self->{nc} == 0x0029) { # )
8253            $self->{group_depth}--;
8254            push @{$self->{ct}->{content}}, chr $self->{nc};
8255            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8256            
8257        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8258          $self->{line_prev} = $self->{line};
8259          $self->{column_prev} = $self->{column};
8260          $self->{column}++;
8261          $self->{nc}
8262              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8263        } else {
8264          $self->{set_nc}->($self);
8265        }
8266      
8267            redo A;
8268          } elsif ($self->{nc} == 0x003E) { # >
8269            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8270            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8271            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8272            
8273        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8274          $self->{line_prev} = $self->{line};
8275          $self->{column_prev} = $self->{column};
8276          $self->{column}++;
8277          $self->{nc}
8278              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8279        } else {
8280          $self->{set_nc}->($self);
8281        }
8282      
8283            return  ($self->{ct}); # ELEMENT
8284            redo A;
8285          } elsif ($self->{nc} == -1) {
8286            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8287            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8288            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8289            
8290        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8291          $self->{line_prev} = $self->{line};
8292          $self->{column_prev} = $self->{column};
8293          $self->{column}++;
8294          $self->{nc}
8295              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8296        } else {
8297          $self->{set_nc}->($self);
8298        }
8299      
8300            return  ($self->{ct}); # ELEMENT
8301            redo A;
8302          } else {
8303            $self->{ct}->{content}->[-1] .= chr $self->{nc};
8304            ## Stay in the state.
8305            
8306        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8307          $self->{line_prev} = $self->{line};
8308          $self->{column_prev} = $self->{column};
8309          $self->{column}++;
8310          $self->{nc}
8311              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8312        } else {
8313          $self->{set_nc}->($self);
8314        }
8315      
8316            redo A;
8317          }
8318        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
8319          if ($is_space->{$self->{nc}}) {
8320            ## Stay in the state.
8321            
8322        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8323          $self->{line_prev} = $self->{line};
8324          $self->{column_prev} = $self->{column};
8325          $self->{column}++;
8326          $self->{nc}
8327              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8328        } else {
8329          $self->{set_nc}->($self);
8330        }
8331      
8332            redo A;
8333          } elsif ($self->{nc} == 0x007C or # |
8334                   $self->{nc} == 0x002C) { # ,
8335            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8336            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8337            
8338        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8339          $self->{line_prev} = $self->{line};
8340          $self->{column_prev} = $self->{column};
8341          $self->{column}++;
8342          $self->{nc}
8343              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8344        } else {
8345          $self->{set_nc}->($self);
8346        }
8347      
8348            redo A;
8349          } elsif ($self->{nc} == 0x0029) { # )
8350            $self->{group_depth}--;
8351            push @{$self->{ct}->{content}}, chr $self->{nc};
8352            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8353            
8354        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8355          $self->{line_prev} = $self->{line};
8356          $self->{column_prev} = $self->{column};
8357          $self->{column}++;
8358          $self->{nc}
8359              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8360        } else {
8361          $self->{set_nc}->($self);
8362        }
8363      
8364            redo A;
8365          } elsif ($self->{nc} == 0x003E) { # >
8366            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8367            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8368            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8369            
8370        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8371          $self->{line_prev} = $self->{line};
8372          $self->{column_prev} = $self->{column};
8373          $self->{column}++;
8374          $self->{nc}
8375              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8376        } else {
8377          $self->{set_nc}->($self);
8378        }
8379      
8380            return  ($self->{ct}); # ELEMENT
8381            redo A;
8382          } elsif ($self->{nc} == -1) {
8383            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8384            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8385            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8386            
8387        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8388          $self->{line_prev} = $self->{line};
8389          $self->{column_prev} = $self->{column};
8390          $self->{column}++;
8391          $self->{nc}
8392              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8393        } else {
8394          $self->{set_nc}->($self);
8395        }
8396      
8397            return  ($self->{ct}); # ELEMENT
8398            redo A;
8399          } else {
8400            $self->{parse_error}->(level => $self->{level}->{must}, type => 'after element name'); ## TODO: type
8401            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8402            $self->{state} = BOGUS_MD_STATE;
8403            
8404        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8405          $self->{line_prev} = $self->{line};
8406          $self->{column_prev} = $self->{column};
8407          $self->{column}++;
8408          $self->{nc}
8409              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8410        } else {
8411          $self->{set_nc}->($self);
8412        }
8413      
8414            redo A;
8415          }
8416        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
8417          if ($is_space->{$self->{nc}}) {
8418            if ($self->{group_depth}) {
8419              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8420            } else {
8421              $self->{state} = AFTER_MD_DEF_STATE;
8422            }
8423            
8424        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8425          $self->{line_prev} = $self->{line};
8426          $self->{column_prev} = $self->{column};
8427          $self->{column}++;
8428          $self->{nc}
8429              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8430        } else {
8431          $self->{set_nc}->($self);
8432        }
8433      
8434            redo A;
8435          } elsif ($self->{nc} == 0x002A or # *
8436                   $self->{nc} == 0x002B or # +
8437                   $self->{nc} == 0x003F) { # ?
8438            push @{$self->{ct}->{content}}, chr $self->{nc};
8439            if ($self->{group_depth}) {
8440              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8441            } else {
8442              $self->{state} = AFTER_MD_DEF_STATE;
8443            }
8444            
8445        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8446          $self->{line_prev} = $self->{line};
8447          $self->{column_prev} = $self->{column};
8448          $self->{column}++;
8449          $self->{nc}
8450              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8451        } else {
8452          $self->{set_nc}->($self);
8453        }
8454      
8455            redo A;
8456          } elsif ($self->{nc} == 0x0029) { # )
8457            if ($self->{group_depth}) {
8458              $self->{group_depth}--;
8459              push @{$self->{ct}->{content}}, chr $self->{nc};
8460              ## Stay in the state.
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            } else {
8474              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8475              $self->{state} = BOGUS_MD_STATE;
8476              ## Reconsume.
8477              redo A;
8478            }
8479          } elsif ($self->{nc} == 0x003E) { # >
8480            if ($self->{group_depth}) {
8481              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8482              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8483            }
8484            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8485            
8486        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8487          $self->{line_prev} = $self->{line};
8488          $self->{column_prev} = $self->{column};
8489          $self->{column}++;
8490          $self->{nc}
8491              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8492        } else {
8493          $self->{set_nc}->($self);
8494        }
8495      
8496            return  ($self->{ct}); # ELEMENT
8497            redo A;
8498          } elsif ($self->{nc} == -1) {
8499            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8500            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8501            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8502            
8503        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8504          $self->{line_prev} = $self->{line};
8505          $self->{column_prev} = $self->{column};
8506          $self->{column}++;
8507          $self->{nc}
8508              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8509        } else {
8510          $self->{set_nc}->($self);
8511        }
8512      
8513            return  ($self->{ct}); # ELEMENT
8514            redo A;
8515          } else {
8516            if ($self->{group_depth}) {
8517              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8518            } else {
8519              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8520              $self->{state} = BOGUS_MD_STATE;
8521            }
8522            ## Reconsume.
8523            redo A;
8524          }
8525        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
8526          if ($is_space->{$self->{nc}}) {
8527            ## Stay in the state.
8528            
8529        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8530          $self->{line_prev} = $self->{line};
8531          $self->{column_prev} = $self->{column};
8532          $self->{column}++;
8533          $self->{nc}
8534              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8535        } else {
8536          $self->{set_nc}->($self);
8537        }
8538      
8539            redo A;
8540          } elsif ($self->{nc} == 0x003E) { # >
8541            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8542            
8543        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8544          $self->{line_prev} = $self->{line};
8545          $self->{column_prev} = $self->{column};
8546          $self->{column}++;
8547          $self->{nc}
8548              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8549        } else {
8550          $self->{set_nc}->($self);
8551        }
8552      
8553            return  ($self->{ct}); # ENTITY/ELEMENT
8554            redo A;
8555          } elsif ($self->{nc} == -1) {
8556            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8557            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8558            
8559        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8560          $self->{line_prev} = $self->{line};
8561          $self->{column_prev} = $self->{column};
8562          $self->{column}++;
8563          $self->{nc}
8564              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8565        } else {
8566          $self->{set_nc}->($self);
8567        }
8568      
8569            return  ($self->{ct}); # ENTITY/ELEMENT
8570            redo A;
8571          } else {
8572            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8573            $self->{state} = BOGUS_MD_STATE;
8574            ## Reconsume.
8575            redo A;
8576          }
8577        } elsif ($self->{state} == BOGUS_MD_STATE) {
8578          if ($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}); # ATTLIST/ENTITY/NOTATION
8592            redo A;
8593          } elsif ($self->{nc} == -1) {
8594            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8595            ## Reconsume.
8596            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8597            redo A;
8598          } else {
8599            ## Stay in the state.
8600            
8601        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8602          $self->{line_prev} = $self->{line};
8603          $self->{column_prev} = $self->{column};
8604          $self->{column}++;
8605          $self->{nc}
8606              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8607        } else {
8608          $self->{set_nc}->($self);
8609        }
8610      
8611            redo A;
8612          }
8613      } else {      } else {
8614        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
8615      }      }

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24