/[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.12 by wakaba, Wed Oct 15 12:49:49 2008 UTC revision 1.31 by wakaba, Sat Sep 5 09:26:55 2009 UTC
# Line 15  BEGIN { Line 15  BEGIN {
15      CHARACTER_TOKEN      CHARACTER_TOKEN
16      PI_TOKEN      PI_TOKEN
17      ABORT_TOKEN      ABORT_TOKEN
18        END_OF_DOCTYPE_TOKEN
19        ATTLIST_TOKEN
20        ELEMENT_TOKEN
21        GENERAL_ENTITY_TOKEN
22        PARAMETER_ENTITY_TOKEN
23        NOTATION_TOKEN
24    );    );
25        
26    our %EXPORT_TAGS = (    our %EXPORT_TAGS = (
# Line 27  BEGIN { Line 33  BEGIN {
33        CHARACTER_TOKEN        CHARACTER_TOKEN
34        PI_TOKEN        PI_TOKEN
35        ABORT_TOKEN        ABORT_TOKEN
36          END_OF_DOCTYPE_TOKEN
37          ATTLIST_TOKEN
38          ELEMENT_TOKEN
39          GENERAL_ENTITY_TOKEN
40          PARAMETER_ENTITY_TOKEN
41          NOTATION_TOKEN
42      )],      )],
43    );    );
44  }  }
# Line 43  sub END_OF_FILE_TOKEN () { 5 } Line 55  sub END_OF_FILE_TOKEN () { 5 }
55  sub CHARACTER_TOKEN () { 6 }  sub CHARACTER_TOKEN () { 6 }
56  sub PI_TOKEN () { 7 } ## NOTE: XML only.  sub PI_TOKEN () { 7 } ## NOTE: XML only.
57  sub ABORT_TOKEN () { 8 } ## NOTE: For internal processing.  sub ABORT_TOKEN () { 8 } ## NOTE: For internal processing.
58    sub END_OF_DOCTYPE_TOKEN () { 9 } ## NOTE: XML only.
59    sub ATTLIST_TOKEN () { 10 } ## NOTE: XML only.
60    sub ELEMENT_TOKEN () { 11 } ## NOTE: XML only.
61    sub GENERAL_ENTITY_TOKEN () { 12 } ## NOTE: XML only.
62    sub PARAMETER_ENTITY_TOKEN () { 13 } ## NOTE: XML only.
63    sub NOTATION_TOKEN () { 14 } ## NOTE: XML only.
64    
65  ## XML5: XML5 has "empty tag token".  In this implementation, it is  ## XML5: XML5 has "empty tag token".  In this implementation, it is
66  ## represented as a start tag token with $self->{self_closing} flag  ## represented as a start tag token with $self->{self_closing} flag
# Line 87  sub COMMENT_START_STATE () { 14 } Line 105  sub COMMENT_START_STATE () { 14 }
105  sub COMMENT_START_DASH_STATE () { 15 }  sub COMMENT_START_DASH_STATE () { 15 }
106  sub COMMENT_STATE () { 16 }  sub COMMENT_STATE () { 16 }
107  sub COMMENT_END_STATE () { 17 }  sub COMMENT_END_STATE () { 17 }
108    sub COMMENT_END_BANG_STATE () { 102 } ## LAST
109  sub COMMENT_END_DASH_STATE () { 18 }  sub COMMENT_END_DASH_STATE () { 18 }
110  sub BOGUS_COMMENT_STATE () { 19 }  sub BOGUS_COMMENT_STATE () { 19 }
111  sub DOCTYPE_STATE () { 20 }  sub DOCTYPE_STATE () { 20 }
# Line 133  sub PI_AFTER_STATE () { 55 } Line 152  sub PI_AFTER_STATE () { 55 }
152  sub PI_DATA_AFTER_STATE () { 56 }  sub PI_DATA_AFTER_STATE () { 56 }
153  sub DOCTYPE_INTERNAL_SUBSET_STATE () { 57 }  sub DOCTYPE_INTERNAL_SUBSET_STATE () { 57 }
154  sub DOCTYPE_INTERNAL_SUBSET_AFTER_STATE () { 58 }  sub DOCTYPE_INTERNAL_SUBSET_AFTER_STATE () { 58 }
155    sub BOGUS_DOCTYPE_INTERNAL_SUBSET_AFTER_STATE () { 59 }
156    sub DOCTYPE_TAG_STATE () { 60 }
157    sub DOCTYPE_MARKUP_DECLARATION_OPEN_STATE () { 61 }
158    sub MD_ATTLIST_STATE () { 62 }
159    sub MD_E_STATE () { 63 }
160    sub MD_ELEMENT_STATE () { 64 }
161    sub MD_ENTITY_STATE () { 65 }
162    sub MD_NOTATION_STATE () { 66 }
163    sub DOCTYPE_MD_STATE () { 67 }
164    sub BEFORE_MD_NAME_STATE () { 68 }
165    sub MD_NAME_STATE () { 69 }
166    sub DOCTYPE_ENTITY_PARAMETER_BEFORE_STATE () { 70 }
167    sub DOCTYPE_ATTLIST_NAME_AFTER_STATE () { 71 }
168    sub DOCTYPE_ATTLIST_ATTRIBUTE_NAME_STATE () { 72 }
169    sub DOCTYPE_ATTLIST_ATTRIBUTE_NAME_AFTER_STATE () { 73 }
170    sub DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_STATE () { 74 }
171    sub DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_AFTER_STATE () { 75 }
172    sub BEFORE_ALLOWED_TOKEN_STATE () { 76 }
173    sub ALLOWED_TOKEN_STATE () { 77 }
174    sub AFTER_ALLOWED_TOKEN_STATE () { 78 }
175    sub AFTER_ALLOWED_TOKENS_STATE () { 79 }
176    sub BEFORE_ATTR_DEFAULT_STATE () { 80 }
177    sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE () { 81 }
178    sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
179    sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
180    sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }
181    sub BEFORE_NDATA_STATE () { 85 }
182    sub NDATA_STATE () { 86 }
183    sub AFTER_NDATA_STATE () { 87 }
184    sub BEFORE_NOTATION_NAME_STATE () { 88 }
185    sub NOTATION_NAME_STATE () { 89 }
186    sub DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE () { 90 }
187    sub DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE () { 91 }
188    sub ENTITY_VALUE_ENTITY_STATE () { 92 }
189    sub AFTER_ELEMENT_NAME_STATE () { 93 }
190    sub BEFORE_ELEMENT_CONTENT_STATE () { 94 }
191    sub CONTENT_KEYWORD_STATE () { 95 }
192    sub AFTER_CM_GROUP_OPEN_STATE () { 96 }
193    sub CM_ELEMENT_NAME_STATE () { 97 }
194    sub AFTER_CM_ELEMENT_NAME_STATE () { 98 }
195    sub AFTER_CM_GROUP_CLOSE_STATE () { 99 }
196    sub AFTER_MD_DEF_STATE () { 100 }
197    sub BOGUS_MD_STATE () { 101 }
198    
199  ## Tree constructor state constants (see Whatpm::HTML for the full  ## Tree constructor state constants (see Whatpm::HTML for the full
200  ## list and descriptions)  ## list and descriptions)
# Line 887  sub _get_next_token ($) { Line 949  sub _get_next_token ($) {
949          if ({          if ({
950               0x0022 => 1, # "               0x0022 => 1, # "
951               0x0027 => 1, # '               0x0027 => 1, # '
952                 0x003C => 1, # <
953               0x003D => 1, # =               0x003D => 1, # =
954              }->{$self->{nc}}) {              }->{$self->{nc}}) {
955            !!!cp (55);            !!!cp (55);
# Line 1009  sub _get_next_token ($) { Line 1072  sub _get_next_token ($) {
1072    
1073          redo A;          redo A;
1074        } else {        } else {
1075          if ($self->{nc} == 0x0022 or # "          if ({
1076              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1077                 0x0027 => 1, # '
1078                 0x003C => 1, # <
1079                }->{$self->{nc}}) {
1080            !!!cp (69);            !!!cp (69);
1081            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1082            !!!parse-error (type => 'bad attribute name');            !!!parse-error (type => 'bad attribute name');
# Line 1121  sub _get_next_token ($) { Line 1187  sub _get_next_token ($) {
1187            !!!cp (78.2);            !!!cp (78.2);
1188          }          }
1189    
1190          if ($self->{nc} == 0x0022 or # "          if ({
1191              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1192                 0x0027 => 1, # '
1193                 0x003C => 1, # <
1194                }->{$self->{nc}}) {
1195            !!!cp (78);            !!!cp (78);
1196            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1197            !!!parse-error (type => 'bad attribute name');            !!!parse-error (type => 'bad attribute name');
# Line 1209  sub _get_next_token ($) { Line 1278  sub _get_next_token ($) {
1278    
1279          redo A;          redo A;
1280        } else {        } else {
1281          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1282            !!!cp (93);            !!!cp (93);
1283            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1284            !!!parse-error (type => 'bad attribute value');            !!!parse-error (type => 'bad attribute value');
# Line 1226  sub _get_next_token ($) { Line 1295  sub _get_next_token ($) {
1295          redo A;          redo A;
1296        }        }
1297      } elsif ($self->{state} == ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE) {      } elsif ($self->{state} == ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE) {
1298        ## XML5: "Tag attribute value double quoted state".        ## XML5: "Tag attribute value double quoted state" and "DOCTYPE
1299          ## ATTLIST attribute value double quoted state".
1300                
1301        if ($self->{nc} == 0x0022) { # "        if ($self->{nc} == 0x0022) { # "
1302          !!!cp (95);          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
1303          ## XML5: "Tag attribute name before state".            !!!cp (95.1);
1304          $self->{state} = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;            ## XML5: "DOCTYPE ATTLIST name after state".
1305              push @{$self->{ct}->{attrdefs}}, $self->{ca};
1306              $self->{state} = AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE;
1307            } else {
1308              !!!cp (95);
1309              ## XML5: "Tag attribute name before state".
1310              $self->{state} = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;
1311            }
1312          !!!next-input-character;          !!!next-input-character;
1313          redo A;          redo A;
1314        } elsif ($self->{nc} == 0x0026) { # &        } elsif ($self->{nc} == 0x0026) { # &
# Line 1247  sub _get_next_token ($) { Line 1324  sub _get_next_token ($) {
1324          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1325          !!!next-input-character;          !!!next-input-character;
1326          redo A;          redo A;
1327          } elsif ($self->{is_xml} and
1328                   $is_space->{$self->{nc}}) {
1329            !!!cp (97.1);
1330            $self->{ca}->{value} .= ' ';
1331            ## Stay in the state.
1332            !!!next-input-character;
1333            redo A;
1334        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1335          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1336          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
1337            !!!cp (97);            !!!cp (97);
1338            $self->{last_stag_name} = $self->{ct}->{tag_name};            $self->{last_stag_name} = $self->{ct}->{tag_name};
1339    
1340              $self->{state} = DATA_STATE;
1341              $self->{s_kwd} = '';
1342              ## reconsume
1343              !!!emit ($self->{ct}); # start tag
1344              redo A;
1345          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
1346            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
1347            if ($self->{ct}->{attributes}) {            if ($self->{ct}->{attributes}) {
# Line 1261  sub _get_next_token ($) { Line 1351  sub _get_next_token ($) {
1351              ## NOTE: This state should never be reached.              ## NOTE: This state should never be reached.
1352              !!!cp (99);              !!!cp (99);
1353            }            }
1354    
1355              $self->{state} = DATA_STATE;
1356              $self->{s_kwd} = '';
1357              ## reconsume
1358              !!!emit ($self->{ct}); # end tag
1359              redo A;
1360            } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1361              ## XML5: No parse error above; not defined yet.
1362              push @{$self->{ct}->{attrdefs}}, $self->{ca};
1363              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1364              ## Reconsume.
1365              !!!emit ($self->{ct}); # ATTLIST
1366              redo A;
1367          } else {          } else {
1368            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1369          }          }
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
         ## reconsume  
   
         !!!emit ($self->{ct}); # start tag or end tag  
   
         redo A;  
1370        } else {        } else {
1371            ## XML5 [ATTLIST]: Not defined yet.
1372          if ($self->{is_xml} and $self->{nc} == 0x003C) { # <          if ($self->{is_xml} and $self->{nc} == 0x003C) { # <
1373            !!!cp (100);            !!!cp (100);
1374            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 1281  sub _get_next_token ($) { Line 1378  sub _get_next_token ($) {
1378          }          }
1379          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1380          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1381                                q["&<],                                qq["&<\x09\x0C\x20],
1382                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1383    
1384          ## Stay in the state          ## Stay in the state
# Line 1289  sub _get_next_token ($) { Line 1386  sub _get_next_token ($) {
1386          redo A;          redo A;
1387        }        }
1388      } elsif ($self->{state} == ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE) {      } elsif ($self->{state} == ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE) {
1389        ## XML5: "Tag attribute value single quoted state".        ## XML5: "Tag attribute value single quoted state" and "DOCTYPE
1390          ## ATTLIST attribute value single quoted state".
1391    
1392        if ($self->{nc} == 0x0027) { # '        if ($self->{nc} == 0x0027) { # '
1393          !!!cp (101);          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
1394          ## XML5: "Before attribute name state" (sic).            !!!cp (101.1);
1395          $self->{state} = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;            ## XML5: "DOCTYPE ATTLIST name after state".
1396              push @{$self->{ct}->{attrdefs}}, $self->{ca};
1397              $self->{state} = AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE;
1398            } else {
1399              !!!cp (101);
1400              ## XML5: "Before attribute name state" (sic).
1401              $self->{state} = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;
1402            }
1403          !!!next-input-character;          !!!next-input-character;
1404          redo A;          redo A;
1405        } elsif ($self->{nc} == 0x0026) { # &        } elsif ($self->{nc} == 0x0026) { # &
# Line 1310  sub _get_next_token ($) { Line 1415  sub _get_next_token ($) {
1415          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1416          !!!next-input-character;          !!!next-input-character;
1417          redo A;          redo A;
1418          } elsif ($self->{is_xml} and
1419                   $is_space->{$self->{nc}}) {
1420            !!!cp (103.1);
1421            $self->{ca}->{value} .= ' ';
1422            ## Stay in the state.
1423            !!!next-input-character;
1424            redo A;
1425        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1426          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1427          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
1428            !!!cp (103);            !!!cp (103);
1429            $self->{last_stag_name} = $self->{ct}->{tag_name};            $self->{last_stag_name} = $self->{ct}->{tag_name};
1430    
1431              $self->{state} = DATA_STATE;
1432              $self->{s_kwd} = '';
1433              ## reconsume
1434              !!!emit ($self->{ct}); # start tag
1435              redo A;
1436          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
1437            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
1438            if ($self->{ct}->{attributes}) {            if ($self->{ct}->{attributes}) {
# Line 1324  sub _get_next_token ($) { Line 1442  sub _get_next_token ($) {
1442              ## NOTE: This state should never be reached.              ## NOTE: This state should never be reached.
1443              !!!cp (105);              !!!cp (105);
1444            }            }
1445    
1446              $self->{state} = DATA_STATE;
1447              $self->{s_kwd} = '';
1448              ## reconsume
1449              !!!emit ($self->{ct}); # end tag
1450              redo A;
1451            } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1452              ## XML5: No parse error above; not defined yet.
1453              push @{$self->{ct}->{attrdefs}}, $self->{ca};
1454              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1455              ## Reconsume.
1456              !!!emit ($self->{ct}); # ATTLIST
1457              redo A;
1458          } else {          } else {
1459            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1460          }          }
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
         ## reconsume  
   
         !!!emit ($self->{ct}); # start tag or end tag  
   
         redo A;  
