1---------------------------------------------------------------------------- 2-- 3-- Copyright (C) 2016 The Qt Company Ltd. 4-- Contact: https://www.qt.io/licensing/ 5-- 6-- This file is part of the QtCore module of the Qt Toolkit. 7-- 8-- $QT_BEGIN_LICENSE:LGPL$ 9-- Commercial License Usage 10-- Licensees holding valid commercial Qt licenses may use this file in 11-- accordance with the commercial license agreement provided with the 12-- Software or, alternatively, in accordance with the terms contained in 13-- a written agreement between you and The Qt Company. For licensing terms 14-- and conditions see https://www.qt.io/terms-conditions. For further 15-- information use the contact form at https://www.qt.io/contact-us. 16-- 17-- GNU Lesser General Public License Usage 18-- Alternatively, this file may be used under the terms of the GNU Lesser 19-- General Public License version 3 as published by the Free Software 20-- Foundation and appearing in the file LICENSE.LGPL3 included in the 21-- packaging of this file. Please review the following information to 22-- ensure the GNU Lesser General Public License version 3 requirements 23-- will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24-- 25-- GNU General Public License Usage 26-- Alternatively, this file may be used under the terms of the GNU 27-- General Public License version 2.0 or (at your option) the GNU General 28-- Public license version 3 or any later version approved by the KDE Free 29-- Qt Foundation. The licenses are as published by the Free Software 30-- Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31-- included in the packaging of this file. Please review the following 32-- information to ensure the GNU General Public License requirements will 33-- be met: https://www.gnu.org/licenses/gpl-2.0.html and 34-- https://www.gnu.org/licenses/gpl-3.0.html. 35-- 36-- $QT_END_LICENSE$ 37-- 38---------------------------------------------------------------------------- 39 40%parser QXmlStreamReader_Table 41 42%merged_output qxmlstream_p.h 43 44%expect 4 45 46%token NOTOKEN 47%token SPACE " " 48%token LANGLE "<" 49%token RANGLE ">" 50%token AMPERSAND "&" 51%token HASH "#" 52%token QUOTE "\'" 53%token DBLQUOTE "\"" 54%token LBRACK "[" 55%token RBRACK "]" 56%token LPAREN "(" 57%token RPAREN ")" 58%token PIPE "|" 59%token EQ "=" 60%token PERCENT "%" 61%token SLASH "/" 62%token COLON ":" 63%token SEMICOLON ";" 64%token COMMA "," 65%token DASH "-" 66%token PLUS "+" 67%token STAR "*" 68%token DOT "." 69%token QUESTIONMARK "?" 70%token BANG "!" 71%token LETTER "[a-zA-Z]" 72%token DIGIT "[0-9]" 73 74-- after langle_bang 75%token CDATA_START "[CDATA[" 76%token DOCTYPE "DOCTYPE" 77%token ELEMENT "ELEMENT" 78%token ATTLIST "ATTLIST" 79%token ENTITY "ENTITY" 80%token NOTATION "NOTATION" 81 82-- entity decl 83%token SYSTEM "SYSTEM" 84%token PUBLIC "PUBLIC" 85%token NDATA "NDATA" 86 87-- default decl 88%token REQUIRED "REQUIRED" 89%token IMPLIED "IMPLIED" 90%token FIXED "FIXED" 91 92-- conent spec 93%token EMPTY "EMPTY" 94%token ANY "ANY" 95%token PCDATA "PCDATA" 96 97-- error 98%token ERROR 99 100-- entities 101%token PARSE_ENTITY 102%token ENTITY_DONE 103%token UNRESOLVED_ENTITY 104 105-- att type 106%token CDATA "CDATA" 107%token ID "ID" 108%token IDREF "IDREF" 109%token IDREFS "IDREFS" 110%token ENTITY "ENTITY" 111%token ENTITIES "ENTITIES" 112%token NMTOKEN "NMTOKEN" 113%token NMTOKENS "NMTOKENS" 114 115-- xml declaration 116%token XML "<?xml" 117%token VERSION "version" 118 119%nonassoc SHIFT_THERE 120%nonassoc AMPERSAND 121 BANG 122 COLON 123 COMMA 124 DASH 125 DBLQUOTE 126 DIGIT 127 DOT 128 ENTITY_DONE 129 EQ 130 HASH 131 LBRACK 132 LETTER 133 LPAREN 134 PERCENT 135 PIPE 136 PLUS 137 QUESTIONMARK 138 QUOTE 139 RANGLE 140 RBRACK 141 RPAREN 142 SEMICOLON 143 SLASH 144 SPACE 145 STAR 146 147%start document 148 149 150 151/. 152 153#include <QtCore/private/qglobal_p.h> 154 155template <typename T> class QXmlStreamSimpleStack { 156 T *data; 157 int tos, cap; 158public: 159 inline QXmlStreamSimpleStack():data(0), tos(-1), cap(0){} 160 inline ~QXmlStreamSimpleStack(){ if (data) free(data); } 161 162 inline void reserve(int extraCapacity) { 163 if (tos + extraCapacity + 1 > cap) { 164 cap = qMax(tos + extraCapacity + 1, cap << 1 ); 165 void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T)); 166 data = reinterpret_cast<T *>(ptr); 167 Q_CHECK_PTR(data); 168 } 169 } 170 171 inline T &push() { reserve(1); return data[++tos]; } 172 inline T &rawPush() { return data[++tos]; } 173 inline const T &top() const { return data[tos]; } 174 inline T &top() { return data[tos]; } 175 inline T &pop() { return data[tos--]; } 176 inline T &operator[](int index) { return data[index]; } 177 inline const T &at(int index) const { return data[index]; } 178 inline int size() const { return tos + 1; } 179 inline void resize(int s) { tos = s - 1; } 180 inline bool isEmpty() const { return tos < 0; } 181 inline void clear() { tos = -1; } 182}; 183 184 185class QXmlStream 186{ 187 Q_DECLARE_TR_FUNCTIONS(QXmlStream) 188}; 189 190class QXmlStreamPrivateTagStack { 191public: 192 struct NamespaceDeclaration 193 { 194 QStringRef prefix; 195 QStringRef namespaceUri; 196 }; 197 198 struct Tag 199 { 200 QStringRef name; 201 QStringRef qualifiedName; 202 NamespaceDeclaration namespaceDeclaration; 203 int tagStackStringStorageSize; 204 int namespaceDeclarationsSize; 205 }; 206 207 208 QXmlStreamPrivateTagStack(); 209 QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations; 210 QString tagStackStringStorage; 211 int tagStackStringStorageSize; 212 int initialTagStackStringStorageSize; 213 bool tagsDone; 214 215 inline QStringRef addToStringStorage(const QStringRef &s) { 216 return addToStringStorage(qToStringViewIgnoringNull(s)); 217 } 218 inline QStringRef addToStringStorage(const QString &s) { 219 return addToStringStorage(qToStringViewIgnoringNull(s)); 220 } 221 QStringRef addToStringStorage(QStringView s) 222 { 223 int pos = tagStackStringStorageSize; 224 int sz = s.size(); 225 if (pos != tagStackStringStorage.size()) 226 tagStackStringStorage.resize(pos); 227 tagStackStringStorage.append(s.data(), sz); 228 tagStackStringStorageSize += sz; 229 return QStringRef(&tagStackStringStorage, pos, sz); 230 } 231 232 QXmlStreamSimpleStack<Tag> tagStack; 233 234 235 inline Tag &tagStack_pop() { 236 Tag& tag = tagStack.pop(); 237 tagStackStringStorageSize = tag.tagStackStringStorageSize; 238 namespaceDeclarations.resize(tag.namespaceDeclarationsSize); 239 tagsDone = tagStack.isEmpty(); 240 return tag; 241 } 242 inline Tag &tagStack_push() { 243 Tag &tag = tagStack.push(); 244 tag.tagStackStringStorageSize = tagStackStringStorageSize; 245 tag.namespaceDeclarationsSize = namespaceDeclarations.size(); 246 return tag; 247 } 248}; 249 250 251class QXmlStreamEntityResolver; 252#ifndef QT_NO_XMLSTREAMREADER 253class QXmlStreamReaderPrivate : public QXmlStreamReader_Table, public QXmlStreamPrivateTagStack{ 254 QXmlStreamReader *q_ptr; 255 Q_DECLARE_PUBLIC(QXmlStreamReader) 256public: 257 QXmlStreamReaderPrivate(QXmlStreamReader *q); 258 ~QXmlStreamReaderPrivate(); 259 void init(); 260 261 QByteArray rawReadBuffer; 262 QByteArray dataBuffer; 263 uchar firstByte; 264 qint64 nbytesread; 265 QString readBuffer; 266 int readBufferPos; 267 QXmlStreamSimpleStack<uint> putStack; 268 struct Entity { 269 Entity() = default; 270 Entity(const QString &name, const QString &value) 271 : name(name), value(value), external(false), unparsed(false), literal(false), 272 hasBeenParsed(false), isCurrentlyReferenced(false){} 273 static inline Entity createLiteral(QLatin1String name, QLatin1String value) 274 { Entity result(name, value); result.literal = result.hasBeenParsed = true; return result; } 275 QString name, value; 276 uint external : 1; 277 uint unparsed : 1; 278 uint literal : 1; 279 uint hasBeenParsed : 1; 280 uint isCurrentlyReferenced : 1; 281 }; 282 // these hash tables use a QStringView as a key to avoid creating QStrings 283 // just for lookup. The keys are usually views into Entity::name and thus 284 // are guaranteed to have the same lifetime as the referenced data: 285 QHash<QStringView, Entity> entityHash; 286 QHash<QStringView, Entity> parameterEntityHash; 287 QXmlStreamSimpleStack<Entity *>entityReferenceStack; 288 int entityExpansionLimit = 4096; 289 int entityLength = 0; 290 inline bool referenceEntity(Entity &entity) { 291 if (entity.isCurrentlyReferenced) { 292 raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected.")); 293 return false; 294 } 295 // entityLength represents the amount of additional characters the 296 // entity expands into (can be negative for e.g. &). It's used to 297 // avoid DoS attacks through recursive entity expansions 298 entityLength += entity.value.size() - entity.name.size() - 2; 299 if (entityLength > entityExpansionLimit) { 300 raiseWellFormedError(QXmlStream::tr("Entity expands to more characters than the entity expansion limit.")); 301 return false; 302 } 303 entity.isCurrentlyReferenced = true; 304 entityReferenceStack.push() = &entity; 305 injectToken(ENTITY_DONE); 306 return true; 307 } 308 309 310 QIODevice *device; 311 bool deleteDevice; 312#if QT_CONFIG(textcodec) 313 QTextCodec *codec; 314 QTextDecoder *decoder; 315#endif 316 bool atEnd; 317 318 /*! 319 \sa setType() 320 */ 321 QXmlStreamReader::TokenType type; 322 QXmlStreamReader::Error error; 323 QString errorString; 324 QString unresolvedEntity; 325 326 qint64 lineNumber, lastLineStart, characterOffset; 327 328 329 void write(const QString &); 330 void write(const char *); 331 332 333 QXmlStreamAttributes attributes; 334 QStringRef namespaceForPrefix(const QStringRef &prefix); 335 void resolveTag(); 336 void resolvePublicNamespaces(); 337 void resolveDtd(); 338 uint resolveCharRef(int symbolIndex); 339 bool checkStartDocument(); 340 void startDocument(); 341 void parseError(); 342 void checkPublicLiteral(const QStringRef &publicId); 343 344 bool scanDtd; 345 QStringRef lastAttributeValue; 346 bool lastAttributeIsCData; 347 struct DtdAttribute { 348 QStringRef tagName; 349 QStringRef attributeQualifiedName; 350 QStringRef attributePrefix; 351 QStringRef attributeName; 352 QStringRef defaultValue; 353 bool isCDATA; 354 bool isNamespaceAttribute; 355 }; 356 QXmlStreamSimpleStack<DtdAttribute> dtdAttributes; 357 struct NotationDeclaration { 358 QStringRef name; 359 QStringRef publicId; 360 QStringRef systemId; 361 }; 362 QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations; 363 QXmlStreamNotationDeclarations publicNotationDeclarations; 364 QXmlStreamNamespaceDeclarations publicNamespaceDeclarations; 365 366 struct EntityDeclaration { 367 QStringRef name; 368 QStringRef notationName; 369 QStringRef publicId; 370 QStringRef systemId; 371 QStringRef value; 372 bool parameter; 373 bool external; 374 inline void clear() { 375 name.clear(); 376 notationName.clear(); 377 publicId.clear(); 378 systemId.clear(); 379 value.clear(); 380 parameter = external = false; 381 } 382 }; 383 QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations; 384 QXmlStreamEntityDeclarations publicEntityDeclarations; 385 386 QStringRef text; 387 388 QStringRef prefix, namespaceUri, qualifiedName, name; 389 QStringRef processingInstructionTarget, processingInstructionData; 390 QStringRef dtdName, dtdPublicId, dtdSystemId; 391 QStringRef documentVersion, documentEncoding; 392 uint isEmptyElement : 1; 393 uint isWhitespace : 1; 394 uint isCDATA : 1; 395 uint standalone : 1; 396 uint hasCheckedStartDocument : 1; 397 uint normalizeLiterals : 1; 398 uint hasSeenTag : 1; 399 uint inParseEntity : 1; 400 uint referenceToUnparsedEntityDetected : 1; 401 uint referenceToParameterEntityDetected : 1; 402 uint hasExternalDtdSubset : 1; 403 uint lockEncoding : 1; 404 uint namespaceProcessing : 1; 405 406 int resumeReduction; 407 void resume(int rule); 408 409 inline bool entitiesMustBeDeclared() const { 410 return (!inParseEntity 411 && (standalone 412 || (!referenceToUnparsedEntityDetected 413 && !referenceToParameterEntityDetected // Errata 13 as of 2006-04-25 414 && !hasExternalDtdSubset))); 415 } 416 417 // qlalr parser 418 int tos; 419 int stack_size; 420 struct Value { 421 int pos; 422 int len; 423 int prefix; 424 ushort c; 425 }; 426 427 Value *sym_stack; 428 int *state_stack; 429 inline void reallocateStack(); 430 inline Value &sym(int index) const 431 { return sym_stack[tos + index - 1]; } 432 QString textBuffer; 433 inline void clearTextBuffer() { 434 if (!scanDtd) { 435 textBuffer.resize(0); 436 textBuffer.reserve(256); 437 } 438 } 439 struct Attribute { 440 Value key; 441 Value value; 442 }; 443 QXmlStreamSimpleStack<Attribute> attributeStack; 444 445 inline QStringRef symString(int index) { 446 const Value &symbol = sym(index); 447 return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix); 448 } 449 QStringView symView(int index) const 450 { 451 const Value &symbol = sym(index); 452 return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix); 453 } 454 inline QStringRef symName(int index) { 455 const Value &symbol = sym(index); 456 return QStringRef(&textBuffer, symbol.pos, symbol.len); 457 } 458 inline QStringRef symString(int index, int offset) { 459 const Value &symbol = sym(index); 460 return QStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset); 461 } 462 inline QStringRef symPrefix(int index) { 463 const Value &symbol = sym(index); 464 if (symbol.prefix) 465 return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1); 466 return QStringRef(); 467 } 468 inline QStringRef symString(const Value &symbol) { 469 return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix); 470 } 471 inline QStringRef symName(const Value &symbol) { 472 return QStringRef(&textBuffer, symbol.pos, symbol.len); 473 } 474 inline QStringRef symPrefix(const Value &symbol) { 475 if (symbol.prefix) 476 return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1); 477 return QStringRef(); 478 } 479 480 inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; } 481 482 483 short token; 484 uint token_char; 485 486 uint filterCarriageReturn(); 487 inline uint getChar(); 488 inline uint peekChar(); 489 inline void putChar(uint c) { putStack.push() = c; } 490 inline void putChar(QChar c) { putStack.push() = c.unicode(); } 491 void putString(const QString &s, int from = 0); 492 void putStringLiteral(const QString &s); 493 void putReplacement(const QString &s); 494 void putReplacementInAttributeValue(const QString &s); 495 uint getChar_helper(); 496 497 bool scanUntil(const char *str, short tokenToInject = -1); 498 bool scanString(const char *str, short tokenToInject, bool requireSpace = true); 499 inline void injectToken(ushort tokenToInject) { 500 putChar(int(tokenToInject) << 16); 501 } 502 503 QString resolveUndeclaredEntity(const QString &name); 504 void parseEntity(const QString &value); 505 QXmlStreamReaderPrivate *entityParser; 506 507 bool scanAfterLangleBang(); 508 bool scanPublicOrSystem(); 509 bool scanNData(); 510 bool scanAfterDefaultDecl(); 511 bool scanAttType(); 512 513 514 // scan optimization functions. Not strictly necessary but LALR is 515 // not very well suited for scanning fast 516 int fastScanLiteralContent(); 517 int fastScanSpace(); 518 int fastScanContentCharList(); 519 int fastScanName(int *prefix = nullptr); 520 inline int fastScanNMTOKEN(); 521 522 523 bool parse(); 524 inline void consumeRule(int); 525 526 void raiseError(QXmlStreamReader::Error error, const QString& message = QString()); 527 void raiseWellFormedError(const QString &message); 528 529 QXmlStreamEntityResolver *entityResolver; 530 531private: 532 /*! \internal 533 Never assign to variable type directly. Instead use this function. 534 535 This prevents errors from being ignored. 536 */ 537 inline void setType(const QXmlStreamReader::TokenType t) 538 { 539 if(type != QXmlStreamReader::Invalid) 540 type = t; 541 } 542}; 543 544bool QXmlStreamReaderPrivate::parse() 545{ 546 // cleanup currently reported token 547 548 switch (type) { 549 case QXmlStreamReader::StartElement: 550 name.clear(); 551 prefix.clear(); 552 qualifiedName.clear(); 553 namespaceUri.clear(); 554 publicNamespaceDeclarations.clear(); 555 attributes.clear(); 556 if (isEmptyElement) { 557 setType(QXmlStreamReader::EndElement); 558 Tag &tag = tagStack_pop(); 559 namespaceUri = tag.namespaceDeclaration.namespaceUri; 560 name = tag.name; 561 qualifiedName = tag.qualifiedName; 562 isEmptyElement = false; 563 return true; 564 } 565 clearTextBuffer(); 566 break; 567 case QXmlStreamReader::EndElement: 568 name.clear(); 569 prefix.clear(); 570 qualifiedName.clear(); 571 namespaceUri.clear(); 572 clearTextBuffer(); 573 break; 574 case QXmlStreamReader::DTD: 575 publicNotationDeclarations.clear(); 576 publicEntityDeclarations.clear(); 577 dtdName.clear(); 578 dtdPublicId.clear(); 579 dtdSystemId.clear(); 580 Q_FALLTHROUGH(); 581 case QXmlStreamReader::Comment: 582 case QXmlStreamReader::Characters: 583 isCDATA = false; 584 isWhitespace = true; 585 text.clear(); 586 clearTextBuffer(); 587 break; 588 case QXmlStreamReader::EntityReference: 589 text.clear(); 590 name.clear(); 591 clearTextBuffer(); 592 break; 593 case QXmlStreamReader::ProcessingInstruction: 594 processingInstructionTarget.clear(); 595 processingInstructionData.clear(); 596 clearTextBuffer(); 597 break; 598 case QXmlStreamReader::NoToken: 599 case QXmlStreamReader::Invalid: 600 break; 601 case QXmlStreamReader::StartDocument: 602 lockEncoding = true; 603 documentVersion.clear(); 604 documentEncoding.clear(); 605#if QT_CONFIG(textcodec) 606 if (decoder && decoder->hasFailure()) { 607 raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content.")); 608 readBuffer.clear(); 609 return false; 610 } 611#endif 612 Q_FALLTHROUGH(); 613 default: 614 clearTextBuffer(); 615 ; 616 } 617 618 setType(QXmlStreamReader::NoToken); 619 620 621 // the main parse loop 622 int act, r; 623 624 if (resumeReduction) { 625 act = state_stack[tos-1]; 626 r = resumeReduction; 627 resumeReduction = 0; 628 goto ResumeReduction; 629 } 630 631 act = state_stack[tos]; 632 633 forever { 634 if (token == -1 && - TERMINAL_COUNT != action_index[act]) { 635 uint cu = getChar(); 636 token = NOTOKEN; 637 token_char = cu == ~0U ? cu : ushort(cu); 638 if ((cu != ~0U) && (cu & 0xff0000)) { 639 token = cu >> 16; 640 } else switch (token_char) { 641 case 0xfffe: 642 case 0xffff: 643 token = ERROR; 644 break; 645 case '\r': 646 token = SPACE; 647 if (cu == '\r') { 648 if ((token_char = filterCarriageReturn())) { 649 ++lineNumber; 650 lastLineStart = characterOffset + readBufferPos; 651 break; 652 } 653 } else { 654 break; 655 } 656 Q_FALLTHROUGH(); 657 case ~0U: { 658 token = EOF_SYMBOL; 659 if (!tagsDone && !inParseEntity) { 660 int a = t_action(act, token); 661 if (a < 0) { 662 raiseError(QXmlStreamReader::PrematureEndOfDocumentError); 663 return false; 664 } 665 } 666 667 } break; 668 case '\n': 669 ++lineNumber; 670 lastLineStart = characterOffset + readBufferPos; 671 Q_FALLTHROUGH(); 672 case ' ': 673 case '\t': 674 token = SPACE; 675 break; 676 case '&': 677 token = AMPERSAND; 678 break; 679 case '#': 680 token = HASH; 681 break; 682 case '\'': 683 token = QUOTE; 684 break; 685 case '\"': 686 token = DBLQUOTE; 687 break; 688 case '<': 689 token = LANGLE; 690 break; 691 case '>': 692 token = RANGLE; 693 break; 694 case '[': 695 token = LBRACK; 696 break; 697 case ']': 698 token = RBRACK; 699 break; 700 case '(': 701 token = LPAREN; 702 break; 703 case ')': 704 token = RPAREN; 705 break; 706 case '|': 707 token = PIPE; 708 break; 709 case '=': 710 token = EQ; 711 break; 712 case '%': 713 token = PERCENT; 714 break; 715 case '/': 716 token = SLASH; 717 break; 718 case ':': 719 token = COLON; 720 break; 721 case ';': 722 token = SEMICOLON; 723 break; 724 case ',': 725 token = COMMA; 726 break; 727 case '-': 728 token = DASH; 729 break; 730 case '+': 731 token = PLUS; 732 break; 733 case '*': 734 token = STAR; 735 break; 736 case '.': 737 token = DOT; 738 break; 739 case '?': 740 token = QUESTIONMARK; 741 break; 742 case '!': 743 token = BANG; 744 break; 745 case '0': 746 case '1': 747 case '2': 748 case '3': 749 case '4': 750 case '5': 751 case '6': 752 case '7': 753 case '8': 754 case '9': 755 token = DIGIT; 756 break; 757 default: 758 if (cu < 0x20) 759 token = NOTOKEN; 760 else 761 token = LETTER; 762 break; 763 } 764 } 765 766 act = t_action (act, token); 767 if (act == ACCEPT_STATE) { 768 // reset the parser in case someone resumes (process instructions can follow a valid document) 769 tos = 0; 770 state_stack[tos++] = 0; 771 state_stack[tos] = 0; 772 return true; 773 } else if (act > 0) { 774 if (++tos >= stack_size-1) 775 reallocateStack(); 776 777 Value &val = sym_stack[tos]; 778 val.c = token_char; 779 val.pos = textBuffer.size(); 780 val.prefix = 0; 781 val.len = 1; 782 if (token_char) 783 textBuffer += QChar(token_char); 784 785 state_stack[tos] = act; 786 token = -1; 787 788 789 } else if (act < 0) { 790 r = - act - 1; 791 792#if defined (QLALR_DEBUG) 793 int ridx = rule_index[r]; 794 printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]); 795 ++ridx; 796 for (int i = ridx; i < ridx + rhs[r]; ++i) { 797 int symbol = rule_info[i]; 798 if (const char *name = spell[symbol]) 799 printf (" %s", name); 800 else 801 printf (" #%d", symbol); 802 } 803 printf ("\n"); 804#endif 805 806 tos -= rhs[r]; 807 act = state_stack[tos++]; 808 ResumeReduction: 809 switch (r) { 810./ 811 812document ::= PARSE_ENTITY content; 813/. 814 case $rule_number: 815 setType(QXmlStreamReader::EndDocument); 816 break; 817./ 818 819document ::= prolog; 820/. 821 case $rule_number: 822 if (type != QXmlStreamReader::Invalid) { 823 if (hasSeenTag || inParseEntity) { 824 setType(QXmlStreamReader::EndDocument); 825 } else { 826 raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected.")); 827 // reset the parser 828 tos = 0; 829 state_stack[tos++] = 0; 830 state_stack[tos] = 0; 831 return false; 832 } 833 } 834 break; 835./ 836 837 838prolog ::= prolog stag content etag; 839prolog ::= prolog empty_element_tag; 840prolog ::= prolog comment; 841prolog ::= prolog xml_decl; 842prolog ::= prolog processing_instruction; 843prolog ::= prolog doctype_decl; 844prolog ::= prolog SPACE; 845prolog ::=; 846 847entity_done ::= ENTITY_DONE; 848/. 849 case $rule_number: 850 entityReferenceStack.pop()->isCurrentlyReferenced = false; 851 if (entityReferenceStack.isEmpty()) 852 entityLength = 0; 853 clearSym(); 854 break; 855./ 856 857 858xml_decl_start ::= XML; 859/. 860 case $rule_number: 861 if (!scanString(spell[VERSION], VERSION, false) && atEnd) { 862 resume($rule_number); 863 return false; 864 } 865 break; 866./ 867 868xml_decl ::= xml_decl_start VERSION space_opt EQ space_opt literal attribute_list_opt QUESTIONMARK RANGLE; 869/. 870 case $rule_number: 871 setType(QXmlStreamReader::StartDocument); 872 documentVersion = symString(6); 873 startDocument(); 874 break; 875./ 876 877external_id ::= SYSTEM literal; 878/. 879 case $rule_number: 880 hasExternalDtdSubset = true; 881 dtdSystemId = symString(2); 882 break; 883./ 884external_id ::= PUBLIC public_literal space literal; 885/. 886 case $rule_number: 887 checkPublicLiteral(symString(2)); 888 dtdPublicId = symString(2); 889 dtdSystemId = symString(4); 890 hasExternalDtdSubset = true; 891 break; 892./ 893external_id ::=; 894 895doctype_decl_start ::= langle_bang DOCTYPE qname space; 896/. 897 case $rule_number: 898 if (!scanPublicOrSystem() && atEnd) { 899 resume($rule_number); 900 return false; 901 } 902 dtdName = symString(3); 903 break; 904./ 905 906doctype_decl ::= langle_bang DOCTYPE qname RANGLE; 907/. 908 case $rule_number:./ 909doctype_decl ::= langle_bang DOCTYPE qname markup space_opt RANGLE; 910/. 911 case $rule_number: 912 dtdName = symString(3); 913 Q_FALLTHROUGH(); 914./ 915doctype_decl ::= doctype_decl_start external_id space_opt markup space_opt RANGLE; 916/. 917 case $rule_number:./ 918doctype_decl ::= doctype_decl_start external_id space_opt RANGLE; 919/. 920 case $rule_number: 921 setType(QXmlStreamReader::DTD); 922 text = &textBuffer; 923 break; 924./ 925 926markup_start ::= LBRACK; 927/. 928 case $rule_number: 929 scanDtd = true; 930 break; 931./ 932 933markup ::= markup_start markup_list RBRACK; 934/. 935 case $rule_number: 936 scanDtd = false; 937 break; 938./ 939 940 941markup_list ::= markup_decl | space | pereference; 942markup_list ::= markup_list markup_decl | markup_list space | markup_list pereference; 943markup_list ::=; 944 945markup_decl ::= element_decl | attlist_decl | entity_decl | entity_done | notation_decl | processing_instruction | comment; 946 947 948element_decl_start ::= langle_bang ELEMENT qname space; 949/. 950 case $rule_number: 951 if (!scanString(spell[EMPTY], EMPTY, false) 952 && !scanString(spell[ANY], ANY, false) 953 && atEnd) { 954 resume($rule_number); 955 return false; 956 } 957 break; 958./ 959 960element_decl ::= element_decl_start content_spec space_opt RANGLE; 961 962 963content_spec ::= EMPTY | ANY | mixed | children; 964 965pcdata_start ::= HASH; 966/. 967 case $rule_number: 968 if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) { 969 resume($rule_number); 970 return false; 971 } 972 break; 973./ 974 975pcdata ::= pcdata_start PCDATA; 976 977questionmark_or_star_or_plus_opt ::= QUESTIONMARK | STAR | PLUS; 978questionmark_or_star_or_plus_opt ::=; 979 980cp ::= qname questionmark_or_star_or_plus_opt | choice_or_seq questionmark_or_star_or_plus_opt; 981 982cp_pipe_or_comma_list ::= cp space_opt; 983cp_pipe_or_comma_list ::= cp space_opt PIPE space_opt cp_pipe_list space_opt; 984cp_pipe_or_comma_list ::= cp space_opt COMMA space_opt cp_comma_list space_opt; 985cp_pipe_list ::= cp | cp_pipe_list space_opt PIPE space_opt cp; 986cp_comma_list ::= cp | cp_comma_list space_opt COMMA space_opt cp; 987 988 989name_pipe_list ::= PIPE space_opt qname; 990name_pipe_list ::= name_pipe_list space_opt PIPE space_opt qname; 991 992star_opt ::= | STAR; 993 994mixed ::= LPAREN space_opt pcdata space_opt RPAREN star_opt; 995mixed ::= LPAREN space_opt pcdata space_opt name_pipe_list space_opt RPAREN STAR; 996 997choice_or_seq ::= LPAREN space_opt cp_pipe_or_comma_list RPAREN; 998 999children ::= choice_or_seq questionmark_or_star_or_plus_opt; 1000 1001 1002nmtoken_pipe_list ::= nmtoken; 1003nmtoken_pipe_list ::= nmtoken_pipe_list space_opt PIPE space_opt nmtoken; 1004 1005 1006att_type ::= CDATA; 1007/. 1008 case $rule_number: { 1009 lastAttributeIsCData = true; 1010 } break; 1011./ 1012att_type ::= ID | IDREF | IDREFS | ENTITY | ENTITIES | NMTOKEN | NMTOKENS; 1013att_type ::= LPAREN space_opt nmtoken_pipe_list space_opt RPAREN space; 1014att_type ::= NOTATION LPAREN space_opt nmtoken_pipe_list space_opt RPAREN space; 1015 1016 1017default_declhash ::= HASH; 1018/. 1019 case $rule_number: 1020 if (!scanAfterDefaultDecl() && atEnd) { 1021 resume($rule_number); 1022 return false; 1023 } 1024 break; 1025./ 1026 1027default_decl ::= default_declhash REQUIRED; 1028default_decl ::= default_declhash IMPLIED; 1029default_decl ::= attribute_value; 1030default_decl ::= default_declhash FIXED space attribute_value; 1031attdef_start ::= space qname space; 1032/. 1033 case $rule_number: 1034 sym(1) = sym(2); 1035 lastAttributeValue.clear(); 1036 lastAttributeIsCData = false; 1037 if (!scanAttType() && atEnd) { 1038 resume($rule_number); 1039 return false; 1040 } 1041 break; 1042./ 1043 1044attdef ::= attdef_start att_type default_decl; 1045/. 1046 case $rule_number: { 1047 DtdAttribute &dtdAttribute = dtdAttributes.push(); 1048 dtdAttribute.tagName.clear(); 1049 dtdAttribute.isCDATA = lastAttributeIsCData; 1050 dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1)); 1051 dtdAttribute.attributeName = addToStringStorage(symString(1)); 1052 dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1)); 1053 dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns") 1054 || (dtdAttribute.attributePrefix.isEmpty() 1055 && dtdAttribute.attributeName == QLatin1String("xmlns"))); 1056 if (lastAttributeValue.isNull()) { 1057 dtdAttribute.defaultValue.clear(); 1058 } else { 1059 if (dtdAttribute.isCDATA) 1060 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue); 1061 else 1062 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified()); 1063 1064 } 1065 } break; 1066./ 1067 1068attdef_list ::= attdef; 1069attdef_list ::= attdef_list attdef; 1070 1071attlist_decl ::= langle_bang ATTLIST qname space_opt RANGLE; 1072attlist_decl ::= langle_bang ATTLIST qname attdef_list space_opt RANGLE; 1073/. 1074 case $rule_number: { 1075 if (referenceToUnparsedEntityDetected && !standalone) 1076 break; 1077 int n = dtdAttributes.size(); 1078 QStringRef tagName = addToStringStorage(symName(3)); 1079 while (n--) { 1080 DtdAttribute &dtdAttribute = dtdAttributes[n]; 1081 if (!dtdAttribute.tagName.isNull()) 1082 break; 1083 dtdAttribute.tagName = tagName; 1084 for (int i = 0; i < n; ++i) { 1085 if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName) 1086 && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) { 1087 dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it 1088 break; 1089 } 1090 } 1091 } 1092 } break; 1093./ 1094 1095entity_decl_start ::= langle_bang ENTITY name space; 1096/. 1097 case $rule_number: { 1098 if (!scanPublicOrSystem() && atEnd) { 1099 resume($rule_number); 1100 return false; 1101 } 1102 EntityDeclaration &entityDeclaration = entityDeclarations.push(); 1103 entityDeclaration.clear(); 1104 entityDeclaration.name = symString(3); 1105 } break; 1106./ 1107 1108entity_decl_start ::= langle_bang ENTITY PERCENT space name space; 1109/. 1110 case $rule_number: { 1111 if (!scanPublicOrSystem() && atEnd) { 1112 resume($rule_number); 1113 return false; 1114 } 1115 EntityDeclaration &entityDeclaration = entityDeclarations.push(); 1116 entityDeclaration.clear(); 1117 entityDeclaration.name = symString(5); 1118 entityDeclaration.parameter = true; 1119 } break; 1120./ 1121 1122entity_decl_external ::= entity_decl_start SYSTEM literal; 1123/. 1124 case $rule_number: { 1125 if (!scanNData() && atEnd) { 1126 resume($rule_number); 1127 return false; 1128 } 1129 EntityDeclaration &entityDeclaration = entityDeclarations.top(); 1130 entityDeclaration.systemId = symString(3); 1131 entityDeclaration.external = true; 1132 } break; 1133./ 1134 1135entity_decl_external ::= entity_decl_start PUBLIC public_literal space literal; 1136/. 1137 case $rule_number: { 1138 if (!scanNData() && atEnd) { 1139 resume($rule_number); 1140 return false; 1141 } 1142 EntityDeclaration &entityDeclaration = entityDeclarations.top(); 1143 checkPublicLiteral((entityDeclaration.publicId = symString(3))); 1144 entityDeclaration.systemId = symString(5); 1145 entityDeclaration.external = true; 1146 } break; 1147./ 1148 1149entity_decl ::= entity_decl_external NDATA name space_opt RANGLE; 1150/. 1151 case $rule_number: { 1152 EntityDeclaration &entityDeclaration = entityDeclarations.top(); 1153 entityDeclaration.notationName = symString(3); 1154 if (entityDeclaration.parameter) 1155 raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration.")); 1156 } 1157 Q_FALLTHROUGH(); 1158./ 1159 1160entity_decl ::= entity_decl_external space_opt RANGLE; 1161/. 1162 case $rule_number:./ 1163 1164entity_decl ::= entity_decl_start entity_value space_opt RANGLE; 1165/. 1166 case $rule_number: { 1167 if (referenceToUnparsedEntityDetected && !standalone) { 1168 entityDeclarations.pop(); 1169 break; 1170 } 1171 EntityDeclaration &entityDeclaration = entityDeclarations.top(); 1172 if (!entityDeclaration.external) 1173 entityDeclaration.value = symString(2); 1174 auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash; 1175 if (!hash.contains(qToStringViewIgnoringNull(entityDeclaration.name))) { 1176 Entity entity(entityDeclaration.name.toString(), 1177 entityDeclaration.value.toString()); 1178 entity.unparsed = (!entityDeclaration.notationName.isNull()); 1179 entity.external = entityDeclaration.external; 1180 hash.insert(qToStringViewIgnoringNull(entity.name), entity); 1181 } 1182 } break; 1183./ 1184 1185 1186processing_instruction ::= LANGLE QUESTIONMARK name space; 1187/. 1188 case $rule_number: { 1189 setType(QXmlStreamReader::ProcessingInstruction); 1190 int pos = sym(4).pos + sym(4).len; 1191 processingInstructionTarget = symString(3); 1192 if (scanUntil("?>")) { 1193 processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2); 1194 if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) { 1195 raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document.")); 1196 } 1197 else if (!QXmlUtils::isNCName(processingInstructionTarget)) 1198 raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.") 1199 .arg(processingInstructionTarget)); 1200 } else if (type != QXmlStreamReader::Invalid){ 1201 resume($rule_number); 1202 return false; 1203 } 1204 } break; 1205./ 1206 1207processing_instruction ::= LANGLE QUESTIONMARK name QUESTIONMARK RANGLE; 1208/. 1209 case $rule_number: 1210 setType(QXmlStreamReader::ProcessingInstruction); 1211 processingInstructionTarget = symString(3); 1212 if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) 1213 raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name.")); 1214 break; 1215./ 1216 1217 1218langle_bang ::= LANGLE BANG; 1219/. 1220 case $rule_number: 1221 if (!scanAfterLangleBang() && atEnd) { 1222 resume($rule_number); 1223 return false; 1224 } 1225 break; 1226./ 1227 1228comment_start ::= langle_bang DASH DASH; 1229/. 1230 case $rule_number: 1231 if (!scanUntil("--")) { 1232 resume($rule_number); 1233 return false; 1234 } 1235 break; 1236./ 1237 1238comment ::= comment_start RANGLE; 1239/. 1240 case $rule_number: { 1241 setType(QXmlStreamReader::Comment); 1242 int pos = sym(1).pos + 4; 1243 text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3); 1244 } break; 1245./ 1246 1247 1248cdata ::= langle_bang CDATA_START; 1249/. 1250 case $rule_number: { 1251 setType(QXmlStreamReader::Characters); 1252 isCDATA = true; 1253 isWhitespace = false; 1254 int pos = sym(2).pos; 1255 if (scanUntil("]]>", -1)) { 1256 text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3); 1257 } else { 1258 resume($rule_number); 1259 return false; 1260 } 1261 } break; 1262./ 1263 1264notation_decl_start ::= langle_bang NOTATION name space; 1265/. 1266 case $rule_number: { 1267 if (!scanPublicOrSystem() && atEnd) { 1268 resume($rule_number); 1269 return false; 1270 } 1271 NotationDeclaration ¬ationDeclaration = notationDeclarations.push(); 1272 notationDeclaration.name = symString(3); 1273 } break; 1274./ 1275 1276notation_decl ::= notation_decl_start SYSTEM literal space_opt RANGLE; 1277/. 1278 case $rule_number: { 1279 NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); 1280 notationDeclaration.systemId = symString(3); 1281 notationDeclaration.publicId.clear(); 1282 } break; 1283./ 1284 1285notation_decl ::= notation_decl_start PUBLIC public_literal space_opt RANGLE; 1286/. 1287 case $rule_number: { 1288 NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); 1289 notationDeclaration.systemId.clear(); 1290 checkPublicLiteral((notationDeclaration.publicId = symString(3))); 1291 } break; 1292./ 1293 1294notation_decl ::= notation_decl_start PUBLIC public_literal space literal space_opt RANGLE; 1295/. 1296 case $rule_number: { 1297 NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); 1298 checkPublicLiteral((notationDeclaration.publicId = symString(3))); 1299 notationDeclaration.systemId = symString(5); 1300 } break; 1301./ 1302 1303 1304 1305content_char ::= RANGLE | HASH | LBRACK | RBRACK | LPAREN | RPAREN | PIPE | EQ | PERCENT | SLASH | COLON | SEMICOLON | COMMA | DASH | PLUS | STAR | DOT | QUESTIONMARK | BANG | QUOTE | DBLQUOTE | LETTER | DIGIT; 1306 1307scan_content_char ::= content_char; 1308/. 1309 case $rule_number: 1310 isWhitespace = false; 1311 Q_FALLTHROUGH(); 1312./ 1313 1314scan_content_char ::= SPACE; 1315/. 1316 case $rule_number: 1317 sym(1).len += fastScanContentCharList(); 1318 if (atEnd && !inParseEntity) { 1319 resume($rule_number); 1320 return false; 1321 } 1322 break; 1323./ 1324 1325content_char_list ::= content_char_list char_ref; 1326content_char_list ::= content_char_list entity_ref; 1327content_char_list ::= content_char_list entity_done; 1328content_char_list ::= content_char_list scan_content_char; 1329content_char_list ::= char_ref; 1330content_char_list ::= entity_ref; 1331content_char_list ::= entity_done; 1332content_char_list ::= scan_content_char; 1333 1334 1335character_content ::= content_char_list %prec SHIFT_THERE; 1336/. 1337 case $rule_number: 1338 if (!textBuffer.isEmpty()) { 1339 setType(QXmlStreamReader::Characters); 1340 text = &textBuffer; 1341 } 1342 break; 1343./ 1344 1345literal ::= QUOTE QUOTE; 1346/. 1347 case $rule_number:./ 1348literal ::= DBLQUOTE DBLQUOTE; 1349/. 1350 case $rule_number: 1351 clearSym(); 1352 break; 1353./ 1354literal ::= QUOTE literal_content_with_dblquote QUOTE; 1355/. 1356 case $rule_number:./ 1357literal ::= DBLQUOTE literal_content_with_quote DBLQUOTE; 1358/. 1359 case $rule_number: 1360 sym(1) = sym(2); 1361 break; 1362./ 1363 1364literal_content_with_dblquote ::= literal_content_with_dblquote literal_content; 1365/. 1366 case $rule_number:./ 1367literal_content_with_quote ::= literal_content_with_quote literal_content; 1368/. 1369 case $rule_number:./ 1370literal_content_with_dblquote ::= literal_content_with_dblquote DBLQUOTE; 1371/. 1372 case $rule_number:./ 1373literal_content_with_quote ::= literal_content_with_quote QUOTE; 1374/. 1375 case $rule_number: 1376 sym(1).len += sym(2).len; 1377 break; 1378./ 1379literal_content_with_dblquote ::= literal_content; 1380literal_content_with_quote ::= literal_content; 1381literal_content_with_dblquote ::= DBLQUOTE; 1382literal_content_with_quote ::= QUOTE; 1383 1384literal_content_start ::= LETTER | DIGIT | RANGLE | HASH | LBRACK | RBRACK | LPAREN | RPAREN | PIPE | EQ | PERCENT | SLASH | COLON | SEMICOLON | COMMA | DASH | PLUS | STAR | DOT | QUESTIONMARK | BANG; 1385 1386literal_content_start ::= SPACE; 1387/. 1388 case $rule_number: 1389 if (normalizeLiterals) 1390 textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' '); 1391 break; 1392./ 1393 1394literal_content ::= literal_content_start; 1395/. 1396 case $rule_number: 1397 sym(1).len += fastScanLiteralContent(); 1398 if (atEnd) { 1399 resume($rule_number); 1400 return false; 1401 } 1402 break; 1403./ 1404 1405 1406public_literal ::= literal; 1407/. 1408 case $rule_number: { 1409 if (!QXmlUtils::isPublicID(symString(1))) { 1410 raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1))); 1411 resume($rule_number); 1412 return false; 1413 } 1414 } break; 1415./ 1416 1417entity_value ::= QUOTE QUOTE; 1418/. 1419 case $rule_number:./ 1420entity_value ::= DBLQUOTE DBLQUOTE; 1421/. 1422 case $rule_number: 1423 clearSym(); 1424 break; 1425./ 1426 1427entity_value ::= QUOTE entity_value_content_with_dblquote QUOTE; 1428/. 1429 case $rule_number:./ 1430entity_value ::= DBLQUOTE entity_value_content_with_quote DBLQUOTE; 1431/. 1432 case $rule_number: 1433 sym(1) = sym(2); 1434 break; 1435./ 1436 1437entity_value_content_with_dblquote ::= entity_value_content_with_dblquote entity_value_content; 1438/. 1439 case $rule_number:./ 1440entity_value_content_with_quote ::= entity_value_content_with_quote entity_value_content; 1441/. 1442 case $rule_number:./ 1443entity_value_content_with_dblquote ::= entity_value_content_with_dblquote DBLQUOTE; 1444/. 1445 case $rule_number:./ 1446entity_value_content_with_quote ::= entity_value_content_with_quote QUOTE; 1447/. 1448 case $rule_number: 1449 sym(1).len += sym(2).len; 1450 break; 1451./ 1452entity_value_content_with_dblquote ::= entity_value_content; 1453entity_value_content_with_quote ::= entity_value_content; 1454entity_value_content_with_dblquote ::= DBLQUOTE; 1455entity_value_content_with_quote ::= QUOTE; 1456 1457entity_value_content ::= LETTER | DIGIT | LANGLE | RANGLE | HASH | LBRACK | RBRACK | LPAREN | RPAREN | PIPE | EQ | SLASH | COLON | SEMICOLON | COMMA | SPACE | DASH | PLUS | STAR | DOT | QUESTIONMARK | BANG; 1458entity_value_content ::= char_ref | entity_ref_in_entity_value | entity_done; 1459 1460 1461attribute_value ::= QUOTE QUOTE; 1462/. 1463 case $rule_number:./ 1464attribute_value ::= DBLQUOTE DBLQUOTE; 1465/. 1466 case $rule_number: 1467 clearSym(); 1468 break; 1469./ 1470attribute_value ::= QUOTE attribute_value_content_with_dblquote QUOTE; 1471/. 1472 case $rule_number:./ 1473attribute_value ::= DBLQUOTE attribute_value_content_with_quote DBLQUOTE; 1474/. 1475 case $rule_number: 1476 sym(1) = sym(2); 1477 lastAttributeValue = symString(1); 1478 break; 1479./ 1480 1481attribute_value_content_with_dblquote ::= attribute_value_content_with_dblquote attribute_value_content; 1482/. 1483 case $rule_number:./ 1484attribute_value_content_with_quote ::= attribute_value_content_with_quote attribute_value_content; 1485/. 1486 case $rule_number:./ 1487attribute_value_content_with_dblquote ::= attribute_value_content_with_dblquote DBLQUOTE; 1488/. 1489 case $rule_number:./ 1490attribute_value_content_with_quote ::= attribute_value_content_with_quote QUOTE; 1491/. 1492 case $rule_number: 1493 sym(1).len += sym(2).len; 1494 break; 1495./ 1496attribute_value_content_with_dblquote ::= attribute_value_content | DBLQUOTE; 1497attribute_value_content_with_quote ::= attribute_value_content | QUOTE; 1498 1499attribute_value_content ::= literal_content | char_ref | entity_ref_in_attribute_value | entity_done; 1500 1501attribute ::= qname space_opt EQ space_opt attribute_value; 1502/. 1503 case $rule_number: { 1504 QStringRef prefix = symPrefix(1); 1505 if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) { 1506 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); 1507 namespaceDeclaration.prefix.clear(); 1508 1509 const QStringRef ns(symString(5)); 1510 if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") || 1511 ns == QLatin1String("http://www.w3.org/XML/1998/namespace")) 1512 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration.")); 1513 else 1514 namespaceDeclaration.namespaceUri = addToStringStorage(ns); 1515 } else { 1516 Attribute &attribute = attributeStack.push(); 1517 attribute.key = sym(1); 1518 attribute.value = sym(5); 1519 1520 QStringRef attributeQualifiedName = symName(1); 1521 bool normalize = false; 1522 for (int a = 0; a < dtdAttributes.size(); ++a) { 1523 DtdAttribute &dtdAttribute = dtdAttributes[a]; 1524 if (!dtdAttribute.isCDATA 1525 && dtdAttribute.tagName == qualifiedName 1526 && dtdAttribute.attributeQualifiedName == attributeQualifiedName 1527 ) { 1528 normalize = true; 1529 break; 1530 } 1531 } 1532 if (normalize) { 1533 // normalize attribute value (simplify and trim) 1534 int pos = textBuffer.size(); 1535 int n = 0; 1536 bool wasSpace = true; 1537 for (int i = 0; i < attribute.value.len; ++i) { 1538 QChar c = textBuffer.at(attribute.value.pos + i); 1539 if (c.unicode() == ' ') { 1540 if (wasSpace) 1541 continue; 1542 wasSpace = true; 1543 } else { 1544 wasSpace = false; 1545 } 1546 textBuffer += textBuffer.at(attribute.value.pos + i); 1547 ++n; 1548 } 1549 if (wasSpace) 1550 while (n && textBuffer.at(pos + n - 1).unicode() == ' ') 1551 --n; 1552 attribute.value.pos = pos; 1553 attribute.value.len = n; 1554 } 1555 if (prefix == QLatin1String("xmlns") && namespaceProcessing) { 1556 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); 1557 QStringRef namespacePrefix = symString(attribute.key); 1558 QStringRef namespaceUri = symString(attribute.value); 1559 attributeStack.pop(); 1560 if (((namespacePrefix == QLatin1String("xml")) 1561 ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))) 1562 || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/") 1563 || namespaceUri.isEmpty() 1564 || namespacePrefix == QLatin1String("xmlns")) 1565 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration.")); 1566 1567 namespaceDeclaration.prefix = addToStringStorage(namespacePrefix); 1568 namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri); 1569 } 1570 } 1571 } break; 1572./ 1573 1574 1575 1576attribute_list_opt ::= | space | space attribute_list space_opt; 1577attribute_list ::= attribute | attribute_list space attribute; 1578 1579stag_start ::= LANGLE qname; 1580/. 1581 case $rule_number: { 1582 normalizeLiterals = true; 1583 Tag &tag = tagStack_push(); 1584 prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2)); 1585 name = tag.name = addToStringStorage(symString(2)); 1586 qualifiedName = tag.qualifiedName = addToStringStorage(symName(2)); 1587 if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name)) 1588 raiseWellFormedError(QXmlStream::tr("Invalid XML name.")); 1589 } break; 1590./ 1591 1592 1593empty_element_tag ::= stag_start attribute_list_opt SLASH RANGLE; 1594/. 1595 case $rule_number: 1596 isEmptyElement = true; 1597 Q_FALLTHROUGH(); 1598./ 1599 1600 1601stag ::= stag_start attribute_list_opt RANGLE; 1602/. 1603 case $rule_number: 1604 setType(QXmlStreamReader::StartElement); 1605 resolveTag(); 1606 if (tagStack.size() == 1 && hasSeenTag && !inParseEntity) 1607 raiseWellFormedError(QXmlStream::tr("Extra content at end of document.")); 1608 hasSeenTag = true; 1609 break; 1610./ 1611 1612 1613etag ::= LANGLE SLASH qname space_opt RANGLE; 1614/. 1615 case $rule_number: { 1616 setType(QXmlStreamReader::EndElement); 1617 Tag &tag = tagStack_pop(); 1618 1619 namespaceUri = tag.namespaceDeclaration.namespaceUri; 1620 name = tag.name; 1621 qualifiedName = tag.qualifiedName; 1622 if (qualifiedName != symName(3)) 1623 raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch.")); 1624 } break; 1625./ 1626 1627 1628unresolved_entity ::= UNRESOLVED_ENTITY; 1629/. 1630 case $rule_number: 1631 if (entitiesMustBeDeclared()) { 1632 raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity)); 1633 break; 1634 } 1635 setType(QXmlStreamReader::EntityReference); 1636 name = &unresolvedEntity; 1637 break; 1638./ 1639 1640entity_ref ::= AMPERSAND name SEMICOLON; 1641/. 1642 case $rule_number: { 1643 sym(1).len += sym(2).len + 1; 1644 QStringView reference = symView(2); 1645 if (entityHash.contains(reference)) { 1646 Entity &entity = entityHash[reference]; 1647 if (entity.unparsed) { 1648 raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference)); 1649 } else { 1650 if (!entity.hasBeenParsed) { 1651 parseEntity(entity.value); 1652 entity.hasBeenParsed = true; 1653 } 1654 if (entity.literal) 1655 putStringLiteral(entity.value); 1656 else if (referenceEntity(entity)) 1657 putReplacement(entity.value); 1658 textBuffer.chop(2 + sym(2).len); 1659 clearSym(); 1660 } 1661 break; 1662 } 1663 1664 if (entityResolver) { 1665 QString replacementText = resolveUndeclaredEntity(reference.toString()); 1666 if (!replacementText.isNull()) { 1667 putReplacement(replacementText); 1668 textBuffer.chop(2 + sym(2).len); 1669 clearSym(); 1670 break; 1671 } 1672 } 1673 1674 injectToken(UNRESOLVED_ENTITY); 1675 unresolvedEntity = symString(2).toString(); 1676 textBuffer.chop(2 + sym(2).len); 1677 clearSym(); 1678 1679 } break; 1680./ 1681 1682pereference ::= PERCENT name SEMICOLON; 1683/. 1684 case $rule_number: { 1685 sym(1).len += sym(2).len + 1; 1686 QStringView reference = symView(2); 1687 if (parameterEntityHash.contains(reference)) { 1688 referenceToParameterEntityDetected = true; 1689 Entity &entity = parameterEntityHash[reference]; 1690 if (entity.unparsed || entity.external) { 1691 referenceToUnparsedEntityDetected = true; 1692 } else { 1693 if (referenceEntity(entity)) 1694 putString(entity.value); 1695 textBuffer.chop(2 + sym(2).len); 1696 clearSym(); 1697 } 1698 } else if (entitiesMustBeDeclared()) { 1699 raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2))); 1700 } 1701 } break; 1702./ 1703 1704 1705 1706entity_ref_in_entity_value ::= AMPERSAND name SEMICOLON; 1707/. 1708 case $rule_number: 1709 sym(1).len += sym(2).len + 1; 1710 break; 1711./ 1712 1713entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON; 1714/. 1715 case $rule_number: { 1716 sym(1).len += sym(2).len + 1; 1717 QStringView reference = symView(2); 1718 if (entityHash.contains(reference)) { 1719 Entity &entity = entityHash[reference]; 1720 if (entity.unparsed || entity.value.isNull()) { 1721 raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference)); 1722 break; 1723 } 1724 if (!entity.hasBeenParsed) { 1725 parseEntity(entity.value); 1726 entity.hasBeenParsed = true; 1727 } 1728 if (entity.literal) 1729 putStringLiteral(entity.value); 1730 else if (referenceEntity(entity)) 1731 putReplacementInAttributeValue(entity.value); 1732 textBuffer.chop(2 + sym(2).len); 1733 clearSym(); 1734 break; 1735 } 1736 1737 if (entityResolver) { 1738 QString replacementText = resolveUndeclaredEntity(reference.toString()); 1739 if (!replacementText.isNull()) { 1740 putReplacement(replacementText); 1741 textBuffer.chop(2 + sym(2).len); 1742 clearSym(); 1743 break; 1744 } 1745 } 1746 if (entitiesMustBeDeclared()) { 1747 raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference)); 1748 } 1749 } break; 1750./ 1751 1752char_ref ::= AMPERSAND HASH char_ref_value SEMICOLON; 1753/. 1754 case $rule_number: { 1755 if (uint s = resolveCharRef(3)) { 1756 if (s >= 0xffff) 1757 putStringLiteral(QString::fromUcs4(&s, 1)); 1758 else 1759 putChar((LETTER << 16) | s); 1760 1761 textBuffer.chop(3 + sym(3).len); 1762 clearSym(); 1763 } else { 1764 raiseWellFormedError(QXmlStream::tr("Invalid character reference.")); 1765 } 1766 } break; 1767./ 1768 1769 1770char_ref_value ::= LETTER | DIGIT; 1771char_ref_value ::= char_ref_value LETTER; 1772/. 1773 case $rule_number:./ 1774char_ref_value ::= char_ref_value DIGIT; 1775/. 1776 case $rule_number: 1777 sym(1).len += sym(2).len; 1778 break; 1779./ 1780 1781 1782content ::= content character_content; 1783content ::= content stag content etag; 1784content ::= content empty_element_tag; 1785content ::= content comment; 1786content ::= content cdata; 1787content ::= content xml_decl; 1788content ::= content processing_instruction; 1789content ::= content doctype_decl; 1790content ::= content unresolved_entity; 1791content ::= ; 1792 1793 1794space ::= SPACE; 1795/. 1796 case $rule_number: 1797 sym(1).len += fastScanSpace(); 1798 if (atEnd) { 1799 resume($rule_number); 1800 return false; 1801 } 1802 break; 1803./ 1804 1805 1806space_opt ::=; 1807space_opt ::= space; 1808 1809qname ::= LETTER; 1810/. 1811 case $rule_number: { 1812 sym(1).len += fastScanName(&sym(1).prefix); 1813 if (atEnd) { 1814 resume($rule_number); 1815 return false; 1816 } 1817 } break; 1818./ 1819 1820name ::= LETTER; 1821/. 1822 case $rule_number: 1823 sym(1).len += fastScanName(); 1824 if (atEnd) { 1825 resume($rule_number); 1826 return false; 1827 } 1828 break; 1829./ 1830 1831nmtoken ::= LETTER; 1832/. 1833 case $rule_number:./ 1834nmtoken ::= DIGIT; 1835/. 1836 case $rule_number:./ 1837nmtoken ::= DOT; 1838/. 1839 case $rule_number:./ 1840nmtoken ::= DASH; 1841/. 1842 case $rule_number:./ 1843nmtoken ::= COLON; 1844/. 1845 case $rule_number: 1846 sym(1).len += fastScanNMTOKEN(); 1847 if (atEnd) { 1848 resume($rule_number); 1849 return false; 1850 } 1851 1852 break; 1853./ 1854 1855 1856/. 1857 default: 1858 ; 1859 } // switch 1860 act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT); 1861 if (type != QXmlStreamReader::NoToken) 1862 return true; 1863 } else { 1864 parseError(); 1865 break; 1866 } 1867 } 1868 return false; 1869} 1870#endif //QT_NO_XMLSTREAMREADER.xml 1871 1872./ 1873