1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2020 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtQml 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 | |
41 | // |
42 | // W A R N I N G |
43 | // ------------- |
44 | // |
45 | // This file is not part of the Qt API. It exists purely as an |
46 | // implementation detail. This header file may change from version to |
47 | // version without notice, or even be removed. |
48 | // |
49 | // We mean it. |
50 | // |
51 | |
52 | // |
53 | // W A R N I N G |
54 | // ------------- |
55 | // |
56 | // This file is automatically generated from qxmlstream.g. |
57 | // Changes should be made to that file, not here. Any change to this file will |
58 | // be lost! |
59 | // |
60 | // To regenerate this file, run: |
61 | // qlalr --no-debug --no-lines --qt qxmlstream.g |
62 | // |
63 | |
64 | #include <QtCore/private/qglobal_p.h> |
65 | #include <qxmlstream.h> |
66 | #include "qxmlstream_p.h" |
67 | #include "qxmlutils_p.h" |
68 | #include <qstringconverter.h> |
69 | |
70 | #include <memory> |
71 | |
72 | #ifndef QXMLSTREAMPARSER_P_H |
73 | #define QXMLSTREAMPARSER_P_H |
74 | |
75 | QT_BEGIN_NAMESPACE |
76 | |
77 | #ifndef QT_NO_XMLSTREAMREADER |
78 | |
79 | bool QXmlStreamReaderPrivate::parse() |
80 | { |
81 | // cleanup currently reported token |
82 | |
83 | switch (type) { |
84 | case QXmlStreamReader::StartElement: |
85 | name.clear(); |
86 | prefix.clear(); |
87 | qualifiedName.clear(); |
88 | namespaceUri.clear(); |
89 | publicNamespaceDeclarations.clear(); |
90 | attributes.clear(); |
91 | if (isEmptyElement) { |
92 | setType(QXmlStreamReader::EndElement); |
93 | Tag tag = tagStack_pop(); |
94 | namespaceUri = tag.namespaceDeclaration.namespaceUri; |
95 | name = tag.name; |
96 | qualifiedName = tag.qualifiedName; |
97 | isEmptyElement = false; |
98 | return true; |
99 | } |
100 | clearTextBuffer(); |
101 | break; |
102 | case QXmlStreamReader::EndElement: |
103 | name.clear(); |
104 | prefix.clear(); |
105 | qualifiedName.clear(); |
106 | namespaceUri.clear(); |
107 | clearTextBuffer(); |
108 | break; |
109 | case QXmlStreamReader::DTD: |
110 | publicNotationDeclarations.clear(); |
111 | publicEntityDeclarations.clear(); |
112 | dtdName.clear(); |
113 | dtdPublicId.clear(); |
114 | dtdSystemId.clear(); |
115 | Q_FALLTHROUGH(); |
116 | case QXmlStreamReader::Comment: |
117 | case QXmlStreamReader::Characters: |
118 | isCDATA = false; |
119 | isWhitespace = true; |
120 | text.clear(); |
121 | clearTextBuffer(); |
122 | break; |
123 | case QXmlStreamReader::EntityReference: |
124 | text.clear(); |
125 | name.clear(); |
126 | clearTextBuffer(); |
127 | break; |
128 | case QXmlStreamReader::ProcessingInstruction: |
129 | processingInstructionTarget.clear(); |
130 | processingInstructionData.clear(); |
131 | clearTextBuffer(); |
132 | break; |
133 | case QXmlStreamReader::NoToken: |
134 | case QXmlStreamReader::Invalid: |
135 | break; |
136 | case QXmlStreamReader::StartDocument: |
137 | lockEncoding = true; |
138 | documentVersion.clear(); |
139 | documentEncoding.clear(); |
140 | if (decoder.isValid() && decoder.hasError()) { |
141 | raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content." )); |
142 | readBuffer.clear(); |
143 | return false; |
144 | } |
145 | Q_FALLTHROUGH(); |
146 | default: |
147 | clearTextBuffer(); |
148 | ; |
149 | } |
150 | |
151 | setType(QXmlStreamReader::NoToken); |
152 | |
153 | |
154 | // the main parse loop |
155 | int act, r; |
156 | |
157 | if (resumeReduction) { |
158 | act = state_stack[tos-1]; |
159 | r = resumeReduction; |
160 | resumeReduction = 0; |
161 | goto ResumeReduction; |
162 | } |
163 | |
164 | act = state_stack[tos]; |
165 | |
166 | forever { |
167 | if (token == -1 && - TERMINAL_COUNT != action_index[act]) { |
168 | uint cu = getChar(); |
169 | token = NOTOKEN; |
170 | token_char = cu == ~0U ? cu : ushort(cu); |
171 | if ((cu != ~0U) && (cu & 0xff0000)) { |
172 | token = cu >> 16; |
173 | } else switch (token_char) { |
174 | case 0xfffe: |
175 | case 0xffff: |
176 | token = ERROR; |
177 | break; |
178 | case '\r': |
179 | token = SPACE; |
180 | if (cu == '\r') { |
181 | if ((token_char = filterCarriageReturn())) { |
182 | ++lineNumber; |
183 | lastLineStart = characterOffset + readBufferPos; |
184 | break; |
185 | } |
186 | } else { |
187 | break; |
188 | } |
189 | Q_FALLTHROUGH(); |
190 | case ~0U: { |
191 | token = EOF_SYMBOL; |
192 | if (!tagsDone && !inParseEntity) { |
193 | int a = t_action(act, token); |
194 | if (a < 0) { |
195 | raiseError(QXmlStreamReader::PrematureEndOfDocumentError); |
196 | return false; |
197 | } |
198 | } |
199 | |
200 | } break; |
201 | case '\n': |
202 | ++lineNumber; |
203 | lastLineStart = characterOffset + readBufferPos; |
204 | Q_FALLTHROUGH(); |
205 | case ' ': |
206 | case '\t': |
207 | token = SPACE; |
208 | break; |
209 | case '&': |
210 | token = AMPERSAND; |
211 | break; |
212 | case '#': |
213 | token = HASH; |
214 | break; |
215 | case '\'': |
216 | token = QUOTE; |
217 | break; |
218 | case '\"': |
219 | token = DBLQUOTE; |
220 | break; |
221 | case '<': |
222 | token = LANGLE; |
223 | break; |
224 | case '>': |
225 | token = RANGLE; |
226 | break; |
227 | case '[': |
228 | token = LBRACK; |
229 | break; |
230 | case ']': |
231 | token = RBRACK; |
232 | break; |
233 | case '(': |
234 | token = LPAREN; |
235 | break; |
236 | case ')': |
237 | token = RPAREN; |
238 | break; |
239 | case '|': |
240 | token = PIPE; |
241 | break; |
242 | case '=': |
243 | token = EQ; |
244 | break; |
245 | case '%': |
246 | token = PERCENT; |
247 | break; |
248 | case '/': |
249 | token = SLASH; |
250 | break; |
251 | case ':': |
252 | token = COLON; |
253 | break; |
254 | case ';': |
255 | token = SEMICOLON; |
256 | break; |
257 | case ',': |
258 | token = COMMA; |
259 | break; |
260 | case '-': |
261 | token = DASH; |
262 | break; |
263 | case '+': |
264 | token = PLUS; |
265 | break; |
266 | case '*': |
267 | token = STAR; |
268 | break; |
269 | case '.': |
270 | token = DOT; |
271 | break; |
272 | case '?': |
273 | token = QUESTIONMARK; |
274 | break; |
275 | case '!': |
276 | token = BANG; |
277 | break; |
278 | case '0': |
279 | case '1': |
280 | case '2': |
281 | case '3': |
282 | case '4': |
283 | case '5': |
284 | case '6': |
285 | case '7': |
286 | case '8': |
287 | case '9': |
288 | token = DIGIT; |
289 | break; |
290 | default: |
291 | if (cu < 0x20) |
292 | token = NOTOKEN; |
293 | else |
294 | token = LETTER; |
295 | break; |
296 | } |
297 | } |
298 | |
299 | act = t_action (act, token); |
300 | if (act == ACCEPT_STATE) { |
301 | // reset the parser in case someone resumes (process instructions can follow a valid document) |
302 | tos = 0; |
303 | state_stack[tos++] = 0; |
304 | state_stack[tos] = 0; |
305 | return true; |
306 | } else if (act > 0) { |
307 | if (++tos >= stack_size-1) |
308 | reallocateStack(); |
309 | |
310 | Value &val = sym_stack[tos]; |
311 | val.c = token_char; |
312 | val.pos = textBuffer.size(); |
313 | val.prefix = 0; |
314 | val.len = 1; |
315 | if (token_char) |
316 | textBuffer += QChar(token_char); |
317 | |
318 | state_stack[tos] = act; |
319 | token = -1; |
320 | |
321 | |
322 | } else if (act < 0) { |
323 | r = - act - 1; |
324 | |
325 | #if defined (QLALR_DEBUG) |
326 | int ridx = rule_index[r]; |
327 | printf ("%3d) %s ::=" , r + 1, spell[rule_info[ridx]]); |
328 | ++ridx; |
329 | for (int i = ridx; i < ridx + rhs[r]; ++i) { |
330 | int symbol = rule_info[i]; |
331 | if (const char *name = spell[symbol]) |
332 | printf (" %s" , name); |
333 | else |
334 | printf (" #%d" , symbol); |
335 | } |
336 | printf ("\n" ); |
337 | #endif |
338 | |
339 | tos -= rhs[r]; |
340 | act = state_stack[tos++]; |
341 | ResumeReduction: |
342 | switch (r) { |
343 | |
344 | case 0: |
345 | setType(QXmlStreamReader::EndDocument); |
346 | break; |
347 | |
348 | case 1: |
349 | if (type != QXmlStreamReader::Invalid) { |
350 | if (hasSeenTag || inParseEntity) { |
351 | setType(QXmlStreamReader::EndDocument); |
352 | } else { |
353 | raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected." )); |
354 | // reset the parser |
355 | tos = 0; |
356 | state_stack[tos++] = 0; |
357 | state_stack[tos] = 0; |
358 | return false; |
359 | } |
360 | } |
361 | break; |
362 | |
363 | case 10: |
364 | entityReferenceStack.pop()->isCurrentlyReferenced = false; |
365 | if (entityReferenceStack.isEmpty()) |
366 | entityLength = 0; |
367 | clearSym(); |
368 | break; |
369 | |
370 | case 11: |
371 | if (!scanString(spell[VERSION], VERSION, false) && atEnd) { |
372 | resume(11); |
373 | return false; |
374 | } |
375 | break; |
376 | |
377 | case 12: |
378 | setType(QXmlStreamReader::StartDocument); |
379 | documentVersion = symString(6); |
380 | startDocument(); |
381 | break; |
382 | |
383 | case 13: |
384 | hasExternalDtdSubset = true; |
385 | dtdSystemId = symString(2); |
386 | break; |
387 | |
388 | case 14: |
389 | checkPublicLiteral(symString(2)); |
390 | dtdPublicId = symString(2); |
391 | dtdSystemId = symString(4); |
392 | hasExternalDtdSubset = true; |
393 | break; |
394 | |
395 | case 16: |
396 | if (!scanPublicOrSystem() && atEnd) { |
397 | resume(16); |
398 | return false; |
399 | } |
400 | dtdName = symString(3); |
401 | break; |
402 | |
403 | case 17: |
404 | case 18: |
405 | dtdName = symString(3); |
406 | Q_FALLTHROUGH(); |
407 | |
408 | case 19: |
409 | case 20: |
410 | setType(QXmlStreamReader::DTD); |
411 | text = &textBuffer; |
412 | break; |
413 | |
414 | case 21: |
415 | scanDtd = true; |
416 | break; |
417 | |
418 | case 22: |
419 | scanDtd = false; |
420 | break; |
421 | |
422 | case 37: |
423 | if (!scanString(spell[EMPTY], EMPTY, false) |
424 | && !scanString(spell[ANY], ANY, false) |
425 | && atEnd) { |
426 | resume(37); |
427 | return false; |
428 | } |
429 | break; |
430 | |
431 | case 43: |
432 | if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) { |
433 | resume(43); |
434 | return false; |
435 | } |
436 | break; |
437 | |
438 | case 68: { |
439 | lastAttributeIsCData = true; |
440 | } break; |
441 | |
442 | case 78: |
443 | if (!scanAfterDefaultDecl() && atEnd) { |
444 | resume(78); |
445 | return false; |
446 | } |
447 | break; |
448 | |
449 | case 83: |
450 | sym(1) = sym(2); |
451 | lastAttributeValue.clear(); |
452 | lastAttributeIsCData = false; |
453 | if (!scanAttType() && atEnd) { |
454 | resume(83); |
455 | return false; |
456 | } |
457 | break; |
458 | |
459 | case 84: { |
460 | DtdAttribute &dtdAttribute = dtdAttributes.push(); |
461 | dtdAttribute.tagName.clear(); |
462 | dtdAttribute.isCDATA = lastAttributeIsCData; |
463 | dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1)); |
464 | dtdAttribute.attributeName = addToStringStorage(symString(1)); |
465 | dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1)); |
466 | dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns" ) |
467 | || (dtdAttribute.attributePrefix.isEmpty() |
468 | && dtdAttribute.attributeName == QLatin1String("xmlns" ))); |
469 | if (lastAttributeValue.isNull()) { |
470 | dtdAttribute.defaultValue.clear(); |
471 | } else { |
472 | if (dtdAttribute.isCDATA) |
473 | dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue); |
474 | else |
475 | dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified()); |
476 | |
477 | } |
478 | } break; |
479 | |
480 | case 88: { |
481 | if (referenceToUnparsedEntityDetected && !standalone) |
482 | break; |
483 | int n = dtdAttributes.size(); |
484 | XmlStringRef tagName = addToStringStorage(symName(3)); |
485 | while (n--) { |
486 | DtdAttribute &dtdAttribute = dtdAttributes[n]; |
487 | if (!dtdAttribute.tagName.isNull()) |
488 | break; |
489 | dtdAttribute.tagName = tagName; |
490 | for (int i = 0; i < n; ++i) { |
491 | if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName) |
492 | && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) { |
493 | dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it |
494 | break; |
495 | } |
496 | } |
497 | } |
498 | } break; |
499 | |
500 | case 89: { |
501 | if (!scanPublicOrSystem() && atEnd) { |
502 | resume(89); |
503 | return false; |
504 | } |
505 | EntityDeclaration &entityDeclaration = entityDeclarations.push(); |
506 | entityDeclaration.clear(); |
507 | entityDeclaration.name = symString(3); |
508 | } break; |
509 | |
510 | case 90: { |
511 | if (!scanPublicOrSystem() && atEnd) { |
512 | resume(90); |
513 | return false; |
514 | } |
515 | EntityDeclaration &entityDeclaration = entityDeclarations.push(); |
516 | entityDeclaration.clear(); |
517 | entityDeclaration.name = symString(5); |
518 | entityDeclaration.parameter = true; |
519 | } break; |
520 | |
521 | case 91: { |
522 | if (!scanNData() && atEnd) { |
523 | resume(91); |
524 | return false; |
525 | } |
526 | EntityDeclaration &entityDeclaration = entityDeclarations.top(); |
527 | entityDeclaration.systemId = symString(3); |
528 | entityDeclaration.external = true; |
529 | } break; |
530 | |
531 | case 92: { |
532 | if (!scanNData() && atEnd) { |
533 | resume(92); |
534 | return false; |
535 | } |
536 | EntityDeclaration &entityDeclaration = entityDeclarations.top(); |
537 | checkPublicLiteral((entityDeclaration.publicId = symString(3))); |
538 | entityDeclaration.systemId = symString(5); |
539 | entityDeclaration.external = true; |
540 | } break; |
541 | |
542 | case 93: { |
543 | EntityDeclaration &entityDeclaration = entityDeclarations.top(); |
544 | entityDeclaration.notationName = symString(3); |
545 | if (entityDeclaration.parameter) |
546 | raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration." )); |
547 | } |
548 | Q_FALLTHROUGH(); |
549 | |
550 | case 94: |
551 | case 95: { |
552 | if (referenceToUnparsedEntityDetected && !standalone) { |
553 | entityDeclarations.pop(); |
554 | break; |
555 | } |
556 | EntityDeclaration &entityDeclaration = entityDeclarations.top(); |
557 | if (!entityDeclaration.external) |
558 | entityDeclaration.value = symString(2); |
559 | auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash; |
560 | if (!hash.contains(entityDeclaration.name)) { |
561 | Entity entity(entityDeclaration.name.toString(), |
562 | entityDeclaration.value.toString()); |
563 | entity.unparsed = (!entityDeclaration.notationName.isNull()); |
564 | entity.external = entityDeclaration.external; |
565 | hash.insert(qToStringViewIgnoringNull(entity.name), entity); |
566 | } |
567 | } break; |
568 | |
569 | case 96: { |
570 | setType(QXmlStreamReader::ProcessingInstruction); |
571 | int pos = sym(4).pos + sym(4).len; |
572 | processingInstructionTarget = symString(3); |
573 | if (scanUntil("?>" )) { |
574 | processingInstructionData = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 2); |
575 | if (!processingInstructionTarget.view().compare(QLatin1String("xml" ), Qt::CaseInsensitive)) { |
576 | raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document." )); |
577 | } |
578 | else if (!QXmlUtils::isNCName(processingInstructionTarget)) |
579 | raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name." ) |
580 | .arg(processingInstructionTarget)); |
581 | } else if (type != QXmlStreamReader::Invalid){ |
582 | resume(96); |
583 | return false; |
584 | } |
585 | } break; |
586 | |
587 | case 97: |
588 | setType(QXmlStreamReader::ProcessingInstruction); |
589 | processingInstructionTarget = symString(3); |
590 | if (!processingInstructionTarget.view().compare(QLatin1String("xml" ), Qt::CaseInsensitive)) |
591 | raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name." )); |
592 | break; |
593 | |
594 | case 98: |
595 | if (!scanAfterLangleBang() && atEnd) { |
596 | resume(98); |
597 | return false; |
598 | } |
599 | break; |
600 | |
601 | case 99: |
602 | if (!scanUntil("--" )) { |
603 | resume(99); |
604 | return false; |
605 | } |
606 | break; |
607 | |
608 | case 100: { |
609 | setType(QXmlStreamReader::Comment); |
610 | int pos = sym(1).pos + 4; |
611 | text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3); |
612 | } break; |
613 | |
614 | case 101: { |
615 | setType(QXmlStreamReader::Characters); |
616 | isCDATA = true; |
617 | isWhitespace = false; |
618 | int pos = sym(2).pos; |
619 | if (scanUntil("]]>" , -1)) { |
620 | text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3); |
621 | } else { |
622 | resume(101); |
623 | return false; |
624 | } |
625 | } break; |
626 | |
627 | case 102: { |
628 | if (!scanPublicOrSystem() && atEnd) { |
629 | resume(102); |
630 | return false; |
631 | } |
632 | NotationDeclaration ¬ationDeclaration = notationDeclarations.push(); |
633 | notationDeclaration.name = symString(3); |
634 | } break; |
635 | |
636 | case 103: { |
637 | NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); |
638 | notationDeclaration.systemId = symString(3); |
639 | notationDeclaration.publicId.clear(); |
640 | } break; |
641 | |
642 | case 104: { |
643 | NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); |
644 | notationDeclaration.systemId.clear(); |
645 | checkPublicLiteral((notationDeclaration.publicId = symString(3))); |
646 | } break; |
647 | |
648 | case 105: { |
649 | NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); |
650 | checkPublicLiteral((notationDeclaration.publicId = symString(3))); |
651 | notationDeclaration.systemId = symString(5); |
652 | } break; |
653 | |
654 | case 129: |
655 | isWhitespace = false; |
656 | Q_FALLTHROUGH(); |
657 | |
658 | case 130: |
659 | sym(1).len += fastScanContentCharList(); |
660 | if (atEnd && !inParseEntity) { |
661 | resume(130); |
662 | return false; |
663 | } |
664 | break; |
665 | |
666 | case 139: |
667 | if (!textBuffer.isEmpty()) { |
668 | setType(QXmlStreamReader::Characters); |
669 | text = &textBuffer; |
670 | } |
671 | break; |
672 | |
673 | case 140: |
674 | case 141: |
675 | clearSym(); |
676 | break; |
677 | |
678 | case 142: |
679 | case 143: |
680 | sym(1) = sym(2); |
681 | break; |
682 | |
683 | case 144: |
684 | case 145: |
685 | case 146: |
686 | case 147: |
687 | sym(1).len += sym(2).len; |
688 | break; |
689 | |
690 | case 173: |
691 | if (normalizeLiterals) |
692 | textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' '); |
693 | break; |
694 | |
695 | case 174: |
696 | sym(1).len += fastScanLiteralContent(); |
697 | if (atEnd) { |
698 | resume(174); |
699 | return false; |
700 | } |
701 | break; |
702 | |
703 | case 175: { |
704 | if (!QXmlUtils::isPublicID(symString(1))) { |
705 | raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier." ).arg(symString(1))); |
706 | resume(175); |
707 | return false; |
708 | } |
709 | } break; |
710 | |
711 | case 176: |
712 | case 177: |
713 | clearSym(); |
714 | break; |
715 | |
716 | case 178: |
717 | case 179: |
718 | sym(1) = sym(2); |
719 | break; |
720 | |
721 | case 180: |
722 | case 181: |
723 | case 182: |
724 | case 183: |
725 | sym(1).len += sym(2).len; |
726 | break; |
727 | |
728 | case 213: |
729 | case 214: |
730 | clearSym(); |
731 | break; |
732 | |
733 | case 215: |
734 | case 216: |
735 | sym(1) = sym(2); |
736 | lastAttributeValue = symString(1); |
737 | break; |
738 | |
739 | case 217: |
740 | case 218: |
741 | case 219: |
742 | case 220: |
743 | sym(1).len += sym(2).len; |
744 | break; |
745 | |
746 | case 229: { |
747 | XmlStringRef prefix = symPrefix(1); |
748 | if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns" ) && namespaceProcessing) { |
749 | NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); |
750 | namespaceDeclaration.prefix.clear(); |
751 | |
752 | const XmlStringRef ns(symString(5)); |
753 | if (ns.view() == QLatin1String("http://www.w3.org/2000/xmlns/" ) || |
754 | ns.view() == QLatin1String("http://www.w3.org/XML/1998/namespace" )) |
755 | raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration." )); |
756 | else |
757 | namespaceDeclaration.namespaceUri = addToStringStorage(ns); |
758 | } else { |
759 | Attribute &attribute = attributeStack.push(); |
760 | attribute.key = sym(1); |
761 | attribute.value = sym(5); |
762 | |
763 | XmlStringRef attributeQualifiedName = symName(1); |
764 | bool normalize = false; |
765 | for (int a = 0; a < dtdAttributes.size(); ++a) { |
766 | DtdAttribute &dtdAttribute = dtdAttributes[a]; |
767 | if (!dtdAttribute.isCDATA |
768 | && dtdAttribute.tagName == qualifiedName |
769 | && dtdAttribute.attributeQualifiedName == attributeQualifiedName |
770 | ) { |
771 | normalize = true; |
772 | break; |
773 | } |
774 | } |
775 | if (normalize) { |
776 | // normalize attribute value (simplify and trim) |
777 | int pos = textBuffer.size(); |
778 | int n = 0; |
779 | bool wasSpace = true; |
780 | for (int i = 0; i < attribute.value.len; ++i) { |
781 | QChar c = textBuffer.at(attribute.value.pos + i); |
782 | if (c.unicode() == ' ') { |
783 | if (wasSpace) |
784 | continue; |
785 | wasSpace = true; |
786 | } else { |
787 | wasSpace = false; |
788 | } |
789 | textBuffer += textBuffer.at(attribute.value.pos + i); |
790 | ++n; |
791 | } |
792 | if (wasSpace) |
793 | while (n && textBuffer.at(pos + n - 1).unicode() == ' ') |
794 | --n; |
795 | attribute.value.pos = pos; |
796 | attribute.value.len = n; |
797 | } |
798 | if (prefix == QLatin1String("xmlns" ) && namespaceProcessing) { |
799 | NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); |
800 | XmlStringRef namespacePrefix = symString(attribute.key); |
801 | XmlStringRef namespaceUri = symString(attribute.value); |
802 | attributeStack.pop(); |
803 | if (((namespacePrefix == QLatin1String("xml" )) |
804 | ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace" ))) |
805 | || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/" ) |
806 | || namespaceUri.isEmpty() |
807 | || namespacePrefix == QLatin1String("xmlns" )) |
808 | raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration." )); |
809 | |
810 | namespaceDeclaration.prefix = addToStringStorage(namespacePrefix); |
811 | namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri); |
812 | } |
813 | } |
814 | } break; |
815 | |
816 | case 235: { |
817 | normalizeLiterals = true; |
818 | Tag &tag = tagStack_push(); |
819 | prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2)); |
820 | name = tag.name = addToStringStorage(symString(2)); |
821 | qualifiedName = tag.qualifiedName = addToStringStorage(symName(2)); |
822 | if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name)) |
823 | raiseWellFormedError(QXmlStream::tr("Invalid XML name." )); |
824 | } break; |
825 | |
826 | case 236: |
827 | isEmptyElement = true; |
828 | Q_FALLTHROUGH(); |
829 | |
830 | case 237: |
831 | setType(QXmlStreamReader::StartElement); |
832 | resolveTag(); |
833 | if (tagStack.size() == 1 && hasSeenTag && !inParseEntity) |
834 | raiseWellFormedError(QXmlStream::tr("Extra content at end of document." )); |
835 | hasSeenTag = true; |
836 | break; |
837 | |
838 | case 238: { |
839 | setType(QXmlStreamReader::EndElement); |
840 | Tag tag = tagStack_pop(); |
841 | |
842 | namespaceUri = tag.namespaceDeclaration.namespaceUri; |
843 | name = tag.name; |
844 | qualifiedName = tag.qualifiedName; |
845 | if (qualifiedName != symName(3)) |
846 | raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch." )); |
847 | } break; |
848 | |
849 | case 239: |
850 | if (entitiesMustBeDeclared()) { |
851 | raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared." ).arg(unresolvedEntity)); |
852 | break; |
853 | } |
854 | setType(QXmlStreamReader::EntityReference); |
855 | name = &unresolvedEntity; |
856 | break; |
857 | |
858 | case 240: { |
859 | sym(1).len += sym(2).len + 1; |
860 | QStringView reference = symView(2); |
861 | if (const auto it = entityHash.find(reference); it != entityHash.end()) { |
862 | Entity &entity = *it; |
863 | if (entity.unparsed) { |
864 | raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'." ).arg(reference)); |
865 | } else { |
866 | if (!entity.hasBeenParsed) { |
867 | parseEntity(entity.value); |
868 | entity.hasBeenParsed = true; |
869 | } |
870 | if (entity.literal) |
871 | putStringLiteral(entity.value); |
872 | else if (referenceEntity(entity)) |
873 | putReplacement(entity.value); |
874 | textBuffer.chop(2 + sym(2).len); |
875 | clearSym(); |
876 | } |
877 | break; |
878 | } |
879 | |
880 | if (entityResolver) { |
881 | QString replacementText = resolveUndeclaredEntity(reference.toString()); |
882 | if (!replacementText.isNull()) { |
883 | putReplacement(replacementText); |
884 | textBuffer.chop(2 + sym(2).len); |
885 | clearSym(); |
886 | break; |
887 | } |
888 | } |
889 | |
890 | injectToken(UNRESOLVED_ENTITY); |
891 | unresolvedEntity = symString(2).toString(); |
892 | textBuffer.chop(2 + sym(2).len); |
893 | clearSym(); |
894 | |
895 | } break; |
896 | |
897 | case 241: { |
898 | sym(1).len += sym(2).len + 1; |
899 | QStringView reference = symView(2); |
900 | if (const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) { |
901 | referenceToParameterEntityDetected = true; |
902 | Entity &entity = *it; |
903 | if (entity.unparsed || entity.external) { |
904 | referenceToUnparsedEntityDetected = true; |
905 | } else { |
906 | if (referenceEntity(entity)) |
907 | putString(entity.value); |
908 | textBuffer.chop(2 + sym(2).len); |
909 | clearSym(); |
910 | } |
911 | } else if (entitiesMustBeDeclared()) { |
912 | raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared." ).arg(symString(2))); |
913 | } |
914 | } break; |
915 | |
916 | case 242: |
917 | sym(1).len += sym(2).len + 1; |
918 | break; |
919 | |
920 | case 243: { |
921 | sym(1).len += sym(2).len + 1; |
922 | QStringView reference = symView(2); |
923 | if (const auto it = entityHash.find(reference); it != entityHash.end()) { |
924 | Entity &entity = *it; |
925 | if (entity.unparsed || entity.value.isNull()) { |
926 | raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value." ).arg(reference)); |
927 | break; |
928 | } |
929 | if (!entity.hasBeenParsed) { |
930 | parseEntity(entity.value); |
931 | entity.hasBeenParsed = true; |
932 | } |
933 | if (entity.literal) |
934 | putStringLiteral(entity.value); |
935 | else if (referenceEntity(entity)) |
936 | putReplacementInAttributeValue(entity.value); |
937 | textBuffer.chop(2 + sym(2).len); |
938 | clearSym(); |
939 | break; |
940 | } |
941 | |
942 | if (entityResolver) { |
943 | QString replacementText = resolveUndeclaredEntity(reference.toString()); |
944 | if (!replacementText.isNull()) { |
945 | putReplacement(replacementText); |
946 | textBuffer.chop(2 + sym(2).len); |
947 | clearSym(); |
948 | break; |
949 | } |
950 | } |
951 | if (entitiesMustBeDeclared()) { |
952 | raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared." ).arg(reference)); |
953 | } |
954 | } break; |
955 | |
956 | case 244: { |
957 | if (char32_t s = resolveCharRef(3)) { |
958 | putStringLiteral(QChar::fromUcs4(s)); |
959 | textBuffer.chop(3 + sym(3).len); |
960 | clearSym(); |
961 | } else { |
962 | raiseWellFormedError(QXmlStream::tr("Invalid character reference." )); |
963 | } |
964 | } break; |
965 | |
966 | case 247: |
967 | case 248: |
968 | sym(1).len += sym(2).len; |
969 | break; |
970 | |
971 | case 259: |
972 | sym(1).len += fastScanSpace(); |
973 | if (atEnd) { |
974 | resume(259); |
975 | return false; |
976 | } |
977 | break; |
978 | |
979 | case 262: { |
980 | sym(1).len += fastScanName(&sym(1).prefix); |
981 | if (atEnd) { |
982 | resume(262); |
983 | return false; |
984 | } |
985 | } break; |
986 | |
987 | case 263: |
988 | sym(1).len += fastScanName(); |
989 | if (atEnd) { |
990 | resume(263); |
991 | return false; |
992 | } |
993 | break; |
994 | |
995 | case 264: |
996 | case 265: |
997 | case 266: |
998 | case 267: |
999 | case 268: |
1000 | sym(1).len += fastScanNMTOKEN(); |
1001 | if (atEnd) { |
1002 | resume(268); |
1003 | return false; |
1004 | } |
1005 | |
1006 | break; |
1007 | |
1008 | default: |
1009 | ; |
1010 | } // switch |
1011 | act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT); |
1012 | if (type != QXmlStreamReader::NoToken) |
1013 | return true; |
1014 | } else { |
1015 | parseError(); |
1016 | break; |
1017 | } |
1018 | } |
1019 | return false; |
1020 | } |
1021 | |
1022 | #endif |
1023 | |
1024 | QT_END_NAMESPACE |
1025 | |
1026 | #endif |
1027 | |
1028 | |