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

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

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

revision 1.1 by wakaba, Tue Oct 14 02:27:58 2008 UTC revision 1.10 by wakaba, Wed Oct 15 08:51:02 2008 UTC
# Line 2  package Whatpm::HTML::Tokenizer; Line 2  package Whatpm::HTML::Tokenizer;
2  use strict;  use strict;
3  our $VERSION=do{my @r=(q$Revision$=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};  our $VERSION=do{my @r=(q$Revision$=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
4    
5    BEGIN {
6      require Exporter;
7      push our @ISA, 'Exporter';
8    
9      our @EXPORT_OK = qw(
10        DOCTYPE_TOKEN
11        COMMENT_TOKEN
12        START_TAG_TOKEN
13        END_TAG_TOKEN
14        END_OF_FILE_TOKEN
15        CHARACTER_TOKEN
16        PI_TOKEN
17        ABORT_TOKEN
18      );
19      
20      our %EXPORT_TAGS = (
21        token => [qw(
22          DOCTYPE_TOKEN
23          COMMENT_TOKEN
24          START_TAG_TOKEN
25          END_TAG_TOKEN
26          END_OF_FILE_TOKEN
27          CHARACTER_TOKEN
28          PI_TOKEN
29          ABORT_TOKEN
30        )],
31      );
32    }
33    
34    ## Token types
35    
36    sub DOCTYPE_TOKEN () { 1 }
37    sub COMMENT_TOKEN () { 2 }
38    sub START_TAG_TOKEN () { 3 }
39    sub END_TAG_TOKEN () { 4 }
40    sub END_OF_FILE_TOKEN () { 5 }
41    sub CHARACTER_TOKEN () { 6 }
42    sub PI_TOKEN () { 7 } # XML5
43    sub ABORT_TOKEN () { 8 } # Not a token actually
44    
45  package Whatpm::HTML;  package Whatpm::HTML;
46    
47    BEGIN { Whatpm::HTML::Tokenizer->import (':token') }
48    
49  ## Content model flags  ## Content model flags
50    
51  sub CM_ENTITY () { 0b001 } # & markup in data  sub CM_ENTITY () { 0b001 } # & markup in data
# Line 72  sub HEXREF_HEX_STATE () { 48 } Line 114  sub HEXREF_HEX_STATE () { 48 }
114  sub ENTITY_NAME_STATE () { 49 }  sub ENTITY_NAME_STATE () { 49 }
115  sub PCDATA_STATE () { 50 } # "data state" in the spec  sub PCDATA_STATE () { 50 } # "data state" in the spec
116    
117  ## Token types  ## XML states
118    sub PI_STATE () { 51 }
119  sub DOCTYPE_TOKEN () { 1 }  sub PI_TARGET_STATE () { 52 }
120  sub COMMENT_TOKEN () { 2 }  sub PI_TARGET_AFTER_STATE () { 53 }
121  sub START_TAG_TOKEN () { 3 }  sub PI_DATA_STATE () { 54 }
122  sub END_TAG_TOKEN () { 4 }  sub PI_AFTER_STATE () { 55 }
123  sub END_OF_FILE_TOKEN () { 5 }  sub PI_DATA_AFTER_STATE () { 56 }
 sub CHARACTER_TOKEN () { 6 }  
124    
125  ## Tree constructor state constants (see Whatpm::HTML for the full  ## Tree constructor state constants (see Whatpm::HTML for the full
126  ## list and descriptions)  ## list and descriptions)
# Line 142  sub _initialize_tokenizer ($) { Line 183  sub _initialize_tokenizer ($) {
183    #$self->{level}    #$self->{level}
184    #$self->{set_nc}    #$self->{set_nc}
185    #$self->{parse_error}    #$self->{parse_error}
186      #$self->{is_xml} (if XML)
187    
188    $self->{state} = DATA_STATE; # MUST    $self->{state} = DATA_STATE; # MUST
189    #$self->{s_kwd}; # state keyword - initialized when used    $self->{s_kwd} = ''; # state keyword
190    #$self->{entity__value}; # initialized when used    #$self->{entity__value}; # initialized when used
191    #$self->{entity__match}; # initialized when used    #$self->{entity__match}; # initialized when used
192    $self->{content_model} = PCDATA_CONTENT_MODEL; # be    $self->{content_model} = PCDATA_CONTENT_MODEL; # be
# Line 175  sub _initialize_tokenizer ($) { Line 217  sub _initialize_tokenizer ($) {
217  ##        ->{value}  ##        ->{value}
218  ##        ->{has_reference} == 1 or 0  ##        ->{has_reference} == 1 or 0
219  ##   ->{data} (COMMENT_TOKEN, CHARACTER_TOKEN)  ##   ->{data} (COMMENT_TOKEN, CHARACTER_TOKEN)
220    ##   ->{has_reference} == 1 or 0 (CHARACTER_TOKEN)
221  ## NOTE: The "self-closing flag" is hold as |$self->{self_closing}|.  ## NOTE: The "self-closing flag" is hold as |$self->{self_closing}|.
222  ##     |->{self_closing}| is used to save the value of |$self->{self_closing}|  ##     |->{self_closing}| is used to save the value of |$self->{self_closing}|
223  ##     while the token is pushed back to the stack.  ##     while the token is pushed back to the stack.
# Line 278  sub _get_next_token ($) { Line 321  sub _get_next_token ($) {
321          }          }
322        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
323          if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA          if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA
324            $self->{s_kwd} .= '-';            if ($self->{s_kwd} eq '<!-') {
             
           if ($self->{s_kwd} eq '<!--') {  
325              !!!cp (3);              !!!cp (3);
326              $self->{escape} = 1; # unless $self->{escape};              $self->{escape} = 1; # unless $self->{escape};
327              $self->{s_kwd} = '--';              $self->{s_kwd} = '--';
328              #              #
329            } elsif ($self->{s_kwd} eq '---') {            } elsif ($self->{s_kwd} eq '-') {
330              !!!cp (4);              !!!cp (4);
331              $self->{s_kwd} = '--';              $self->{s_kwd} = '--';
332              #              #
333              } elsif ($self->{s_kwd} eq '<!' or $self->{s_kwd} eq '-') {
334                !!!cp (4.1);
335                $self->{s_kwd} .= '-';
336                #
337            } else {            } else {
338              !!!cp (5);              !!!cp (5);
339                $self->{s_kwd} = '-';
340              #              #
341            }            }
342          }          }
# Line 326  sub _get_next_token ($) { Line 372  sub _get_next_token ($) {
372            if ($self->{s_kwd} eq '--') {            if ($self->{s_kwd} eq '--') {
373              !!!cp (8);              !!!cp (8);
374              delete $self->{escape};              delete $self->{escape};
375                #
376            } else {            } else {
377              !!!cp (9);              !!!cp (9);
378                #
379            }            }
380            } elsif ($self->{is_xml} and $self->{s_kwd} eq ']]') {
381              !!!cp (9.1);
382              !!!parse-error (type => 'unmatched mse', ## TODO: type
383                              line => $self->{line_prev},
384                              column => $self->{column_prev} - 1);
385              #
386          } else {          } else {
387            !!!cp (10);            !!!cp (10);
388              #
389          }          }
390                    
391          $self->{s_kwd} = '';          $self->{s_kwd} = '';
392          #          #
393          } elsif ($self->{nc} == 0x005D) { # ]
394            if ($self->{s_kwd} eq ']' or $self->{s_kwd} eq '') {
395              !!!cp (10.1);
396              $self->{s_kwd} .= ']';
397            } elsif ($self->{s_kwd} eq ']]') {
398              !!!cp (10.2);
399              #
400            } else {
401              !!!cp (10.3);
402              $self->{s_kwd} = '';
403            }
404            #
405        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
406          !!!cp (11);          !!!cp (11);
407          $self->{s_kwd} = '';          $self->{s_kwd} = '';
# Line 352  sub _get_next_token ($) { Line 419  sub _get_next_token ($) {
419                     data => chr $self->{nc},                     data => chr $self->{nc},
420                     line => $self->{line}, column => $self->{column},                     line => $self->{line}, column => $self->{column},
421                    };                    };
422        if ($self->{read_until}->($token->{data}, q[-!<>&],        if ($self->{read_until}->($token->{data}, q{-!<>&\]},
423                                  length $token->{data})) {                                  length $token->{data})) {
424          $self->{s_kwd} = '';          $self->{s_kwd} = '';
425        }        }
426    
427        ## Stay in the data state.        ## Stay in the data state.
428        if ($self->{content_model} == PCDATA_CONTENT_MODEL) {        if (not $self->{is_xml} and
429              $self->{content_model} == PCDATA_CONTENT_MODEL) {
430          !!!cp (13);          !!!cp (13);
431          $self->{state} = PCDATA_STATE;          $self->{state} = PCDATA_STATE;
432        } else {        } else {
# Line 369  sub _get_next_token ($) { Line 437  sub _get_next_token ($) {
437        !!!emit ($token);        !!!emit ($token);
438        redo A;        redo A;
439      } elsif ($self->{state} == TAG_OPEN_STATE) {      } elsif ($self->{state} == TAG_OPEN_STATE) {
440          ## XML5: "tag state".
441    
442        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA
443          if ($self->{nc} == 0x002F) { # /          if ($self->{nc} == 0x002F) { # /
444            !!!cp (15);            !!!cp (15);
# Line 386  sub _get_next_token ($) { Line 456  sub _get_next_token ($) {
456    
457          ## reconsume          ## reconsume
458          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
459            $self->{s_kwd} = '';
460          !!!emit ({type => CHARACTER_TOKEN, data => '<',          !!!emit ({type => CHARACTER_TOKEN, data => '<',
461                    line => $self->{line_prev},                    line => $self->{line_prev},
462                    column => $self->{column_prev},                    column => $self->{column_prev},
# Line 407  sub _get_next_token ($) { Line 478  sub _get_next_token ($) {
478            !!!cp (19);            !!!cp (19);
479            $self->{ct}            $self->{ct}
480              = {type => START_TAG_TOKEN,              = {type => START_TAG_TOKEN,
481                 tag_name => chr ($self->{nc} + 0x0020),                 tag_name => chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020)),
482                 line => $self->{line_prev},                 line => $self->{line_prev},
483                 column => $self->{column_prev}};                 column => $self->{column_prev}};
484            $self->{state} = TAG_NAME_STATE;            $self->{state} = TAG_NAME_STATE;
# Line 429  sub _get_next_token ($) { Line 500  sub _get_next_token ($) {
500                            line => $self->{line_prev},                            line => $self->{line_prev},
501                            column => $self->{column_prev});                            column => $self->{column_prev});
502            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
503              $self->{s_kwd} = '';
504            !!!next-input-character;            !!!next-input-character;
505    
506            !!!emit ({type => CHARACTER_TOKEN, data => '<>',            !!!emit ({type => CHARACTER_TOKEN, data => '<>',
# Line 438  sub _get_next_token ($) { Line 510  sub _get_next_token ($) {
510    
511            redo A;            redo A;
512          } elsif ($self->{nc} == 0x003F) { # ?          } elsif ($self->{nc} == 0x003F) { # ?
513            !!!cp (22);            if ($self->{is_xml}) {
514            !!!parse-error (type => 'pio',              !!!cp (22.1);
515                            line => $self->{line_prev},              $self->{state} = PI_STATE;
516                            column => $self->{column_prev});              !!!next-input-character;
517            $self->{state} = BOGUS_COMMENT_STATE;              redo A;
518            $self->{ct} = {type => COMMENT_TOKEN, data => '',            } else {
519                                      line => $self->{line_prev},              !!!cp (22);
520                                      column => $self->{column_prev},              !!!parse-error (type => 'pio',
521                                     };                              line => $self->{line_prev},
522            ## $self->{nc} is intentionally left as is                              column => $self->{column_prev});
523            redo A;              $self->{state} = BOGUS_COMMENT_STATE;
524          } else {              $self->{ct} = {type => COMMENT_TOKEN, data => '',
525                               line => $self->{line_prev},
526                               column => $self->{column_prev},
527                              };
528                ## $self->{nc} is intentionally left as is
529                redo A;
530              }
531            } elsif (not $self->{is_xml} or $is_space->{$self->{nc}}) {
532            !!!cp (23);            !!!cp (23);
533            !!!parse-error (type => 'bare stago',            !!!parse-error (type => 'bare stago',
534                            line => $self->{line_prev},                            line => $self->{line_prev},
535                            column => $self->{column_prev});                            column => $self->{column_prev});
536            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
537              $self->{s_kwd} = '';
538            ## reconsume            ## reconsume
539    
540            !!!emit ({type => CHARACTER_TOKEN, data => '<',            !!!emit ({type => CHARACTER_TOKEN, data => '<',
# Line 463  sub _get_next_token ($) { Line 543  sub _get_next_token ($) {
543                     });                     });
544    
545            redo A;            redo A;
546            } else {
547              ## XML5: "<:" is a parse error.
548              !!!cp (23.1);
549              $self->{ct} = {type => START_TAG_TOKEN,
550                                        tag_name => chr ($self->{nc}),
551                                        line => $self->{line_prev},
552                                        column => $self->{column_prev}};
553              $self->{state} = TAG_NAME_STATE;
554              !!!next-input-character;
555              redo A;
556          }          }
557        } else {        } else {
558          die "$0: $self->{content_model} in tag open";          die "$0: $self->{content_model} in tag open";
# Line 471  sub _get_next_token ($) { Line 561  sub _get_next_token ($) {
561        ## NOTE: The "close tag open state" in the spec is implemented as        ## NOTE: The "close tag open state" in the spec is implemented as
562        ## |CLOSE_TAG_OPEN_STATE| and |CDATA_RCDATA_CLOSE_TAG_STATE|.        ## |CLOSE_TAG_OPEN_STATE| and |CDATA_RCDATA_CLOSE_TAG_STATE|.
563    
564          ## XML5: "end tag state".
565    
566        my ($l, $c) = ($self->{line_prev}, $self->{column_prev} - 1); # "<"of"</"        my ($l, $c) = ($self->{line_prev}, $self->{column_prev} - 1); # "<"of"</"
567        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA
568          if (defined $self->{last_stag_name}) {          if (defined $self->{last_stag_name}) {
# Line 483  sub _get_next_token ($) { Line 575  sub _get_next_token ($) {
575            ## NOTE: See <http://krijnhoetmer.nl/irc-logs/whatwg/20070626#l-564>.            ## NOTE: See <http://krijnhoetmer.nl/irc-logs/whatwg/20070626#l-564>.
576            !!!cp (28);            !!!cp (28);
577            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
578              $self->{s_kwd} = '';
579            ## Reconsume.            ## Reconsume.
580            !!!emit ({type => CHARACTER_TOKEN, data => '</',            !!!emit ({type => CHARACTER_TOKEN, data => '</',
581                      line => $l, column => $c,                      line => $l, column => $c,
# Line 496  sub _get_next_token ($) { Line 589  sub _get_next_token ($) {
589          !!!cp (29);          !!!cp (29);
590          $self->{ct}          $self->{ct}
591              = {type => END_TAG_TOKEN,              = {type => END_TAG_TOKEN,
592                 tag_name => chr ($self->{nc} + 0x0020),                 tag_name => chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020)),
593                 line => $l, column => $c};                 line => $l, column => $c};
594          $self->{state} = TAG_NAME_STATE;          $self->{state} = TAG_NAME_STATE;
595          !!!next-input-character;          !!!next-input-character;
# Line 511  sub _get_next_token ($) { Line 604  sub _get_next_token ($) {
604          !!!next-input-character;          !!!next-input-character;
605          redo A;          redo A;
606        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
         !!!cp (31);  
607          !!!parse-error (type => 'empty end tag',          !!!parse-error (type => 'empty end tag',
608                          line => $self->{line_prev}, ## "<" in "</>"                          line => $self->{line_prev}, ## "<" in "</>"
609                          column => $self->{column_prev} - 1);                          column => $self->{column_prev} - 1);
610          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
611          !!!next-input-character;          $self->{s_kwd} = '';
612            if ($self->{is_xml}) {
613              !!!cp (31);
614              ## XML5: No parse error.
615              
616              ## NOTE: This parser raises a parse error, since it supports
617              ## XML1, not XML5.
618    
619              ## NOTE: A short end tag token.
620              my $ct = {type => END_TAG_TOKEN,
621                        tag_name => '',
622                        line => $self->{line_prev},
623                        column => $self->{column_prev} - 1,
624                       };
625              !!!next-input-character;
626              !!!emit ($ct);
627            } else {
628              !!!cp (31.1);
629              !!!next-input-character;
630            }
631          redo A;          redo A;
632        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
633          !!!cp (32);          !!!cp (32);
634          !!!parse-error (type => 'bare etago');          !!!parse-error (type => 'bare etago');
635            $self->{s_kwd} = '';
636          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
637          # reconsume          # reconsume
638    
# Line 529  sub _get_next_token ($) { Line 641  sub _get_next_token ($) {
641                   });                   });
642    
643          redo A;          redo A;
644        } else {        } elsif (not $self->{is_xml} or
645                   $is_space->{$self->{nc}}) {
646          !!!cp (33);          !!!cp (33);
647          !!!parse-error (type => 'bogus end tag');          !!!parse-error (type => 'bogus end tag',
648                            line => $self->{line_prev}, # "<" of "</"
649                            column => $self->{column_prev} - 1);
650          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = BOGUS_COMMENT_STATE;
651          $self->{ct} = {type => COMMENT_TOKEN, data => '',          $self->{ct} = {type => COMMENT_TOKEN, data => '',
652                                    line => $self->{line_prev}, # "<" of "</"                                    line => $self->{line_prev}, # "<" of "</"
# Line 544  sub _get_next_token ($) { Line 659  sub _get_next_token ($) {
659          ## generated from the bogus end tag, as defined in the          ## generated from the bogus end tag, as defined in the
660          ## "bogus comment state" entry.          ## "bogus comment state" entry.
661          redo A;          redo A;
662          } else {
663            ## XML5: "</:" is a parse error.
664            !!!cp (30.1);
665            $self->{ct} = {type => END_TAG_TOKEN,
666                           tag_name => chr ($self->{nc}),
667                           line => $l, column => $c};
668            $self->{state} = TAG_NAME_STATE; ## XML5: "end tag name state".
669            !!!next-input-character;
670            redo A;
671        }        }
672      } elsif ($self->{state} == CDATA_RCDATA_CLOSE_TAG_STATE) {      } elsif ($self->{state} == CDATA_RCDATA_CLOSE_TAG_STATE) {
673        my $ch = substr $self->{last_stag_name}, length $self->{s_kwd}, 1;        my $ch = substr $self->{last_stag_name}, length $self->{s_kwd}, 1;
# Line 560  sub _get_next_token ($) { Line 684  sub _get_next_token ($) {
684          } else {          } else {
685            !!!cp (25);            !!!cp (25);
686            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
687              $self->{s_kwd} = '';
688            ## Reconsume.            ## Reconsume.
689            !!!emit ({type => CHARACTER_TOKEN,            !!!emit ({type => CHARACTER_TOKEN,
690                      data => '</' . $self->{s_kwd},                      data => '</' . $self->{s_kwd},
# Line 578  sub _get_next_token ($) { Line 703  sub _get_next_token ($) {
703            !!!cp (26);            !!!cp (26);
704            ## Reconsume.            ## Reconsume.
705            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
706              $self->{s_kwd} = '';
707            !!!emit ({type => CHARACTER_TOKEN,            !!!emit ({type => CHARACTER_TOKEN,
708                      data => '</' . $self->{s_kwd},                      data => '</' . $self->{s_kwd},
709                      line => $self->{line_prev},                      line => $self->{line_prev},
# Line 619  sub _get_next_token ($) { Line 745  sub _get_next_token ($) {
745            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
746          }          }
747          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
748            $self->{s_kwd} = '';
749          !!!next-input-character;          !!!next-input-character;
750    
751          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 627  sub _get_next_token ($) { Line 754  sub _get_next_token ($) {
754        } elsif (0x0041 <= $self->{nc} and        } elsif (0x0041 <= $self->{nc} and
755                 $self->{nc} <= 0x005A) { # A..Z                 $self->{nc} <= 0x005A) { # A..Z
756          !!!cp (38);          !!!cp (38);
757          $self->{ct}->{tag_name} .= chr ($self->{nc} + 0x0020);          $self->{ct}->{tag_name}
758                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
759            # start tag or end tag            # start tag or end tag
760          ## Stay in this state          ## Stay in this state
761          !!!next-input-character;          !!!next-input-character;
# Line 650  sub _get_next_token ($) { Line 778  sub _get_next_token ($) {
778            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
779          }          }
780          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
781            $self->{s_kwd} = '';
782          # reconsume          # reconsume
783    
784          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 690  sub _get_next_token ($) { Line 819  sub _get_next_token ($) {
819            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
820          }          }
821          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
822            $self->{s_kwd} = '';
823          !!!next-input-character;          !!!next-input-character;
824    
825          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 699  sub _get_next_token ($) { Line 829  sub _get_next_token ($) {
829                 $self->{nc} <= 0x005A) { # A..Z                 $self->{nc} <= 0x005A) { # A..Z
830          !!!cp (49);          !!!cp (49);
831          $self->{ca}          $self->{ca}
832              = {name => chr ($self->{nc} + 0x0020),              = {name => chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020)),
833                 value => '',                 value => '',
834                 line => $self->{line}, column => $self->{column}};                 line => $self->{line}, column => $self->{column}};
835          $self->{state} = ATTRIBUTE_NAME_STATE;          $self->{state} = ATTRIBUTE_NAME_STATE;
# Line 727  sub _get_next_token ($) { Line 857  sub _get_next_token ($) {
857            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
858          }          }
859          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
860            $self->{s_kwd} = '';
861          # reconsume          # reconsume
862    
863          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 792  sub _get_next_token ($) { Line 923  sub _get_next_token ($) {
923            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
924          }          }
925          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
926            $self->{s_kwd} = '';
927          !!!next-input-character;          !!!next-input-character;
928    
929          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 800  sub _get_next_token ($) { Line 932  sub _get_next_token ($) {
932        } elsif (0x0041 <= $self->{nc} and        } elsif (0x0041 <= $self->{nc} and
933                 $self->{nc} <= 0x005A) { # A..Z                 $self->{nc} <= 0x005A) { # A..Z
934          !!!cp (63);          !!!cp (63);
935          $self->{ca}->{name} .= chr ($self->{nc} + 0x0020);          $self->{ca}->{name}
936                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
937          ## Stay in the state          ## Stay in the state
938          !!!next-input-character;          !!!next-input-character;
939          redo A;          redo A;
# Line 829  sub _get_next_token ($) { Line 962  sub _get_next_token ($) {
962            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
963          }          }
964          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
965            $self->{s_kwd} = '';
966          # reconsume          # reconsume
967    
968          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 875  sub _get_next_token ($) { Line 1009  sub _get_next_token ($) {
1009            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1010          }          }
1011          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1012            $self->{s_kwd} = '';
1013          !!!next-input-character;          !!!next-input-character;
1014    
1015          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 884  sub _get_next_token ($) { Line 1019  sub _get_next_token ($) {
1019                 $self->{nc} <= 0x005A) { # A..Z                 $self->{nc} <= 0x005A) { # A..Z
1020          !!!cp (76);          !!!cp (76);
1021          $self->{ca}          $self->{ca}
1022              = {name => chr ($self->{nc} + 0x0020),              = {name => chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020)),
1023                 value => '',                 value => '',
1024                 line => $self->{line}, column => $self->{column}};                 line => $self->{line}, column => $self->{column}};
1025          $self->{state} = ATTRIBUTE_NAME_STATE;          $self->{state} = ATTRIBUTE_NAME_STATE;
# Line 912  sub _get_next_token ($) { Line 1047  sub _get_next_token ($) {
1047          } else {          } else {
1048            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1049          }          }
1050            $self->{s_kwd} = '';
1051          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1052          # reconsume          # reconsume
1053    
# Line 973  sub _get_next_token ($) { Line 1109  sub _get_next_token ($) {
1109            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1110          }          }
1111          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1112            $self->{s_kwd} = '';
1113          !!!next-input-character;          !!!next-input-character;
1114    
1115          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 996  sub _get_next_token ($) { Line 1133  sub _get_next_token ($) {
1133            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1134          }          }
1135          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1136            $self->{s_kwd} = '';
1137          ## reconsume          ## reconsume
1138    
1139          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 1048  sub _get_next_token ($) { Line 1186  sub _get_next_token ($) {
1186            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1187          }          }
1188          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1189            $self->{s_kwd} = '';
1190          ## reconsume          ## reconsume
1191    
1192          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 1099  sub _get_next_token ($) { Line 1238  sub _get_next_token ($) {
1238            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1239          }          }
1240          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1241            $self->{s_kwd} = '';
1242          ## reconsume          ## reconsume
1243    
1244          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 1149  sub _get_next_token ($) { Line 1289  sub _get_next_token ($) {
1289            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1290          }          }
1291          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1292            $self->{s_kwd} = '';
1293          !!!next-input-character;          !!!next-input-character;
1294    
1295          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 1172  sub _get_next_token ($) { Line 1313  sub _get_next_token ($) {
1313            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1314          }          }
1315          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1316            $self->{s_kwd} = '';
1317          ## reconsume          ## reconsume
1318    
1319          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 1220  sub _get_next_token ($) { Line 1362  sub _get_next_token ($) {
1362            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1363          }          }
1364          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1365            $self->{s_kwd} = '';
1366          !!!next-input-character;          !!!next-input-character;
1367    
1368          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 1247  sub _get_next_token ($) { Line 1390  sub _get_next_token ($) {
1390            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1391          }          }
1392          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1393            $self->{s_kwd} = '';
1394          ## Reconsume.          ## Reconsume.
1395          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
1396          redo A;          redo A;
# Line 1277  sub _get_next_token ($) { Line 1421  sub _get_next_token ($) {
1421          }          }
1422    
1423          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1424            $self->{s_kwd} = '';
1425          !!!next-input-character;          !!!next-input-character;
1426    
1427          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
# Line 1299  sub _get_next_token ($) { Line 1444  sub _get_next_token ($) {
1444            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1445          }          }
1446          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1447            $self->{s_kwd} = '';
1448          ## Reconsume.          ## Reconsume.
1449          !!!emit ($self->{ct}); # start tag or end tag          !!!emit ($self->{ct}); # start tag or end tag
1450          redo A;          redo A;
# Line 1319  sub _get_next_token ($) { Line 1465  sub _get_next_token ($) {
1465        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
1466          !!!cp (124);          !!!cp (124);
1467          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1468            $self->{s_kwd} = '';
1469          !!!next-input-character;          !!!next-input-character;
1470    
1471          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1326  sub _get_next_token ($) { Line 1473  sub _get_next_token ($) {
1473        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1474          !!!cp (125);          !!!cp (125);
1475          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1476            $self->{s_kwd} = '';
1477          ## reconsume          ## reconsume
1478    
1479          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1357  sub _get_next_token ($) { Line 1505  sub _get_next_token ($) {
1505          $self->{s_kwd} = chr $self->{nc};          $self->{s_kwd} = chr $self->{nc};
1506          !!!next-input-character;          !!!next-input-character;
1507          redo A;          redo A;
1508        } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM and        } elsif ((($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM and
1509                 $self->{open_elements}->[-1]->[1] & FOREIGN_EL and                   $self->{open_elements}->[-1]->[1] & FOREIGN_EL) or
1510                    $self->{is_xml}) and
1511                 $self->{nc} == 0x005B) { # [                 $self->{nc} == 0x005B) { # [
1512          !!!cp (135.4);                          !!!cp (135.4);                
1513          $self->{state} = MD_CDATA_STATE;          $self->{state} = MD_CDATA_STATE;
# Line 1386  sub _get_next_token ($) { Line 1535  sub _get_next_token ($) {
1535                                    line => $self->{line_prev},                                    line => $self->{line_prev},
1536                                    column => $self->{column_prev} - 2,                                    column => $self->{column_prev} - 2,
1537                                   };                                   };
1538          $self->{state} = COMMENT_START_STATE;          $self->{state} = COMMENT_START_STATE; ## XML5: "comment state".
1539          !!!next-input-character;          !!!next-input-character;
1540          redo A;          redo A;
1541        } else {        } else {
# Line 1429  sub _get_next_token ($) { Line 1578  sub _get_next_token ($) {
1578        } elsif ((length $self->{s_kwd}) == 6 and        } elsif ((length $self->{s_kwd}) == 6 and
1579                 ($self->{nc} == 0x0045 or # E                 ($self->{nc} == 0x0045 or # E
1580                  $self->{nc} == 0x0065)) { # e                  $self->{nc} == 0x0065)) { # e
1581          !!!cp (129);          if ($self->{s_kwd} ne 'DOCTYP') {
1582              !!!cp (129);
1583              ## XML5: case-sensitive.
1584              !!!parse-error (type => 'lowercase keyword', ## TODO
1585                              text => 'DOCTYPE',
1586                              line => $self->{line_prev},
1587                              column => $self->{column_prev} - 5);
1588            } else {
1589              !!!cp (129.1);
1590            }
1591          $self->{state} = DOCTYPE_STATE;          $self->{state} = DOCTYPE_STATE;
1592          $self->{ct} = {type => DOCTYPE_TOKEN,          $self->{ct} = {type => DOCTYPE_TOKEN,
1593                                    quirks => 1,                                    quirks => 1,
# Line 1467  sub _get_next_token ($) { Line 1625  sub _get_next_token ($) {
1625          redo A;          redo A;
1626        } elsif ($self->{s_kwd} eq '[CDATA' and        } elsif ($self->{s_kwd} eq '[CDATA' and
1627                 $self->{nc} == 0x005B) { # [                 $self->{nc} == 0x005B) { # [
1628          !!!cp (135.2);          if ($self->{is_xml} and
1629                not $self->{tainted} and
1630                @{$self->{open_elements} or []} == 0) {
1631              !!!cp (135.2);
1632              !!!parse-error (type => 'cdata outside of root element',
1633                              line => $self->{line_prev},
1634                              column => $self->{column_prev} - 7);
1635              $self->{tainted} = 1;
1636            } else {
1637              !!!cp (135.21);
1638            }
1639    
1640          $self->{ct} = {type => CHARACTER_TOKEN,          $self->{ct} = {type => CHARACTER_TOKEN,
1641                                    data => '',                                    data => '',
1642                                    line => $self->{line_prev},                                    line => $self->{line_prev},
# Line 1499  sub _get_next_token ($) { Line 1668  sub _get_next_token ($) {
1668          !!!cp (138);          !!!cp (138);
1669          !!!parse-error (type => 'bogus comment');          !!!parse-error (type => 'bogus comment');
1670          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1671            $self->{s_kwd} = '';
1672          !!!next-input-character;          !!!next-input-character;
1673    
1674          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1508  sub _get_next_token ($) { Line 1678  sub _get_next_token ($) {
1678          !!!cp (139);          !!!cp (139);
1679          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
1680          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1681            $self->{s_kwd} = '';
1682          ## reconsume          ## reconsume
1683    
1684          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1531  sub _get_next_token ($) { Line 1702  sub _get_next_token ($) {
1702          !!!cp (142);          !!!cp (142);
1703          !!!parse-error (type => 'bogus comment');          !!!parse-error (type => 'bogus comment');
1704          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1705            $self->{s_kwd} = '';
1706          !!!next-input-character;          !!!next-input-character;
1707    
1708          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1540  sub _get_next_token ($) { Line 1712  sub _get_next_token ($) {
1712          !!!cp (143);          !!!cp (143);
1713          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
1714          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1715            $self->{s_kwd} = '';
1716          ## reconsume          ## reconsume
1717    
1718          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1563  sub _get_next_token ($) { Line 1736  sub _get_next_token ($) {
1736          !!!cp (146);          !!!cp (146);
1737          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
1738          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1739            $self->{s_kwd} = '';
1740          ## reconsume          ## reconsume
1741    
1742          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1580  sub _get_next_token ($) { Line 1754  sub _get_next_token ($) {
1754          redo A;          redo A;
1755        }        }
1756      } elsif ($self->{state} == COMMENT_END_DASH_STATE) {      } elsif ($self->{state} == COMMENT_END_DASH_STATE) {
1757          ## XML5: "comment dash state".
1758    
1759        if ($self->{nc} == 0x002D) { # -        if ($self->{nc} == 0x002D) { # -
1760          !!!cp (148);          !!!cp (148);
1761          $self->{state} = COMMENT_END_STATE;          $self->{state} = COMMENT_END_STATE;
# Line 1588  sub _get_next_token ($) { Line 1764  sub _get_next_token ($) {
1764        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1765          !!!cp (149);          !!!cp (149);
1766          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
1767            $self->{s_kwd} = '';
1768          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1769            $self->{s_kwd} = '';
1770          ## reconsume          ## reconsume
1771    
1772          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1605  sub _get_next_token ($) { Line 1783  sub _get_next_token ($) {
1783        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
1784          !!!cp (151);          !!!cp (151);
1785          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1786            $self->{s_kwd} = '';
1787          !!!next-input-character;          !!!next-input-character;
1788    
1789          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1612  sub _get_next_token ($) { Line 1791  sub _get_next_token ($) {
1791          redo A;          redo A;
1792        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
1793          !!!cp (152);          !!!cp (152);
1794            ## XML5: Not a parse error.
1795          !!!parse-error (type => 'dash in comment',          !!!parse-error (type => 'dash in comment',
1796                          line => $self->{line_prev},                          line => $self->{line_prev},
1797                          column => $self->{column_prev});                          column => $self->{column_prev});
# Line 1623  sub _get_next_token ($) { Line 1803  sub _get_next_token ($) {
1803          !!!cp (153);          !!!cp (153);
1804          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
1805          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1806            $self->{s_kwd} = '';
1807          ## reconsume          ## reconsume
1808    
1809          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1630  sub _get_next_token ($) { Line 1811  sub _get_next_token ($) {
1811          redo A;          redo A;
1812        } else {        } else {
1813          !!!cp (154);          !!!cp (154);
1814            ## XML5: Not a parse error.
1815          !!!parse-error (type => 'dash in comment',          !!!parse-error (type => 'dash in comment',
1816                          line => $self->{line_prev},                          line => $self->{line_prev},
1817                          column => $self->{column_prev});                          column => $self->{column_prev});
# Line 1661  sub _get_next_token ($) { Line 1843  sub _get_next_token ($) {
1843          !!!cp (158);          !!!cp (158);
1844          !!!parse-error (type => 'no DOCTYPE name');          !!!parse-error (type => 'no DOCTYPE name');
1845          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1846            $self->{s_kwd} = '';
1847          !!!next-input-character;          !!!next-input-character;
1848    
1849          !!!emit ($self->{ct}); # DOCTYPE (quirks)          !!!emit ($self->{ct}); # DOCTYPE (quirks)
# Line 1670  sub _get_next_token ($) { Line 1853  sub _get_next_token ($) {
1853          !!!cp (159);          !!!cp (159);
1854          !!!parse-error (type => 'no DOCTYPE name');          !!!parse-error (type => 'no DOCTYPE name');
1855          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1856            $self->{s_kwd} = '';
1857          ## reconsume          ## reconsume
1858    
1859          !!!emit ($self->{ct}); # DOCTYPE (quirks)          !!!emit ($self->{ct}); # DOCTYPE (quirks)
# Line 1693  sub _get_next_token ($) { Line 1877  sub _get_next_token ($) {
1877        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
1878          !!!cp (162);          !!!cp (162);
1879          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1880            $self->{s_kwd} = '';
1881          !!!next-input-character;          !!!next-input-character;
1882    
1883          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
# Line 1702  sub _get_next_token ($) { Line 1887  sub _get_next_token ($) {
1887          !!!cp (163);          !!!cp (163);
1888          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
1889          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1890            $self->{s_kwd} = '';
1891          ## reconsume          ## reconsume
1892    
1893          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 1725  sub _get_next_token ($) { Line 1911  sub _get_next_token ($) {
1911        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
1912          !!!cp (166);          !!!cp (166);
1913          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1914            $self->{s_kwd} = '';
1915          !!!next-input-character;          !!!next-input-character;
1916    
1917          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
# Line 1734  sub _get_next_token ($) { Line 1921  sub _get_next_token ($) {
1921          !!!cp (167);          !!!cp (167);
1922          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
1923          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1924            $self->{s_kwd} = '';
1925          ## reconsume          ## reconsume
1926    
1927          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 1862  sub _get_next_token ($) { Line 2050  sub _get_next_token ($) {
2050          !!!parse-error (type => 'no PUBLIC literal');          !!!parse-error (type => 'no PUBLIC literal');
2051    
2052          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2053            $self->{s_kwd} = '';
2054          !!!next-input-character;          !!!next-input-character;
2055    
2056          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 1873  sub _get_next_token ($) { Line 2062  sub _get_next_token ($) {
2062          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
2063    
2064          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2065            $self->{s_kwd} = '';
2066          ## reconsume          ## reconsume
2067    
2068          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 1899  sub _get_next_token ($) { Line 2089  sub _get_next_token ($) {
2089          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2090    
2091          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2092            $self->{s_kwd} = '';
2093          !!!next-input-character;          !!!next-input-character;
2094    
2095          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 1910  sub _get_next_token ($) { Line 2101  sub _get_next_token ($) {
2101          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2102    
2103          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2104            $self->{s_kwd} = '';
2105          ## reconsume          ## reconsume
2106    
2107          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 1938  sub _get_next_token ($) { Line 2130  sub _get_next_token ($) {
2130          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2131    
2132          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2133            $self->{s_kwd} = '';
2134          !!!next-input-character;          !!!next-input-character;
2135    
2136          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 1949  sub _get_next_token ($) { Line 2142  sub _get_next_token ($) {
2142          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2143    
2144          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2145            $self->{s_kwd} = '';
2146          ## reconsume          ## reconsume
2147    
2148          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 1987  sub _get_next_token ($) { Line 2181  sub _get_next_token ($) {
2181        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
2182          !!!cp (198);          !!!cp (198);
2183          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2184            $self->{s_kwd} = '';
2185          !!!next-input-character;          !!!next-input-character;
2186    
2187          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
# Line 1997  sub _get_next_token ($) { Line 2192  sub _get_next_token ($) {
2192          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
2193    
2194          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2195            $self->{s_kwd} = '';
2196          ## reconsume          ## reconsume
2197    
2198          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 2034  sub _get_next_token ($) { Line 2230  sub _get_next_token ($) {
2230          !!!cp (204);          !!!cp (204);
2231          !!!parse-error (type => 'no SYSTEM literal');          !!!parse-error (type => 'no SYSTEM literal');
2232          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2233            $self->{s_kwd} = '';
2234          !!!next-input-character;          !!!next-input-character;
2235    
2236          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 2045  sub _get_next_token ($) { Line 2242  sub _get_next_token ($) {
2242          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
2243    
2244          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2245            $self->{s_kwd} = '';
2246          ## reconsume          ## reconsume
2247    
2248          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 2071  sub _get_next_token ($) { Line 2269  sub _get_next_token ($) {
2269          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2270    
2271          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2272            $self->{s_kwd} = '';
2273          !!!next-input-character;          !!!next-input-character;
2274    
2275          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 2082  sub _get_next_token ($) { Line 2281  sub _get_next_token ($) {
2281          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2282    
2283          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2284            $self->{s_kwd} = '';
2285          ## reconsume          ## reconsume
2286    
2287          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 2110  sub _get_next_token ($) { Line 2310  sub _get_next_token ($) {
2310          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2311    
2312          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2313            $self->{s_kwd} = '';
2314          !!!next-input-character;          !!!next-input-character;
2315    
2316          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 2121  sub _get_next_token ($) { Line 2322  sub _get_next_token ($) {
2322          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2323    
2324          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2325            $self->{s_kwd} = '';
2326          ## reconsume          ## reconsume
2327    
2328          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 2147  sub _get_next_token ($) { Line 2349  sub _get_next_token ($) {
2349        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
2350          !!!cp (216);          !!!cp (216);
2351          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2352            $self->{s_kwd} = '';
2353          !!!next-input-character;          !!!next-input-character;
2354    
2355          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
# Line 2156  sub _get_next_token ($) { Line 2359  sub _get_next_token ($) {
2359          !!!cp (217);          !!!cp (217);
2360          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
2361          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2362            $self->{s_kwd} = '';
2363          ## reconsume          ## reconsume
2364    
2365          $self->{ct}->{quirks} = 1;          $self->{ct}->{quirks} = 1;
# Line 2175  sub _get_next_token ($) { Line 2379  sub _get_next_token ($) {
2379        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2380          !!!cp (219);          !!!cp (219);
2381          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2382            $self->{s_kwd} = '';
2383          !!!next-input-character;          !!!next-input-character;
2384    
2385          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
# Line 2183  sub _get_next_token ($) { Line 2388  sub _get_next_token ($) {
2388        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2389          !!!cp (220);          !!!cp (220);
2390          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2391            $self->{s_kwd} = '';
2392          ## reconsume          ## reconsume
2393    
2394          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
# Line 2201  sub _get_next_token ($) { Line 2407  sub _get_next_token ($) {
2407        ## NOTE: "CDATA section state" in the state is jointly implemented        ## NOTE: "CDATA section state" in the state is jointly implemented
2408        ## by three states, |CDATA_SECTION_STATE|, |CDATA_SECTION_MSE1_STATE|,        ## by three states, |CDATA_SECTION_STATE|, |CDATA_SECTION_MSE1_STATE|,
2409        ## and |CDATA_SECTION_MSE2_STATE|.        ## and |CDATA_SECTION_MSE2_STATE|.
2410    
2411          ## XML5: "CDATA state".
2412                
2413        if ($self->{nc} == 0x005D) { # ]        if ($self->{nc} == 0x005D) { # ]
2414          !!!cp (221.1);          !!!cp (221.1);
# Line 2208  sub _get_next_token ($) { Line 2416  sub _get_next_token ($) {
2416          !!!next-input-character;          !!!next-input-character;
2417          redo A;          redo A;
2418        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2419            if ($self->{is_xml}) {
2420              !!!cp (221.11);
2421              !!!parse-error (type => 'no mse'); ## TODO: type
2422            } else {
2423              !!!cp (221.12);
2424            }
2425    
2426          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2427          !!!next-input-character;          $self->{s_kwd} = '';
2428            ## Reconsume.
2429          if (length $self->{ct}->{data}) { # character          if (length $self->{ct}->{data}) { # character
2430            !!!cp (221.2);            !!!cp (221.2);
2431            !!!emit ($self->{ct}); # character            !!!emit ($self->{ct}); # character
# Line 2232  sub _get_next_token ($) { Line 2448  sub _get_next_token ($) {
2448    
2449        ## ISSUE: "text tokens" in spec.        ## ISSUE: "text tokens" in spec.
2450      } elsif ($self->{state} == CDATA_SECTION_MSE1_STATE) {      } elsif ($self->{state} == CDATA_SECTION_MSE1_STATE) {
2451          ## XML5: "CDATA bracket state".
2452    
2453        if ($self->{nc} == 0x005D) { # ]        if ($self->{nc} == 0x005D) { # ]
2454          !!!cp (221.5);          !!!cp (221.5);
2455          $self->{state} = CDATA_SECTION_MSE2_STATE;          $self->{state} = CDATA_SECTION_MSE2_STATE;
# Line 2239  sub _get_next_token ($) { Line 2457  sub _get_next_token ($) {
2457          redo A;          redo A;
2458        } else {        } else {
2459          !!!cp (221.6);          !!!cp (221.6);
2460            ## XML5: If EOF, "]" is not appended and changed to the data state.
2461          $self->{ct}->{data} .= ']';          $self->{ct}->{data} .= ']';
2462          $self->{state} = CDATA_SECTION_STATE;          $self->{state} = CDATA_SECTION_STATE; ## XML5: Stay in the state.
2463          ## Reconsume.          ## Reconsume.
2464          redo A;          redo A;
2465        }        }
2466      } elsif ($self->{state} == CDATA_SECTION_MSE2_STATE) {      } elsif ($self->{state} == CDATA_SECTION_MSE2_STATE) {
2467          ## XML5: "CDATA end state".
2468    
2469        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2470          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2471            $self->{s_kwd} = '';
2472          !!!next-input-character;          !!!next-input-character;
2473          if (length $self->{ct}->{data}) { # character          if (length $self->{ct}->{data}) { # character
2474            !!!cp (221.7);            !!!cp (221.7);
# Line 2266  sub _get_next_token ($) { Line 2488  sub _get_next_token ($) {
2488          !!!cp (221.11);          !!!cp (221.11);
2489          $self->{ct}->{data} .= ']]'; # character          $self->{ct}->{data} .= ']]'; # character
2490          $self->{state} = CDATA_SECTION_STATE;          $self->{state} = CDATA_SECTION_STATE;
2491          ## Reconsume.          ## Reconsume. ## XML5: Emit.
2492          redo A;          redo A;
2493        }        }
2494      } elsif ($self->{state} == ENTITY_STATE) {      } elsif ($self->{state} == ENTITY_STATE) {
# Line 2314  sub _get_next_token ($) { Line 2536  sub _get_next_token ($) {
2536        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
2537          !!!cp (997);          !!!cp (997);
2538          $self->{state} = $self->{prev_state};          $self->{state} = $self->{prev_state};
2539            $self->{s_kwd} = '';
2540          ## Reconsume.          ## Reconsume.
2541          !!!emit ({type => CHARACTER_TOKEN, data => '&',          !!!emit ({type => CHARACTER_TOKEN, data => '&',
2542                    line => $self->{line_prev},                    line => $self->{line_prev},
# Line 2324  sub _get_next_token ($) { Line 2547  sub _get_next_token ($) {
2547          !!!cp (996);          !!!cp (996);
2548          $self->{ca}->{value} .= '&';          $self->{ca}->{value} .= '&';
2549          $self->{state} = $self->{prev_state};          $self->{state} = $self->{prev_state};
2550            $self->{s_kwd} = '';
2551          ## Reconsume.          ## Reconsume.
2552          redo A;          redo A;
2553        }        }
# Line 2354  sub _get_next_token ($) { Line 2578  sub _get_next_token ($) {
2578          if ($self->{prev_state} == DATA_STATE) {          if ($self->{prev_state} == DATA_STATE) {
2579            !!!cp (1019);            !!!cp (1019);
2580            $self->{state} = $self->{prev_state};            $self->{state} = $self->{prev_state};
2581              $self->{s_kwd} = '';
2582            ## Reconsume.            ## Reconsume.
2583            !!!emit ({type => CHARACTER_TOKEN,            !!!emit ({type => CHARACTER_TOKEN,
2584                      data => '&#',                      data => '&#',
# Line 2365  sub _get_next_token ($) { Line 2590  sub _get_next_token ($) {
2590            !!!cp (993);            !!!cp (993);
2591            $self->{ca}->{value} .= '&#';            $self->{ca}->{value} .= '&#';
2592            $self->{state} = $self->{prev_state};            $self->{state} = $self->{prev_state};
2593              $self->{s_kwd} = '';
2594            ## Reconsume.            ## Reconsume.
2595            redo A;            redo A;
2596          }          }
# Line 2410  sub _get_next_token ($) { Line 2636  sub _get_next_token ($) {
2636        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
2637          !!!cp (992);          !!!cp (992);
2638          $self->{state} = $self->{prev_state};          $self->{state} = $self->{prev_state};
2639            $self->{s_kwd} = '';
2640          ## Reconsume.          ## Reconsume.
2641          !!!emit ({type => CHARACTER_TOKEN, data => chr $code,          !!!emit ({type => CHARACTER_TOKEN, data => chr $code,
2642                      has_reference => 1,
2643                    line => $l, column => $c,                    line => $l, column => $c,
2644                   });                   });
2645          redo A;          redo A;
# Line 2420  sub _get_next_token ($) { Line 2648  sub _get_next_token ($) {
2648          $self->{ca}->{value} .= chr $code;          $self->{ca}->{value} .= chr $code;
2649          $self->{ca}->{has_reference} = 1;          $self->{ca}->{has_reference} = 1;
2650          $self->{state} = $self->{prev_state};          $self->{state} = $self->{prev_state};
2651            $self->{s_kwd} = '';
2652          ## Reconsume.          ## Reconsume.
2653          redo A;          redo A;
2654        }        }
# Line 2445  sub _get_next_token ($) { Line 2674  sub _get_next_token ($) {
2674          if ($self->{prev_state} == DATA_STATE) {          if ($self->{prev_state} == DATA_STATE) {
2675            !!!cp (1005);            !!!cp (1005);
2676            $self->{state} = $self->{prev_state};            $self->{state} = $self->{prev_state};
2677              $self->{s_kwd} = '';
2678            ## Reconsume.            ## Reconsume.
2679            !!!emit ({type => CHARACTER_TOKEN,            !!!emit ({type => CHARACTER_TOKEN,
2680                      data => '&' . $self->{s_kwd},                      data => '&' . $self->{s_kwd},
# Line 2456  sub _get_next_token ($) { Line 2686  sub _get_next_token ($) {
2686            !!!cp (989);            !!!cp (989);
2687            $self->{ca}->{value} .= '&' . $self->{s_kwd};            $self->{ca}->{value} .= '&' . $self->{s_kwd};
2688            $self->{state} = $self->{prev_state};            $self->{state} = $self->{prev_state};
2689              $self->{s_kwd} = '';
2690            ## Reconsume.            ## Reconsume.
2691            redo A;            redo A;
2692          }          }
# Line 2518  sub _get_next_token ($) { Line 2749  sub _get_next_token ($) {
2749        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
2750          !!!cp (988);          !!!cp (988);
2751          $self->{state} = $self->{prev_state};          $self->{state} = $self->{prev_state};
2752            $self->{s_kwd} = '';
2753          ## Reconsume.          ## Reconsume.
2754          !!!emit ({type => CHARACTER_TOKEN, data => chr $code,          !!!emit ({type => CHARACTER_TOKEN, data => chr $code,
2755                      has_reference => 1,
2756                    line => $l, column => $c,                    line => $l, column => $c,
2757                   });                   });
2758          redo A;          redo A;
# Line 2528  sub _get_next_token ($) { Line 2761  sub _get_next_token ($) {
2761          $self->{ca}->{value} .= chr $code;          $self->{ca}->{value} .= chr $code;
2762          $self->{ca}->{has_reference} = 1;          $self->{ca}->{has_reference} = 1;
2763          $self->{state} = $self->{prev_state};          $self->{state} = $self->{prev_state};
2764            $self->{s_kwd} = '';
2765          ## Reconsume.          ## Reconsume.
2766          redo A;          redo A;
2767        }        }
# Line 2610  sub _get_next_token ($) { Line 2844  sub _get_next_token ($) {
2844        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
2845          !!!cp (986);          !!!cp (986);
2846          $self->{state} = $self->{prev_state};          $self->{state} = $self->{prev_state};
2847            $self->{s_kwd} = '';
2848          ## Reconsume.          ## Reconsume.
2849          !!!emit ({type => CHARACTER_TOKEN,          !!!emit ({type => CHARACTER_TOKEN,
2850                    data => $data,                    data => $data,
2851                      has_reference => $has_ref,
2852                    line => $self->{line_prev},                    line => $self->{line_prev},
2853                    column => $self->{column_prev} + 1 - length $self->{s_kwd},                    column => $self->{column_prev} + 1 - length $self->{s_kwd},
2854                   });                   });
# Line 2622  sub _get_next_token ($) { Line 2858  sub _get_next_token ($) {
2858          $self->{ca}->{value} .= $data;          $self->{ca}->{value} .= $data;
2859          $self->{ca}->{has_reference} = 1 if $has_ref;          $self->{ca}->{has_reference} = 1 if $has_ref;
2860          $self->{state} = $self->{prev_state};          $self->{state} = $self->{prev_state};
2861            $self->{s_kwd} = '';
2862            ## Reconsume.
2863            redo A;
2864          }
2865    
2866        ## XML-only states
2867    
2868        } elsif ($self->{state} == PI_STATE) {
2869          if ($is_space->{$self->{nc}} or
2870              $self->{nc} == 0x003F or # ? ## XML5: Same as "Anything else"
2871              $self->{nc} == -1) {
2872            !!!parse-error (type => 'bare pio', ## TODO: type
2873                            line => $self->{line_prev},
2874                            column => $self->{column_prev}
2875                                - 1 * ($self->{nc} != -1));
2876            $self->{state} = BOGUS_COMMENT_STATE;
2877          ## Reconsume.          ## Reconsume.
2878            $self->{ct} = {type => COMMENT_TOKEN,
2879                           data => '?',
2880                           line => $self->{line_prev},
2881                           column => $self->{column_prev}
2882                               - 1 * ($self->{nc} != -1),
2883                          };
2884            redo A;
2885          } else {
2886            $self->{ct} = {type => PI_TOKEN,
2887                           target => chr $self->{nc},
2888                           data => '',
2889                           line => $self->{line_prev},
2890                           column => $self->{column_prev} - 1,
2891                          };
2892            $self->{state} = PI_TARGET_STATE;
2893            !!!next-input-character;
2894          redo A;          redo A;
2895        }        }
2896        } elsif ($self->{state} == PI_TARGET_STATE) {
2897          if ($is_space->{$self->{nc}}) {
2898            $self->{state} = PI_TARGET_AFTER_STATE;
2899            !!!next-input-character;
2900            redo A;
2901          } elsif ($self->{nc} == -1) {
2902            !!!parse-error (type => 'no pic'); ## TODO: type
2903            $self->{state} = DATA_STATE;
2904            $self->{s_kwd} = '';
2905            ## Reconsume.
2906            !!!emit ($self->{ct}); # pi
2907            redo A;
2908          } elsif ($self->{nc} == 0x003F) { # ?
2909            $self->{state} = PI_AFTER_STATE;
2910            !!!next-input-character;
2911            redo A;
2912          } else {
2913            ## XML5: typo ("tag name" -> "target")
2914            $self->{ct}->{target} .= chr $self->{nc}; # pi
2915            !!!next-input-character;
2916            redo A;
2917          }
2918        } elsif ($self->{state} == PI_TARGET_AFTER_STATE) {
2919          if ($is_space->{$self->{nc}}) {
2920            ## Stay in the state.
2921            !!!next-input-character;
2922            redo A;
2923          } else {
2924            $self->{state} = PI_DATA_STATE;
2925            ## Reprocess.
2926            redo A;
2927          }
2928        } elsif ($self->{state} == PI_DATA_STATE) {
2929          if ($self->{nc} == 0x003F) { # ?
2930            $self->{state} = PI_DATA_AFTER_STATE;
2931            !!!next-input-character;
2932            redo A;
2933          } elsif ($self->{nc} == -1) {
2934            !!!parse-error (type => 'no pic'); ## TODO: type
2935            $self->{state} = DATA_STATE;
2936            $self->{s_kwd} = '';
2937            ## Reprocess.
2938            !!!emit ($self->{ct}); # pi
2939            redo A;
2940          } else {
2941            $self->{ct}->{data} .= chr $self->{nc}; # pi
2942            $self->{read_until}->($self->{ct}->{data}, q[?],
2943                                  length $self->{ct}->{data});
2944            ## Stay in the state.
2945            !!!next-input-character;
2946            ## Reprocess.
2947            redo A;
2948          }
2949        } elsif ($self->{state} == PI_AFTER_STATE) {
2950          if ($self->{nc} == 0x003E) { # >
2951            $self->{state} = DATA_STATE;
2952            $self->{s_kwd} = '';
2953            !!!next-input-character;
2954            !!!emit ($self->{ct}); # pi
2955            redo A;
2956          } elsif ($self->{nc} == 0x003F) { # ?
2957            !!!parse-error (type => 'no s after target', ## TODO: type
2958                            line => $self->{line_prev},
2959                            column => $self->{column_prev}); ## XML5: no error
2960            $self->{ct}->{data} .= '?';
2961            $self->{state} = PI_DATA_AFTER_STATE;
2962            !!!next-input-character;
2963            redo A;
2964          } else {
2965            !!!parse-error (type => 'no s after target', ## TODO: type
2966                            line => $self->{line_prev},
2967                            column => $self->{column_prev}
2968                                + 1 * ($self->{nc} == -1)); ## XML5: no error
2969            $self->{ct}->{data} .= '?'; ## XML5: not appended
2970            $self->{state} = PI_DATA_STATE;
2971            ## Reprocess.
2972            redo A;
2973          }
2974        } elsif ($self->{state} == PI_DATA_AFTER_STATE) {
2975          ## XML5: Same as "pi after state" in XML5
2976          if ($self->{nc} == 0x003E) { # >
2977            $self->{state} = DATA_STATE;
2978            $self->{s_kwd} = '';
2979            !!!next-input-character;
2980            !!!emit ($self->{ct}); # pi
2981            redo A;
2982          } elsif ($self->{nc} == 0x003F) { # ?
2983            $self->{ct}->{data} .= '?';
2984            ## Stay in the state.
2985            !!!next-input-character;
2986            redo A;
2987          } else {
2988            $self->{ct}->{data} .= '?'; ## XML5: not appended
2989            $self->{state} = PI_DATA_STATE;
2990            ## Reprocess.
2991            redo A;
2992          }
2993            
2994      } else {      } else {
2995        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
2996      }      }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.10

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24