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. &amp;). 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 &notationDeclaration = 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 &notationDeclaration = 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 &notationDeclaration = 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 &notationDeclaration = 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