/[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.30 by wakaba, Sun Aug 16 05:24:47 2009 UTC
# Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO
177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
178  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
179  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }
180    sub BEFORE_NDATA_STATE () { 85 }
181    sub NDATA_STATE () { 86 }
182    sub AFTER_NDATA_STATE () { 87 }
183    sub BEFORE_NOTATION_NAME_STATE () { 88 }
184    sub NOTATION_NAME_STATE () { 89 }
185    sub DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE () { 90 }
186    sub DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE () { 91 }
187    sub ENTITY_VALUE_ENTITY_STATE () { 92 }
188    sub AFTER_ELEMENT_NAME_STATE () { 93 }
189    sub BEFORE_ELEMENT_CONTENT_STATE () { 94 }
190    sub CONTENT_KEYWORD_STATE () { 95 }
191    sub AFTER_CM_GROUP_OPEN_STATE () { 96 }
192    sub CM_ELEMENT_NAME_STATE () { 97 }
193    sub AFTER_CM_ELEMENT_NAME_STATE () { 98 }
194    sub AFTER_CM_GROUP_CLOSE_STATE () { 99 }
195    sub AFTER_MD_DEF_STATE () { 100 }
196    sub BOGUS_MD_STATE () { 101 }
197    
198  ## Tree constructor state constants (see Whatpm::HTML for the full  ## Tree constructor state constants (see Whatpm::HTML for the full
199  ## list and descriptions)  ## list and descriptions)
# Line 1231  sub _get_next_token ($) { Line 1248  sub _get_next_token ($) {
1248          if ({          if ({
1249               0x0022 => 1, # "               0x0022 => 1, # "
1250               0x0027 => 1, # '               0x0027 => 1, # '
1251                 0x003C => 1, # <
1252               0x003D => 1, # =               0x003D => 1, # =
1253              }->{$self->{nc}}) {              }->{$self->{nc}}) {
1254                        
# Line 1413  sub _get_next_token ($) { Line 1431  sub _get_next_token ($) {
1431    
1432          redo A;          redo A;
1433        } else {        } else {
1434          if ($self->{nc} == 0x0022 or # "          if ({
1435              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1436                 0x0027 => 1, # '
1437                 0x003C => 1, # <
1438                }->{$self->{nc}}) {
1439                        
1440            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1441            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1585  sub _get_next_token ($) { Line 1606  sub _get_next_token ($) {
1606                        
1607          }          }
1608    
1609          if ($self->{nc} == 0x0022 or # "          if ({
1610              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1611                 0x0027 => 1, # '
1612                 0x003C => 1, # <
1613                }->{$self->{nc}}) {
1614                        
1615            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1616            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1723  sub _get_next_token ($) { Line 1747  sub _get_next_token ($) {
1747    
1748          redo A;          redo A;
1749        } else {        } else {
1750          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1751                        
1752            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1753            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute value');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute value');
# Line 1799  sub _get_next_token ($) { Line 1823  sub _get_next_token ($) {
1823      }      }
1824        
1825          redo A;          redo A;
1826          } elsif ($self->{is_xml} and
1827                   $is_space->{$self->{nc}}) {
1828            
1829            $self->{ca}->{value} .= ' ';
1830            ## Stay in the state.
1831            
1832        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1833          $self->{line_prev} = $self->{line};
1834          $self->{column_prev} = $self->{column};
1835          $self->{column}++;
1836          $self->{nc}
1837              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1838        } else {
1839          $self->{set_nc}->($self);
1840        }
1841      
1842            redo A;
1843        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1844          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1845          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1846  sub _get_next_token ($) { Line 1887  sub _get_next_token ($) {
1887          }          }
1888          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1889          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1890                                q["&<],                                qq["&<\x09\x0C\x20],
1891                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1892    
1893          ## Stay in the state          ## Stay in the state
# Line 1913  sub _get_next_token ($) { Line 1954  sub _get_next_token ($) {
1954      }      }
1955        
1956          redo A;          redo A;
1957          } elsif ($self->{is_xml} and
1958                   $is_space->{$self->{nc}}) {
1959            
1960            $self->{ca}->{value} .= ' ';
1961            ## Stay in the state.
1962            
1963        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1964          $self->{line_prev} = $self->{line};
1965          $self->{column_prev} = $self->{column};
1966          $self->{column}++;
1967          $self->{nc}
1968              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1969        } else {
1970          $self->{set_nc}->($self);
1971        }
1972      
1973            redo A;
1974        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1975          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1976          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1960  sub _get_next_token ($) { Line 2018  sub _get_next_token ($) {
2018          }          }
2019          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2020          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2021                                q['&<],                                qq['&<\x09\x0C\x20],
2022                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2023    
2024          ## Stay in the state          ## Stay in the state
# Line 2132  sub _get_next_token ($) { Line 2190  sub _get_next_token ($) {
2190               0x0022 => 1, # "               0x0022 => 1, # "
2191               0x0027 => 1, # '               0x0027 => 1, # '
2192               0x003D => 1, # =               0x003D => 1, # =
2193                 0x003C => 1, # <
2194              }->{$self->{nc}}) {              }->{$self->{nc}}) {
2195                        
2196            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 2141  sub _get_next_token ($) { Line 2200  sub _get_next_token ($) {
2200          }          }
2201          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2202          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2203                                q["'=& >],                                qq["'=& \x09\x0C>],
2204                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2205    
2206          ## Stay in the state          ## Stay in the state
# Line 2947  sub _get_next_token ($) { Line 3006  sub _get_next_token ($) {
3006          redo A;          redo A;
3007        } else {        } else {
3008                    
         ## XML5: Not a parse error.  
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',  
                         line => $self->{line_prev},  
                         column => $self->{column_prev});  
3009          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3010          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
3011                    
# Line 2982  sub _get_next_token ($) { Line 3037  sub _get_next_token ($) {
3037      }      }
3038        
3039          redo A;          redo A;
3040          } elsif ($self->{nc} == -1) {
3041            
3042            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3043            $self->{ct}->{quirks} = 1;
3044    
3045            $self->{state} = DATA_STATE;
3046            ## Reconsume.
3047            return  ($self->{ct}); # DOCTYPE (quirks)
3048    
3049            redo A;
3050        } else {        } else {
3051                    
3052          ## XML5: Unless EOF, swith to the bogus comment state.          ## XML5: Swith to the bogus comment state.
3053          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before DOCTYPE name');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before DOCTYPE name');
3054          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
3055          ## reconsume          ## reconsume
# Line 3029  sub _get_next_token ($) { Line 3094  sub _get_next_token ($) {
3094          return  ($self->{ct}); # DOCTYPE (quirks)          return  ($self->{ct}); # DOCTYPE (quirks)
3095    
3096          redo A;          redo A;
3097          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3098            
3099            $self->{ct}->{name} # DOCTYPE
3100                = chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3101            delete $self->{ct}->{quirks};
3102            $self->{state} = DOCTYPE_NAME_STATE;
3103            
3104        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3105          $self->{line_prev} = $self->{line};
3106          $self->{column_prev} = $self->{column};
3107          $self->{column}++;
3108          $self->{nc}
3109              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3110        } else {
3111          $self->{set_nc}->($self);
3112        }
3113      
3114            redo A;
3115        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3116                    
3117          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');
# Line 3115  sub _get_next_token ($) { Line 3198  sub _get_next_token ($) {
3198          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3199    
3200          redo A;          redo A;
3201          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3202            
3203            $self->{ct}->{name} # DOCTYPE
3204                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3205            delete $self->{ct}->{quirks};
3206            ## Stay in the state.
3207            
3208        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3209          $self->{line_prev} = $self->{line};
3210          $self->{column_prev} = $self->{column};
3211          $self->{column}++;
3212          $self->{nc}
3213              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3214        } else {
3215          $self->{set_nc}->($self);
3216        }
3217      
3218            redo A;
3219        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3220                    
3221          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
# Line 3146  sub _get_next_token ($) { Line 3247  sub _get_next_token ($) {
3247          redo A;          redo A;
3248        } else {        } else {
3249                    
3250          $self->{ct}->{name}          $self->{ct}->{name} .= chr ($self->{nc}); # DOCTYPE
3251            .= chr ($self->{nc}); # DOCTYPE          ## Stay in the state.
         ## Stay in the state  
3252                    
3253      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3254        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3182  sub _get_next_token ($) { Line 3282  sub _get_next_token ($) {
3282        
3283          redo A;          redo A;
3284        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3285            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3286              
3287              $self->{state} = DATA_STATE;
3288              $self->{s_kwd} = '';
3289            } else {
3290              
3291              $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
3292              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3293            }
3294                    
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3295                    
3296      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3297        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3196  sub _get_next_token ($) { Line 3303  sub _get_next_token ($) {
3303        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3304      }      }
3305        
3306            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3307          redo A;          redo A;
3308        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3309            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3310              
3311              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3312              $self->{state} = DATA_STATE;
3313              $self->{s_kwd} = '';
3314              $self->{ct}->{quirks} = 1;
3315            } else {
3316              
3317              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3318              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3319            }
3320                    
3321          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          ## Reconsume.
3322          $self->{state} = DATA_STATE;          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{s_kwd} = '';  
         ## reconsume  
   
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3323          redo A;          redo A;
3324        } elsif ($self->{nc} == 0x0050 or # P        } elsif ($self->{nc} == 0x0050 or # P
3325                 $self->{nc} == 0x0070) { # p                 $self->{nc} == 0x0070) { # p
# Line 3245  sub _get_next_token ($) { Line 3355  sub _get_next_token ($) {
3355      }      }
3356        
3357          redo A;          redo A;
3358        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{nc} == 0x0022 and # "
3359                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3360                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3361            
3362            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
3363            $self->{ct}->{value} = ''; # ENTITY
3364            
3365        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3366          $self->{line_prev} = $self->{line};
3367          $self->{column_prev} = $self->{column};
3368          $self->{column}++;
3369          $self->{nc}
3370              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3371        } else {
3372          $self->{set_nc}->($self);
3373        }
3374      
3375            redo A;
3376          } elsif ($self->{nc} == 0x0027 and # '
3377                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3378                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3379            
3380            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
3381            $self->{ct}->{value} = ''; # ENTITY
3382            
3383        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3384          $self->{line_prev} = $self->{line};
3385          $self->{column_prev} = $self->{column};
3386          $self->{column}++;
3387          $self->{nc}
3388              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3389        } else {
3390          $self->{set_nc}->($self);
3391        }
3392      
3393            redo A;
3394          } elsif ($self->{is_xml} and
3395                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3396                   $self->{nc} == 0x005B) { # [
3397                    
3398          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3399          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 3264  sub _get_next_token ($) { Line 3412  sub _get_next_token ($) {
3412          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3413          redo A;          redo A;
3414        } else {        } else {
3415                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name'); ## TODO: type
3416          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name');  
3417          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3418              
3419              $self->{ct}->{quirks} = 1;
3420              $self->{state} = BOGUS_DOCTYPE_STATE;
3421            } else {
3422              
3423              $self->{state} = BOGUS_MD_STATE;
3424            }
3425    
         $self->{state} = BOGUS_DOCTYPE_STATE;  
3426                    
3427      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3428        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3340  sub _get_next_token ($) { Line 3494  sub _get_next_token ($) {
3494        
3495          redo A;          redo A;
3496        } else {        } else {
3497                    $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',  
3498                          line => $self->{line_prev},                          line => $self->{line_prev},
3499                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3500          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3501              
3502          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3503              $self->{state} = BOGUS_DOCTYPE_STATE;
3504            } else {
3505              
3506              $self->{state} = BOGUS_MD_STATE;
3507            }
3508          ## Reconsume.          ## Reconsume.
3509          redo A;          redo A;
3510        }        }
# Line 3408  sub _get_next_token ($) { Line 3566  sub _get_next_token ($) {
3566        
3567          redo A;          redo A;
3568        } else {        } else {
3569                    $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',  
3570                          line => $self->{line_prev},                          line => $self->{line_prev},
3571                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3572          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3573              
3574          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3575              $self->{state} = BOGUS_DOCTYPE_STATE;
3576            } else {
3577              
3578              $self->{state} = BOGUS_MD_STATE;
3579            }
3580          ## Reconsume.          ## Reconsume.
3581          redo A;          redo A;
3582        }        }
# Line 3467  sub _get_next_token ($) { Line 3629  sub _get_next_token ($) {
3629        
3630          redo A;          redo A;
3631        } elsif ($self->{nc} eq 0x003E) { # >        } elsif ($self->{nc} eq 0x003E) { # >
           
3632          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3633            
3634          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3635          $self->{s_kwd} = '';            
3636              $self->{state} = DATA_STATE;
3637              $self->{s_kwd} = '';
3638              $self->{ct}->{quirks} = 1;
3639            } else {
3640              
3641              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3642            }
3643            
3644                    
3645      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3646        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3483  sub _get_next_token ($) { Line 3652  sub _get_next_token ($) {
3652        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3653      }      }
3654        
3655            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3656          redo A;          redo A;
3657        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3658            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3659              
3660              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3661              $self->{state} = DATA_STATE;
3662              $self->{s_kwd} = '';
3663              $self->{ct}->{quirks} = 1;
3664            } else {
3665              
3666              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3667              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3668            }
3669                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3670          ## reconsume          ## reconsume
   
         $self->{ct}->{quirks} = 1;  