1461        } else {        } else {
1462            ## XML5 [ATTLIST]: Not defined yet.
1463          if ($self->{is_xml} and $self->{nc} == 0x003C) { # <          if ($self->{is_xml} and $self->{nc} == 0x003C) { # <
1464            !!!cp (106);            !!!cp (106);
1465            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 1344  sub _get_next_token ($) { Line 1469  sub _get_next_token ($) {
1469          }          }
1470          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1471          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1472                                q['&<],                                qq['&<\x09\x0C\x20],
1473                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1474    
1475          ## Stay in the state          ## Stay in the state
# Line 1355  sub _get_next_token ($) { Line 1480  sub _get_next_token ($) {
1480        ## XML5: "Tag attribute value unquoted state".        ## XML5: "Tag attribute value unquoted state".
1481    
1482        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
1483          !!!cp (107);          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
1484          ## XML5: "Tag attribute name before state".            !!!cp (107.1);
1485          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;            push @{$self->{ct}->{attrdefs}}, $self->{ca};
1486              $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
1487            } else {
1488              !!!cp (107);
1489              ## XML5: "Tag attribute name before state".
1490              $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
1491            }
1492          !!!next-input-character;          !!!next-input-character;
1493          redo A;          redo A;
1494        } elsif ($self->{nc} == 0x0026) { # &        } elsif ($self->{nc} == 0x0026) { # &
# Line 1378  sub _get_next_token ($) { Line 1509  sub _get_next_token ($) {
1509          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
1510            !!!cp (109);            !!!cp (109);
1511            $self->{last_stag_name} = $self->{ct}->{tag_name};            $self->{last_stag_name} = $self->{ct}->{tag_name};
1512    
1513              $self->{state} = DATA_STATE;
1514              $self->{s_kwd} = '';
1515              !!!next-input-character;
1516              !!!emit ($self->{ct}); # start tag
1517              redo A;
1518          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
1519            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
1520            if ($self->{ct}->{attributes}) {            if ($self->{ct}->{attributes}) {
# Line 1387  sub _get_next_token ($) { Line 1524  sub _get_next_token ($) {
1524              ## NOTE: This state should never be reached.              ## NOTE: This state should never be reached.
1525              !!!cp (111);              !!!cp (111);
1526            }            }
1527    
1528              $self->{state} = DATA_STATE;
1529              $self->{s_kwd} = '';
1530              !!!next-input-character;
1531              !!!emit ($self->{ct}); # end tag
1532              redo A;
1533            } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1534              push @{$self->{ct}->{attrdefs}}, $self->{ca};
1535              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1536              !!!next-input-character;
1537              !!!emit ($self->{ct}); # ATTLIST
1538              redo A;
1539          } else {          } else {
1540            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1541          }          }
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
         !!!next-input-character;  
   
         !!!emit ($self->{ct}); # start tag or end tag  
   
         redo A;  
1542        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!parse-error (type => 'unclosed tag');  
1543          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
1544            !!!cp (112);            !!!cp (112);
1545              !!!parse-error (type => 'unclosed tag');
1546            $self->{last_stag_name} = $self->{ct}->{tag_name};            $self->{last_stag_name} = $self->{ct}->{tag_name};
1547    
1548              $self->{state} = DATA_STATE;
1549              $self->{s_kwd} = '';
1550              ## reconsume
1551              !!!emit ($self->{ct}); # start tag
1552              redo A;
1553          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
1554              !!!parse-error (type => 'unclosed tag');
1555            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
1556            if ($self->{ct}->{attributes}) {            if ($self->{ct}->{attributes}) {
1557              !!!cp (113);              !!!cp (113);
# Line 1411  sub _get_next_token ($) { Line 1560  sub _get_next_token ($) {
1560              ## NOTE: This state should never be reached.              ## NOTE: This state should never be reached.
1561              !!!cp (114);              !!!cp (114);
1562            }            }
1563    
1564              $self->{state} = DATA_STATE;
1565              $self->{s_kwd} = '';
1566              ## reconsume
1567              !!!emit ($self->{ct}); # end tag
1568              redo A;
1569            } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1570              !!!parse-error (type => 'unclosed md'); ## TODO: type
1571              push @{$self->{ct}->{attrdefs}}, $self->{ca};
1572              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1573              ## Reconsume.
1574              !!!emit ($self->{ct}); # ATTLIST
1575              redo A;
1576          } else {          } else {
1577            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
1578          }          }
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
         ## reconsume  
   
         !!!emit ($self->{ct}); # start tag or end tag  
   
         redo A;  
1579        } else {        } else {
1580          if ({          if ({
1581               0x0022 => 1, # "               0x0022 => 1, # "
1582               0x0027 => 1, # '               0x0027 => 1, # '
1583               0x003D => 1, # =               0x003D => 1, # =
1584                 0x003C => 1, # <
1585              }->{$self->{nc}}) {              }->{$self->{nc}}) {
1586            !!!cp (115);            !!!cp (115);
1587            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 1435  sub _get_next_token ($) { Line 1591  sub _get_next_token ($) {
1591          }          }
1592          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1593          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1594                                q["'=& >],                                qq["'=& \x09\x0C>],
1595                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1596    
1597          ## Stay in the state          ## Stay in the state
# Line 1563  sub _get_next_token ($) { Line 1719  sub _get_next_token ($) {
1719          redo A;          redo A;
1720        }        }
1721      } elsif ($self->{state} == BOGUS_COMMENT_STATE) {      } elsif ($self->{state} == BOGUS_COMMENT_STATE) {
1722        ## (only happen if PCDATA state)        ## XML5: "Bogus comment state" and "DOCTYPE bogus comment state".
1723    
1724        ## NOTE: Unlike spec's "bogus comment state", this implementation        ## NOTE: Unlike spec's "bogus comment state", this implementation
1725        ## consumes characters one-by-one basis.        ## consumes characters one-by-one basis.
1726                
1727        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
1728          !!!cp (124);          if ($self->{in_subset}) {
1729          $self->{state} = DATA_STATE;            !!!cp (123);
1730          $self->{s_kwd} = '';            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1731            } else {
1732              !!!cp (124);
1733              $self->{state} = DATA_STATE;
1734              $self->{s_kwd} = '';
1735            }
1736          !!!next-input-character;          !!!next-input-character;
1737    
1738          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
1739          redo A;          redo A;
1740        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1741          !!!cp (125);          if ($self->{in_subset}) {
1742          $self->{state} = DATA_STATE;            !!!cp (125.1);
1743          $self->{s_kwd} = '';            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1744            } else {
1745              !!!cp (125);
1746              $self->{state} = DATA_STATE;
1747              $self->{s_kwd} = '';
1748            }
1749          ## reconsume          ## reconsume
1750    
1751          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1596  sub _get_next_token ($) { Line 1762  sub _get_next_token ($) {
1762          redo A;          redo A;
1763        }        }
1764      } elsif ($self->{state} == MARKUP_DECLARATION_OPEN_STATE) {      } elsif ($self->{state} == MARKUP_DECLARATION_OPEN_STATE) {
1765        ## (only happen if PCDATA state)        ## XML5: "Markup declaration state".
1766                
1767        if ($self->{nc} == 0x002D) { # -        if ($self->{nc} == 0x002D) { # -
1768          !!!cp (133);          !!!cp (133);
# Line 1772  sub _get_next_token ($) { Line 1938  sub _get_next_token ($) {
1938          !!!next-input-character;          !!!next-input-character;
1939          redo A;          redo A;
1940        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
         !!!cp (138);  
1941          !!!parse-error (type => 'bogus comment');          !!!parse-error (type => 'bogus comment');
1942          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
1943          $self->{s_kwd} = '';            !!!cp (138.1);
1944              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1945            } else {
1946              !!!cp (138);
1947              $self->{state} = DATA_STATE;
1948              $self->{s_kwd} = '';
1949            }
1950          !!!next-input-character;          !!!next-input-character;
1951    
1952          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
1953    
1954          redo A;          redo A;
1955        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (139);  
1956          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
1957          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
1958          $self->{s_kwd} = '';            !!!cp (139.1);
1959              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1960            } else {
1961              !!!cp (139);
1962              $self->{state} = DATA_STATE;
1963              $self->{s_kwd} = '';
1964            }
1965          ## reconsume          ## reconsume
1966    
1967          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1806  sub _get_next_token ($) { Line 1982  sub _get_next_token ($) {
1982          !!!next-input-character;          !!!next-input-character;
1983          redo A;          redo A;
1984        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
         !!!cp (142);  
1985          !!!parse-error (type => 'bogus comment');          !!!parse-error (type => 'bogus comment');
1986          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
1987          $self->{s_kwd} = '';            !!!cp (142.1);
1988              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1989            } else {
1990              !!!cp (142);
1991              $self->{state} = DATA_STATE;
1992              $self->{s_kwd} = '';
1993            }
1994          !!!next-input-character;          !!!next-input-character;
1995    
1996          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
1997    
1998          redo A;          redo A;
1999        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (143);  
2000          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
2001          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
2002          $self->{s_kwd} = '';            !!!cp (143.1);
2003              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2004            } else {
2005              !!!cp (143);
2006              $self->{state} = DATA_STATE;
2007              $self->{s_kwd} = '';
2008            }
2009          ## reconsume          ## reconsume
2010    
2011          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1834  sub _get_next_token ($) { Line 2020  sub _get_next_token ($) {
2020          redo A;          redo A;
2021        }        }
2022      } elsif ($self->{state} == COMMENT_STATE) {      } elsif ($self->{state} == COMMENT_STATE) {
2023          ## XML5: "Comment state" and "DOCTYPE comment state".
2024    
2025        if ($self->{nc} == 0x002D) { # -        if ($self->{nc} == 0x002D) { # -
2026          !!!cp (145);          !!!cp (145);
2027          $self->{state} = COMMENT_END_DASH_STATE;          $self->{state} = COMMENT_END_DASH_STATE;
2028          !!!next-input-character;          !!!next-input-character;
2029          redo A;          redo A;
2030        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (146);  
2031          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
2032          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
2033          $self->{s_kwd} = '';            !!!cp (146.1);
2034              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2035            } else {
2036              !!!cp (146);
2037              $self->{state} = DATA_STATE;
2038              $self->{s_kwd} = '';
2039            }
2040          ## reconsume          ## reconsume
2041    
2042          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1861  sub _get_next_token ($) { Line 2054  sub _get_next_token ($) {
2054          redo A;          redo A;
2055        }        }
2056      } elsif ($self->{state} == COMMENT_END_DASH_STATE) {      } elsif ($self->{state} == COMMENT_END_DASH_STATE) {
2057        ## XML5: "comment dash state".        ## XML5: "Comment dash state" and "DOCTYPE comment dash state".
2058    
2059        if ($self->{nc} == 0x002D) { # -        if ($self->{nc} == 0x002D) { # -
2060          !!!cp (148);          !!!cp (148);
# Line 1869  sub _get_next_token ($) { Line 2062  sub _get_next_token ($) {
2062          !!!next-input-character;          !!!next-input-character;
2063          redo A;          redo A;
2064        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (149);  
2065          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
2066          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
2067          $self->{s_kwd} = '';            !!!cp (149.1);
2068              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2069            } else {
2070              !!!cp (149);
2071              $self->{state} = DATA_STATE;
2072              $self->{s_kwd} = '';
2073            }
2074          ## reconsume          ## reconsume
2075    
2076          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
# Line 1885  sub _get_next_token ($) { Line 2083  sub _get_next_token ($) {
2083          !!!next-input-character;          !!!next-input-character;
2084          redo A;          redo A;
2085        }        }
2086      } elsif ($self->{state} == COMMENT_END_STATE) {      } elsif ($self->{state} == COMMENT_END_STATE or
2087                 $self->{state} == COMMENT_END_BANG_STATE) {
2088          ## XML5: "Comment end state" and "DOCTYPE comment end state".
2089          ## (No comment end bang state.)
2090    
2091        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2092          !!!cp (151);          if ($self->{in_subset}) {
2093          $self->{state} = DATA_STATE;            !!!cp (151.1);
2094          $self->{s_kwd} = '';            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2095            } else {
2096              !!!cp (151);
2097              $self->{state} = DATA_STATE;
2098              $self->{s_kwd} = '';
2099            }
2100          !!!next-input-character;          !!!next-input-character;
2101    
2102          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
2103    
2104          redo A;          redo A;
2105        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
2106          !!!cp (152);          if ($self->{state} == COMMENT_END_BANG_STATE) {
2107          ## XML5: Not a parse error.            !!!cp (154.3);
2108          !!!parse-error (type => 'dash in comment',            $self->{ct}->{data} .= '--!'; # comment
2109                          line => $self->{line_prev},            $self->{state} = COMMENT_END_DASH_STATE;
2110                          column => $self->{column_prev});          } else {
2111          $self->{ct}->{data} .= '-'; # comment            !!!cp (152);
2112          ## Stay in the state            ## XML5: Not a parse error.
2113              !!!parse-error (type => 'dash in comment',
2114                              line => $self->{line_prev},
2115                              column => $self->{column_prev});
2116              $self->{ct}->{data} .= '-'; # comment
2117              ## Stay in the state
2118            }
2119            !!!next-input-character;
2120            redo A;
2121          } elsif ($self->{nc} == 0x0021 and # !
2122                   $self->{state} != COMMENT_END_BANG_STATE) {
2123            !!!parse-error (type => 'comment end bang'); # XXX error type
2124            $self->{state} = COMMENT_END_BANG_STATE;
2125          !!!next-input-character;          !!!next-input-character;
2126          redo A;          redo A;
2127        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (153);  
2128          !!!parse-error (type => 'unclosed comment');          !!!parse-error (type => 'unclosed comment');
2129          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
2130          $self->{s_kwd} = '';            !!!cp (153.1);
2131          ## reconsume            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2132            } else {
2133              !!!cp (153);
2134              $self->{state} = DATA_STATE;
2135              $self->{s_kwd} = '';
2136            }
2137            ## Reconsume.
2138    
2139          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
2140    
2141          redo A;          redo A;
2142        } else {        } else {
2143          !!!cp (154);          !!!cp (154);
2144          ## XML5: Not a parse error.          if ($self->{state} == COMMENT_END_BANG_STATE) {
2145          !!!parse-error (type => 'dash in comment',            $self->{ct}->{data} .= '--!' . chr ($self->{nc}); # comment
2146                          line => $self->{line_prev},          } else {
2147                          column => $self->{column_prev});            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
2148          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          }
2149          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
2150          !!!next-input-character;          !!!next-input-character;
2151          redo A;          redo A;
# Line 1932  sub _get_next_token ($) { Line 2156  sub _get_next_token ($) {
2156          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
2157          !!!next-input-character;          !!!next-input-character;
2158          redo A;          redo A;
2159          } elsif ($self->{nc} == -1) {
2160            !!!cp (155.1);
2161            !!!parse-error (type => 'unclosed DOCTYPE');
2162            $self->{ct}->{quirks} = 1;
2163    
2164            $self->{state} = DATA_STATE;
2165            ## Reconsume.
2166            !!!emit ($self->{ct}); # DOCTYPE (quirks)
2167    
2168            redo A;
2169        } else {        } else {
2170          !!!cp (156);          !!!cp (156);
2171          ## XML5: Unless EOF, swith to the bogus comment state.          ## XML5: Swith to the bogus comment state.
2172          !!!parse-error (type => 'no space before DOCTYPE name');          !!!parse-error (type => 'no space before DOCTYPE name');
2173          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
2174          ## reconsume          ## reconsume
# Line 1959  sub _get_next_token ($) { Line 2193  sub _get_next_token ($) {
2193          !!!emit ($self->{ct}); # DOCTYPE (quirks)          !!!emit ($self->{ct}); # DOCTYPE (quirks)
2194    
2195          redo A;          redo A;
2196          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
2197            !!!cp (158.1);
2198            $self->{ct}->{name} # DOCTYPE
2199                = chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
2200            delete $self->{ct}->{quirks};
2201            $self->{state} = DOCTYPE_NAME_STATE;
2202            !!!next-input-character;
2203            redo A;
2204        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2205          !!!cp (159);          !!!cp (159);
2206          !!!parse-error (type => 'no DOCTYPE name');          !!!parse-error (type => 'no DOCTYPE name');
# Line 1973  sub _get_next_token ($) { Line 2215  sub _get_next_token ($) {
2215          !!!cp (159.1);          !!!cp (159.1);
2216          !!!parse-error (type => 'no DOCTYPE name');          !!!parse-error (type => 'no DOCTYPE name');
2217          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2218            $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
2219            $self->{in_subset} = 1;
2220          !!!next-input-character;          !!!next-input-character;
2221            !!!emit ($self->{ct}); # DOCTYPE
2222          redo A;          redo A;
2223        } else {        } else {
2224          !!!cp (160);          !!!cp (160);
# Line 2002  sub _get_next_token ($) { Line 2247  sub _get_next_token ($) {
2247          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
2248    
2249          redo A;          redo A;
2250          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
2251            !!!cp (162.1);
2252            $self->{ct}->{name} # DOCTYPE
2253                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
2254            delete $self->{ct}->{quirks};
2255            ## Stay in the state.
2256            !!!next-input-character;
2257            redo A;
2258        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2259          !!!cp (163);          !!!cp (163);
2260          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
# Line 2016  sub _get_next_token ($) { Line 2269  sub _get_next_token ($) {
2269        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [
2270          !!!cp (163.1);          !!!cp (163.1);
2271          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2272            $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
2273            $self->{in_subset} = 1;
2274          !!!next-input-character;          !!!next-input-character;
2275            !!!emit ($self->{ct}); # DOCTYPE
2276          redo A;          redo A;
2277        } else {        } else {
2278          !!!cp (164);          !!!cp (164);
2279          $self->{ct}->{name}          $self->{ct}->{name} .= chr ($self->{nc}); # DOCTYPE
2280            .= chr ($self->{nc}); # DOCTYPE          ## Stay in the state.
         ## Stay in the state  
2281          !!!next-input-character;          !!!next-input-character;
2282          redo A;          redo A;
2283        }        }
# Line 2036  sub _get_next_token ($) { Line 2291  sub _get_next_token ($) {
2291          !!!next-input-character;          !!!next-input-character;
2292          redo A;          redo A;
2293        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
2294          !!!cp (166);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2295          $self->{state} = DATA_STATE;            !!!cp (166);
2296          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
2297              $self->{s_kwd} = '';
2298            } else {
2299              !!!cp (166.1);
2300              !!!parse-error (type => 'no md def'); ## TODO: type
2301              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2302            }
2303            
2304          !!!next-input-character;          !!!next-input-character;
2305            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         !!!emit ($self->{ct}); # DOCTYPE  
   
