/[suikacvs]/markup/html/whatpm/Whatpm/HTML.pm.src
Suika

Diff of /markup/html/whatpm/Whatpm/HTML.pm.src

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.167 by wakaba, Sat Sep 13 09:02:28 2008 UTC revision 1.173 by wakaba, Sun Sep 14 03:59:08 2008 UTC
# Line 618  sub parse_byte_stream ($$$$;$$) { Line 618  sub parse_byte_stream ($$$$;$$) {
618  sub parse_char_string ($$$;$$) {  sub parse_char_string ($$$;$$) {
619    #my ($self, $s, $doc, $onerror, $get_wrapper) = @_;    #my ($self, $s, $doc, $onerror, $get_wrapper) = @_;
620    my $self = shift;    my $self = shift;
   require utf8;  
621    my $s = ref $_[0] ? $_[0] : \($_[0]);    my $s = ref $_[0] ? $_[0] : \($_[0]);
622    open my $input, '<' . (utf8::is_utf8 ($$s) ? ':utf8' : ''), $s;    require Whatpm::Charset::DecodeHandle;
623      my $input = Whatpm::Charset::DecodeHandle::CharString->new ($s);
624    if ($_[3]) {    if ($_[3]) {
625      $input = $_[3]->($input);      $input = $_[3]->($input);
626    }    }
# Line 669  sub parse_char_stream ($$$;$) { Line 669  sub parse_char_stream ($$$;$) {
669        $self->{column} = 0;        $self->{column} = 0;
670      } elsif ($self->{next_char} == 0x000D) { # CR      } elsif ($self->{next_char} == 0x000D) { # CR
671        !!!cp ('j2');        !!!cp ('j2');
672    ## TODO: support for abort/streaming
673        my $next = $input->getc;        my $next = $input->getc;
674        if (defined $next and $next ne "\x0A") {        if (defined $next and $next ne "\x0A") {
675          $self->{next_next_char} = $next;          $self->{next_next_char} = $next;
# Line 688  sub parse_char_stream ($$$;$) { Line 689  sub parse_char_stream ($$$;$) {
689               (0x007F <= $self->{next_char} and $self->{next_char} <= 0x009F) or               (0x007F <= $self->{next_char} and $self->{next_char} <= 0x009F) or
690               (0xD800 <= $self->{next_char} and $self->{next_char} <= 0xDFFF) or               (0xD800 <= $self->{next_char} and $self->{next_char} <= 0xDFFF) or
691               (0xFDD0 <= $self->{next_char} and $self->{next_char} <= 0xFDDF) or               (0xFDD0 <= $self->{next_char} and $self->{next_char} <= 0xFDDF) or
692    ## ISSUE: U+FDE0-U+FDEF are not excluded
693               {               {
694                0xFFFE => 1, 0xFFFF => 1, 0x1FFFE => 1, 0x1FFFF => 1,                0xFFFE => 1, 0xFFFF => 1, 0x1FFFE => 1, 0x1FFFF => 1,
695                0x2FFFE => 1, 0x2FFFF => 1, 0x3FFFE => 1, 0x3FFFF => 1,                0x2FFFE => 1, 0x2FFFF => 1, 0x3FFFE => 1, 0x3FFFF => 1,
# Line 712  sub parse_char_stream ($$$;$) { Line 714  sub parse_char_stream ($$$;$) {
714    $self->{prev_char} = [-1, -1, -1];    $self->{prev_char} = [-1, -1, -1];
715    $self->{next_char} = -1;    $self->{next_char} = -1;
716    
717      $self->{read_until} = sub {
718        #my ($scalar, $specials_range, $offset) = @_;
719        my $specials_range = $_[1];
720        return 0 if defined $self->{next_next_char};
721        my $count = $input->manakai_read_until
722           ($_[0],
723            qr/(?![$specials_range\x{FDD0}-\x{FDDF}\x{FFFE}\x{FFFF}\x{1FFFE}\x{1FFFF}\x{2FFFE}\x{2FFFF}\x{3FFFE}\x{3FFFF}\x{4FFFE}\x{4FFFF}\x{5FFFE}\x{5FFFF}\x{6FFFE}\x{6FFFF}\x{7FFFE}\x{7FFFF}\x{8FFFE}\x{8FFFF}\x{9FFFE}\x{9FFFF}\x{AFFFE}\x{AFFFF}\x{BFFFE}\x{BFFFF}\x{CFFFE}\x{CFFFF}\x{DFFFE}\x{DFFFF}\x{EFFFE}\x{EFFFF}\x{FFFFE}\x{FFFFF}])[\x20-\x7E\xA0-\x{D7FF}\x{E000}-\x{10FFFD}]/,
724            $_[2]);
725        if ($count) {
726          $self->{column} += $count;
727          $self->{column_prev} += $count;
728          $self->{prev_char} = [-1, -1, -1];
729          $self->{next_char} = -1;
730        }
731        return $count;
732      }; # $self->{read_until}
733    
734    my $onerror = $_[2] || sub {    my $onerror = $_[2] || sub {
735      my (%opt) = @_;      my (%opt) = @_;
736      my $line = $opt{token} ? $opt{token}->{line} : $opt{line};      my $line = $opt{token} ? $opt{token}->{line} : $opt{line};
# Line 769  sub RCDATA_CONTENT_MODEL () { CM_ENTITY Line 788  sub RCDATA_CONTENT_MODEL () { CM_ENTITY
788  sub PCDATA_CONTENT_MODEL () { CM_ENTITY | CM_FULL_MARKUP }  sub PCDATA_CONTENT_MODEL () { CM_ENTITY | CM_FULL_MARKUP }
789    
790  sub DATA_STATE () { 0 }  sub DATA_STATE () { 0 }
791  sub ENTITY_DATA_STATE () { 1 }  #sub ENTITY_DATA_STATE () { 1 }
792  sub TAG_OPEN_STATE () { 2 }  sub TAG_OPEN_STATE () { 2 }
793  sub CLOSE_TAG_OPEN_STATE () { 3 }  sub CLOSE_TAG_OPEN_STATE () { 3 }
794  sub TAG_NAME_STATE () { 4 }  sub TAG_NAME_STATE () { 4 }
# Line 780  sub BEFORE_ATTRIBUTE_VALUE_STATE () { 8 Line 799  sub BEFORE_ATTRIBUTE_VALUE_STATE () { 8
799  sub ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE () { 9 }  sub ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE () { 9 }
800  sub ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE () { 10 }  sub ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE () { 10 }
801  sub ATTRIBUTE_VALUE_UNQUOTED_STATE () { 11 }  sub ATTRIBUTE_VALUE_UNQUOTED_STATE () { 11 }
802  sub ENTITY_IN_ATTRIBUTE_VALUE_STATE () { 12 }  #sub ENTITY_IN_ATTRIBUTE_VALUE_STATE () { 12 }
803  sub MARKUP_DECLARATION_OPEN_STATE () { 13 }  sub MARKUP_DECLARATION_OPEN_STATE () { 13 }
804  sub COMMENT_START_STATE () { 14 }  sub COMMENT_START_STATE () { 14 }
805  sub COMMENT_START_DASH_STATE () { 15 }  sub COMMENT_START_DASH_STATE () { 15 }
# Line 812  sub CDATA_SECTION_MSE1_STATE () { 40 } # Line 831  sub CDATA_SECTION_MSE1_STATE () { 40 } #
831  sub CDATA_SECTION_MSE2_STATE () { 41 } # "CDATA section state" in the spec  sub CDATA_SECTION_MSE2_STATE () { 41 } # "CDATA section state" in the spec
832  sub PUBLIC_STATE () { 42 } # "after DOCTYPE name state" in the spec  sub PUBLIC_STATE () { 42 } # "after DOCTYPE name state" in the spec
833  sub SYSTEM_STATE () { 43 } # "after DOCTYPE name state" in the spec  sub SYSTEM_STATE () { 43 } # "after DOCTYPE name state" in the spec
834  sub ENTITY_STATE () { 44 } # "consume a character reference" in the spec  ## NOTE: "Entity data state", "entity in attribute value state", and
835    ## "consume a character reference" algorithm are jointly implemented
836    ## using the following six states:
837    sub ENTITY_STATE () { 44 }
838    sub ENTITY_HASH_STATE () { 45 }
839    sub NCR_NUM_STATE () { 46 }
840    sub HEXREF_X_STATE () { 47 }
841    sub HEXREF_HEX_STATE () { 48 }
842    sub ENTITY_NAME_STATE () { 49 }
843    
844  sub DOCTYPE_TOKEN () { 1 }  sub DOCTYPE_TOKEN () { 1 }
845  sub COMMENT_TOKEN () { 2 }  sub COMMENT_TOKEN () { 2 }
# Line 866  sub _initialize_tokenizer ($) { Line 893  sub _initialize_tokenizer ($) {
893    my $self = shift;    my $self = shift;
894    $self->{state} = DATA_STATE; # MUST    $self->{state} = DATA_STATE; # MUST
895    #$self->{state_keyword}; # initialized when used    #$self->{state_keyword}; # initialized when used
896      #$self->{entity__value}; # initialized when used
897      #$self->{entity__match}; # initialized when used
898    $self->{content_model} = PCDATA_CONTENT_MODEL; # be    $self->{content_model} = PCDATA_CONTENT_MODEL; # be
899    undef $self->{current_token};    undef $self->{current_token};
900    undef $self->{current_attribute};    undef $self->{current_attribute};
901    undef $self->{last_emitted_start_tag_name};    undef $self->{last_emitted_start_tag_name};
902    undef $self->{last_attribute_value_state};    #$self->{prev_state}; # initialized when used
903    delete $self->{self_closing};    delete $self->{self_closing};
   $self->{char} = [];  
904    # $self->{next_char}    # $self->{next_char}
905    !!!next-input-character;    !!!next-input-character;
906    $self->{token} = [];    $self->{token} = [];
# Line 904  sub _initialize_tokenizer ($) { Line 932  sub _initialize_tokenizer ($) {
932  ## has completed loading.  If one has, then it MUST be executed  ## has completed loading.  If one has, then it MUST be executed
933  ## and removed from the list.  ## and removed from the list.
934    
935  ## NOTE: HTML5 "Writing HTML documents" section, applied to  ## TODO: Polytheistic slash SHOULD NOT be used. (Applied only to atheists.)
936  ## documents and not to user agents and conformance checkers,  ## (This requirement was dropped from HTML5 spec, unfortunately.)
 ## contains some requirements that are not detected by the  
 ## parsing algorithm:  
 ## - Some requirements on character encoding declarations. ## TODO  
 ## - "Elements MUST NOT contain content that their content model disallows."  
 ##   ... Some are parse error, some are not (will be reported by c.c.).  
 ## - Polytheistic slash SHOULD NOT be used. (Applied only to atheists.) ## TODO  
 ## - Text (in elements, attributes, and comments) SHOULD NOT contain  
 ##   control characters other than space characters. ## TODO: (what is control character? C0, C1 and DEL?  Unicode control character?)  
   
 ## TODO: HTML5 poses authors two SHOULD-level requirements that cannot  
 ## be detected by the HTML5 parsing algorithm:  
 ## - Text,  
937    
938  sub _get_next_token ($) {  sub _get_next_token ($) {
939    my $self = shift;    my $self = shift;
# Line 945  sub _get_next_token ($) { Line 961  sub _get_next_token ($) {
961            ## "entity data state".  In this implementation, the tokenizer            ## "entity data state".  In this implementation, the tokenizer
962            ## is switched to the |ENTITY_STATE|, which is an implementation            ## is switched to the |ENTITY_STATE|, which is an implementation
963            ## of the "consume a character reference" algorithm.            ## of the "consume a character reference" algorithm.
           #$self->{state} = ENTITY_DATA_STATE;  
           $self->{entity_in_attr} = 0;  
964            $self->{entity_additional} = -1;            $self->{entity_additional} = -1;
965              $self->{prev_state} = DATA_STATE;
966            $self->{state} = ENTITY_STATE;            $self->{state} = ENTITY_STATE;
967            !!!next-input-character;            !!!next-input-character;
968            redo A;            redo A;
# Line 1012  sub _get_next_token ($) { Line 1027  sub _get_next_token ($) {
1027                     data => chr $self->{next_char},                     data => chr $self->{next_char},
1028                     line => $self->{line}, column => $self->{column},                     line => $self->{line}, column => $self->{column},
1029                    };                    };
1030          $self->{read_until}->($token->{data}, q[-!<>&], length $token->{data});
1031    
1032        ## Stay in the data state        ## Stay in the data state
1033        !!!next-input-character;        !!!next-input-character;
1034    
1035        !!!emit ($token);        !!!emit ($token);
1036    
1037        redo A;        redo A;
     } elsif ($self->{state} == ENTITY_DATA_STATE) {  
       my ($l, $c) = ($self->{line_prev}, $self->{column_prev});  
   
       my $token = $self->{entity_return};  
   
       $self->{state} = DATA_STATE;  
       # next-input-character is already done  
   
       unless (defined $token) {  
         !!!cp (13);  
         !!!emit ({type => CHARACTER_TOKEN, data => '&',  
                   line => $l, column => $c,  
                  });  
       } else {  
         !!!cp (14);  
         !!!emit ($token);  
       }  
   
       redo A;  
1038      } elsif ($self->{state} == TAG_OPEN_STATE) {      } elsif ($self->{state} == TAG_OPEN_STATE) {
1039        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA
1040          if ($self->{next_char} == 0x002F) { # /          if ($self->{next_char} == 0x002F) { # /
# Line 1710  sub _get_next_token ($) { Line 1708  sub _get_next_token ($) {
1708          redo A;          redo A;
1709        } elsif ($self->{next_char} == 0x0026) { # &        } elsif ($self->{next_char} == 0x0026) { # &
1710          !!!cp (96);          !!!cp (96);
         $self->{last_attribute_value_state} = $self->{state};  
1711          ## NOTE: In the spec, the tokenizer is switched to the          ## NOTE: In the spec, the tokenizer is switched to the
1712          ## "entity in attribute value state".  In this implementation, the          ## "entity in attribute value state".  In this implementation, the
1713          ## tokenizer is switched to the |ENTITY_STATE|, which is an          ## tokenizer is switched to the |ENTITY_STATE|, which is an
1714          ## implementation of the "consume a character reference" algorithm.          ## implementation of the "consume a character reference" algorithm.
1715          #$self->{state} = ENTITY_IN_ATTRIBUTE_VALUE_STATE;          $self->{prev_state} = $self->{state};
         $self->{entity_in_attr} = 1;  
1716          $self->{entity_additional} = 0x0022; # "          $self->{entity_additional} = 0x0022; # "
1717          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1718          !!!next-input-character;          !!!next-input-character;
# Line 1747  sub _get_next_token ($) { Line 1743  sub _get_next_token ($) {
1743        } else {        } else {
1744          !!!cp (100);          !!!cp (100);
1745          $self->{current_attribute}->{value} .= chr ($self->{next_char});          $self->{current_attribute}->{value} .= chr ($self->{next_char});
1746            $self->{read_until}->($self->{current_attribute}->{value},
1747                                  q["&],
1748                                  length $self->{current_attribute}->{value});
1749    
1750          ## Stay in the state          ## Stay in the state
1751          !!!next-input-character;          !!!next-input-character;
1752          redo A;          redo A;
# Line 1759  sub _get_next_token ($) { Line 1759  sub _get_next_token ($) {
1759          redo A;          redo A;
1760        } elsif ($self->{next_char} == 0x0026) { # &        } elsif ($self->{next_char} == 0x0026) { # &
1761          !!!cp (102);          !!!cp (102);
         $self->{last_attribute_value_state} = $self->{state};  
1762          ## NOTE: In the spec, the tokenizer is switched to the          ## NOTE: In the spec, the tokenizer is switched to the
1763          ## "entity in attribute value state".  In this implementation, the          ## "entity in attribute value state".  In this implementation, the
1764          ## tokenizer is switched to the |ENTITY_STATE|, which is an          ## tokenizer is switched to the |ENTITY_STATE|, which is an
1765          ## implementation of the "consume a character reference" algorithm.          ## implementation of the "consume a character reference" algorithm.
         #$self->{state} = ENTITY_IN_ATTRIBUTE_VALUE_STATE;  
         $self->{entity_in_attr} = 1;  
1766          $self->{entity_additional} = 0x0027; # '          $self->{entity_additional} = 0x0027; # '
1767            $self->{prev_state} = $self->{state};
1768          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1769          !!!next-input-character;          !!!next-input-character;
1770          redo A;          redo A;
# Line 1796  sub _get_next_token ($) { Line 1794  sub _get_next_token ($) {
1794        } else {        } else {
1795          !!!cp (106);          !!!cp (106);
1796          $self->{current_attribute}->{value} .= chr ($self->{next_char});          $self->{current_attribute}->{value} .= chr ($self->{next_char});
1797            $self->{read_until}->($self->{current_attribute}->{value},
1798                                  q['&],
1799                                  length $self->{current_attribute}->{value});
1800    
1801          ## Stay in the state          ## Stay in the state
1802          !!!next-input-character;          !!!next-input-character;
1803          redo A;          redo A;
# Line 1812  sub _get_next_token ($) { Line 1814  sub _get_next_token ($) {
1814          redo A;          redo A;
1815        } elsif ($self->{next_char} == 0x0026) { # &        } elsif ($self->{next_char} == 0x0026) { # &
1816          !!!cp (108);          !!!cp (108);
         $self->{last_attribute_value_state} = $self->{state};  
1817          ## NOTE: In the spec, the tokenizer is switched to the          ## NOTE: In the spec, the tokenizer is switched to the
1818          ## "entity in attribute value state".  In this implementation, the          ## "entity in attribute value state".  In this implementation, the
1819          ## tokenizer is switched to the |ENTITY_STATE|, which is an          ## tokenizer is switched to the |ENTITY_STATE|, which is an
1820          ## implementation of the "consume a character reference" algorithm.          ## implementation of the "consume a character reference" algorithm.
         #$self->{state} = ENTITY_IN_ATTRIBUTE_VALUE_STATE;  
         $self->{entity_in_attr} = 1;  
1821          $self->{entity_additional} = -1;          $self->{entity_additional} = -1;
1822            $self->{prev_state} = $self->{state};
1823          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1824          !!!next-input-character;          !!!next-input-character;
1825          redo A;          redo A;
# Line 1880  sub _get_next_token ($) { Line 1880  sub _get_next_token ($) {
1880            !!!cp (116);            !!!cp (116);
1881          }          }
1882          $self->{current_attribute}->{value} .= chr ($self->{next_char});          $self->{current_attribute}->{value} .= chr ($self->{next_char});
1883            $self->{read_until}->($self->{current_attribute}->{value},
1884                                  q["'=& >],
1885                                  length $self->{current_attribute}->{value});
1886    
1887          ## Stay in the state          ## Stay in the state
1888          !!!next-input-character;          !!!next-input-character;
1889          redo A;          redo A;
1890        }        }
     } elsif ($self->{state} == ENTITY_IN_ATTRIBUTE_VALUE_STATE) {  
       my $token = $self->{entity_return};  
   
       unless (defined $token) {  
         !!!cp (117);  
         $self->{current_attribute}->{value} .= '&';  
       } else {  
         !!!cp (118);  
         $self->{current_attribute}->{value} .= $token->{data};  
         $self->{current_attribute}->{has_reference} = $token->{has_reference};  
         ## ISSUE: spec says "append the returned character token to the current attribute's value"  
       }  
   
       $self->{state} = $self->{last_attribute_value_state};  
       # next-input-character is already done  
       redo A;  
1891      } elsif ($self->{state} == AFTER_ATTRIBUTE_VALUE_QUOTED_STATE) {      } elsif ($self->{state} == AFTER_ATTRIBUTE_VALUE_QUOTED_STATE) {
1892        if ($self->{next_char} == 0x0009 or # HT        if ($self->{next_char} == 0x0009 or # HT
1893            $self->{next_char} == 0x000A or # LF            $self->{next_char} == 0x000A or # LF
# Line 2040  sub _get_next_token ($) { Line 2028  sub _get_next_token ($) {
2028        } else {        } else {
2029          !!!cp (126);          !!!cp (126);
2030          $self->{current_token}->{data} .= chr ($self->{next_char}); # comment          $self->{current_token}->{data} .= chr ($self->{next_char}); # comment
2031            $self->{read_until}->($self->{current_token}->{data},
2032                                  q[>],
2033                                  length $self->{current_token}->{data});
2034    
2035          ## Stay in the state.          ## Stay in the state.
2036          !!!next-input-character;          !!!next-input-character;
2037          redo A;          redo A;
# Line 2274  sub _get_next_token ($) { Line 2266  sub _get_next_token ($) {
2266        } else {        } else {
2267          !!!cp (147);          !!!cp (147);
2268          $self->{current_token}->{data} .= chr ($self->{next_char}); # comment          $self->{current_token}->{data} .= chr ($self->{next_char}); # comment
2269            $self->{read_until}->($self->{current_token}->{data},
2270                                  q[-],
2271                                  length $self->{current_token}->{data});
2272    
2273          ## Stay in the state          ## Stay in the state
2274          !!!next-input-character;          !!!next-input-character;
2275          redo A;          redo A;
# Line 2639  sub _get_next_token ($) { Line 2635  sub _get_next_token ($) {
2635          !!!cp (190);          !!!cp (190);
2636          $self->{current_token}->{public_identifier} # DOCTYPE          $self->{current_token}->{public_identifier} # DOCTYPE
2637              .= chr $self->{next_char};              .= chr $self->{next_char};
2638            $self->{read_until}->($self->{current_token}->{public_identifier},
2639                                  q[">],
2640                                  length $self->{current_token}->{public_identifier});
2641    
2642          ## Stay in the state          ## Stay in the state
2643          !!!next-input-character;          !!!next-input-character;
2644          redo A;          redo A;
# Line 2675  sub _get_next_token ($) { Line 2675  sub _get_next_token ($) {
2675          !!!cp (194);          !!!cp (194);
2676          $self->{current_token}->{public_identifier} # DOCTYPE          $self->{current_token}->{public_identifier} # DOCTYPE
2677              .= chr $self->{next_char};              .= chr $self->{next_char};
2678            $self->{read_until}->($self->{current_token}->{public_identifier},
2679                                  q['>],
2680                                  length $self->{current_token}->{public_identifier});
2681    
2682          ## Stay in the state          ## Stay in the state
2683          !!!next-input-character;          !!!next-input-character;
2684          redo A;          redo A;
# Line 2811  sub _get_next_token ($) { Line 2815  sub _get_next_token ($) {
2815          !!!cp (210);          !!!cp (210);
2816          $self->{current_token}->{system_identifier} # DOCTYPE          $self->{current_token}->{system_identifier} # DOCTYPE
2817              .= chr $self->{next_char};              .= chr $self->{next_char};
2818            $self->{read_until}->($self->{current_token}->{system_identifier},
2819                                  q[">],
2820                                  length $self->{current_token}->{system_identifier});
2821    
2822          ## Stay in the state          ## Stay in the state
2823          !!!next-input-character;          !!!next-input-character;
2824          redo A;          redo A;
# Line 2847  sub _get_next_token ($) { Line 2855  sub _get_next_token ($) {
2855          !!!cp (214);          !!!cp (214);
2856          $self->{current_token}->{system_identifier} # DOCTYPE          $self->{current_token}->{system_identifier} # DOCTYPE
2857              .= chr $self->{next_char};              .= chr $self->{next_char};
2858            $self->{read_until}->($self->{current_token}->{system_identifier},
2859                                  q['>],
2860                                  length $self->{current_token}->{system_identifier});
2861    
2862          ## Stay in the state          ## Stay in the state
2863          !!!next-input-character;          !!!next-input-character;
2864          redo A;          redo A;
# Line 2907  sub _get_next_token ($) { Line 2919  sub _get_next_token ($) {
2919          redo A;          redo A;
2920        } else {        } else {
2921          !!!cp (221);          !!!cp (221);
2922            my $s = '';
2923            $self->{read_until}->($s, q[>], 0);
2924    
2925          ## Stay in the state          ## Stay in the state
2926          !!!next-input-character;          !!!next-input-character;
2927          redo A;          redo A;
# Line 2935  sub _get_next_token ($) { Line 2950  sub _get_next_token ($) {
2950        } else {        } else {
2951          !!!cp (221.4);          !!!cp (221.4);
2952          $self->{current_token}->{data} .= chr $self->{next_char};          $self->{current_token}->{data} .= chr $self->{next_char};
2953            $self->{read_until}->($self->{current_token}->{data},
2954                                  q<]>,
2955                                  length $self->{current_token}->{data});
2956    
2957          ## Stay in the state.          ## Stay in the state.
2958          !!!next-input-character;          !!!next-input-character;
2959          redo A;          redo A;
# Line 2979  sub _get_next_token ($) { Line 2998  sub _get_next_token ($) {
2998          ## Reconsume.          ## Reconsume.
2999          redo A;          redo A;
3000        }        }
   
3001      } elsif ($self->{state} == ENTITY_STATE) {      } elsif ($self->{state} == ENTITY_STATE) {
3002        my $in_attr = $self->{entity_in_attr};        if ({
3003        my $additional = $self->{entity_additional};          0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, # HT, LF, VT, FF,
3004            0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, &
3005            $self->{entity_additional} => 1,
3006          }->{$self->{next_char}}) {
3007            !!!cp (1001);
3008            ## Don't consume
3009            ## No error
3010            ## Return nothing.
3011            #
3012          } elsif ($self->{next_char} == 0x0023) { # #
3013            !!!cp (999);
3014            $self->{state} = ENTITY_HASH_STATE;
3015            $self->{state_keyword} = '#';
3016            !!!next-input-character;
3017            redo A;
3018          } elsif ((0x0041 <= $self->{next_char} and
3019                    $self->{next_char} <= 0x005A) or # A..Z
3020                   (0x0061 <= $self->{next_char} and
3021                    $self->{next_char} <= 0x007A)) { # a..z
3022            !!!cp (998);
3023            require Whatpm::_NamedEntityList;
3024            $self->{state} = ENTITY_NAME_STATE;
3025            $self->{state_keyword} = chr $self->{next_char};
3026            $self->{entity__value} = $self->{state_keyword};
3027            $self->{entity__match} = 0;
3028            !!!next-input-character;
3029            redo A;
3030          } else {
3031            !!!cp (1027);
3032            !!!parse-error (type => 'bare ero');
3033            ## Return nothing.
3034            #
3035          }
3036    
3037    my ($l, $c) = ($self->{line_prev}, $self->{column_prev});        ## NOTE: No character is consumed by the "consume a character
3038          ## reference" algorithm.  In other word, there is an "&" character
3039          ## that does not introduce a character reference, which would be
3040          ## appended to the parent element or the attribute value in later
3041          ## process of the tokenizer.
3042    
3043          if ($self->{prev_state} == DATA_STATE) {
3044            !!!cp (997);
3045            $self->{state} = $self->{prev_state};
3046            ## Reconsume.
3047            !!!emit ({type => CHARACTER_TOKEN, data => '&',
3048                      line => $self->{line_prev},
3049                      column => $self->{column_prev},
3050                     });
3051            redo A;
3052          } else {
3053            !!!cp (996);
3054            $self->{current_attribute}->{value} .= '&';
3055            $self->{state} = $self->{prev_state};
3056            ## Reconsume.
3057            redo A;
3058          }
3059        } elsif ($self->{state} == ENTITY_HASH_STATE) {
3060          if ($self->{next_char} == 0x0078 or # x
3061              $self->{next_char} == 0x0058) { # X
3062            !!!cp (995);
3063            $self->{state} = HEXREF_X_STATE;
3064            $self->{state_keyword} .= chr $self->{next_char};
3065            !!!next-input-character;
3066            redo A;
3067          } elsif (0x0030 <= $self->{next_char} and
3068                   $self->{next_char} <= 0x0039) { # 0..9
3069            !!!cp (994);
3070            $self->{state} = NCR_NUM_STATE;
3071            $self->{state_keyword} = $self->{next_char} - 0x0030;
3072            !!!next-input-character;
3073            redo A;
3074          } else {
3075            !!!parse-error (type => 'bare nero',
3076                            line => $self->{line_prev},
3077                            column => $self->{column_prev} - 1);
3078    
3079    if ({          ## NOTE: According to the spec algorithm, nothing is returned,
3080         0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, # HT, LF, VT, FF,          ## and then "&#" is appended to the parent element or the attribute
3081         0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, & # 0x000D # CR          ## value in the later processing.
3082         $additional => 1,  
3083        }->{$self->{next_char}}) {          if ($self->{prev_state} == DATA_STATE) {
3084      !!!cp (1001);            !!!cp (1019);
3085      ## Don't consume            $self->{state} = $self->{prev_state};
3086      ## No error            ## Reconsume.
3087      $self->{entity_return} = undef;            !!!emit ({type => CHARACTER_TOKEN,
3088      $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;                      data => '&#',
3089      redo A;                      line => $self->{line_prev},
3090    } elsif ($self->{next_char} == 0x0023) { # #                      column => $self->{column_prev} - 1,
3091      !!!next-input-character;                     });
     if ($self->{next_char} == 0x0078 or # x  
         $self->{next_char} == 0x0058) { # X  
       my $code;  
       X: {  
         my $x_char = $self->{next_char};  
         !!!next-input-character;  
         if (0x0030 <= $self->{next_char} and  
             $self->{next_char} <= 0x0039) { # 0..9  
           !!!cp (1002);  
           $code ||= 0;  
           $code *= 0x10;  
           $code += $self->{next_char} - 0x0030;  
           redo X;  
         } elsif (0x0061 <= $self->{next_char} and  
                  $self->{next_char} <= 0x0066) { # a..f  
           !!!cp (1003);  
           $code ||= 0;  
           $code *= 0x10;  
           $code += $self->{next_char} - 0x0060 + 9;  
           redo X;  
         } elsif (0x0041 <= $self->{next_char} and  
                  $self->{next_char} <= 0x0046) { # A..F  
           !!!cp (1004);  
           $code ||= 0;  
           $code *= 0x10;  
           $code += $self->{next_char} - 0x0040 + 9;  
           redo X;  
         } elsif (not defined $code) { # no hexadecimal digit  
           !!!cp (1005);  
           !!!parse-error (type => 'bare hcro', line => $l, column => $c);  
           !!!back-next-input-character ($x_char, $self->{next_char});  
           $self->{next_char} = 0x0023; # #  
           $self->{entity_return} = undef;  
           $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;  
3092            redo A;            redo A;
         } elsif ($self->{next_char} == 0x003B) { # ;  
           !!!cp (1006);  
           !!!next-input-character;  
3093          } else {          } else {
3094            !!!cp (1007);            !!!cp (993);
3095            !!!parse-error (type => 'no refc', line => $l, column => $c);            $self->{current_attribute}->{value} .= '&#';
3096              $self->{state} = $self->{prev_state};
3097              ## Reconsume.
3098              redo A;
3099          }          }
3100          }
3101          if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {      } elsif ($self->{state} == NCR_NUM_STATE) {
3102            !!!cp (1008);        if (0x0030 <= $self->{next_char} and
3103            !!!parse-error (type => 'invalid character reference',            $self->{next_char} <= 0x0039) { # 0..9
                           text => (sprintf 'U+%04X', $code),  
                           line => $l, column => $c);  
           $code = 0xFFFD;  
         } elsif ($code > 0x10FFFF) {  
           !!!cp (1009);  
           !!!parse-error (type => 'invalid character reference',  
                           text => (sprintf 'U-%08X', $code),  
                           line => $l, column => $c);  
           $code = 0xFFFD;  
         } elsif ($code == 0x000D) {  
           !!!cp (1010);  
           !!!parse-error (type => 'CR character reference', line => $l, column => $c);  
           $code = 0x000A;  
         } elsif (0x80 <= $code and $code <= 0x9F) {  
           !!!cp (1011);  
           !!!parse-error (type => 'C1 character reference', text => (sprintf 'U+%04X', $code), line => $l, column => $c);  
           $code = $c1_entity_char->{$code};  
         }  
   
         $self->{entity_return} = {type => CHARACTER_TOKEN, data => chr $code,  
                 has_reference => 1,  
                 line => $l, column => $c,  
                };  
         $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;  
         redo A;  
       } # X  
     } elsif (0x0030 <= $self->{next_char} and  
              $self->{next_char} <= 0x0039) { # 0..9  
       my $code = $self->{next_char} - 0x0030;  
       !!!next-input-character;  
         
       while (0x0030 <= $self->{next_char} and  
                 $self->{next_char} <= 0x0039) { # 0..9  
3104          !!!cp (1012);          !!!cp (1012);
3105          $code *= 10;          $self->{state_keyword} *= 10;
3106          $code += $self->{next_char} - 0x0030;          $self->{state_keyword} += $self->{next_char} - 0x0030;
3107                    
3108            ## Stay in the state.
3109          !!!next-input-character;          !!!next-input-character;
3110        }          redo A;
3111          } elsif ($self->{next_char} == 0x003B) { # ;
       if ($self->{next_char} == 0x003B) { # ;  
3112          !!!cp (1013);          !!!cp (1013);
3113          !!!next-input-character;          !!!next-input-character;
3114            #
3115        } else {        } else {
3116          !!!cp (1014);          !!!cp (1014);
3117          !!!parse-error (type => 'no refc', line => $l, column => $c);          !!!parse-error (type => 'no refc');
3118            ## Reconsume.
3119            #
3120        }        }
3121    
3122          my $code = $self->{state_keyword};
3123          my $l = $self->{line_prev};
3124          my $c = $self->{column_prev};
3125        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {
3126          !!!cp (1015);          !!!cp (1015);
3127          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
# Line 3117  sub _get_next_token ($) { Line 3146  sub _get_next_token ($) {
3146                          line => $l, column => $c);                          line => $l, column => $c);
3147          $code = $c1_entity_char->{$code};          $code = $c1_entity_char->{$code};
3148        }        }
3149          
3150        $self->{entity_return} = {type => CHARACTER_TOKEN, data => chr $code, has_reference => 1,        if ($self->{prev_state} == DATA_STATE) {
3151                line => $l, column => $c,          !!!cp (992);
3152               };          $self->{state} = $self->{prev_state};
3153        $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;          ## Reconsume.
3154        redo A;          !!!emit ({type => CHARACTER_TOKEN, data => chr $code,
3155      } else {                    line => $l, column => $c,
3156        !!!cp (1019);                   });
3157        !!!parse-error (type => 'bare nero', line => $l, column => $c);          redo A;
3158        !!!back-next-input-character ($self->{next_char});        } else {
3159        $self->{next_char} = 0x0023; # #          !!!cp (991);
3160        $self->{entity_return} = undef;          $self->{current_attribute}->{value} .= chr $code;
3161        $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;          $self->{current_attribute}->{has_reference} = 1;
3162        redo A;          $self->{state} = $self->{prev_state};
3163      }          ## Reconsume.
3164    } elsif ((0x0041 <= $self->{next_char} and          redo A;
3165              $self->{next_char} <= 0x005A) or        }
3166             (0x0061 <= $self->{next_char} and      } elsif ($self->{state} == HEXREF_X_STATE) {
3167              $self->{next_char} <= 0x007A)) {        if ((0x0030 <= $self->{next_char} and $self->{next_char} <= 0x0039) or
3168      my $entity_name = chr $self->{next_char};            (0x0041 <= $self->{next_char} and $self->{next_char} <= 0x0046) or
3169      !!!next-input-character;            (0x0061 <= $self->{next_char} and $self->{next_char} <= 0x0066)) {
3170            # 0..9, A..F, a..f
3171      my $value = $entity_name;          !!!cp (990);
3172      my $match = 0;          $self->{state} = HEXREF_HEX_STATE;
3173      require Whatpm::_NamedEntityList;          $self->{state_keyword} = 0;
3174      our $EntityChar;          ## Reconsume.
3175            redo A;
3176      while (length $entity_name < 30 and        } else {
3177             ## NOTE: Some number greater than the maximum length of entity name          !!!parse-error (type => 'bare hcro',
3178             ((0x0041 <= $self->{next_char} and # a                          line => $self->{line_prev},
3179               $self->{next_char} <= 0x005A) or # x                          column => $self->{column_prev} - 2);
3180              (0x0061 <= $self->{next_char} and # a  
3181               $self->{next_char} <= 0x007A) or # z          ## NOTE: According to the spec algorithm, nothing is returned,
3182              (0x0030 <= $self->{next_char} and # 0          ## and then "&#" followed by "X" or "x" is appended to the parent
3183               $self->{next_char} <= 0x0039) or # 9          ## element or the attribute value in the later processing.
3184              $self->{next_char} == 0x003B)) { # ;  
3185        $entity_name .= chr $self->{next_char};          if ($self->{prev_state} == DATA_STATE) {
3186        if (defined $EntityChar->{$entity_name}) {            !!!cp (1005);
3187          if ($self->{next_char} == 0x003B) { # ;            $self->{state} = $self->{prev_state};
3188            !!!cp (1020);            ## Reconsume.
3189            $value = $EntityChar->{$entity_name};            !!!emit ({type => CHARACTER_TOKEN,
3190            $match = 1;                      data => '&' . $self->{state_keyword},
3191            !!!next-input-character;                      line => $self->{line_prev},
3192            last;                      column => $self->{column_prev} - length $self->{state_keyword},
3193                       });
3194              redo A;
3195          } else {          } else {
3196            !!!cp (1021);            !!!cp (989);
3197            $value = $EntityChar->{$entity_name};            $self->{current_attribute}->{value} .= '&' . $self->{state_keyword};
3198            $match = -1;            $self->{state} = $self->{prev_state};
3199            !!!next-input-character;            ## Reconsume.
3200              redo A;
3201          }          }
3202        } else {        }
3203          !!!cp (1022);      } elsif ($self->{state} == HEXREF_HEX_STATE) {
3204          $value .= chr $self->{next_char};        if (0x0030 <= $self->{next_char} and $self->{next_char} <= 0x0039) {
3205          $match *= 2;          # 0..9
3206            !!!cp (1002);
3207            $self->{state_keyword} *= 0x10;
3208            $self->{state_keyword} += $self->{next_char} - 0x0030;
3209            ## Stay in the state.
3210          !!!next-input-character;          !!!next-input-character;
3211            redo A;
3212          } elsif (0x0061 <= $self->{next_char} and
3213                   $self->{next_char} <= 0x0066) { # a..f
3214            !!!cp (1003);
3215            $self->{state_keyword} *= 0x10;
3216            $self->{state_keyword} += $self->{next_char} - 0x0060 + 9;
3217            ## Stay in the state.
3218            !!!next-input-character;
3219            redo A;
3220          } elsif (0x0041 <= $self->{next_char} and
3221                   $self->{next_char} <= 0x0046) { # A..F
3222            !!!cp (1004);
3223            $self->{state_keyword} *= 0x10;
3224            $self->{state_keyword} += $self->{next_char} - 0x0040 + 9;
3225            ## Stay in the state.
3226            !!!next-input-character;
3227            redo A;
3228          } elsif ($self->{next_char} == 0x003B) { # ;
3229            !!!cp (1006);
3230            !!!next-input-character;
3231            #
3232          } else {
3233            !!!cp (1007);
3234            !!!parse-error (type => 'no refc',
3235                            line => $self->{line},
3236                            column => $self->{column});
3237            ## Reconsume.
3238            #
3239        }        }
3240      }  
3241              my $code = $self->{state_keyword};
3242      if ($match > 0) {        my $l = $self->{line_prev};
3243        !!!cp (1023);        my $c = $self->{column_prev};
3244        $self->{entity_return} = {type => CHARACTER_TOKEN, data => $value, has_reference => 1,        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {
3245                line => $l, column => $c,          !!!cp (1008);
3246               };          !!!parse-error (type => 'invalid character reference',
3247        $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;                          text => (sprintf 'U+%04X', $code),
3248        redo A;                          line => $l, column => $c);
3249      } elsif ($match < 0) {          $code = 0xFFFD;
3250        !!!parse-error (type => 'no refc', line => $l, column => $c);        } elsif ($code > 0x10FFFF) {
3251        if ($in_attr and $match < -1) {          !!!cp (1009);
3252          !!!cp (1024);          !!!parse-error (type => 'invalid character reference',
3253          $self->{entity_return} = {type => CHARACTER_TOKEN, data => '&'.$entity_name,                          text => (sprintf 'U-%08X', $code),
3254                  line => $l, column => $c,                          line => $l, column => $c);
3255                 };          $code = 0xFFFD;
3256          $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;        } elsif ($code == 0x000D) {
3257            !!!cp (1010);
3258            !!!parse-error (type => 'CR character reference', line => $l, column => $c);
3259            $code = 0x000A;
3260          } elsif (0x80 <= $code and $code <= 0x9F) {
3261            !!!cp (1011);
3262            !!!parse-error (type => 'C1 character reference', text => (sprintf 'U+%04X', $code), line => $l, column => $c);
3263            $code = $c1_entity_char->{$code};
3264          }
3265    
3266          if ($self->{prev_state} == DATA_STATE) {
3267            !!!cp (988);
3268            $self->{state} = $self->{prev_state};
3269            ## Reconsume.
3270            !!!emit ({type => CHARACTER_TOKEN, data => chr $code,
3271                      line => $l, column => $c,
3272                     });
3273          redo A;          redo A;
3274        } else {        } else {
3275          !!!cp (1025);          !!!cp (987);
3276          $self->{entity_return} = {type => CHARACTER_TOKEN, data => $value, has_reference => 1,          $self->{current_attribute}->{value} .= chr $code;
3277                  line => $l, column => $c,          $self->{current_attribute}->{has_reference} = 1;
3278                 };          $self->{state} = $self->{prev_state};
3279          $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;          ## Reconsume.
3280          redo A;          redo A;
3281        }        }
3282      } else {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
3283        !!!cp (1026);        if (length $self->{state_keyword} < 30 and
3284        !!!parse-error (type => 'bare ero', line => $l, column => $c);            ## NOTE: Some number greater than the maximum length of entity name
3285        ## NOTE: "No characters are consumed" in the spec.            ((0x0041 <= $self->{next_char} and # a
3286        $self->{entity_return} = {type => CHARACTER_TOKEN, data => '&'.$value,              $self->{next_char} <= 0x005A) or # x
3287                line => $l, column => $c,             (0x0061 <= $self->{next_char} and # a
3288               };              $self->{next_char} <= 0x007A) or # z
3289        $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;             (0x0030 <= $self->{next_char} and # 0
3290        redo A;              $self->{next_char} <= 0x0039) or # 9
3291      }             $self->{next_char} == 0x003B)) { # ;
3292    } else {          our $EntityChar;
3293      !!!cp (1027);          $self->{state_keyword} .= chr $self->{next_char};
3294      ## no characters are consumed          if (defined $EntityChar->{$self->{state_keyword}}) {
3295      !!!parse-error (type => 'bare ero', line => $l, column => $c);            if ($self->{next_char} == 0x003B) { # ;
3296      $self->{entity_return} = undef;              !!!cp (1020);
3297      $self->{state} = $self->{entity_in_attr} ? ENTITY_IN_ATTRIBUTE_VALUE_STATE : ENTITY_DATA_STATE;              $self->{entity__value} = $EntityChar->{$self->{state_keyword}};
3298      redo A;              $self->{entity__match} = 1;
3299    }              !!!next-input-character;
3300                #
3301              } else {
3302                !!!cp (1021);
3303                $self->{entity__value} = $EntityChar->{$self->{state_keyword}};
3304                $self->{entity__match} = -1;
3305                ## Stay in the state.
3306                !!!next-input-character;
3307                redo A;
3308              }
3309            } else {
3310              !!!cp (1022);
3311              $self->{entity__value} .= chr $self->{next_char};
3312              $self->{entity__match} *= 2;
3313              ## Stay in the state.
3314              !!!next-input-character;
3315              redo A;
3316            }
3317          }
3318    
3319          my $data;
3320          my $has_ref;
3321          if ($self->{entity__match} > 0) {
3322            !!!cp (1023);
3323            $data = $self->{entity__value};
3324            $has_ref = 1;
3325            #
3326          } elsif ($self->{entity__match} < 0) {
3327            !!!parse-error (type => 'no refc');
3328            if ($self->{prev_state} != DATA_STATE and # in attribute
3329                $self->{entity__match} < -1) {
3330              !!!cp (1024);
3331              $data = '&' . $self->{state_keyword};
3332              #
3333            } else {
3334              !!!cp (1025);
3335              $data = $self->{entity__value};
3336              $has_ref = 1;
3337              #
3338            }
3339          } else {
3340            !!!cp (1026);
3341            !!!parse-error (type => 'bare ero',
3342                            line => $self->{line_prev},
3343                            column => $self->{column_prev});
3344            $data = '&' . $self->{state_keyword};
3345            #
3346          }
3347      
3348          ## NOTE: In these cases, when a character reference is found,
3349          ## it is consumed and a character token is returned, or, otherwise,
3350          ## nothing is consumed and returned, according to the spec algorithm.
3351          ## In this implementation, anything that has been examined by the
3352          ## tokenizer is appended to the parent element or the attribute value
3353          ## as string, either literal string when no character reference or
3354          ## entity-replaced string otherwise, in this stage, since any characters
3355          ## that would not be consumed are appended in the data state or in an
3356          ## appropriate attribute value state anyway.
3357    
3358          if ($self->{prev_state} == DATA_STATE) {
3359            !!!cp (986);
3360            $self->{state} = $self->{prev_state};
3361            ## Reconsume.
3362            !!!emit ({type => CHARACTER_TOKEN,
3363                      data => $data,
3364                      line => $self->{line_prev},
3365                      column => $self->{column_prev} + 1 - length $self->{state_keyword},
3366                     });
3367            redo A;
3368          } else {
3369            !!!cp (985);
3370            $self->{current_attribute}->{value} .= $data;
3371            $self->{current_attribute}->{has_reference} = 1 if $has_ref;
3372            $self->{state} = $self->{prev_state};
3373            ## Reconsume.
3374            redo A;
3375          }
3376      } else {      } else {
3377        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
3378      }      }
# Line 7682  sub set_inner_html ($$$;$) { Line 7837  sub set_inner_html ($$$;$) {
7837      };      };
7838      $p->{prev_char} = [-1, -1, -1];      $p->{prev_char} = [-1, -1, -1];
7839      $p->{next_char} = -1;      $p->{next_char} = -1;
7840        
7841        $p->{read_until} = sub {
7842          ## TODO: ...
7843          return 0;
7844        }; # $p->{read_until};
7845    
7846      my $ponerror = $onerror || sub {      my $ponerror = $onerror || sub {
7847        my (%opt) = @_;        my (%opt) = @_;
7848        my $line = $opt{line};        my $line = $opt{line};

Legend:
Removed from v.1.167  
changed lines
  Added in v.1.173

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24