3671          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3672          redo A;          redo A;
3673        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3674                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3675                   $self->{nc} == 0x005B) { # [
3676                    
3677          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3678          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3520  sub _get_next_token ($) { Line 3692  sub _get_next_token ($) {
3692          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3693          redo A;          redo A;
3694        } else {        } else {
           
3695          $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;  
3696    
3697          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3698              
3699              $self->{ct}->{quirks} = 1;
3700              $self->{state} = BOGUS_DOCTYPE_STATE;
3701            } else {
3702              
3703              $self->{state} = BOGUS_MD_STATE;
3704            }
3705    
3706                    
3707      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3708        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3555  sub _get_next_token ($) { Line 3733  sub _get_next_token ($) {
3733        
3734          redo A;          redo A;
3735        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3736          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3737    
3738          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3739          $self->{s_kwd} = '';            
3740              $self->{state} = DATA_STATE;
3741              $self->{s_kwd} = '';
3742              $self->{ct}->{quirks} = 1;
3743            } else {
3744              
3745              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3746            }
3747    
3748                    
3749      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3750        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3571  sub _get_next_token ($) { Line 3756  sub _get_next_token ($) {
3756        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3757      }      }
3758        
3759            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3760          redo A;          redo A;
3761        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3762          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3763    
3764          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3765          $self->{s_kwd} = '';            
3766          ## reconsume            $self->{state} = DATA_STATE;
3767              $self->{s_kwd} = '';
3768          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
3769            } else {
3770              
3771              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3772            }
3773            
3774            ## Reconsume.
3775          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3776          redo A;          redo A;
3777        } else {        } else {
3778                    
3779          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3780          $self->{read_until}->($self->{ct}->{pubid}, q[">],          $self->{read_until}->($self->{ct}->{pubid}, q[">],
3781                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3782    
# Line 3626  sub _get_next_token ($) { Line 3811  sub _get_next_token ($) {
3811        
3812          redo A;          redo A;
3813        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3814          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3815    
3816          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3817          $self->{s_kwd} = '';            
3818              $self->{state} = DATA_STATE;
3819              $self->{s_kwd} = '';
3820              $self->{ct}->{quirks} = 1;
3821            } else {
3822              
3823              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3824            }
3825    
3826                    
3827      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3828        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3642  sub _get_next_token ($) { Line 3834  sub _get_next_token ($) {
3834        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3835      }      }
3836        
3837            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3838          redo A;          redo A;
3839        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3840          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3841    
3842          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3843          $self->{s_kwd} = '';            
3844              $self->{state} = DATA_STATE;
3845              $self->{s_kwd} = '';
3846              $self->{ct}->{quirks} = 1;
3847            } else {
3848              
3849              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3850            }
3851          
3852          ## reconsume          ## reconsume
3853            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3854          redo A;          redo A;
3855        } else {        } else {
3856                    
3857          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3858          $self->{read_until}->($self->{ct}->{pubid}, q['>],          $self->{read_until}->($self->{ct}->{pubid}, q['>],
3859                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3860    
# Line 3698  sub _get_next_token ($) { Line 3890  sub _get_next_token ($) {
3890          redo A;          redo A;
3891        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
3892                    
3893          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
3894          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
3895                    
3896      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 3906  sub _get_next_token ($) {
3906          redo A;          redo A;
3907        } elsif ($self->{nc} == 0x0027) { # '        } elsif ($self->{nc} == 0x0027) { # '
3908                    
3909          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
3910          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
3911                    
3912      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 3921  sub _get_next_token ($) {
3921        
3922          redo A;          redo A;
3923        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3924          if ($self->{is_xml}) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3925                        if ($self->{is_xml}) {
3926            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');              
3927                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
3928              } else {
3929                
3930              }
3931              $self->{state} = DATA_STATE;
3932              $self->{s_kwd} = '';
3933          } else {          } else {
3934                        if ($self->{ct}->{type} == NOTATION_TOKEN) {
3935                
3936              } else {
3937                
3938                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');            
3939              }
3940              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3941          }          }
3942          $self->{state} = DATA_STATE;          
         $self->{s_kwd} = '';  
3943                    
3944      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3945        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3748  sub _get_next_token ($) { Line 3951  sub _get_next_token ($) {
3951        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3952      }      }
3953        
3954            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3955          redo A;          redo A;
3956        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3957            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3958              
3959              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3960              
3961              $self->{state} = DATA_STATE;
3962              $self->{s_kwd} = '';
3963              $self->{ct}->{quirks} = 1;
3964            } else {
3965              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3966              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3967            }
3968                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3969          ## reconsume          ## reconsume
3970            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3971          redo A;          redo A;
3972        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3973                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3974                   $self->{nc} == 0x005B) { # [
3975                    
3976          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
3977          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3784  sub _get_next_token ($) { Line 3991  sub _get_next_token ($) {
3991          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3992          redo A;          redo A;
3993        } else {        } else {
           
3994          $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;  
3995    
3996          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3997              
3998              $self->{ct}->{quirks} = 1;
3999              $self->{state} = BOGUS_DOCTYPE_STATE;
4000            } else {
4001              
4002              $self->{state} = BOGUS_MD_STATE;
4003            }
4004    
4005                    
4006      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4007        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3851  sub _get_next_token ($) { Line 4064  sub _get_next_token ($) {
4064        
4065          redo A;          redo A;
4066        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
4067          $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} = '';  
4068                    
4069      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4070        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3867  sub _get_next_token ($) { Line 4077  sub _get_next_token ($) {
4077      }      }
4078        
4079    
4080          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4081          return  ($self->{ct}); # DOCTYPE            
4082              $self->{state} = DATA_STATE;
4083              $self->{s_kwd} = '';
4084              $self->{ct}->{quirks} = 1;
4085            } else {
4086              
4087              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4088            }
4089    
4090            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4091          redo A;          redo A;
4092        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4093            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4094              
4095              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4096              $self->{state} = DATA_STATE;
4097              $self->{s_kwd} = '';
4098              $self->{ct}->{quirks} = 1;
4099            } else {
4100              
4101              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4102              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4103            }
4104                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4105          ## reconsume          ## reconsume
4106            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4107          redo A;          redo A;
4108        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4109                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4110                   $self->{nc} == 0x005B) { # [
4111                    
4112          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4113    
# Line 3904  sub _get_next_token ($) { Line 4128  sub _get_next_token ($) {
4128          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4129          redo A;          redo A;
4130        } else {        } else {
           
4131          $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;  
4132    
4133          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4134                        
4135              $self->{ct}->{quirks} = 1;
4136              $self->{state} = BOGUS_DOCTYPE_STATE;
4137            } else {
4138              
4139              $self->{state} = BOGUS_MD_STATE;
4140            }
4141    
4142                    
4143      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4144        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3939  sub _get_next_token ($) { Line 4169  sub _get_next_token ($) {
4169        
4170          redo A;          redo A;
4171        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >
           
4172          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4173    
4174          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4175          $self->{s_kwd} = '';            
4176              $self->{state} = DATA_STATE;
4177              $self->{s_kwd} = '';
4178              $self->{ct}->{quirks} = 1;
4179            } else {
4180              
4181              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4182            }
4183            
4184                    
4185      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4186        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3955  sub _get_next_token ($) { Line 4192  sub _get_next_token ($) {
4192        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4193      }      }
4194        
4195            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4196          redo A;          redo A;
4197        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4198          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4199    
4200          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4201          $self->{s_kwd} = '';            
4202              $self->{state} = DATA_STATE;
4203              $self->{s_kwd} = '';
4204              $self->{ct}->{quirks} = 1;
4205            } else {
4206              
4207              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4208            }
4209            
4210          ## reconsume          ## reconsume
4211            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4212          redo A;          redo A;
4213        } else {        } else {
4214                    
4215          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4216          $self->{read_until}->($self->{ct}->{sysid}, q[">],          $self->{read_until}->($self->{ct}->{sysid}, q[">],
4217                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4218    
# Line 4032  sub _get_next_token ($) { Line 4269  sub _get_next_token ($) {
4269    
4270          redo A;          redo A;
4271        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4272          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4273    
4274          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4275          $self->{s_kwd} = '';            
4276          ## reconsume            $self->{state} = DATA_STATE;
4277              $self->{s_kwd} = '';
4278          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
4279          return  ($self->{ct}); # DOCTYPE          } else {
4280              
4281              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4282            }
4283    
4284            ## reconsume
4285            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4286          redo A;          redo A;
4287        } else {        } else {
4288                    
4289          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4290          $self->{read_until}->($self->{ct}->{sysid}, q['>],          $self->{read_until}->($self->{ct}->{sysid}, q['>],
4291                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4292    
# Line 4066  sub _get_next_token ($) { Line 4306  sub _get_next_token ($) {
4306        }        }
4307      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
4308        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4309                    if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
4310          ## Stay in the state            
4311              $self->{state} = BEFORE_NDATA_STATE;
4312            } else {
4313              
4314              ## Stay in the state
4315            }
4316                    
4317      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4318        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4081  sub _get_next_token ($) { Line 4326  sub _get_next_token ($) {
4326        
4327          redo A;          redo A;
4328        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4329            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4330              
4331              $self->{state} = DATA_STATE;
4332              $self->{s_kwd} = '';
4333            } else {
4334              
4335              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4336            }
4337    
4338                    
4339          $self->{state} = DATA_STATE;      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4340          $self->{s_kwd} = '';        $self->{line_prev} = $self->{line};
4341          $self->{column_prev} = $self->{column};
4342          $self->{column}++;
4343          $self->{nc}
4344              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4345        } else {
4346          $self->{set_nc}->($self);
4347        }
4348      
4349            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4350            redo A;
4351          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4352                   ($self->{nc} == 0x004E or # N
4353                    $self->{nc} == 0x006E)) { # n
4354            
4355            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before NDATA'); ## TODO: type
4356            $self->{state} = NDATA_STATE;
4357            $self->{kwd} = chr $self->{nc};
4358                    
4359      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4360        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4095  sub _get_next_token ($) { Line 4366  sub _get_next_token ($) {
4366        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4367      }      }
4368        
   
         return  ($self->{ct}); # DOCTYPE  
   
4369          redo A;          redo A;
4370        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4371                    if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4372          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');            
4373          $self->{state} = DATA_STATE;            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4374          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
4375          ## reconsume            $self->{s_kwd} = '';
4376              $self->{ct}->{quirks} = 1;
4377          $self->{ct}->{quirks} = 1;          } else {
4378          return  ($self->{ct}); # DOCTYPE            
4379              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4380              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4381            }
4382    
4383            ## reconsume
4384            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4385          redo A;          redo A;
4386        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4387                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4388                   $self->{nc} == 0x005B) { # [
4389                    
4390          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4391          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 4129  sub _get_next_token ($) { Line 4404  sub _get_next_token ($) {
4404          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4405          redo A;          redo A;
4406        } else {        } else {
           
4407          $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;  
4408    
4409          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4410              
4411              #$self->{ct}->{quirks} = 1;
4412              $self->{state} = BOGUS_DOCTYPE_STATE;
4413            } else {
4414              
4415              $self->{state} = BOGUS_MD_STATE;
4416            }
4417    
4418            
4419        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4420          $self->{line_prev} = $self->{line};
4421          $self->{column_prev} = $self->{column};
4422          $self->{column}++;
4423          $self->{nc}
4424              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4425        } else {
4426          $self->{set_nc}->($self);
4427        }
4428      
4429            redo A;
4430          }
4431        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
4432          if ($is_space->{$self->{nc}}) {
4433            
4434            ## Stay in the state.
4435            
4436        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4437          $self->{line_prev} = $self->{line};
4438          $self->{column_prev} = $self->{column};
4439          $self->{column}++;
4440          $self->{nc}
4441              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4442        } else {
4443          $self->{set_nc}->($self);
4444        }
4445      
4446            redo A;
4447          } elsif ($self->{nc} == 0x003E) { # >
4448            
4449            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4450            
4451        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4452          $self->{line_prev} = $self->{line};
4453          $self->{column_prev} = $self->{column};
4454          $self->{column}++;
4455          $self->{nc}
4456              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4457        } else {
4458          $self->{set_nc}->($self);
4459        }
4460      
4461            return  ($self->{ct}); # ENTITY
4462            redo A;
4463          } elsif ($self->{nc} == 0x004E or # N
4464                   $self->{nc} == 0x006E) { # n
4465            
4466            $self->{state} = NDATA_STATE;
4467            $self->{kwd} = chr $self->{nc};
4468            
4469        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4470          $self->{line_prev} = $self->{line};
4471          $self->{column_prev} = $self->{column};
4472          $self->{column}++;
4473          $self->{nc}
4474              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4475        } else {
4476          $self->{set_nc}->($self);
4477        }
4478      
4479            redo A;
4480          } elsif ($self->{nc} == -1) {
4481            
4482            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4483            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4484            ## reconsume
4485            return  ($self->{ct}); # ENTITY
4486            redo A;
4487          } else {
4488            
4489            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
4490            $self->{state} = BOGUS_MD_STATE;
4491                    
4492      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4493        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4357  sub _get_next_token ($) { Line 4711  sub _get_next_token ($) {
4711              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4712              $self->{entity_add} => 1,              $self->{entity_add} => 1,
4713            }->{$self->{nc}}) {            }->{$self->{nc}}) {
4714                    if ($self->{is_xml}) {
4715              
4716              $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
4717                              line => $self->{line_prev},
4718                              column => $self->{column_prev}
4719                                  + ($self->{nc} == -1 ? 1 : 0));
4720            } else {
4721              
4722              ## No error
4723            }
4724          ## Don't consume          ## Don't consume
         ## No error  