2306          redo A;          redo A;
2307        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2308          !!!cp (167);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2309          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (167);
2310          $self->{state} = DATA_STATE;            !!!parse-error (type => 'unclosed DOCTYPE');
2311          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
2312          ## reconsume            $self->{s_kwd} = '';
2313              $self->{ct}->{quirks} = 1;
2314          $self->{ct}->{quirks} = 1;          } else {
2315          !!!emit ($self->{ct}); # DOCTYPE            !!!cp (167.12);
2316              !!!parse-error (type => 'unclosed md'); ## TODO: type
2317              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2318            }
2319            
2320            ## Reconsume.
2321            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2322          redo A;          redo A;
2323        } elsif ($self->{nc} == 0x0050 or # P        } elsif ($self->{nc} == 0x0050 or # P
2324                 $self->{nc} == 0x0070) { # p                 $self->{nc} == 0x0070) { # p
# Line 2069  sub _get_next_token ($) { Line 2334  sub _get_next_token ($) {
2334          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
2335          !!!next-input-character;          !!!next-input-character;
2336          redo A;          redo A;
2337        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{nc} == 0x0022 and # "
2338                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
2339                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
2340            !!!cp (167.21);
2341            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
2342            $self->{ct}->{value} = ''; # ENTITY
2343            !!!next-input-character;
2344            redo A;
2345          } elsif ($self->{nc} == 0x0027 and # '
2346                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
2347                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
2348            !!!cp (167.22);
2349            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
2350            $self->{ct}->{value} = ''; # ENTITY
2351            !!!next-input-character;
2352            redo A;
2353          } elsif ($self->{is_xml} and
2354                   $self->{ct}->{type} == DOCTYPE_TOKEN and
2355                   $self->{nc} == 0x005B) { # [
2356          !!!cp (167.3);          !!!cp (167.3);
2357          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2358          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
2359            $self->{in_subset} = 1;
2360          !!!next-input-character;          !!!next-input-character;
2361            !!!emit ($self->{ct}); # DOCTYPE
2362          redo A;          redo A;
2363        } else {        } else {
2364          !!!cp (180);          !!!parse-error (type => 'string after DOCTYPE name'); ## TODO: type
2365          !!!parse-error (type => 'string after DOCTYPE name');  
2366          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2367              !!!cp (180);
2368              $self->{ct}->{quirks} = 1;
2369              $self->{state} = BOGUS_DOCTYPE_STATE;
2370            } else {
2371              !!!cp (180.1);
2372              $self->{state} = BOGUS_MD_STATE;
2373            }
2374    
         $self->{state} = BOGUS_DOCTYPE_STATE;  
2375          !!!next-input-character;          !!!next-input-character;
2376          redo A;          redo A;
2377        }        }
# Line 2122  sub _get_next_token ($) { Line 2413  sub _get_next_token ($) {
2413          !!!next-input-character;          !!!next-input-character;
2414          redo A;          redo A;
2415        } else {        } else {
2416          !!!cp (169);          !!!parse-error (type => 'string after DOCTYPE name', ## TODO: type
         !!!parse-error (type => 'string after DOCTYPE name',  
2417                          line => $self->{line_prev},                          line => $self->{line_prev},
2418                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
2419          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2420              !!!cp (169);
2421          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
2422              $self->{state} = BOGUS_DOCTYPE_STATE;
2423            } else {
2424              !!!cp (169.1);
2425              $self->{state} = BOGUS_MD_STATE;
2426            }
2427          ## Reconsume.          ## Reconsume.
2428          redo A;          redo A;
2429        }        }
# Line 2170  sub _get_next_token ($) { Line 2465  sub _get_next_token ($) {
2465          !!!next-input-character;          !!!next-input-character;
2466          redo A;          redo A;
2467        } else {        } else {
2468          !!!cp (172);          !!!parse-error (type => 'string after DOCTYPE name', ## TODO: type
         !!!parse-error (type => 'string after DOCTYPE name',  
2469                          line => $self->{line_prev},                          line => $self->{line_prev},
2470                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
2471          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2472              !!!cp (172);
2473          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
2474              $self->{state} = BOGUS_DOCTYPE_STATE;
2475            } else {
2476              !!!cp (172.1);
2477              $self->{state} = BOGUS_MD_STATE;
2478            }
2479          ## Reconsume.          ## Reconsume.
2480          redo A;          redo A;
2481        }        }
# Line 2199  sub _get_next_token ($) { Line 2498  sub _get_next_token ($) {
2498          !!!next-input-character;          !!!next-input-character;
2499          redo A;          redo A;
2500        } elsif ($self->{nc} eq 0x003E) { # >        } elsif ($self->{nc} eq 0x003E) { # >
         !!!cp (184);  
2501          !!!parse-error (type => 'no PUBLIC literal');          !!!parse-error (type => 'no PUBLIC literal');
2502            
2503          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2504          $self->{s_kwd} = '';            !!!cp (184);
2505              $self->{state} = DATA_STATE;
2506              $self->{s_kwd} = '';
2507              $self->{ct}->{quirks} = 1;
2508            } else {
2509              !!!cp (184.1);
2510              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2511            }
2512            
2513          !!!next-input-character;          !!!next-input-character;
2514            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2515          redo A;          redo A;
2516        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2517          !!!cp (185);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2518          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (185);
2519              !!!parse-error (type => 'unclosed DOCTYPE');
2520          $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2521          $self->{s_kwd} = '';            $self->{s_kwd} = '';
2522              $self->{ct}->{quirks} = 1;
2523            } else {
2524              !!!cp (185.1);
2525              !!!parse-error (type => 'unclosed md'); ## TODO: type
2526              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2527            }
2528            
2529          ## reconsume          ## reconsume
   
         $self->{ct}->{quirks} = 1;  
2530          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
   
2531          redo A;          redo A;
2532        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
2533                   $self->{ct}->{type} == DOCTYPE_TOKEN and
2534                   $self->{nc} == 0x005B) { # [
2535          !!!cp (186.1);          !!!cp (186.1);
2536          !!!parse-error (type => 'no PUBLIC literal');          !!!parse-error (type => 'no PUBLIC literal');
2537          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2538          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
2539            $self->{in_subset} = 1;
2540          !!!next-input-character;          !!!next-input-character;
2541            !!!emit ($self->{ct}); # DOCTYPE
2542          redo A;          redo A;
2543        } else {        } else {
         !!!cp (186);  
2544          !!!parse-error (type => 'string after PUBLIC');          !!!parse-error (type => 'string after PUBLIC');
         $self->{ct}->{quirks} = 1;  
2545    
2546          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2547              !!!cp (186);
2548              $self->{ct}->{quirks} = 1;
2549              $self->{state} = BOGUS_DOCTYPE_STATE;
2550            } else {
2551              !!!cp (186.2);
2552              $self->{state} = BOGUS_MD_STATE;
2553            }
2554    
2555          !!!next-input-character;          !!!next-input-character;
2556          redo A;          redo A;
2557        }        }
# Line 2245  sub _get_next_token ($) { Line 2562  sub _get_next_token ($) {
2562          !!!next-input-character;          !!!next-input-character;
2563          redo A;          redo A;
2564        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
         !!!cp (188);  
2565          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2566    
2567          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2568          $self->{s_kwd} = '';            !!!cp (188);
2569          !!!next-input-character;            $self->{state} = DATA_STATE;
2570              $self->{s_kwd} = '';
2571          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
2572          !!!emit ($self->{ct}); # DOCTYPE          } else {
2573              !!!cp (188.1);
2574              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2575            }
2576    
2577            !!!next-input-character;
2578            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2579          redo A;          redo A;
2580        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (189);  
2581          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2582    
2583          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2584          $self->{s_kwd} = '';            !!!cp (189);
2585          ## reconsume            $self->{state} = DATA_STATE;
2586              $self->{s_kwd} = '';
2587          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
2588            } else {
2589              !!!cp (189.1);
2590              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2591            }
2592            
2593            ## Reconsume.
2594          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
   
2595          redo A;          redo A;
2596        } else {        } else {
2597          !!!cp (190);          !!!cp (190);
2598          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
2599          $self->{read_until}->($self->{ct}->{pubid}, q[">],          $self->{read_until}->($self->{ct}->{pubid}, q[">],
2600                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
2601    
# Line 2286  sub _get_next_token ($) { Line 2610  sub _get_next_token ($) {
2610          !!!next-input-character;          !!!next-input-character;
2611          redo A;          redo A;
2612        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
         !!!cp (192);  
2613          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2614    
2615          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2616          $self->{s_kwd} = '';            !!!cp (192);
2617          !!!next-input-character;            $self->{state} = DATA_STATE;
2618              $self->{s_kwd} = '';
2619          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
2620          !!!emit ($self->{ct}); # DOCTYPE          } else {
2621              !!!cp (192.1);
2622              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2623            }
2624    
2625            !!!next-input-character;
2626            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2627          redo A;          redo A;
2628        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (193);  
2629          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2630    
2631          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2632          $self->{s_kwd} = '';            !!!cp (193);
2633              $self->{state} = DATA_STATE;
2634              $self->{s_kwd} = '';
2635              $self->{ct}->{quirks} = 1;
2636            } else {
2637              !!!cp (193.1);
2638              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2639            }
2640          
2641          ## reconsume          ## reconsume
2642            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2643          redo A;          redo A;
2644        } else {        } else {
2645          !!!cp (194);          !!!cp (194);
2646          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
2647          $self->{read_until}->($self->{ct}->{pubid}, q['>],          $self->{read_until}->($self->{ct}->{pubid}, q['>],
2648                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
2649    
# Line 2328  sub _get_next_token ($) { Line 2659  sub _get_next_token ($) {
2659          redo A;          redo A;
2660        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
2661          !!!cp (196);          !!!cp (196);
2662          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
2663          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
2664          !!!next-input-character;          !!!next-input-character;
2665          redo A;          redo A;
2666        } elsif ($self->{nc} == 0x0027) { # '        } elsif ($self->{nc} == 0x0027) { # '
2667          !!!cp (197);          !!!cp (197);
2668          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
2669          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
2670          !!!next-input-character;          !!!next-input-character;
2671          redo A;          redo A;
2672        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
2673          if ($self->{is_xml}) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2674            !!!cp (198.1);            if ($self->{is_xml}) {
2675            !!!parse-error (type => 'no SYSTEM literal');              !!!cp (198.1);
2676                !!!parse-error (type => 'no SYSTEM literal');
2677              } else {
2678                !!!cp (198);
2679              }
2680              $self->{state} = DATA_STATE;
2681              $self->{s_kwd} = '';
2682          } else {          } else {
2683            !!!cp (198);            if ($self->{ct}->{type} == NOTATION_TOKEN) {
2684                !!!cp (198.2);
2685              } else {
2686                !!!cp (198.3);
2687                !!!parse-error (type => 'no SYSTEM literal');            
2688              }
2689              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2690          }          }
2691          $self->{state} = DATA_STATE;          
         $self->{s_kwd} = '';  
2692          !!!next-input-character;          !!!next-input-character;
2693            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         !!!emit ($self->{ct}); # DOCTYPE  
   