4725          ## Return nothing.          ## Return nothing.
4726          #          #
4727        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 4378  sub _get_next_token ($) { Line 4740  sub _get_next_token ($) {
4740      }      }
4741        
4742          redo A;          redo A;
4743        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
4744                   (0x0041 <= $self->{nc} and
4745                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
4746                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
4747                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 4432  sub _get_next_token ($) { Line 4795  sub _get_next_token ($) {
4795          redo A;          redo A;
4796        }        }
4797      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
4798        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
4799            $self->{nc} == 0x0058) { # X          
4800            $self->{state} = HEXREF_X_STATE;
4801            $self->{kwd} .= chr $self->{nc};
4802            
4803        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4804          $self->{line_prev} = $self->{line};
4805          $self->{column_prev} = $self->{column};
4806          $self->{column}++;
4807          $self->{nc}
4808              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4809        } else {
4810          $self->{set_nc}->($self);
4811        }
4812      
4813            redo A;
4814          } elsif ($self->{nc} == 0x0058) { # X
4815                    
4816            if ($self->{is_xml}) {
4817              $self->{parse_error}->(level => $self->{level}->{must}, type => 'uppercase hcro'); ## TODO: type
4818            }
4819          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
4820          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4821                    
# Line 4539  sub _get_next_token ($) { Line 4920  sub _get_next_token ($) {
4920        my $code = $self->{kwd};        my $code = $self->{kwd};
4921        my $l = $self->{line_prev};        my $l = $self->{line_prev};
4922        my $c = $self->{column_prev};        my $c = $self->{column_prev};
4923        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
4924              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
4925              ($self->{is_xml} and $code == 0x0000)) {
4926                    
4927          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
4928                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4692  sub _get_next_token ($) { Line 5075  sub _get_next_token ($) {
5075        my $code = $self->{kwd};        my $code = $self->{kwd};
5076        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5077        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5078        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5079              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5080              ($self->{is_xml} and $code == 0x0000)) {
5081                    
5082          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5083                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4726  sub _get_next_token ($) { Line 5111  sub _get_next_token ($) {
5111          redo A;          redo A;
5112        }        }
5113      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
5114        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
5115            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
5116            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
5117              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
5118             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
5119              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
5120             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
5121              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
5122             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
5123                    {
5124                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
5125                      $self->{entity_add} => 1,
5126                    }->{$self->{nc}}))) {
5127          our $EntityChar;          our $EntityChar;
5128          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5129          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
5130                $self->{ge}->{$self->{kwd}}) {
5131            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
5132                            if (defined $self->{ge}->{$self->{kwd}}) {
5133              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
5134                    
5135                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
5136                  } else {
5137                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
5138                      
5139                      $self->{parse_error}->(level => $self->{level}->{must}, type => 'unparsed entity', ## TODO: type
5140                                      value => $self->{kwd});
5141                    } else {
5142                      
5143                    }
5144                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
5145                  }
5146                } else {
5147                  if ($self->{is_xml}) {
5148                    
5149                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'entity not declared', ## TODO: type
5150                                    value => $self->{kwd},
5151                                    level => {
5152                                              'amp;' => $self->{level}->{warn},
5153                                              'quot;' => $self->{level}->{warn},
5154                                              'lt;' => $self->{level}->{warn},
5155                                              'gt;' => $self->{level}->{warn},
5156                                              'apos;' => $self->{level}->{warn},
5157                                             }->{$self->{kwd}} ||
5158                                             $self->{level}->{must});
5159                  } else {
5160                    
5161                  }
5162                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
5163                }
5164              $self->{entity__match} = 1;              $self->{entity__match} = 1;
5165                            
5166      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 5556  sub _get_next_token ($) {
5556          ## XML5: Not defined yet.          ## XML5: Not defined yet.
5557    
5558          ## TODO:          ## TODO:
5559    
5560            if (not $self->{stop_processing} and
5561                not $self->{document}->xml_standalone) {
5562              $self->{parse_error}->(level => $self->{level}->{must}, type => 'stop processing', ## TODO: type
5563                              level => $self->{level}->{info});
5564              $self->{stop_processing} = 1;
5565            }
5566    
5567                    
5568      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
5569        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5358  sub _get_next_token ($) { Line 5786  sub _get_next_token ($) {
5786      }      }
5787        
5788          redo A;          redo A;
5789        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
5790                   $self->{nc} == 0x0065) { # e
5791          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
5792          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5793                    
# Line 5373  sub _get_next_token ($) { Line 5802  sub _get_next_token ($) {
5802      }      }
5803        
5804          redo A;          redo A;
5805        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
5806                   $self->{nc} == 0x0061) { # a
5807          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
5808          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5809                    
# Line 5388  sub _get_next_token ($) { Line 5818  sub _get_next_token ($) {
5818      }      }
5819        
5820          redo A;          redo A;
5821        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
5822                   $self->{nc} == 0x006E) { # n
5823          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
5824          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5825                    
# Line 5416  sub _get_next_token ($) { Line 5847  sub _get_next_token ($) {
5847        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
5848        redo A;        redo A;
5849      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
5850        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
5851              $self->{nc} == 0x006E) { # n
5852          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
5853          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5854                    
# Line 5431  sub _get_next_token ($) { Line 5863  sub _get_next_token ($) {
5863      }      }
5864        
5865          redo A;          redo A;
5866        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
5867                   $self->{nc} == 0x006C) { # l
5868          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
5869          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
5870          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 5459  sub _get_next_token ($) { Line 5892  sub _get_next_token ($) {
5892          redo A;          redo A;
5893        }        }
5894      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
5895        if ($self->{nc} == {        if ($self->{nc} == [
5896              'EN' => 0x0054, # T              undef,
5897              'ENT' => 0x0049, # I              undef,
5898              'ENTI' => 0x0054, # T              0x0054, # T
5899            }->{$self->{kwd}}) {              0x0049, # I
5900                0x0054, # T
5901              ]->[length $self->{kwd}] or
5902              $self->{nc} == [
5903                undef,
5904                undef,
5905                0x0074, # t
5906                0x0069, # i
5907                0x0074, # t
5908              ]->[length $self->{kwd}]) {
5909          ## Stay in the state.          ## Stay in the state.
5910          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5911                    
# Line 5478  sub _get_next_token ($) { Line 5920  sub _get_next_token ($) {
5920      }      }
5921        
5922          redo A;          redo A;
5923        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
5924                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
5925          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
5926            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
5927              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5928                              text => 'ENTITY',
5929                              line => $self->{line_prev},
5930                              column => $self->{column_prev} - 4);
5931            }
5932            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
5933                         line => $self->{line_prev},                         line => $self->{line_prev},
5934                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
5935          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 5508  sub _get_next_token ($) { Line 5957  sub _get_next_token ($) {
5957          redo A;          redo A;
5958        }        }
5959      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
5960        if ($self->{nc} == {        if ($self->{nc} == [
5961              'EL' => 0x0045, # E             undef,
5962              'ELE' => 0x004D, # M             undef,
5963              'ELEM' => 0x0045, # E             0x0045, # E
5964              'ELEME' => 0x004E, # N             0x004D, # M
5965            }->{$self->{kwd}}) {             0x0045, # E
5966               0x004E, # N
5967              ]->[length $self->{kwd}] or
5968              $self->{nc} == [
5969               undef,
5970               undef,
5971               0x0065, # e
5972               0x006D, # m
5973               0x0065, # e
5974               0x006E, # n
5975              ]->[length $self->{kwd}]) {
5976          ## Stay in the state.          ## Stay in the state.
5977          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5978                    
# Line 5528  sub _get_next_token ($) { Line 5987  sub _get_next_token ($) {
5987      }      }
5988        
5989          redo A;          redo A;
5990        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
5991                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
5992                    $self->{nc} == 0x0074)) { # t
5993            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
5994              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5995                              text => 'ELEMENT',
5996                              line => $self->{line_prev},
5997                              column => $self->{column_prev} - 5);
5998            }
5999          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
6000                         line => $self->{line_prev},                         line => $self->{line_prev},
6001                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6002          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6003                    
6004      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 6024  sub _get_next_token ($) {
6024          redo A;          redo A;
6025        }        }
6026      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
6027        if ($self->{nc} == {        if ($self->{nc} == [
6028              'A' => 0x0054, # T             undef,
6029              'AT' => 0x0054, # T             0x0054, # T
6030              'ATT' => 0x004C, # L             0x0054, # T
6031              'ATTL' => 0x0049, # I             0x004C, # L
6032              'ATTLI' => 0x0053, # S             0x0049, # I
6033            }->{$self->{kwd}}) {             0x0053, # S
6034              ]->[length $self->{kwd}] or
6035              $self->{nc} == [
6036               undef,
6037               0x0074, # t
6038               0x0074, # t
6039               0x006C, # l
6040               0x0069, # i
6041               0x0073, # s
6042              ]->[length $self->{kwd}]) {
6043          ## Stay in the state.          ## Stay in the state.
6044          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6045                    
# Line 5579  sub _get_next_token ($) { Line 6054  sub _get_next_token ($) {
6054      }      }
6055        
6056          redo A;          redo A;
6057        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
6058                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6059                    $self->{nc} == 0x0074)) { # t
6060            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
6061              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6062                              text => 'ATTLIST',
6063                              line => $self->{line_prev},
6064                              column => $self->{column_prev} - 5);
6065            }
6066          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
6067                         attrdefs => [],                         attrdefs => [],
6068                         line => $self->{line_prev},                         line => $self->{line_prev},
6069                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6070          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6071                    
6072      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 6092  sub _get_next_token ($) {
6092          redo A;          redo A;
6093        }        }
6094      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
6095        if ($self->{nc} == {        if ($self->{nc} == [
6096              'N' => 0x004F, # O             undef,
6097              'NO' => 0x0054, # T             0x004F, # O
6098              'NOT' => 0x0041, # A             0x0054, # T
6099              'NOTA' => 0x0054, # T             0x0041, # A
6100              'NOTAT' => 0x0049, # I             0x0054, # T
6101              'NOTATI' => 0x004F, # O             0x0049, # I
6102            }->{$self->{kwd}}) {             0x004F, # O
6103              ]->[length $self->{kwd}] or
6104              $self->{nc} == [
6105               undef,
6106               0x006F, # o
6107               0x0074, # t
6108               0x0061, # a
6109               0x0074, # t
6110               0x0069, # i
6111               0x006F, # o
6112              ]->[length $self->{kwd}]) {
6113          ## Stay in the state.          ## Stay in the state.
6114          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6115                    
# Line 5632  sub _get_next_token ($) { Line 6124  sub _get_next_token ($) {
6124      }      }
6125        
6126          redo A;          redo A;
6127        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
6128                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
6129                    $self->{nc} == 0x006E)) { # n
6130            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
6131              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6132                              text => 'NOTATION',
6133                              line => $self->{line_prev},
6134                              column => $self->{column_prev} - 6);
6135            }
6136          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
6137                         line => $self->{line_prev},                         line => $self->{line_prev},
6138                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
6139          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6140                    
6141      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 6344  sub _get_next_token ($) {
6344        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".
6345                
6346        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
6347          ## TODO:          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6348          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
6349            } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6350              $self->{state} = AFTER_ELEMENT_NAME_STATE;
6351            } else { # ENTITY/NOTATION
6352              $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6353            }
6354                    
6355      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6356        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5863  sub _get_next_token ($) { Line 6367  sub _get_next_token ($) {
6367          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6368            #            #
6369          } else {          } else {
6370            $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
6371          }          }
6372          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6373                    
# Line 6853  sub _get_next_token ($) { Line 7357  sub _get_next_token ($) {
7357        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
7358          ## XML5: No parse error.          ## XML5: No parse error.
7359          $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
7360          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = BOGUS_MD_STATE;
         $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded  
7361          ## Reconsume.          ## Reconsume.
7362          redo A;          redo A;
7363        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
# Line 7141  sub _get_next_token ($) { Line 7644  sub _get_next_token ($) {
7644          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
7645          ## Reconsume.          ## Reconsume.
7646          redo A;          redo A;
7647        }              }
7648        } elsif ($self->{state} == NDATA_STATE) {
7649          ## ASCII case-insensitive
7650          if ($self->{nc} == [
7651                undef,
7652                0x0044, # D
7653                0x0041, # A
7654                0x0054, # T
7655              ]->[length $self->{kwd}] or
7656              $self->{nc} == [
7657                undef,
7658                0x0064, # d
7659                0x0061, # a
7660                0x0074, # t
7661              ]->[length $self->{kwd}]) {
7662            
7663            ## Stay in the state.
7664            $self->{kwd} .= chr $self->{nc};
7665            
7666        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7667          $self->{line_prev} = $self->{line};
7668          $self->{column_prev} = $self->{column};
7669          $self->{column}++;
7670          $self->{nc}
7671              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7672        } else {
7673          $self->{set_nc}->($self);
7674        }
7675      
7676            redo A;
7677          } elsif ((length $self->{kwd}) == 4 and
7678                   ($self->{nc} == 0x0041 or # A
7679                    $self->{nc} == 0x0061)) { # a
7680            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
7681              
7682              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
7683                              text => 'NDATA',
7684                              line => $self->{line_prev},
7685                              column => $self->{column_prev} - 4);
7686            } else {
7687              
7688            }
7689            $self->{state} = AFTER_NDATA_STATE;
7690            
7691        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7692          $self->{line_prev} = $self->{line};
7693          $self->{column_prev} = $self->{column};
7694          $self->{column}++;
7695          $self->{nc}
7696              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7697        } else {
7698          $self->{set_nc}->($self);
7699        }
7700      
7701            redo A;
7702          } else {
7703            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7704                            line => $self->{line_prev},
7705                            column => $self->{column_prev} + 1
7706                                - length $self->{kwd});
7707            
7708            $self->{state} = BOGUS_MD_STATE;
7709            ## Reconsume.
7710            redo A;
7711          }
7712        } elsif ($self->{state} == AFTER_NDATA_STATE) {
7713          if ($is_space->{$self->{nc}}) {
7714            $self->{state} = BEFORE_NOTATION_NAME_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            redo A;
7727          } elsif ($self->{nc} == 0x003E) { # >
7728            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7729            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7730            
7731        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7732          $self->{line_prev} = $self->{line};
7733          $self->{column_prev} = $self->{column};
7734          $self->{column}++;
7735          $self->{nc}
7736              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7737        } else {
7738          $self->{set_nc}->($self);
7739        }
7740      
7741            return  ($self->{ct}); # ENTITY
7742            redo A;
7743          } elsif ($self->{nc} == -1) {
7744            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7745            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7746            
7747        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7748          $self->{line_prev} = $self->{line};
7749          $self->{column_prev} = $self->{column};
7750          $self->{column}++;
7751          $self->{nc}
7752              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7753        } else {
7754          $self->{set_nc}->($self);
7755        }
7756      
7757            return  ($self->{ct}); # ENTITY
7758            redo A;
7759          } else {
7760            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7761                            line => $self->{line_prev},
7762                            column => $self->{column_prev} + 1
7763                                - length $self->{kwd});
7764            $self->{state} = BOGUS_MD_STATE;
7765            ## Reconsume.
7766            redo A;
7767          }
7768        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
7769          if ($is_space->{$self->{nc}}) {
7770            ## Stay in the state.
7771            
7772        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7773          $self->{line_prev} = $self->{line};
7774          $self->{column_prev} = $self->{column};
7775          $self->{column}++;
7776          $self->{nc}
7777              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7778        } else {
7779          $self->{set_nc}->($self);
7780        }
7781      
7782            redo A;
7783          } elsif ($self->{nc} == 0x003E) { # >
7784            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7785            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7786            
7787        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7788          $self->{line_prev} = $self->{line};
7789          $self->{column_prev} = $self->{column};
7790          $self->{column}++;
7791          $self->{nc}
7792              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7793        } else {
7794          $self->{set_nc}->($self);
7795        }
7796      
7797            return  ($self->{ct}); # ENTITY
7798            redo A;
7799          } elsif ($self->{nc} == -1) {
7800            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7801            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7802            
7803        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7804          $self->{line_prev} = $self->{line};
7805          $self->{column_prev} = $self->{column};
7806          $self->{column}++;
7807          $self->{nc}
7808              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7809        } else {
7810          $self->{set_nc}->($self);
7811        }
7812      
7813            return  ($self->{ct}); # ENTITY
7814            redo A;
7815          } else {
7816            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
7817            $self->{state} = NOTATION_NAME_STATE;
7818            
7819        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7820          $self->{line_prev} = $self->{line};
7821          $self->{column_prev} = $self->{column};
7822          $self->{column}++;
7823          $self->{nc}
7824              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7825        } else {
7826          $self->{set_nc}->($self);
7827        }
7828      
7829            redo A;
7830          }
7831        } elsif ($self->{state} == NOTATION_NAME_STATE) {
7832          if ($is_space->{$self->{nc}}) {
7833            $self->{state} = AFTER_MD_DEF_STATE;
7834            
7835        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7836          $self->{line_prev} = $self->{line};
7837          $self->{column_prev} = $self->{column};
7838          $self->{column}++;
7839          $self->{nc}
7840              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7841        } else {
7842          $self->{set_nc}->($self);
7843        }
7844      
7845            redo A;
7846          } elsif ($self->{nc} == 0x003E) { # >
7847            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7848            
7849        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7850          $self->{line_prev} = $self->{line};
7851          $self->{column_prev} = $self->{column};
7852          $self->{column}++;
7853          $self->{nc}
7854              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7855        } else {
7856          $self->{set_nc}->($self);
7857        }
7858      
7859            return  ($self->{ct}); # ENTITY
7860            redo A;
7861          } elsif ($self->{nc} == -1) {
7862            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7863            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7864            
7865        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7866          $self->{line_prev} = $self->{line};
7867          $self->{column_prev} = $self->{column};
7868          $self->{column}++;
7869          $self->{nc}
7870              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7871        } else {
7872          $self->{set_nc}->($self);
7873        }
7874      
7875            return  ($self->{ct}); # ENTITY
7876            redo A;
7877          } else {
7878            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
7879            ## Stay in the state.
7880            
7881        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7882          $self->{line_prev} = $self->{line};
7883          $self->{column_prev} = $self->{column};
7884          $self->{column}++;
7885          $self->{nc}
7886              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7887        } else {
7888          $self->{set_nc}->($self);
7889        }
7890      
7891            redo A;
7892          }
7893        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
7894          if ($self->{nc} == 0x0022) { # "
7895            $self->{state} = AFTER_MD_DEF_STATE;
7896            
7897        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7898          $self->{line_prev} = $self->{line};
7899          $self->{column_prev} = $self->{column};
7900          $self->{column}++;
7901          $self->{nc}
7902              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7903        } else {
7904          $self->{set_nc}->($self);
7905        }
7906      
7907            redo A;
7908          } elsif ($self->{nc} == 0x0026) { # &
7909            $self->{prev_state} = $self->{state};
7910            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7911            $self->{entity_add} = 0x0022; # "
7912            
7913        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7914          $self->{line_prev} = $self->{line};
7915          $self->{column_prev} = $self->{column};
7916          $self->{column}++;
7917          $self->{nc}
7918              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7919        } else {
7920          $self->{set_nc}->($self);
7921        }
7922      
7923            redo A;
7924    ## TODO: %
7925          } elsif ($self->{nc} == -1) {
7926            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7927            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7928            ## Reconsume.
7929            return  ($self->{ct}); # ENTITY
7930            redo A;
7931          } else {
7932            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7933            
7934        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7935          $self->{line_prev} = $self->{line};
7936          $self->{column_prev} = $self->{column};
7937          $self->{column}++;
7938          $self->{nc}
7939              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7940        } else {
7941          $self->{set_nc}->($self);
7942        }
7943      
7944            redo A;
7945          }
7946        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
7947          if ($self->{nc} == 0x0027) { # '
7948            $self->{state} = AFTER_MD_DEF_STATE;
7949            
7950        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7951          $self->{line_prev} = $self->{line};
7952          $self->{column_prev} = $self->{column};
7953          $self->{column}++;
7954          $self->{nc}
7955              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7956        } else {
7957          $self->{set_nc}->($self);
7958        }
7959      
7960            redo A;
7961          } elsif ($self->{nc} == 0x0026) { # &
7962            $self->{prev_state} = $self->{state};
7963            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7964            $self->{entity_add} = 0x0027; # '
7965            
7966        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7967          $self->{line_prev} = $self->{line};
7968          $self->{column_prev} = $self->{column};
7969          $self->{column}++;
7970          $self->{nc}
7971              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7972        } else {
7973          $self->{set_nc}->($self);
7974        }
7975      
7976            redo A;
7977    ## TODO: %
7978          } elsif ($self->{nc} == -1) {
7979            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7980            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7981            ## Reconsume.
7982            return  ($self->{ct}); # ENTITY
7983            redo A;
7984          } else {
7985            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7986            
7987        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7988          $self->{line_prev} = $self->{line};
7989          $self->{column_prev} = $self->{column};
7990          $self->{column}++;
7991          $self->{nc}
7992              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7993        } else {
7994          $self->{set_nc}->($self);
7995        }
7996      
7997            redo A;
7998          }
7999        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
8000          if ($is_space->{$self->{nc}} or
8001              {
8002                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
8003                $self->{entity_add} => 1,
8004              }->{$self->{nc}}) {
8005            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
8006                            line => $self->{line_prev},
8007                            column => $self->{column_prev}
8008                                + ($self->{nc} == -1 ? 1 : 0));
8009            ## Don't consume
8010            ## Return nothing.
8011            #
8012          } elsif ($self->{nc} == 0x0023) { # #
8013            $self->{ca} = $self->{ct};
8014            $self->{state} = ENTITY_HASH_STATE;
8015            $self->{kwd} = '#';
8016            
8017        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8018          $self->{line_prev} = $self->{line};
8019          $self->{column_prev} = $self->{column};
8020          $self->{column}++;
8021          $self->{nc}
8022              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8023        } else {
8024          $self->{set_nc}->($self);
8025        }
8026      
8027            redo A;
8028          } else {
8029            #
8030          }
8031    
8032          $self->{ct}->{value} .= '&';
8033          $self->{state} = $self->{prev_state};
8034          ## Reconsume.
8035          redo A;
8036        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
8037          if ($is_space->{$self->{nc}}) {
8038            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
8039            
8040        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8041          $self->{line_prev} = $self->{line};
8042          $self->{column_prev} = $self->{column};
8043          $self->{column}++;
8044          $self->{nc}
8045              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8046        } else {
8047          $self->{set_nc}->($self);
8048        }
8049      
8050            redo A;
8051          } elsif ($self->{nc} == 0x0028) { # (
8052            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8053            $self->{ct}->{content} = ['('];
8054            $self->{group_depth} = 1;
8055            
8056        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8057          $self->{line_prev} = $self->{line};
8058          $self->{column_prev} = $self->{column};
8059          $self->{column}++;
8060          $self->{nc}
8061              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8062        } else {
8063          $self->{set_nc}->($self);
8064        }
8065      
8066            redo A;
8067          } elsif ($self->{nc} == 0x003E) { # >
8068            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
8069            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8070            
8071        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8072          $self->{line_prev} = $self->{line};
8073          $self->{column_prev} = $self->{column};
8074          $self->{column}++;
8075          $self->{nc}
8076              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8077        } else {
8078          $self->{set_nc}->($self);
8079        }
8080      
8081            return  ($self->{ct}); # ELEMENT
8082            redo A;
8083          } elsif ($self->{nc} == -1) {
8084            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8085            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8086            
8087        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8088          $self->{line_prev} = $self->{line};
8089          $self->{column_prev} = $self->{column};
8090          $self->{column}++;
8091          $self->{nc}
8092              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8093        } else {
8094          $self->{set_nc}->($self);
8095        }
8096      
8097            return  ($self->{ct}); # ELEMENT
8098            redo A;
8099          } else {
8100            $self->{ct}->{content} = [chr $self->{nc}];
8101            $self->{state} = CONTENT_KEYWORD_STATE;
8102            
8103        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8104          $self->{line_prev} = $self->{line};
8105          $self->{column_prev} = $self->{column};
8106          $self->{column}++;
8107          $self->{nc}
8108              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8109        } else {
8110          $self->{set_nc}->($self);
8111        }
8112      
8113            redo A;
8114          }
8115        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
8116          if ($is_space->{$self->{nc}}) {
8117            $self->{state} = AFTER_MD_DEF_STATE;
8118            
8119        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8120          $self->{line_prev} = $self->{line};
8121          $self->{column_prev} = $self->{column};
8122          $self->{column}++;
8123          $self->{nc}
8124              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8125        } else {
8126          $self->{set_nc}->($self);
8127        }
8128      
8129            redo A;
8130          } elsif ($self->{nc} == 0x003E) { # >
8131            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8132            
8133        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8134          $self->{line_prev} = $self->{line};
8135          $self->{column_prev} = $self->{column};
8136          $self->{column}++;
8137          $self->{nc}
8138              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8139        } else {
8140          $self->{set_nc}->($self);
8141        }
8142      
8143            return  ($self->{ct}); # ELEMENT
8144            redo A;
8145          } elsif ($self->{nc} == -1) {
8146            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8147            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8148            
8149        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8150          $self->{line_prev} = $self->{line};
8151          $self->{column_prev} = $self->{column};
8152          $self->{column}++;
8153          $self->{nc}
8154              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8155        } else {
8156          $self->{set_nc}->($self);
8157        }
8158      
8159            return  ($self->{ct}); # ELEMENT
8160            redo A;
8161          } else {
8162            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
8163            ## Stay in the state.
8164            
8165        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8166          $self->{line_prev} = $self->{line};
8167          $self->{column_prev} = $self->{column};
8168          $self->{column}++;
8169          $self->{nc}
8170              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8171        } else {
8172          $self->{set_nc}->($self);
8173        }
8174      
8175            redo A;
8176          }
8177        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
8178          if ($is_space->{$self->{nc}}) {
8179            ## Stay in the state.
8180            
8181        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8182          $self->{line_prev} = $self->{line};
8183          $self->{column_prev} = $self->{column};
8184          $self->{column}++;
8185          $self->{nc}
8186              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8187        } else {
8188          $self->{set_nc}->($self);
8189        }
8190      
8191            redo A;
8192          } elsif ($self->{nc} == 0x0028) { # (
8193            $self->{group_depth}++;
8194            push @{$self->{ct}->{content}}, chr $self->{nc};
8195            ## Stay in the state.
8196            
8197        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8198          $self->{line_prev} = $self->{line};
8199          $self->{column_prev} = $self->{column};
8200          $self->{column}++;
8201          $self->{nc}
8202              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8203        } else {
8204          $self->{set_nc}->($self);
8205        }
8206      
8207            redo A;
8208          } elsif ($self->{nc} == 0x007C or # |
8209                   $self->{nc} == 0x002C) { # ,
8210            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8211            ## Stay in the state.
8212            
8213        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8214          $self->{line_prev} = $self->{line};
8215          $self->{column_prev} = $self->{column};
8216          $self->{column}++;
8217          $self->{nc}
8218              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8219        } else {
8220          $self->{set_nc}->($self);
8221        }
8222      
8223            redo A;
8224          } elsif ($self->{nc} == 0x0029) { # )
8225            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8226            push @{$self->{ct}->{content}}, chr $self->{nc};
8227            $self->{group_depth}--;
8228            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8229            
8230        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8231          $self->{line_prev} = $self->{line};
8232          $self->{column_prev} = $self->{column};
8233          $self->{column}++;
8234          $self->{nc}
8235              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8236        } else {
8237          $self->{set_nc}->($self);
8238        }
8239      
8240            redo A;
8241          } elsif ($self->{nc} == 0x003E) { # >
8242            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8243            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8244            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8245            
8246        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8247          $self->{line_prev} = $self->{line};
8248          $self->{column_prev} = $self->{column};
8249          $self->{column}++;
8250          $self->{nc}
8251              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8252        } else {
8253          $self->{set_nc}->($self);
8254        }
8255      
8256            return  ($self->{ct}); # ELEMENT
8257            redo A;
8258          } elsif ($self->{nc} == -1) {
8259            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8260            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8261            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8262            
8263        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8264          $self->{line_prev} = $self->{line};
8265          $self->{column_prev} = $self->{column};
8266          $self->{column}++;
8267          $self->{nc}
8268              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8269        } else {
8270          $self->{set_nc}->($self);
8271        }
8272      
8273            return  ($self->{ct}); # ELEMENT
8274            redo A;
8275          } else {
8276            push @{$self->{ct}->{content}}, chr $self->{nc};
8277            $self->{state} = CM_ELEMENT_NAME_STATE;
8278            
8279        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8280          $self->{line_prev} = $self->{line};
8281          $self->{column_prev} = $self->{column};
8282          $self->{column}++;
8283          $self->{nc}
8284              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8285        } else {
8286          $self->{set_nc}->($self);
8287        }
8288      
8289            redo A;
8290          }
8291        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
8292          if ($is_space->{$self->{nc}}) {
8293            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8294            
8295        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8296          $self->{line_prev} = $self->{line};
8297          $self->{column_prev} = $self->{column};
8298          $self->{column}++;
8299          $self->{nc}
8300              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8301        } else {
8302          $self->{set_nc}->($self);
8303        }
8304      
8305            redo A;
8306          } elsif ($self->{nc} == 0x002A or # *
8307                   $self->{nc} == 0x002B or # +
8308                   $self->{nc} == 0x003F) { # ?
8309            push @{$self->{ct}->{content}}, chr $self->{nc};
8310            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8311            
8312        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8313          $self->{line_prev} = $self->{line};
8314          $self->{column_prev} = $self->{column};
8315          $self->{column}++;
8316          $self->{nc}
8317              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8318        } else {
8319          $self->{set_nc}->($self);
8320        }
8321      
8322            redo A;
8323          } elsif ($self->{nc} == 0x007C or # |
8324                   $self->{nc} == 0x002C) { # ,
8325            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8326            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8327            
8328        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8329          $self->{line_prev} = $self->{line};
8330          $self->{column_prev} = $self->{column};
8331          $self->{column}++;
8332          $self->{nc}
8333              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8334        } else {
8335          $self->{set_nc}->($self);
8336        }
8337      
8338            redo A;
8339          } elsif ($self->{nc} == 0x0029) { # )
8340            $self->{group_depth}--;
8341            push @{$self->{ct}->{content}}, chr $self->{nc};
8342            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8343            
8344        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8345          $self->{line_prev} = $self->{line};
8346          $self->{column_prev} = $self->{column};
8347          $self->{column}++;
8348          $self->{nc}
8349              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8350        } else {
8351          $self->{set_nc}->($self);
8352        }
8353      
8354            redo A;
8355          } elsif ($self->{nc} == 0x003E) { # >
8356            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8357            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8358            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8359            
8360        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8361          $self->{line_prev} = $self->{line};
8362          $self->{column_prev} = $self->{column};
8363          $self->{column}++;
8364          $self->{nc}
8365              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8366        } else {
8367          $self->{set_nc}->($self);
8368        }
8369      
8370            return  ($self->{ct}); # ELEMENT
8371            redo A;
8372          } elsif ($self->{nc} == -1) {
8373            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8374            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8375            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8376            
8377        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8378          $self->{line_prev} = $self->{line};
8379          $self->{column_prev} = $self->{column};
8380          $self->{column}++;
8381          $self->{nc}
8382              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8383        } else {
8384          $self->{set_nc}->($self);
8385        }
8386      
8387            return  ($self->{ct}); # ELEMENT
8388            redo A;
8389          } else {
8390            $self->{ct}->{content}->[-1] .= chr $self->{nc};
8391            ## Stay in the state.
8392            
8393        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8394          $self->{line_prev} = $self->{line};
8395          $self->{column_prev} = $self->{column};
8396          $self->{column}++;
8397          $self->{nc}
8398              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8399        } else {
8400          $self->{set_nc}->($self);
8401        }
8402      
8403            redo A;
8404          }
8405        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
8406          if ($is_space->{$self->{nc}}) {
8407            ## Stay in the state.
8408            
8409        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8410          $self->{line_prev} = $self->{line};
8411          $self->{column_prev} = $self->{column};
8412          $self->{column}++;
8413          $self->{nc}
8414              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8415        } else {
8416          $self->{set_nc}->($self);
8417        }
8418      
8419            redo A;
8420          } elsif ($self->{nc} == 0x007C or # |
8421                   $self->{nc} == 0x002C) { # ,
8422            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8423            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8424            
8425        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8426          $self->{line_prev} = $self->{line};
8427          $self->{column_prev} = $self->{column};
8428          $self->{column}++;
8429          $self->{nc}
8430              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8431        } else {
8432          $self->{set_nc}->($self);
8433        }
8434      
8435            redo A;
8436          } elsif ($self->{nc} == 0x0029) { # )
8437            $self->{group_depth}--;
8438            push @{$self->{ct}->{content}}, chr $self->{nc};
8439            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8440            
8441        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8442          $self->{line_prev} = $self->{line};
8443          $self->{column_prev} = $self->{column};
8444          $self->{column}++;
8445          $self->{nc}
8446              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8447        } else {
8448          $self->{set_nc}->($self);
8449        }
8450      
8451            redo A;
8452          } elsif ($self->{nc} == 0x003E) { # >
8453            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8454            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8455            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8456            
8457        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8458          $self->{line_prev} = $self->{line};
8459          $self->{column_prev} = $self->{column};
8460          $self->{column}++;
8461          $self->{nc}
8462              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8463        } else {
8464          $self->{set_nc}->($self);
8465        }
8466      
8467            return  ($self->{ct}); # ELEMENT
8468            redo A;
8469          } elsif ($self->{nc} == -1) {
8470            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8471            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8472            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8473            
8474        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8475          $self->{line_prev} = $self->{line};
8476          $self->{column_prev} = $self->{column};
8477          $self->{column}++;
8478          $self->{nc}
8479              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8480        } else {
8481          $self->{set_nc}->($self);
8482        }
8483      
8484            return  ($self->{ct}); # ELEMENT
8485            redo A;
8486          } else {
8487            $self->{parse_error}->(level => $self->{level}->{must}, type => 'after element name'); ## TODO: type
8488            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8489            $self->{state} = BOGUS_MD_STATE;
8490            
8491        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8492          $self->{line_prev} = $self->{line};
8493          $self->{column_prev} = $self->{column};
8494          $self->{column}++;
8495          $self->{nc}
8496              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8497        } else {
8498          $self->{set_nc}->($self);
8499        }
8500      
8501            redo A;
8502          }
8503        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
8504          if ($is_space->{$self->{nc}}) {
8505            if ($self->{group_depth}) {
8506              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8507            } else {
8508              $self->{state} = AFTER_MD_DEF_STATE;
8509            }
8510            
8511        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8512          $self->{line_prev} = $self->{line};
8513          $self->{column_prev} = $self->{column};
8514          $self->{column}++;
8515          $self->{nc}
8516              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8517        } else {
8518          $self->{set_nc}->($self);
8519        }
8520      
8521            redo A;
8522          } elsif ($self->{nc} == 0x002A or # *
8523                   $self->{nc} == 0x002B or # +
8524                   $self->{nc} == 0x003F) { # ?
8525            push @{$self->{ct}->{content}}, chr $self->{nc};
8526            if ($self->{group_depth}) {
8527              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8528            } else {
8529              $self->{state} = AFTER_MD_DEF_STATE;
8530            }
8531            
8532        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8533          $self->{line_prev} = $self->{line};
8534          $self->{column_prev} = $self->{column};
8535          $self->{column}++;
8536          $self->{nc}
8537              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8538        } else {
8539          $self->{set_nc}->($self);
8540        }
8541      
8542            redo A;
8543          } elsif ($self->{nc} == 0x0029) { # )
8544            if ($self->{group_depth}) {
8545              $self->{group_depth}--;
8546              push @{$self->{ct}->{content}}, chr $self->{nc};
8547              ## Stay in the state.
8548              
8549        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8550          $self->{line_prev} = $self->{line};
8551          $self->{column_prev} = $self->{column};
8552          $self->{column}++;
8553          $self->{nc}
8554              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8555        } else {
8556          $self->{set_nc}->($self);
8557        }
8558      
8559              redo A;
8560            } else {
8561              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8562              $self->{state} = BOGUS_MD_STATE;
8563              ## Reconsume.
8564              redo A;
8565            }
8566          } elsif ($self->{nc} == 0x003E) { # >
8567            if ($self->{group_depth}) {
8568              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8569              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8570            }
8571            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8572            
8573        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8574          $self->{line_prev} = $self->{line};
8575          $self->{column_prev} = $self->{column};
8576          $self->{column}++;
8577          $self->{nc}
8578              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8579        } else {
8580          $self->{set_nc}->($self);
8581        }
8582      
8583            return  ($self->{ct}); # ELEMENT
8584            redo A;
8585          } elsif ($self->{nc} == -1) {
8586            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8587            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8588            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8589            
8590        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8591          $self->{line_prev} = $self->{line};
8592          $self->{column_prev} = $self->{column};
8593          $self->{column}++;
8594          $self->{nc}
8595              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8596        } else {
8597          $self->{set_nc}->($self);
8598        }
8599      
8600            return  ($self->{ct}); # ELEMENT
8601            redo A;
8602          } else {
8603            if ($self->{group_depth}) {
8604              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8605            } else {
8606              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8607              $self->{state} = BOGUS_MD_STATE;
8608            }
8609            ## Reconsume.
8610            redo A;
8611          }
8612        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
8613          if ($is_space->{$self->{nc}}) {
8614            ## Stay in the state.
8615            
8616        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8617          $self->{line_prev} = $self->{line};
8618          $self->{column_prev} = $self->{column};
8619          $self->{column}++;
8620          $self->{nc}
8621              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8622        } else {
8623          $self->{set_nc}->($self);
8624        }
8625      
8626            redo A;
8627          } elsif ($self->{nc} == 0x003E) { # >
8628            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8629            
8630        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8631          $self->{line_prev} = $self->{line};
8632          $self->{column_prev} = $self->{column};
8633          $self->{column}++;
8634          $self->{nc}
8635              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8636        } else {
8637          $self->{set_nc}->($self);
8638        }
8639      
8640            return  ($self->{ct}); # ENTITY/ELEMENT
8641            redo A;
8642          } elsif ($self->{nc} == -1) {
8643            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8644            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8645            
8646        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8647          $self->{line_prev} = $self->{line};
8648          $self->{column_prev} = $self->{column};
8649          $self->{column}++;
8650          $self->{nc}
8651              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8652        } else {
8653          $self->{set_nc}->($self);
8654        }
8655      
8656            return  ($self->{ct}); # ENTITY/ELEMENT
8657            redo A;
8658          } else {
8659            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8660            $self->{state} = BOGUS_MD_STATE;
8661            ## Reconsume.
8662            redo A;
8663          }
8664        } elsif ($self->{state} == BOGUS_MD_STATE) {
8665          if ($self->{nc} == 0x003E) { # >
8666            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8667            
8668        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8669          $self->{line_prev} = $self->{line};
8670          $self->{column_prev} = $self->{column};
8671          $self->{column}++;
8672          $self->{nc}
8673              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8674        } else {
8675          $self->{set_nc}->($self);
8676        }
8677      
8678            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8679            redo A;
8680          } elsif ($self->{nc} == -1) {
8681            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8682            ## Reconsume.
8683            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8684            redo A;
8685          } else {
8686            ## Stay in the state.
8687            
8688        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8689          $self->{line_prev} = $self->{line};
8690          $self->{column_prev} = $self->{column};
8691          $self->{column}++;
8692          $self->{nc}
8693              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8694        } else {
8695          $self->{set_nc}->($self);
8696        }
8697      
8698            redo A;
8699          }
8700      } else {      } else {
8701        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
8702      }      }

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24