2694          redo A;          redo A;
2695        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2696          !!!cp (199);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2697          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (199);
2698              !!!parse-error (type => 'unclosed DOCTYPE');
2699          $self->{state} = DATA_STATE;            
2700          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
2701              $self->{s_kwd} = '';
2702              $self->{ct}->{quirks} = 1;
2703            } else {
2704              !!!parse-error (type => 'unclosed md'); ## TODO: type
2705              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2706            }
2707            
2708          ## reconsume          ## reconsume
2709            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2710          redo A;          redo A;
2711        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
2712                   $self->{ct}->{type} == DOCTYPE_TOKEN and
2713                   $self->{nc} == 0x005B) { # [
2714          !!!cp (200.1);          !!!cp (200.1);
2715          !!!parse-error (type => 'no SYSTEM literal');          !!!parse-error (type => 'no SYSTEM literal');
2716          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2717          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
2718            $self->{in_subset} = 1;
2719          !!!next-input-character;          !!!next-input-character;
2720            !!!emit ($self->{ct}); # DOCTYPE
2721          redo A;          redo A;
2722        } else {        } else {
         !!!cp (200);  
2723          !!!parse-error (type => 'string after PUBLIC literal');          !!!parse-error (type => 'string after PUBLIC literal');
         $self->{ct}->{quirks} = 1;  
2724    
2725          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2726              !!!cp (200);
2727              $self->{ct}->{quirks} = 1;
2728              $self->{state} = BOGUS_DOCTYPE_STATE;
2729            } else {
2730              !!!cp (200.2);
2731              $self->{state} = BOGUS_MD_STATE;
2732            }
2733    
2734          !!!next-input-character;          !!!next-input-character;
2735          redo A;          redo A;
2736        }        }
# Line 2399  sub _get_next_token ($) { Line 2753  sub _get_next_token ($) {
2753          !!!next-input-character;          !!!next-input-character;
2754          redo A;          redo A;
2755        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
         !!!cp (204);  
2756          !!!parse-error (type => 'no SYSTEM literal');          !!!parse-error (type => 'no SYSTEM literal');
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
2757          !!!next-input-character;          !!!next-input-character;
2758    
2759          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2760          !!!emit ($self->{ct}); # DOCTYPE            !!!cp (204);
2761              $self->{state} = DATA_STATE;
2762              $self->{s_kwd} = '';
2763              $self->{ct}->{quirks} = 1;
2764            } else {
2765              !!!cp (204.1);
2766              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2767            }
2768    
2769            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2770          redo A;          redo A;
2771        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2772          !!!cp (205);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2773          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (205);
2774              !!!parse-error (type => 'unclosed DOCTYPE');
2775          $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2776          $self->{s_kwd} = '';            $self->{s_kwd} = '';
2777              $self->{ct}->{quirks} = 1;
2778            } else {
2779              !!!cp (205.1);
2780              !!!parse-error (type => 'unclosed md'); ## TODO: type
2781              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2782            }
2783            
2784          ## reconsume          ## reconsume
2785            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2786          redo A;          redo A;
2787        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
2788                   $self->{ct}->{type} == DOCTYPE_TOKEN and
2789                   $self->{nc} == 0x005B) { # [
2790          !!!cp (206.1);          !!!cp (206.1);
2791          !!!parse-error (type => 'no SYSTEM literal');          !!!parse-error (type => 'no SYSTEM literal');
2792    
2793          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2794          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
2795            $self->{in_subset} = 1;
2796          !!!next-input-character;          !!!next-input-character;
2797            !!!emit ($self->{ct}); # DOCTYPE
2798          redo A;          redo A;
2799        } else {        } else {
         !!!cp (206);  
2800          !!!parse-error (type => 'string after SYSTEM');          !!!parse-error (type => 'string after SYSTEM');
         $self->{ct}->{quirks} = 1;  
2801    
2802          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2803              !!!cp (206);          
2804              $self->{ct}->{quirks} = 1;
2805              $self->{state} = BOGUS_DOCTYPE_STATE;
2806            } else {
2807              !!!cp (206.2);
2808              $self->{state} = BOGUS_MD_STATE;
2809            }
2810    
2811          !!!next-input-character;          !!!next-input-character;
2812          redo A;          redo A;
2813        }        }
# Line 2445  sub _get_next_token ($) { Line 2818  sub _get_next_token ($) {
2818          !!!next-input-character;          !!!next-input-character;
2819          redo A;          redo A;
2820        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >
         !!!cp (208);  
2821          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2822    
2823          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2824          $self->{s_kwd} = '';            !!!cp (208);
2825              $self->{state} = DATA_STATE;
2826              $self->{s_kwd} = '';
2827              $self->{ct}->{quirks} = 1;
2828            } else {
2829              !!!cp (208.1);
2830              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2831            }
2832            
2833          !!!next-input-character;          !!!next-input-character;
2834            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2835          redo A;          redo A;
2836        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (209);  
2837          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2838    
2839          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2840          $self->{s_kwd} = '';            !!!cp (209);
2841              $self->{state} = DATA_STATE;
2842              $self->{s_kwd} = '';
2843              $self->{ct}->{quirks} = 1;
2844            } else {
2845              !!!cp (209.1);
2846              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2847            }
2848            
2849          ## reconsume          ## reconsume
2850            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2851          redo A;          redo A;
2852        } else {        } else {
2853          !!!cp (210);          !!!cp (210);
2854          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
2855          $self->{read_until}->($self->{ct}->{sysid}, q[">],          $self->{read_until}->($self->{ct}->{sysid}, q[">],
2856                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
2857    
# Line 2498  sub _get_next_token ($) { Line 2878  sub _get_next_token ($) {
2878    
2879          redo A;          redo A;
2880        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (213);  
2881          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2882    
2883          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2884          $self->{s_kwd} = '';            !!!cp (213);
2885          ## reconsume            $self->{state} = DATA_STATE;
2886              $self->{s_kwd} = '';
2887          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
2888          !!!emit ($self->{ct}); # DOCTYPE          } else {
2889              !!!cp (213.1);
2890              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2891            }
2892    
2893            ## reconsume
2894            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2895          redo A;          redo A;
2896        } else {        } else {
2897          !!!cp (214);          !!!cp (214);
2898          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
2899          $self->{read_until}->($self->{ct}->{sysid}, q['>],          $self->{read_until}->($self->{ct}->{sysid}, q['>],
2900                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
2901    
# Line 2522  sub _get_next_token ($) { Line 2905  sub _get_next_token ($) {
2905        }        }
2906      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
2907        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
2908          !!!cp (215);          if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
2909          ## Stay in the state            !!!cp (215.1);
2910              $self->{state} = BEFORE_NDATA_STATE;
2911            } else {
2912              !!!cp (215);
2913              ## Stay in the state
2914            }
2915          !!!next-input-character;          !!!next-input-character;
2916          redo A;          redo A;
2917        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
2918          !!!cp (216);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2919          $self->{state} = DATA_STATE;            !!!cp (216);
2920          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
2921          !!!next-input-character;            $self->{s_kwd} = '';
2922            } else {
2923          !!!emit ($self->{ct}); # DOCTYPE            !!!cp (216.1);
2924              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2925            }
2926    
2927            !!!next-input-character;
2928            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2929            redo A;
2930          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
2931                   ($self->{nc} == 0x004E or # N
2932                    $self->{nc} == 0x006E)) { # n
2933            !!!cp (216.2);
2934            !!!parse-error (type => 'no space before NDATA'); ## TODO: type
2935            $self->{state} = NDATA_STATE;
2936            $self->{kwd} = chr $self->{nc};
2937            !!!next-input-character;
2938          redo A;          redo A;
2939        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2940          !!!cp (217);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2941          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (217);
2942          $self->{state} = DATA_STATE;            !!!parse-error (type => 'unclosed DOCTYPE');
2943          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
2944          ## reconsume            $self->{s_kwd} = '';
2945              $self->{ct}->{quirks} = 1;
2946          $self->{ct}->{quirks} = 1;          } else {
2947          !!!emit ($self->{ct}); # DOCTYPE            !!!cp (217.1);
2948              !!!parse-error (type => 'unclosed md'); ## TODO: type
2949              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2950            }
2951    
2952            ## reconsume
2953            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2954          redo A;          redo A;
2955        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
2956                   $self->{ct}->{type} == DOCTYPE_TOKEN and
2957                   $self->{nc} == 0x005B) { # [
2958          !!!cp (218.1);          !!!cp (218.1);
2959          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2960          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
2961            $self->{in_subset} = 1;
2962          !!!next-input-character;          !!!next-input-character;
2963            !!!emit ($self->{ct}); # DOCTYPE
2964          redo A;          redo A;
2965        } else {        } else {
         !!!cp (218);  
2966          !!!parse-error (type => 'string after SYSTEM literal');          !!!parse-error (type => 'string after SYSTEM literal');
         #$self->{ct}->{quirks} = 1;  
2967    
2968          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2969              !!!cp (218);
2970              #$self->{ct}->{quirks} = 1;
2971              $self->{state} = BOGUS_DOCTYPE_STATE;
2972            } else {
2973              !!!cp (218.2);
2974              $self->{state} = BOGUS_MD_STATE;
2975            }
2976    
2977            !!!next-input-character;
2978            redo A;
2979          }
2980        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
2981          if ($is_space->{$self->{nc}}) {
2982            !!!cp (218.3);
2983            ## Stay in the state.
2984            !!!next-input-character;
2985            redo A;
2986          } elsif ($self->{nc} == 0x003E) { # >
2987            !!!cp (218.4);
2988            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2989            !!!next-input-character;
2990            !!!emit ($self->{ct}); # ENTITY
2991            redo A;
2992          } elsif ($self->{nc} == 0x004E or # N
2993                   $self->{nc} == 0x006E) { # n
2994            !!!cp (218.5);
2995            $self->{state} = NDATA_STATE;
2996            $self->{kwd} = chr $self->{nc};
2997            !!!next-input-character;
2998            redo A;
2999          } elsif ($self->{nc} == -1) {
3000            !!!cp (218.6);
3001            !!!parse-error (type => 'unclosed md'); ## TODO: type
3002            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3003            ## reconsume
3004            !!!emit ($self->{ct}); # ENTITY
3005            redo A;
3006          } else {
3007            !!!cp (218.7);
3008            !!!parse-error (type => 'string after SYSTEM literal');
3009            $self->{state} = BOGUS_MD_STATE;
3010          !!!next-input-character;          !!!next-input-character;
3011          redo A;          redo A;
3012        }        }
# Line 2572  sub _get_next_token ($) { Line 3021  sub _get_next_token ($) {
3021    
3022          redo A;          redo A;
3023        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [
3024          if ($self->{ct}->{has_internal_subset}) { # DOCTYPE          !!!cp (220.1);
3025            !!!cp (220.2);          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3026            ## Stay in the state.          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
3027            !!!next-input-character;          $self->{in_subset} = 1;
3028            redo A;          !!!next-input-character;
3029          } else {          !!!emit ($self->{ct}); # DOCTYPE
3030            !!!cp (220.1);          redo A;
           $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;  
           $self->{ct}->{has_internal_subset} = 1; # DOCTYPE  
           !!!next-input-character;  
           redo A;  
         }  
3031        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3032          !!!cp (220);          !!!cp (220);
3033          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
# Line 2696  sub _get_next_token ($) { Line 3140  sub _get_next_token ($) {
3140              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3141              $self->{entity_add} => 1,              $self->{entity_add} => 1,
3142            }->{$self->{nc}}) {            }->{$self->{nc}}) {
3143          !!!cp (1001);          if ($self->{is_xml}) {
3144              !!!cp (1001.1);
3145              !!!parse-error (type => 'bare ero',
3146                              line => $self->{line_prev},
3147                              column => $self->{column_prev}
3148                                  + ($self->{nc} == -1 ? 1 : 0));
3149            } else {
3150              !!!cp (1001);
3151              ## No error
3152            }
3153          ## Don't consume          ## Don't consume
         ## No error  
3154          ## Return nothing.          ## Return nothing.
3155          #          #
3156        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 2707  sub _get_next_token ($) { Line 3159  sub _get_next_token ($) {
3159          $self->{kwd} = '#';          $self->{kwd} = '#';
3160          !!!next-input-character;          !!!next-input-character;
3161          redo A;          redo A;
3162        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
3163                   (0x0041 <= $self->{nc} and
3164                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
3165                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
3166                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 2751  sub _get_next_token ($) { Line 3204  sub _get_next_token ($) {
3204          redo A;          redo A;
3205        }        }
3206      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
3207        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
           $self->{nc} == 0x0058) { # X  
3208          !!!cp (995);          !!!cp (995);
3209          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
3210          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3211          !!!next-input-character;          !!!next-input-character;
3212          redo A;          redo A;
3213          } elsif ($self->{nc} == 0x0058) { # X
3214            !!!cp (995.1);
3215            if ($self->{is_xml}) {
3216              !!!parse-error (type => 'uppercase hcro'); ## TODO: type
3217            }
3218            $self->{state} = HEXREF_X_STATE;
3219            $self->{kwd} .= chr $self->{nc};
3220            !!!next-input-character;
3221            redo A;
3222        } elsif (0x0030 <= $self->{nc} and        } elsif (0x0030 <= $self->{nc} and
3223                 $self->{nc} <= 0x0039) { # 0..9                 $self->{nc} <= 0x0039) { # 0..9
3224          !!!cp (994);          !!!cp (994);
# Line 2818  sub _get_next_token ($) { Line 3279  sub _get_next_token ($) {
3279        my $code = $self->{kwd};        my $code = $self->{kwd};
3280        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3281        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3282        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
3283              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
3284              ($self->{is_xml} and $code == 0x0000)) {
3285          !!!cp (1015);          !!!cp (1015);
3286          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3287                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 2931  sub _get_next_token ($) { Line 3394  sub _get_next_token ($) {
3394        my $code = $self->{kwd};        my $code = $self->{kwd};
3395        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3396        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3397        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
3398              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
3399              ($self->{is_xml} and $code == 0x0000)) {
3400          !!!cp (1008);          !!!cp (1008);
3401          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3402                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 2965  sub _get_next_token ($) { Line 3430  sub _get_next_token ($) {
3430          redo A;          redo A;
3431        }        }
3432      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
3433        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
3434            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
3435            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
3436              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
3437             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
3438              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
3439             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
3440              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
3441             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
3442                    {
3443                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3444                      $self->{entity_add} => 1,
3445                    }->{$self->{nc}}))) {
3446          our $EntityChar;          our $EntityChar;
3447          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3448          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
3449                $self->{ge}->{$self->{kwd}}) {
3450            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
3451              !!!cp (1020);              if (defined $self->{ge}->{$self->{kwd}}) {
3452              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
3453                    !!!cp (1020.1);
3454                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
3455                  } else {
3456                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
3457                      !!!cp (1020.2);
3458                      !!!parse-error (type => 'unparsed entity', ## TODO: type
3459                                      value => $self->{kwd});
3460                    } else {
3461                      !!!cp (1020.3);
3462                    }
3463                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
3464                  }
3465                } else {
3466                  if ($self->{is_xml}) {
3467                    !!!cp (1020.4);
3468                    !!!parse-error (type => 'entity not declared', ## TODO: type
3469                                    value => $self->{kwd},
3470                                    level => {
3471                                              'amp;' => $self->{level}->{warn},
3472                                              'quot;' => $self->{level}->{warn},
3473                                              'lt;' => $self->{level}->{warn},
3474                                              'gt;' => $self->{level}->{warn},
3475                                              'apos;' => $self->{level}->{warn},
3476                                             }->{$self->{kwd}} ||
3477                                             $self->{level}->{must});
3478                  } else {
3479                    !!!cp (1020);
3480                  }
3481                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
3482                }
3483              $self->{entity__match} = 1;              $self->{entity__match} = 1;
3484              !!!next-input-character;              !!!next-input-character;
3485              #              #
# Line 3065  sub _get_next_token ($) { Line 3565  sub _get_next_token ($) {
3565      ## XML-only states      ## XML-only states
3566    
3567      } elsif ($self->{state} == PI_STATE) {      } elsif ($self->{state} == PI_STATE) {
3568          ## XML5: "Pi state" and "DOCTYPE pi state".
3569    
3570        if ($is_space->{$self->{nc}} or        if ($is_space->{$self->{nc}} or
3571            $self->{nc} == 0x003F or # ? ## XML5: Same as "Anything else"            $self->{nc} == 0x003F or # ?
3572            $self->{nc} == -1) {            $self->{nc} == -1) {
3573            ## XML5: U+003F: "pi state": Same as "Anything else"; "DOCTYPE
3574            ## pi state": Switch to the "DOCTYPE pi after state".  EOF:
3575            ## "DOCTYPE pi state": Parse error, switch to the "data
3576            ## state".
3577          !!!parse-error (type => 'bare pio', ## TODO: type          !!!parse-error (type => 'bare pio', ## TODO: type
3578                          line => $self->{line_prev},                          line => $self->{line_prev},
3579                          column => $self->{column_prev}                          column => $self->{column_prev}
# Line 3082  sub _get_next_token ($) { Line 3588  sub _get_next_token ($) {
3588                        };                        };
3589          redo A;          redo A;
3590        } else {        } else {
3591            ## XML5: "DOCTYPE pi state": Stay in the state.
3592          $self->{ct} = {type => PI_TOKEN,          $self->{ct} = {type => PI_TOKEN,
3593                         target => chr $self->{nc},                         target => chr $self->{nc},
3594                         data => '',                         data => '',
# Line 3099  sub _get_next_token ($) { Line 3606  sub _get_next_token ($) {
3606          redo A;          redo A;
3607        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3608          !!!parse-error (type => 'no pic'); ## TODO: type          !!!parse-error (type => 'no pic'); ## TODO: type
3609          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
3610          $self->{s_kwd} = '';            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3611            } else {
3612              $self->{state} = DATA_STATE;
3613              $self->{s_kwd} = '';
3614            }
3615          ## Reconsume.          ## Reconsume.
3616          !!!emit ($self->{ct}); # pi          !!!emit ($self->{ct}); # pi
3617          redo A;          redo A;
# Line 3131  sub _get_next_token ($) { Line 3642  sub _get_next_token ($) {
3642          redo A;          redo A;
3643        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3644          !!!parse-error (type => 'no pic'); ## TODO: type          !!!parse-error (type => 'no pic'); ## TODO: type
3645          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
3646          $self->{s_kwd} = '';            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state"
3647            } else {
3648              $self->{state} = DATA_STATE;
3649              $self->{s_kwd} = '';
3650            }
3651          ## Reprocess.          ## Reprocess.
3652          !!!emit ($self->{ct}); # pi          !!!emit ($self->{ct}); # pi
3653          redo A;          redo A;
# Line 3146  sub _get_next_token ($) { Line 3661  sub _get_next_token ($) {
3661          redo A;          redo A;
3662        }        }
3663      } elsif ($self->{state} == PI_AFTER_STATE) {      } elsif ($self->{state} == PI_AFTER_STATE) {
3664          ## XML5: Part of "Pi after state".
3665    
3666        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
3667          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
3668          $self->{s_kwd} = '';            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3669            } else {
3670              $self->{state} = DATA_STATE;
3671              $self->{s_kwd} = '';
3672            }
3673          !!!next-input-character;          !!!next-input-character;
3674          !!!emit ($self->{ct}); # pi          !!!emit ($self->{ct}); # pi
3675          redo A;          redo A;
# Line 3171  sub _get_next_token ($) { Line 3692  sub _get_next_token ($) {
3692          redo A;          redo A;
3693        }        }
3694      } elsif ($self->{state} == PI_DATA_AFTER_STATE) {      } elsif ($self->{state} == PI_DATA_AFTER_STATE) {
3695        ## XML5: Same as "pi after state" in XML5        ## XML5: Same as "pi after state" and "DOCTYPE pi after state".
3696    
3697        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
3698          $self->{state} = DATA_STATE;          if ($self->{in_subset}) {
3699          $self->{s_kwd} = '';            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3700            } else {
3701              $self->{state} = DATA_STATE;
3702              $self->{s_kwd} = '';
3703            }
3704          !!!next-input-character;          !!!next-input-character;
3705          !!!emit ($self->{ct}); # pi          !!!emit ($self->{ct}); # pi
3706          redo A;          redo A;
# Line 3192  sub _get_next_token ($) { Line 3718  sub _get_next_token ($) {
3718    
3719      } elsif ($self->{state} == DOCTYPE_INTERNAL_SUBSET_STATE) {      } elsif ($self->{state} == DOCTYPE_INTERNAL_SUBSET_STATE) {
3720        if ($self->{nc} == 0x003C) { # <        if ($self->{nc} == 0x003C) { # <
3721          ## TODO:          $self->{state} = DOCTYPE_TAG_STATE;
3722          !!!next-input-character;          !!!next-input-character;
3723          redo A;          redo A;
3724        } elsif ($self->{nc} == 0x0025) { # %        } elsif ($self->{nc} == 0x0025) { # %
3725          ## XML5: Not defined yet.          ## XML5: Not defined yet.
3726    
3727          ## TODO:          ## TODO:
3728    
3729            if (not $self->{stop_processing} and
3730                not $self->{document}->xml_standalone) {
3731              !!!parse-error (type => 'stop processing', ## TODO: type
3732                              level => $self->{level}->{info});
3733              $self->{stop_processing} = 1;
3734            }
3735    
3736          !!!next-input-character;          !!!next-input-character;
3737          redo A;          redo A;
3738        } elsif ($self->{nc} == 0x005D) { # ]        } elsif ($self->{nc} == 0x005D) { # ]
3739            delete $self->{in_subset};
3740          $self->{state} = DOCTYPE_INTERNAL_SUBSET_AFTER_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_AFTER_STATE;
3741          !!!next-input-character;          !!!next-input-character;
3742          redo A;          redo A;
# Line 3211  sub _get_next_token ($) { Line 3746  sub _get_next_token ($) {
3746          redo A;          redo A;
3747        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3748          !!!parse-error (type => 'unclosed internal subset'); ## TODO: type          !!!parse-error (type => 'unclosed internal subset'); ## TODO: type
3749            delete $self->{in_subset};
3750          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
3751          $self->{s_kwd} = '';          $self->{s_kwd} = '';
3752          ## Reconsume.          ## Reconsume.
3753          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ({type => END_OF_DOCTYPE_TOKEN});
3754          redo A;          redo A;
3755        } else {        } else {
3756          unless ($self->{internal_subset_tainted}) {          unless ($self->{internal_subset_tainted}) {
# Line 3231  sub _get_next_token ($) { Line 3767  sub _get_next_token ($) {
3767          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
3768          $self->{s_kwd} = '';          $self->{s_kwd} = '';
3769          !!!next-input-character;          !!!next-input-character;
3770          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ({type => END_OF_DOCTYPE_TOKEN});
3771          redo A;          redo A;
3772        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3773          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
3774          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
3775          $self->{s_kwd} = '';          $self->{s_kwd} = '';
3776          ## Reconsume.          ## Reconsume.
3777          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ({type => END_OF_DOCTYPE_TOKEN});
3778          redo A;          redo A;
3779        } else {        } else {
3780          ## XML5: No parse error and stay in the state.          ## XML5: No parse error and stay in the state.
3781          !!!parse-error (type => 'string after internal subset'); ## TODO: type          !!!parse-error (type => 'string after internal subset'); ## TODO: type
3782    
3783          $self->{state} = BOGUS_DOCTYPE_STATE;          $self->{state} = BOGUS_DOCTYPE_INTERNAL_SUBSET_AFTER_STATE;
3784            !!!next-input-character;
3785            redo A;
3786          }
3787        } elsif ($self->{state} == BOGUS_DOCTYPE_INTERNAL_SUBSET_AFTER_STATE) {
3788          if ($self->{nc} == 0x003E) { # >
3789            $self->{state} = DATA_STATE;
3790            $self->{s_kwd} = '';
3791            !!!next-input-character;
3792            !!!emit ({type => END_OF_DOCTYPE_TOKEN});
3793            redo A;
3794          } elsif ($self->{nc} == -1) {
3795            $self->{state} = DATA_STATE;
3796            $self->{s_kwd} = '';
3797            ## Reconsume.
3798            !!!emit ({type => END_OF_DOCTYPE_TOKEN});
3799            redo A;
3800          } else {
3801            ## Stay in the state.
3802            !!!next-input-character;
3803            redo A;
3804          }
3805        } elsif ($self->{state} == DOCTYPE_TAG_STATE) {
3806          if ($self->{nc} == 0x0021) { # !
3807            $self->{state} = DOCTYPE_MARKUP_DECLARATION_OPEN_STATE;
3808            !!!next-input-character;
3809            redo A;
3810          } elsif ($self->{nc} == 0x003F) { # ?
3811            $self->{state} = PI_STATE;
3812            !!!next-input-character;
3813            redo A;
3814          } elsif ($self->{nc} == -1) {
3815            !!!parse-error (type => 'bare stago');
3816            $self->{state} = DATA_STATE;
3817            $self->{s_kwd} = '';
3818            ## Reconsume.
3819            redo A;
3820          } else {
3821            !!!parse-error (type => 'bare stago', ## XML5: Not a parse error.
3822                            line => $self->{line_prev},
3823                            column => $self->{column_prev});
3824            $self->{state} = BOGUS_COMMENT_STATE;
3825            $self->{ct} = {type => COMMENT_TOKEN,
3826                           data => '',
3827                          }; ## NOTE: Will be discarded.
3828            !!!next-input-character;
3829            redo A;
3830          }
3831        } elsif ($self->{state} == DOCTYPE_MARKUP_DECLARATION_OPEN_STATE) {
3832          ## XML5: "DOCTYPE markup declaration state".
3833          
3834          if ($self->{nc} == 0x002D) { # -
3835            $self->{state} = MD_HYPHEN_STATE;
3836            !!!next-input-character;
3837            redo A;
3838          } elsif ($self->{nc} == 0x0045 or # E
3839                   $self->{nc} == 0x0065) { # e
3840            $self->{state} = MD_E_STATE;
3841            $self->{kwd} = chr $self->{nc};
3842            !!!next-input-character;
3843            redo A;
3844          } elsif ($self->{nc} == 0x0041 or # A
3845                   $self->{nc} == 0x0061) { # a
3846            $self->{state} = MD_ATTLIST_STATE;
3847            $self->{kwd} = chr $self->{nc};
3848            !!!next-input-character;
3849            redo A;
3850          } elsif ($self->{nc} == 0x004E or # N
3851                   $self->{nc} == 0x006E) { # n
3852            $self->{state} = MD_NOTATION_STATE;
3853            $self->{kwd} = chr $self->{nc};
3854            !!!next-input-character;
3855            redo A;
3856          } else {
3857            #
3858          }
3859          
3860          ## XML5: No parse error.
3861          !!!parse-error (type => 'bogus comment',
3862                          line => $self->{line_prev},
3863                          column => $self->{column_prev} - 1);
3864          ## Reconsume.
3865          $self->{state} = BOGUS_COMMENT_STATE;
3866          $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
3867          redo A;
3868        } elsif ($self->{state} == MD_E_STATE) {
3869          if ($self->{nc} == 0x004E or # N
3870              $self->{nc} == 0x006E) { # n
3871            $self->{state} = MD_ENTITY_STATE;
3872            $self->{kwd} .= chr $self->{nc};
3873            !!!next-input-character;
3874            redo A;
3875          } elsif ($self->{nc} == 0x004C or # L
3876                   $self->{nc} == 0x006C) { # l
3877            ## XML5: <!ELEMENT> not supported.
3878            $self->{state} = MD_ELEMENT_STATE;
3879            $self->{kwd} .= chr $self->{nc};
3880            !!!next-input-character;
3881            redo A;
3882          } else {
3883            ## XML5: No parse error.
3884            !!!parse-error (type => 'bogus comment',
3885                            line => $self->{line_prev},
3886                            column => $self->{column_prev} - 2
3887                                + 1 * ($self->{nc} == -1));
3888            ## Reconsume.
3889            $self->{state} = BOGUS_COMMENT_STATE;
3890            $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded
3891            redo A;
3892          }
3893        } elsif ($self->{state} == MD_ENTITY_STATE) {
3894          if ($self->{nc} == [
3895                undef,
3896                undef,
3897                0x0054, # T
3898                0x0049, # I
3899                0x0054, # T
3900              ]->[length $self->{kwd}] or
3901              $self->{nc} == [
3902                undef,
3903                undef,
3904                0x0074, # t
3905                0x0069, # i
3906                0x0074, # t
3907              ]->[length $self->{kwd}]) {
3908            ## Stay in the state.
3909            $self->{kwd} .= chr $self->{nc};
3910            !!!next-input-character;
3911            redo A;
3912          } elsif ((length $self->{kwd}) == 5 and
3913                   ($self->{nc} == 0x0059 or # Y
3914                    $self->{nc} == 0x0079)) { # y
3915            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
3916              !!!parse-error (type => 'lowercase keyword', ## TODO: type
3917                              text => 'ENTITY',
3918                              line => $self->{line_prev},
3919                              column => $self->{column_prev} - 4);
3920            }
3921            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
3922                           line => $self->{line_prev},
3923                           column => $self->{column_prev} - 6};
3924            $self->{state} = DOCTYPE_MD_STATE;
3925            !!!next-input-character;
3926            redo A;
3927          } else {
3928            !!!parse-error (type => 'bogus comment',
3929                            line => $self->{line_prev},
3930                            column => $self->{column_prev} - 1
3931                                - (length $self->{kwd})
3932                                + 1 * ($self->{nc} == -1));
3933            $self->{state} = BOGUS_COMMENT_STATE;
3934            ## Reconsume.
3935            $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded
3936            redo A;
3937          }
3938        } elsif ($self->{state} == MD_ELEMENT_STATE) {
3939          if ($self->{nc} == [
3940               undef,
3941               undef,
3942               0x0045, # E
3943               0x004D, # M
3944               0x0045, # E
3945               0x004E, # N
3946              ]->[length $self->{kwd}] or
3947              $self->{nc} == [
3948               undef,
3949               undef,
3950               0x0065, # e
3951               0x006D, # m
3952               0x0065, # e
3953               0x006E, # n
3954              ]->[length $self->{kwd}]) {
3955            ## Stay in the state.
3956            $self->{kwd} .= chr $self->{nc};
3957            !!!next-input-character;
3958            redo A;
3959          } elsif ((length $self->{kwd}) == 6 and
3960                   ($self->{nc} == 0x0054 or # T
3961                    $self->{nc} == 0x0074)) { # t
3962            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
3963              !!!parse-error (type => 'lowercase keyword', ## TODO: type
3964                              text => 'ELEMENT',
3965                              line => $self->{line_prev},
3966                              column => $self->{column_prev} - 5);
3967            }
3968            $self->{ct} = {type => ELEMENT_TOKEN, name => '',
3969                           line => $self->{line_prev},
3970                           column => $self->{column_prev} - 7};
3971            $self->{state} = DOCTYPE_MD_STATE;
3972            !!!next-input-character;
3973            redo A;
3974          } else {
3975            !!!parse-error (type => 'bogus comment',
3976                            line => $self->{line_prev},
3977                            column => $self->{column_prev} - 1
3978                                - (length $self->{kwd})
3979                                + 1 * ($self->{nc} == -1));
3980            $self->{state} = BOGUS_COMMENT_STATE;
3981            ## Reconsume.
3982            $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded
3983            redo A;
3984          }
3985        } elsif ($self->{state} == MD_ATTLIST_STATE) {
3986          if ($self->{nc} == [
3987               undef,
3988               0x0054, # T
3989               0x0054, # T
3990               0x004C, # L
3991               0x0049, # I
3992               0x0053, # S
3993              ]->[length $self->{kwd}] or
3994              $self->{nc} == [
3995               undef,
3996               0x0074, # t
3997               0x0074, # t
3998               0x006C, # l
3999               0x0069, # i
4000               0x0073, # s
4001              ]->[length $self->{kwd}]) {
4002            ## Stay in the state.
4003            $self->{kwd} .= chr $self->{nc};
4004            !!!next-input-character;
4005            redo A;
4006          } elsif ((length $self->{kwd}) == 6 and
4007                   ($self->{nc} == 0x0054 or # T
4008                    $self->{nc} == 0x0074)) { # t
4009            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
4010              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4011                              text => 'ATTLIST',
4012                              line => $self->{line_prev},
4013                              column => $self->{column_prev} - 5);
4014            }
4015            $self->{ct} = {type => ATTLIST_TOKEN, name => '',
4016                           attrdefs => [],
4017                           line => $self->{line_prev},
4018                           column => $self->{column_prev} - 7};
4019            $self->{state} = DOCTYPE_MD_STATE;
4020            !!!next-input-character;
4021            redo A;
4022          } else {
4023            !!!parse-error (type => 'bogus comment',
4024                            line => $self->{line_prev},
4025                            column => $self->{column_prev} - 1
4026                                 - (length $self->{kwd})
4027                                 + 1 * ($self->{nc} == -1));
4028            $self->{state} = BOGUS_COMMENT_STATE;
4029            ## Reconsume.
4030            $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded
4031            redo A;
4032          }
4033        } elsif ($self->{state} == MD_NOTATION_STATE) {
4034          if ($self->{nc} == [
4035               undef,
4036               0x004F, # O
4037               0x0054, # T
4038               0x0041, # A
4039               0x0054, # T
4040               0x0049, # I
4041               0x004F, # O
4042              ]->[length $self->{kwd}] or
4043              $self->{nc} == [
4044               undef,
4045               0x006F, # o
4046               0x0074, # t
4047               0x0061, # a
4048               0x0074, # t
4049               0x0069, # i
4050               0x006F, # o
4051              ]->[length $self->{kwd}]) {
4052            ## Stay in the state.
4053            $self->{kwd} .= chr $self->{nc};
4054            !!!next-input-character;
4055            redo A;
4056          } elsif ((length $self->{kwd}) == 7 and
4057                   ($self->{nc} == 0x004E or # N
4058                    $self->{nc} == 0x006E)) { # n
4059            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
4060              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4061                              text => 'NOTATION',
4062                              line => $self->{line_prev},
4063                              column => $self->{column_prev} - 6);
4064            }
4065            $self->{ct} = {type => NOTATION_TOKEN, name => '',
4066                           line => $self->{line_prev},
4067                           column => $self->{column_prev} - 8};
4068            $self->{state} = DOCTYPE_MD_STATE;
4069            !!!next-input-character;
4070            redo A;
4071          } else {
4072            !!!parse-error (type => 'bogus comment',
4073                            line => $self->{line_prev},
4074                            column => $self->{column_prev} - 1
4075                                - (length $self->{kwd})
4076                                + 1 * ($self->{nc} == -1));
4077            $self->{state} = BOGUS_COMMENT_STATE;
4078            ## Reconsume.
4079            $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded
4080            redo A;
4081          }
4082        } elsif ($self->{state} == DOCTYPE_MD_STATE) {
4083          ## XML5: "DOCTYPE ENTITY state", "DOCTYPE ATTLIST state", and
4084          ## "DOCTYPE NOTATION state".
4085    
4086          if ($is_space->{$self->{nc}}) {
4087            ## XML5: [NOTATION] Switch to the "DOCTYPE NOTATION identifier state".
4088            $self->{state} = BEFORE_MD_NAME_STATE;
4089            !!!next-input-character;
4090            redo A;
4091          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4092                   $self->{nc} == 0x0025) { # %
4093            ## XML5: Switch to the "DOCTYPE bogus comment state".
4094            !!!parse-error (type => 'no space before md name'); ## TODO: type
4095            $self->{state} = DOCTYPE_ENTITY_PARAMETER_BEFORE_STATE;
4096            !!!next-input-character;
4097            redo A;
4098          } elsif ($self->{nc} == -1) {
4099            !!!parse-error (type => 'unclosed md'); ## TODO: type
4100            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4101            ## Reconsume.
4102            redo A;
4103          } elsif ($self->{nc} == 0x003E) { # >
4104            ## XML5: Switch to the "DOCTYPE bogus comment state".
4105            !!!parse-error (type => 'no md name'); ## TODO: type
4106            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4107            !!!next-input-character;
4108            redo A;
4109          } else {
4110            ## XML5: Switch to the "DOCTYPE bogus comment state".
4111            !!!parse-error (type => 'no space before md name'); ## TODO: type
4112            $self->{state} = BEFORE_MD_NAME_STATE;
4113            redo A;
4114          }
4115        } elsif ($self->{state} == BEFORE_MD_NAME_STATE) {
4116          ## XML5: "DOCTYPE ENTITY parameter state", "DOCTYPE ENTITY type
4117          ## before state", "DOCTYPE ATTLIST name before state".
4118    
4119          if ($is_space->{$self->{nc}}) {
4120            ## Stay in the state.
4121            !!!next-input-character;
4122            redo A;
4123          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4124                   $self->{nc} == 0x0025) { # %
4125            $self->{state} = DOCTYPE_ENTITY_PARAMETER_BEFORE_STATE;
4126            !!!next-input-character;
4127            redo A;
4128          } elsif ($self->{nc} == 0x003E) { # >
4129            ## XML5: Same as "Anything else".
4130            !!!parse-error (type => 'no md name'); ## TODO: type
4131            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4132            !!!next-input-character;
4133            redo A;
4134          } elsif ($self->{nc} == -1) {
4135            !!!parse-error (type => 'unclosed md'); ## TODO: type
4136            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4137            ## Reconsume.
4138            redo A;
4139          } else {
4140            ## XML5: [ATTLIST] Not defined yet.
4141            $self->{ct}->{name} .= chr $self->{nc};
4142            $self->{state} = MD_NAME_STATE;
4143            !!!next-input-character;
4144            redo A;
4145          }
4146        } elsif ($self->{state} == DOCTYPE_ENTITY_PARAMETER_BEFORE_STATE) {
4147          if ($is_space->{$self->{nc}}) {
4148            ## XML5: Switch to the "DOCTYPE ENTITY parameter state".
4149            $self->{ct}->{type} = PARAMETER_ENTITY_TOKEN;
4150            $self->{state} = BEFORE_MD_NAME_STATE;
4151            !!!next-input-character;
4152            redo A;
4153          } elsif ($self->{nc} == 0x003E) { # >
4154            ## XML5: Same as "Anything else".
4155            !!!parse-error (type => 'no md name'); ## TODO: type
4156            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4157            !!!next-input-character;
4158            redo A;
4159          } elsif ($self->{nc} == -1) {
4160            !!!parse-error (type => 'unclosed md');
4161            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4162            ## Reconsume.
4163            redo A;
4164          } else {
4165            ## XML5: No parse error.
4166            !!!parse-error (type => 'no space after ENTITY percent'); ## TODO: type
4167            $self->{state} = BOGUS_COMMENT_STATE;
4168            $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded
4169            ## Reconsume.
4170            redo A;
4171          }
4172        } elsif ($self->{state} == MD_NAME_STATE) {
4173          ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".
4174          
4175          if ($is_space->{$self->{nc}}) {
4176            if ($self->{ct}->{type} == ATTLIST_TOKEN) {
4177              $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
4178            } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
4179              $self->{state} = AFTER_ELEMENT_NAME_STATE;
4180            } else { # ENTITY/NOTATION
4181              $self->{state} = AFTER_DOCTYPE_NAME_STATE;
4182            }
4183            !!!next-input-character;
4184            redo A;
4185          } elsif ($self->{nc} == 0x003E) { # >
4186            if ($self->{ct}->{type} == ATTLIST_TOKEN) {
4187              #
4188            } else {
4189              !!!parse-error (type => 'no md def'); ## TODO: type
4190            }
4191            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4192            !!!next-input-character;
4193            !!!emit ($self->{ct}); # ELEMENT/ENTITY/ATTLIST/NOTATION
4194            redo A;
4195          } elsif ($self->{nc} == -1) {
4196            ## XML5: [ATTLIST] No parse error.
4197            !!!parse-error (type => 'unclosed md');
4198            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4199            ## Reconsume.
4200            !!!emit ($self->{ct}); # ELEMENT/ENTITY/ATTLIST/NOTATION
4201            redo A;
4202          } else {
4203            ## XML5: [ATTLIST] Not defined yet.
4204            $self->{ct}->{name} .= chr $self->{nc};
4205            ## Stay in the state.
4206            !!!next-input-character;
4207            redo A;
4208          }
4209        } elsif ($self->{state} == DOCTYPE_ATTLIST_NAME_AFTER_STATE) {
4210          if ($is_space->{$self->{nc}}) {
4211            ## Stay in the state.
4212            !!!next-input-character;
4213            redo A;
4214          } elsif ($self->{nc} == 0x003E) { # >
4215            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4216            !!!next-input-character;
4217            !!!emit ($self->{ct}); # ATTLIST
4218            redo A;
4219          } elsif ($self->{nc} == -1) {
4220            ## XML5: No parse error.
4221            !!!parse-error (type => 'unclosed md'); ## TODO: type
4222            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4223            !!!emit ($self->{ct});
4224            redo A;
4225          } else {
4226            ## XML5: Not defined yet.
4227            $self->{ca} = {name => chr ($self->{nc}), # attrdef
4228                           tokens => [],
4229                           line => $self->{line}, column => $self->{column}};
4230            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_NAME_STATE;
4231            !!!next-input-character;
4232            redo A;
4233          }
4234        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_NAME_STATE) {
4235          if ($is_space->{$self->{nc}}) {
4236            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_NAME_AFTER_STATE;
4237            !!!next-input-character;
4238            redo A;
4239          } elsif ($self->{nc} == 0x003E) { # >
4240            ## XML5: Same as "anything else".
4241            !!!parse-error (type => 'no attr type'); ## TODO: type
4242            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4243            !!!next-input-character;
4244            !!!emit ($self->{ct}); # ATTLIST
4245            redo A;
4246          } elsif ($self->{nc} == 0x0028) { # (
4247            ## XML5: Same as "anything else".
4248            !!!parse-error (type => 'no space before paren'); ## TODO: type
4249            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
4250            !!!next-input-character;
4251            redo A;
4252          } elsif ($self->{nc} == -1) {
4253            ## XML5: No parse error.
4254            !!!parse-error (type => 'unclosed md'); ## TODO: type
4255            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4256            !!!next-input-character;
4257            !!!emit ($self->{ct}); # ATTLIST
4258            redo A;
4259          } else {
4260            ## XML5: Not defined yet.
4261            $self->{ca}->{name} .= chr $self->{nc};
4262            ## Stay in the state.
4263            !!!next-input-character;
4264            redo A;
4265          }
4266        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_NAME_AFTER_STATE) {
4267          if ($is_space->{$self->{nc}}) {
4268            ## Stay in the state.
4269            !!!next-input-character;
4270            redo A;
4271          } elsif ($self->{nc} == 0x003E) { # >
4272            ## XML5: Same as "anything else".
4273            !!!parse-error (type => 'no attr type'); ## TODO: type
4274            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4275            !!!next-input-character;
4276            !!!emit ($self->{ct}); # ATTLIST
4277            redo A;
4278          } elsif ($self->{nc} == 0x0028) { # (
4279            ## XML5: Same as "anything else".
4280            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
4281            !!!next-input-character;
4282            redo A;
4283          } elsif ($self->{nc} == -1) {
4284            ## XML5: No parse error.
4285            !!!parse-error (type => 'unclosed md'); ## TODO: type
4286            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4287            !!!next-input-character;
4288            !!!emit ($self->{ct});
4289            redo A;
4290          } else {
4291            ## XML5: Not defined yet.
4292            $self->{ca}->{type} = chr $self->{nc};
4293            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_STATE;
4294            !!!next-input-character;
4295            redo A;
4296          }
4297        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_STATE) {
4298          if ($is_space->{$self->{nc}}) {
4299            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_AFTER_STATE;
4300            !!!next-input-character;
4301            redo A;
4302          } elsif ($self->{nc} == 0x0023) { # #
4303            ## XML5: Same as "anything else".
4304            !!!parse-error (type => 'no space before default value'); ## TODO: type
4305            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE;
4306            !!!next-input-character;
4307            redo A;
4308          } elsif ($self->{nc} == 0x0022) { # "
4309            ## XML5: Same as "anything else".
4310            !!!parse-error (type => 'no space before default value'); ## TODO: type
4311            $self->{ca}->{value} = '';
4312            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
4313            !!!next-input-character;
4314            redo A;
4315          } elsif ($self->{nc} == 0x0027) { # '
4316            ## XML5: Same as "anything else".
4317            !!!parse-error (type => 'no space before default value'); ## TODO: type
4318            $self->{ca}->{value} = '';
4319            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
4320            !!!next-input-character;
4321            redo A;
4322          } elsif ($self->{nc} == 0x003E) { # >
4323            ## XML5: Same as "anything else".
4324            !!!parse-error (type => 'no attr default'); ## TODO: type
4325            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4326            !!!next-input-character;
4327            !!!emit ($self->{ct}); # ATTLIST
4328            redo A;
4329          } elsif ($self->{nc} == 0x0028) { # (
4330            ## XML5: Same as "anything else".
4331            !!!parse-error (type => 'no space before paren'); ## TODO: type
4332            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
4333            !!!next-input-character;
4334            redo A;
4335          } elsif ($self->{nc} == -1) {
4336            ## XML5: No parse error.
4337            !!!parse-error (type => 'unclosed md'); ## TODO: type
4338            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4339            !!!next-input-character;
4340            !!!emit ($self->{ct});
4341            redo A;
4342          } else {
4343            ## XML5: Not defined yet.
4344            $self->{ca}->{type} .= chr $self->{nc};
4345            ## Stay in the state.
4346            !!!next-input-character;
4347            redo A;
4348          }
4349        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_TYPE_AFTER_STATE) {
4350          if ($is_space->{$self->{nc}}) {
4351            ## Stay in the state.
4352            !!!next-input-character;
4353            redo A;
4354          } elsif ($self->{nc} == 0x0028) { # (
4355            ## XML5: Same as "anything else".
4356            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
4357            !!!next-input-character;
4358            redo A;
4359          } elsif ($self->{nc} == 0x0023) { # #
4360            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE;
4361            !!!next-input-character;
4362            redo A;
4363          } elsif ($self->{nc} == 0x0022) { # "
4364            ## XML5: Same as "anything else".
4365            $self->{ca}->{value} = '';
4366            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
4367            !!!next-input-character;
4368            redo A;
4369          } elsif ($self->{nc} == 0x0027) { # '
4370            ## XML5: Same as "anything else".
4371            $self->{ca}->{value} = '';
4372            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
4373            !!!next-input-character;
4374            redo A;
4375          } elsif ($self->{nc} == 0x003E) { # >
4376            ## XML5: Same as "anything else".
4377            !!!parse-error (type => 'no attr default'); ## TODO: type
4378            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4379            !!!next-input-character;
4380            !!!emit ($self->{ct}); # ATTLIST
4381            redo A;
4382          } elsif ($self->{nc} == -1) {
4383            ## XML5: No parse error.
4384            !!!parse-error (type => 'unclosed md'); ## TODO: type
4385            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4386            !!!next-input-character;
4387            !!!emit ($self->{ct});
4388            redo A;
4389          } else {
4390            ## XML5: Switch to the "DOCTYPE bogus comment state".
4391            !!!parse-error (type => 'unquoted attr value'); ## TODO: type
4392            $self->{ca}->{value} = '';
4393            $self->{state} = ATTRIBUTE_VALUE_UNQUOTED_STATE;
4394            ## Reconsume.
4395            redo A;
4396          }
4397        } elsif ($self->{state} == BEFORE_ALLOWED_TOKEN_STATE) {
4398          if ($is_space->{$self->{nc}}) {
4399            ## Stay in the state.
4400            !!!next-input-character;
4401            redo A;
4402          } elsif ($self->{nc} == 0x007C) { # |
4403            !!!parse-error (type => 'empty allowed token'); ## TODO: type
4404            ## Stay in the state.
4405            !!!next-input-character;
4406            redo A;
4407          } elsif ($self->{nc} == 0x0029) { # )
4408            !!!parse-error (type => 'empty allowed token'); ## TODO: type
4409            $self->{state} = AFTER_ALLOWED_TOKENS_STATE;
4410            !!!next-input-character;
4411            redo A;
4412          } elsif ($self->{nc} == 0x003E) { # >
4413            !!!parse-error (type => 'unclosed allowed tokens'); ## TODO: type
4414            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4415            !!!next-input-character;
4416            !!!emit ($self->{ct}); # ATTLIST
4417            redo A;
4418          } elsif ($self->{nc} == -1) {
4419            ## XML5: No parse error.
4420            !!!parse-error (type => 'unclosed md'); ## TODO: type
4421            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4422            !!!next-input-character;
4423            !!!emit ($self->{ct});
4424            redo A;
4425          } else {
4426            push @{$self->{ca}->{tokens}}, chr $self->{nc};
4427            $self->{state} = ALLOWED_TOKEN_STATE;
4428            !!!next-input-character;
4429            redo A;
4430          }
4431        } elsif ($self->{state} == ALLOWED_TOKEN_STATE) {
4432          if ($is_space->{$self->{nc}}) {
4433            $self->{state} = AFTER_ALLOWED_TOKEN_STATE;
4434            !!!next-input-character;
4435            redo A;
4436          } elsif ($self->{nc} == 0x007C) { # |
4437            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
4438            !!!next-input-character;
4439            redo A;
4440          } elsif ($self->{nc} == 0x0029) { # )
4441            $self->{state} = AFTER_ALLOWED_TOKENS_STATE;
4442            !!!next-input-character;
4443            redo A;
4444          } elsif ($self->{nc} == 0x003E) { # >
4445            !!!parse-error (type => 'unclosed allowed tokens'); ## TODO: type
4446            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4447            !!!next-input-character;
4448            !!!emit ($self->{ct}); # ATTLIST
4449            redo A;
4450          } elsif ($self->{nc} == -1) {
4451            ## XML5: No parse error.
4452            !!!parse-error (type => 'unclosed md'); ## TODO: type
4453            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4454            !!!next-input-character;
4455            !!!emit ($self->{ct});
4456            redo A;
4457          } else {
4458            $self->{ca}->{tokens}->[-1] .= chr $self->{nc};
4459            ## Stay in the state.
4460            !!!next-input-character;
4461            redo A;
4462          }
4463        } elsif ($self->{state} == AFTER_ALLOWED_TOKEN_STATE) {
4464          if ($is_space->{$self->{nc}}) {
4465            ## Stay in the state.
4466            !!!next-input-character;
4467            redo A;
4468          } elsif ($self->{nc} == 0x007C) { # |
4469            $self->{state} = BEFORE_ALLOWED_TOKEN_STATE;
4470            !!!next-input-character;
4471            redo A;
4472          } elsif ($self->{nc} == 0x0029) { # )
4473            $self->{state} = AFTER_ALLOWED_TOKENS_STATE;
4474            !!!next-input-character;
4475            redo A;
4476          } elsif ($self->{nc} == 0x003E) { # >
4477            !!!parse-error (type => 'unclosed allowed tokens'); ## TODO: type
4478            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4479            !!!next-input-character;
4480            !!!emit ($self->{ct}); # ATTLIST
4481            redo A;
4482          } elsif ($self->{nc} == -1) {
4483            ## XML5: No parse error.
4484            !!!parse-error (type => 'unclosed md'); ## TODO: type
4485            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4486            !!!next-input-character;
4487            !!!emit ($self->{ct});
4488            redo A;
4489          } else {
4490            !!!parse-error (type => 'space in allowed token', ## TODO: type
4491                            line => $self->{line_prev},
4492                            column => $self->{column_prev});
4493            $self->{ca}->{tokens}->[-1] .= ' ' . chr $self->{nc};
4494            $self->{state} = ALLOWED_TOKEN_STATE;
4495            !!!next-input-character;
4496            redo A;
4497          }
4498        } elsif ($self->{state} == AFTER_ALLOWED_TOKENS_STATE) {
4499          if ($is_space->{$self->{nc}}) {
4500            $self->{state} = BEFORE_ATTR_DEFAULT_STATE;
4501            !!!next-input-character;
4502            redo A;
4503          } elsif ($self->{nc} == 0x0023) { # #
4504            !!!parse-error (type => 'no space before default value'); ## TODO: type
4505            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE;
4506            !!!next-input-character;
4507            redo A;
4508          } elsif ($self->{nc} == 0x0022) { # "
4509            !!!parse-error (type => 'no space before default value'); ## TODO: type
4510            $self->{ca}->{value} = '';
4511            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
4512            !!!next-input-character;
4513            redo A;
4514          } elsif ($self->{nc} == 0x0027) { # '
4515            !!!parse-error (type => 'no space before default value'); ## TODO: type
4516            $self->{ca}->{value} = '';
4517            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
4518            !!!next-input-character;
4519            redo A;
4520          } elsif ($self->{nc} == 0x003E) { # >
4521            !!!parse-error (type => 'no attr default'); ## TODO: type
4522            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4523            !!!next-input-character;
4524            !!!emit ($self->{ct}); # ATTLIST
4525            redo A;
4526          } elsif ($self->{nc} == -1) {
4527            !!!parse-error (type => 'unclosed md'); ## TODO: type
4528            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4529            !!!next-input-character;
4530            !!!emit ($self->{ct});
4531            redo A;
4532          } else {
4533            !!!parse-error (type => 'unquoted attr value'); ## TODO: type
4534            $self->{state} = ATTRIBUTE_VALUE_UNQUOTED_STATE;
4535            ## Reconsume.
4536            redo A;
4537          }
4538        } elsif ($self->{state} == BEFORE_ATTR_DEFAULT_STATE) {
4539          if ($is_space->{$self->{nc}}) {
4540            ## Stay in the state.
4541            !!!next-input-character;
4542            redo A;
4543          } elsif ($self->{nc} == 0x0023) { # #
4544            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE;
4545            !!!next-input-character;
4546            redo A;
4547          } elsif ($self->{nc} == 0x0022) { # "
4548            $self->{ca}->{value} = '';
4549            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
4550            !!!next-input-character;
4551            redo A;
4552          } elsif ($self->{nc} == 0x0027) { # '
4553            $self->{ca}->{value} = '';
4554            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
4555            !!!next-input-character;
4556            redo A;
4557          } elsif ($self->{nc} == 0x003E) { # >
4558            !!!parse-error (type => 'no attr default'); ## TODO: type
4559            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4560            !!!next-input-character;
4561            !!!emit ($self->{ct}); # ATTLIST
4562            redo A;
4563          } elsif ($self->{nc} == -1) {
4564            !!!parse-error (type => 'unclosed md'); ## TODO: type
4565            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4566            !!!next-input-character;
4567            !!!emit ($self->{ct});
4568            redo A;
4569          } else {
4570            !!!parse-error (type => 'unquoted attr value'); ## TODO: type
4571            $self->{state} = ATTRIBUTE_VALUE_UNQUOTED_STATE;
4572            ## Reconsume.
4573            redo A;
4574          }
4575        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_BEFORE_STATE) {
4576          if ($is_space->{$self->{nc}}) {
4577            ## XML5: No parse error.
4578            !!!parse-error (type => 'no default type'); ## TODO: type
4579            $self->{state} = BOGUS_MD_STATE;
4580            ## Reconsume.
4581            redo A;
4582          } elsif ($self->{nc} == 0x0022) { # "
4583            ## XML5: Same as "anything else".
4584            $self->{ca}->{value} = '';
4585            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
4586            !!!next-input-character;
4587            redo A;
4588          } elsif ($self->{nc} == 0x0027) { # '
4589            ## XML5: Same as "anything else".
4590            $self->{ca}->{value} = '';
4591            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
4592            !!!next-input-character;
4593            redo A;
4594          } elsif ($self->{nc} == 0x003E) { # >
4595            ## XML5: Same as "anything else".
4596            !!!parse-error (type => 'no attr default'); ## TODO: type
4597            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4598            !!!next-input-character;
4599            !!!emit ($self->{ct}); # ATTLIST
4600            redo A;
4601          } elsif ($self->{nc} == -1) {
4602            ## XML5: No parse error.
4603            !!!parse-error (type => 'unclosed md'); ## TODO: type
4604            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4605            !!!next-input-character;
4606            !!!emit ($self->{ct});
4607            redo A;
4608          } else {
4609            $self->{ca}->{default} = chr $self->{nc};
4610            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE;
4611            !!!next-input-character;
4612            redo A;
4613          }
4614        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE) {
4615          if ($is_space->{$self->{nc}}) {
4616            $self->{state} = DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE;
4617            !!!next-input-character;
4618            redo A;
4619          } elsif ($self->{nc} == 0x0022) { # "
4620            ## XML5: Same as "anything else".
4621            !!!parse-error (type => 'no space before default value'); ## TODO: type
4622            $self->{ca}->{value} = '';
4623            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
4624            !!!next-input-character;
4625            redo A;
4626          } elsif ($self->{nc} == 0x0027) { # '
4627            ## XML5: Same as "anything else".
4628            !!!parse-error (type => 'no space before default value'); ## TODO: type
4629            $self->{ca}->{value} = '';
4630            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
4631            !!!next-input-character;
4632            redo A;
4633          } elsif ($self->{nc} == 0x003E) { # >
4634            ## XML5: Same as "anything else".
4635            push @{$self->{ct}->{attrdefs}}, $self->{ca};
4636            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4637            !!!next-input-character;
4638            !!!emit ($self->{ct}); # ATTLIST
4639            redo A;
4640          } elsif ($self->{nc} == -1) {
4641            ## XML5: No parse error.
4642            !!!parse-error (type => 'unclosed md'); ## TODO: type
4643            push @{$self->{ct}->{attrdefs}}, $self->{ca};
4644            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4645            !!!next-input-character;
4646            !!!emit ($self->{ct});
4647            redo A;
4648          } else {
4649            $self->{ca}->{default} .= chr $self->{nc};
4650            ## Stay in the state.
4651            !!!next-input-character;
4652            redo A;
4653          }
4654        } elsif ($self->{state} == DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE) {
4655          if ($is_space->{$self->{nc}}) {
4656            ## Stay in the state.
4657            !!!next-input-character;
4658            redo A;
4659          } elsif ($self->{nc} == 0x0022) { # "
4660            $self->{ca}->{value} = '';
4661            $self->{state} = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
4662            !!!next-input-character;
4663            redo A;
4664          } elsif ($self->{nc} == 0x0027) { # '
4665            $self->{ca}->{value} = '';
4666            $self->{state} = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
4667            !!!next-input-character;
4668            redo A;
4669          } elsif ($self->{nc} == 0x003E) { # >
4670            push @{$self->{ct}->{attrdefs}}, $self->{ca};
4671            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4672            !!!next-input-character;
4673            !!!emit ($self->{ct}); # ATTLIST
4674            redo A;
4675          } elsif ($self->{nc} == -1) {
4676            ## XML5: No parse error.
4677            !!!parse-error (type => 'unclosed md'); ## TODO: type
4678            push @{$self->{ct}->{attrdefs}}, $self->{ca};
4679            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE; ## XML5: "Data state".
4680            !!!next-input-character;
4681            !!!emit ($self->{ct});
4682            redo A;
4683          } else {
4684            ## XML5: Not defined yet.
4685            if ($self->{ca}->{default} eq 'FIXED') {
4686              $self->{state} = ATTRIBUTE_VALUE_UNQUOTED_STATE;
4687            } else {
4688              push @{$self->{ct}->{attrdefs}}, $self->{ca};
4689              $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
4690            }
4691            ## Reconsume.
4692            redo A;
4693          }
4694        } elsif ($self->{state} == AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE) {
4695          if ($is_space->{$self->{nc}} or
4696              $self->{nc} == -1 or
4697              $self->{nc} == 0x003E) { # >
4698            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
4699            ## Reconsume.
4700            redo A;
4701          } else {
4702            !!!parse-error (type => 'no space before attr name'); ## TODO: type
4703            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
4704            ## Reconsume.
4705            redo A;
4706          }
4707        } elsif ($self->{state} == NDATA_STATE) {
4708          ## ASCII case-insensitive
4709          if ($self->{nc} == [
4710                undef,
4711                0x0044, # D
4712                0x0041, # A
4713                0x0054, # T
4714              ]->[length $self->{kwd}] or
4715              $self->{nc} == [
4716                undef,
4717                0x0064, # d
4718                0x0061, # a
4719                0x0074, # t
4720              ]->[length $self->{kwd}]) {
4721            !!!cp (172.2);
4722            ## Stay in the state.
4723            $self->{kwd} .= chr $self->{nc};
4724            !!!next-input-character;
4725            redo A;
4726          } elsif ((length $self->{kwd}) == 4 and
4727                   ($self->{nc} == 0x0041 or # A
4728                    $self->{nc} == 0x0061)) { # a
4729            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
4730              !!!cp (172.3);
4731              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4732                              text => 'NDATA',
4733                              line => $self->{line_prev},
4734                              column => $self->{column_prev} - 4);
4735            } else {
4736              !!!cp (172.4);
4737            }
4738            $self->{state} = AFTER_NDATA_STATE;
4739            !!!next-input-character;
4740            redo A;
4741          } else {
4742            !!!parse-error (type => 'string after literal', ## TODO: type
4743                            line => $self->{line_prev},
4744                            column => $self->{column_prev} + 1
4745                                - length $self->{kwd});
4746            !!!cp (172.5);
4747            $self->{state} = BOGUS_MD_STATE;
4748            ## Reconsume.
4749            redo A;
4750          }
4751        } elsif ($self->{state} == AFTER_NDATA_STATE) {
4752          if ($is_space->{$self->{nc}}) {
4753            $self->{state} = BEFORE_NOTATION_NAME_STATE;
4754            !!!next-input-character;
4755            redo A;
4756          } elsif ($self->{nc} == 0x003E) { # >
4757            !!!parse-error (type => 'no notation name'); ## TODO: type
4758            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4759            !!!next-input-character;
4760            !!!emit ($self->{ct}); # ENTITY
4761            redo A;
4762          } elsif ($self->{nc} == -1) {
4763            !!!parse-error (type => 'unclosed md'); ## TODO: type
4764            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4765            !!!next-input-character;
4766            !!!emit ($self->{ct}); # ENTITY
4767            redo A;
4768          } else {
4769            !!!parse-error (type => 'string after literal', ## TODO: type
4770                            line => $self->{line_prev},
4771                            column => $self->{column_prev} + 1
4772                                - length $self->{kwd});
4773            $self->{state} = BOGUS_MD_STATE;
4774            ## Reconsume.
4775            redo A;
4776          }
4777        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
4778          if ($is_space->{$self->{nc}}) {
4779            ## Stay in the state.
4780            !!!next-input-character;
4781            redo A;
4782          } elsif ($self->{nc} == 0x003E) { # >
4783            !!!parse-error (type => 'no notation name'); ## TODO: type
4784            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4785            !!!next-input-character;
4786            !!!emit ($self->{ct}); # ENTITY
4787            redo A;
4788          } elsif ($self->{nc} == -1) {
4789            !!!parse-error (type => 'unclosed md'); ## TODO: type
4790            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4791            !!!next-input-character;
4792            !!!emit ($self->{ct}); # ENTITY
4793            redo A;
4794          } else {
4795            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
4796            $self->{state} = NOTATION_NAME_STATE;
4797            !!!next-input-character;
4798            redo A;
4799          }
4800        } elsif ($self->{state} == NOTATION_NAME_STATE) {
4801          if ($is_space->{$self->{nc}}) {
4802            $self->{state} = AFTER_MD_DEF_STATE;
4803            !!!next-input-character;
4804            redo A;
4805          } elsif ($self->{nc} == 0x003E) { # >
4806            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4807            !!!next-input-character;
4808            !!!emit ($self->{ct}); # ENTITY
4809            redo A;
4810          } elsif ($self->{nc} == -1) {
4811            !!!parse-error (type => 'unclosed md'); ## TODO: type
4812            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4813            !!!next-input-character;
4814            !!!emit ($self->{ct}); # ENTITY
4815            redo A;
4816          } else {
4817            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
4818            ## Stay in the state.
4819            !!!next-input-character;
4820            redo A;
4821          }
4822        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
4823          if ($self->{nc} == 0x0022) { # "
4824            $self->{state} = AFTER_MD_DEF_STATE;
4825            !!!next-input-character;
4826            redo A;
4827          } elsif ($self->{nc} == 0x0026) { # &
4828            $self->{prev_state} = $self->{state};
4829            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
4830            $self->{entity_add} = 0x0022; # "
4831            !!!next-input-character;
4832            redo A;
4833    ## TODO: %
4834          } elsif ($self->{nc} == -1) {
4835            !!!parse-error (type => 'unclosed entity value'); ## TODO: type
4836            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4837            ## Reconsume.
4838            !!!emit ($self->{ct}); # ENTITY
4839            redo A;
4840          } else {
4841            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
4842            !!!next-input-character;
4843            redo A;
4844          }
4845        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
4846          if ($self->{nc} == 0x0027) { # '
4847            $self->{state} = AFTER_MD_DEF_STATE;
4848            !!!next-input-character;
4849            redo A;
4850          } elsif ($self->{nc} == 0x0026) { # &
4851            $self->{prev_state} = $self->{state};
4852            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
4853            $self->{entity_add} = 0x0027; # '
4854            !!!next-input-character;
4855            redo A;
4856    ## TODO: %
4857          } elsif ($self->{nc} == -1) {
4858            !!!parse-error (type => 'unclosed entity value'); ## TODO: type
4859            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4860            ## Reconsume.
4861            !!!emit ($self->{ct}); # ENTITY
4862            redo A;
4863          } else {
4864            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
4865            !!!next-input-character;
4866            redo A;
4867          }
4868        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
4869          if ($is_space->{$self->{nc}} or
4870              {
4871                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4872                $self->{entity_add} => 1,
4873              }->{$self->{nc}}) {
4874            !!!parse-error (type => 'bare ero',
4875                            line => $self->{line_prev},
4876                            column => $self->{column_prev}
4877                                + ($self->{nc} == -1 ? 1 : 0));
4878            ## Don't consume
4879            ## Return nothing.
4880            #
4881          } elsif ($self->{nc} == 0x0023) { # #
4882            $self->{ca} = $self->{ct};
4883            $self->{state} = ENTITY_HASH_STATE;
4884            $self->{kwd} = '#';
4885            !!!next-input-character;
4886            redo A;
4887          } else {
4888            #
4889          }
4890    
4891          $self->{ct}->{value} .= '&';
4892          $self->{state} = $self->{prev_state};
4893          ## Reconsume.
4894          redo A;
4895        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
4896          if ($is_space->{$self->{nc}}) {
4897            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
4898            !!!next-input-character;
4899            redo A;
4900          } elsif ($self->{nc} == 0x0028) { # (
4901            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
4902            $self->{ct}->{content} = ['('];
4903            $self->{group_depth} = 1;
4904            !!!next-input-character;
4905            redo A;
4906          } elsif ($self->{nc} == 0x003E) { # >
4907            !!!parse-error (type => 'no md def'); ## TODO: type
4908            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4909            !!!next-input-character;
4910            !!!emit ($self->{ct}); # ELEMENT
4911            redo A;
4912          } elsif ($self->{nc} == -1) {
4913            !!!parse-error (type => 'unclosed md'); ## TODO: type
4914            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4915            !!!next-input-character;
4916            !!!emit ($self->{ct}); # ELEMENT
4917            redo A;
4918          } else {
4919            $self->{ct}->{content} = [chr $self->{nc}];
4920            $self->{state} = CONTENT_KEYWORD_STATE;
4921            !!!next-input-character;
4922            redo A;
4923          }
4924        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
4925          if ($is_space->{$self->{nc}}) {
4926            $self->{state} = AFTER_MD_DEF_STATE;
4927            !!!next-input-character;
4928            redo A;
4929          } elsif ($self->{nc} == 0x003E) { # >
4930            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4931            !!!next-input-character;
4932            !!!emit ($self->{ct}); # ELEMENT
4933            redo A;
4934          } elsif ($self->{nc} == -1) {
4935            !!!parse-error (type => 'unclosed md'); ## TODO: type
4936            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4937            !!!next-input-character;
4938            !!!emit ($self->{ct}); # ELEMENT
4939            redo A;
4940          } else {
4941            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
4942            ## Stay in the state.
4943            !!!next-input-character;
4944            redo A;
4945          }
4946        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
4947          if ($is_space->{$self->{nc}}) {
4948            ## Stay in the state.
4949            !!!next-input-character;
4950            redo A;
4951          } elsif ($self->{nc} == 0x0028) { # (
4952            $self->{group_depth}++;
4953            push @{$self->{ct}->{content}}, chr $self->{nc};
4954            ## Stay in the state.
4955            !!!next-input-character;
4956            redo A;
4957          } elsif ($self->{nc} == 0x007C or # |
4958                   $self->{nc} == 0x002C) { # ,
4959            !!!parse-error (type => 'empty element name'); ## TODO: type
4960            ## Stay in the state.
4961            !!!next-input-character;
4962            redo A;
4963          } elsif ($self->{nc} == 0x0029) { # )
4964            !!!parse-error (type => 'empty element name'); ## TODO: type
4965            push @{$self->{ct}->{content}}, chr $self->{nc};
4966            $self->{group_depth}--;
4967            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
4968            !!!next-input-character;
4969            redo A;
4970          } elsif ($self->{nc} == 0x003E) { # >
4971            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
4972            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
4973            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4974            !!!next-input-character;
4975            !!!emit ($self->{ct}); # ELEMENT
4976            redo A;
4977          } elsif ($self->{nc} == -1) {
4978            !!!parse-error (type => 'unclosed md'); ## TODO: type
4979            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
4980            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4981            !!!next-input-character;
4982            !!!emit ($self->{ct}); # ELEMENT
4983            redo A;
4984          } else {
4985            push @{$self->{ct}->{content}}, chr $self->{nc};
4986            $self->{state} = CM_ELEMENT_NAME_STATE;
4987            !!!next-input-character;
4988            redo A;
4989          }
4990        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
4991          if ($is_space->{$self->{nc}}) {
4992            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
4993            !!!next-input-character;
4994            redo A;
4995          } elsif ($self->{nc} == 0x002A or # *
4996                   $self->{nc} == 0x002B or # +
4997                   $self->{nc} == 0x003F) { # ?
4998            push @{$self->{ct}->{content}}, chr $self->{nc};
4999            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5000            !!!next-input-character;
5001            redo A;
5002          } elsif ($self->{nc} == 0x007C or # |
5003                   $self->{nc} == 0x002C) { # ,
5004            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
5005            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
5006            !!!next-input-character;
5007            redo A;
5008          } elsif ($self->{nc} == 0x0029) { # )
5009            $self->{group_depth}--;
5010            push @{$self->{ct}->{content}}, chr $self->{nc};
5011            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
5012            !!!next-input-character;
5013            redo A;
5014          } elsif ($self->{nc} == 0x003E) { # >
5015            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5016            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5017            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5018            !!!next-input-character;
5019            !!!emit ($self->{ct}); # ELEMENT
5020            redo A;
5021          } elsif ($self->{nc} == -1) {
5022            !!!parse-error (type => 'unclosed md'); ## TODO: type
5023            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5024            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5025            !!!next-input-character;
5026            !!!emit ($self->{ct}); # ELEMENT
5027            redo A;
5028          } else {
5029            $self->{ct}->{content}->[-1] .= chr $self->{nc};
5030            ## Stay in the state.
5031            !!!next-input-character;
5032            redo A;
5033          }
5034        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
5035          if ($is_space->{$self->{nc}}) {
5036            ## Stay in the state.
5037            !!!next-input-character;
5038            redo A;
5039          } elsif ($self->{nc} == 0x007C or # |
5040                   $self->{nc} == 0x002C) { # ,
5041            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
5042            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
5043            !!!next-input-character;
5044            redo A;
5045          } elsif ($self->{nc} == 0x0029) { # )
5046            $self->{group_depth}--;
5047            push @{$self->{ct}->{content}}, chr $self->{nc};
5048            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
5049            !!!next-input-character;
5050            redo A;
5051          } elsif ($self->{nc} == 0x003E) { # >
5052            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5053            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5054            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5055            !!!next-input-character;
5056            !!!emit ($self->{ct}); # ELEMENT
5057            redo A;
5058          } elsif ($self->{nc} == -1) {
5059            !!!parse-error (type => 'unclosed md'); ## TODO: type
5060            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5061            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5062            !!!next-input-character;
5063            !!!emit ($self->{ct}); # ELEMENT
5064            redo A;
5065          } else {
5066            !!!parse-error (type => 'after element name'); ## TODO: type
5067            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5068            $self->{state} = BOGUS_MD_STATE;
5069            !!!next-input-character;
5070            redo A;
5071          }
5072        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
5073          if ($is_space->{$self->{nc}}) {
5074            if ($self->{group_depth}) {
5075              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5076            } else {
5077              $self->{state} = AFTER_MD_DEF_STATE;
5078            }
5079            !!!next-input-character;
5080            redo A;
5081          } elsif ($self->{nc} == 0x002A or # *
5082                   $self->{nc} == 0x002B or # +
5083                   $self->{nc} == 0x003F) { # ?
5084            push @{$self->{ct}->{content}}, chr $self->{nc};
5085            if ($self->{group_depth}) {
5086              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5087            } else {
5088              $self->{state} = AFTER_MD_DEF_STATE;
5089            }
5090            !!!next-input-character;
5091            redo A;
5092          } elsif ($self->{nc} == 0x0029) { # )
5093            if ($self->{group_depth}) {
5094              $self->{group_depth}--;
5095              push @{$self->{ct}->{content}}, chr $self->{nc};
5096              ## Stay in the state.
5097              !!!next-input-character;
5098              redo A;
5099            } else {
5100              !!!parse-error (type => 'string after md def'); ## TODO: type
5101              $self->{state} = BOGUS_MD_STATE;
5102              ## Reconsume.
5103              redo A;
5104            }
5105          } elsif ($self->{nc} == 0x003E) { # >
5106            if ($self->{group_depth}) {
5107              !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5108              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5109            }
5110            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5111            !!!next-input-character;
5112            !!!emit ($self->{ct}); # ELEMENT
5113            redo A;
5114          } elsif ($self->{nc} == -1) {
5115            !!!parse-error (type => 'unclosed md'); ## TODO: type
5116            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5117            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5118            !!!next-input-character;
5119            !!!emit ($self->{ct}); # ELEMENT
5120            redo A;
5121          } else {
5122            if ($self->{group_depth}) {
5123              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5124            } else {
5125              !!!parse-error (type => 'string after md def'); ## TODO: type
5126              $self->{state} = BOGUS_MD_STATE;
5127            }
5128            ## Reconsume.
5129            redo A;
5130          }
5131        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
5132          if ($is_space->{$self->{nc}}) {
5133            ## Stay in the state.
5134            !!!next-input-character;
5135            redo A;
5136          } elsif ($self->{nc} == 0x003E) { # >
5137            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5138            !!!next-input-character;
5139            !!!emit ($self->{ct}); # ENTITY/ELEMENT
5140            redo A;
5141          } elsif ($self->{nc} == -1) {
5142            !!!parse-error (type => 'unclosed md'); ## TODO: type
5143            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5144            !!!next-input-character;
5145            !!!emit ($self->{ct}); # ENTITY/ELEMENT
5146            redo A;
5147          } else {
5148            !!!parse-error (type => 'string after md def'); ## TODO: type
5149            $self->{state} = BOGUS_MD_STATE;
5150            ## Reconsume.
5151            redo A;
5152          }
5153        } elsif ($self->{state} == BOGUS_MD_STATE) {
5154          if ($self->{nc} == 0x003E) { # >
5155            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5156            !!!next-input-character;
5157            !!!emit ($self->{ct}); # ATTLIST/ENTITY/NOTATION
5158            redo A;
5159          } elsif ($self->{nc} == -1) {
5160            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5161            ## Reconsume.
5162            !!!emit ($self->{ct}); # ATTLIST/ENTITY/NOTATION
5163            redo A;
5164          } else {
5165            ## Stay in the state.
5166          !!!next-input-character;          !!!next-input-character;
5167          redo A;          redo A;
5168        }        }
           
5169      } else {      } else {
5170        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
5171      }      }
# Line 3259  sub _get_next_token ($) { Line 5176  sub _get_next_token ($) {
5176    
5177  1;  1;
5178  ## $Date$  ## $Date$
5179                                    

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.31

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24