2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: parseDecl.C /main/1 1996/07/29 17:09:16 cde-hp $ */
24 // Copyright (c) 1994, 1995 James Clark
25 // See the file COPYING for copying permission.
27 // Prolog, dtd and declaration parsing.
33 #include "ParserMessages.h"
34 #include "MessageArg.h"
35 #include "TokenMessageArg.h"
40 namespace SP_NAMESPACE {
43 static const AllowedParams allowMdc(Param::mdc);
44 static const AllowedParams allowName(Param::name);
45 static const AllowedParams allowParamLiteral(Param::paramLiteral);
46 static const AllowedParams allowNameNameGroup(Param::name, Param::nameGroup);
47 static const AllowedParams allowDsoMdc(Param::dso, Param::mdc);
48 static AllowedParams allowNameMdc(Param::name, Param::mdc);
50 allowExplicitLinkRuleMdc(Param::mdc,
53 Param::indicatedReservedName + Syntax::rIMPLIED);
55 allowNameNameGroupMdc(Param::name, Param::nameGroup, Param::mdc);
57 static const AllowedParams
58 allowLinkSetSpec(Param::name,
59 Param::indicatedReservedName + Syntax::rINITIAL,
60 Param::indicatedReservedName + Syntax::rEMPTY,
61 Param::indicatedReservedName + Syntax::rRESTORE);
63 void Parser::doProlog()
65 const unsigned maxTries = 10;
72 Token token = getToken(proMode);
74 case tokenUnrecognized:
75 if (reportNonSgmlCharacter())
78 currentInput()->ungetToken();
84 if (lookingAtStartTag(gi)) {
85 currentInput()->ungetToken();
87 message(ParserMessages::noDtd);
94 if (++tries >= maxTries) {
95 message(ParserMessages::noDtd);
99 message(ParserMessages::prologCharacter, StringMessageArg(currentToken()));
107 message(ParserMessages::documentEndProlog);
115 if (!parseCommentDecl())
118 case tokenMdoNameStart:
120 if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation()))
121 currentMarkup()->addDelim(Syntax::dMDO);
122 Syntax::ReservedName name;
123 if (parseDeclarationName(&name)) {
125 case Syntax::rDOCTYPE:
126 if (!parseDoctypeDeclStart())
129 case Syntax::rLINKTYPE:
130 if (!parseLinktypeDeclStart())
133 case Syntax::rELEMENT:
134 case Syntax::rATTLIST:
135 case Syntax::rENTITY:
136 case Syntax::rNOTATION:
137 case Syntax::rSHORTREF:
138 case Syntax::rUSEMAP:
139 case Syntax::rUSELINK:
141 case Syntax::rIDLINK:
142 message(ParserMessages::prologDeclaration,
143 StringMessageArg(syntax().reservedName(name)));
149 message(ParserMessages::noSuchDeclarationType,
150 StringMessageArg(syntax().reservedName(name)));
159 if (!parseProcessingInstruction())
163 if (eventsWanted().wantPrologMarkup()) {
165 eventHandler().sSep(new (eventAllocator())
166 SSepEvent(currentInput()->currentTokenStart(),
167 currentInput()->currentTokenLength(),
175 } while (eventQueueEmpty());
178 void Parser::endProlog()
180 if (baseDtd().isNull()
181 || baseDtd()->documentElementType()->definition()->undefined()) {
182 // We could continue, but there's not a lot of point.
186 if (maybeStartPass2())
187 setPhase(prologPhase);
189 if (inputLevel() == 0) {
194 checkEntityStability();
195 setPhase(instanceStartPhase);
197 ConstPtr<ComplexLpd> lpd;
198 Vector<AttributeList> simpleLinkAtts;
199 Vector<StringC> simpleLinkNames;
200 for (size_t i = 0; i < nActiveLink(); i++)
201 if (activeLpd(i).type() == Lpd::simpleLink) {
202 const SimpleLpd &lpd = (SimpleLpd &)activeLpd(i);
203 simpleLinkNames.push_back(lpd.name());
204 simpleLinkAtts.resize(simpleLinkAtts.size() + 1);
205 simpleLinkAtts.back().init(lpd.attributeDef());
206 simpleLinkAtts.back().finish(*this);
209 lpd = (ComplexLpd *)&activeLpd(i);
210 eventHandler().endProlog(new (eventAllocator())
211 EndPrologEvent(baseDtd(),
219 void Parser::prologRecover()
221 unsigned skipCount = 0;
222 const unsigned skipMax = 250;
224 Token token = getToken(proMode);
226 if (token == tokenUnrecognized) {
227 token = getToken(mdMode);
228 if (token == tokenMdc) {
229 token = getToken(proMode);
235 case tokenUnrecognized:
242 case tokenMdoNameStart:
244 currentInput()->ungetToken();
247 if (currentChar() == syntax().standardFunction(Syntax::fRE)
248 && skipCount >= skipMax)
256 void Parser::doDeclSubset()
263 Token token = getToken(currentMode());
264 unsigned startLevel = inputLevel();
265 Boolean inDtd = !haveDefLpd();
267 case tokenUnrecognized:
268 if (reportNonSgmlCharacter())
270 message(ParserMessages::declSubsetCharacter, StringMessageArg(currentToken()));
271 declSubsetRecover(startLevel);
274 if (inputLevel() == specialParseInputLevel()) {
275 // FIXME have separate messages for each type of special parse
276 message(ParserMessages::specialParseEntityEnd);
278 if (eventsWanted().wantPrologMarkup())
279 eventHandler().entityEnd(new (eventAllocator())
280 EntityEndEvent(currentLocation()));
281 if (inputLevel() == 2) {
283 = currentLocation().origin()->asEntityOrigin()->entity();
285 && (e->declType() == Entity::doctype
286 || e->declType() == Entity::linktype)) {
289 ? parseDoctypeDeclEnd(e->defLocation().origin().isNull())
290 : parseLinktypeDeclEnd()))
292 setPhase(prologPhase);
296 if (inputLevel() == 1) {
297 if (finalPhase() == declSubsetPhase) {
302 // Give message before popping stack.
304 ? ParserMessages::documentEndDtdSubset
305 : ParserMessages::documentEndLpdSubset);
312 case tokenDsc: // end of declaration subset
313 // FIXME what's the right location?
314 if (!referenceDsEntity(currentLocation())) {
315 if (!(inDtd ? parseDoctypeDeclEnd() : parseLinktypeDeclEnd()))
317 setPhase(prologPhase);
320 case tokenMdoNameStart: // named markup declaration
321 if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation()))
322 currentMarkup()->addDelim(Syntax::dMDO);
323 Syntax::ReservedName name;
325 if (parseDeclarationName(&name,
326 inDtd && !options().errorAfdr)) {
328 case Syntax::rANY: // used for <!AFDR
329 result = parseAfdrDecl();
331 case Syntax::rELEMENT:
333 result = parseElementDecl();
335 message(ParserMessages::lpdSubsetDeclaration,
336 StringMessageArg(syntax().reservedName(name)));
340 case Syntax::rATTLIST:
341 result = parseAttlistDecl();
343 case Syntax::rENTITY:
344 result = parseEntityDecl();
346 case Syntax::rNOTATION:
347 result = parseNotationDecl();
348 if (!inDtd && options().errorLpdNotation)
349 message(ParserMessages::lpdSubsetDeclaration,
350 StringMessageArg(syntax().reservedName(name)));
352 case Syntax::rSHORTREF:
354 result = parseShortrefDecl();
356 message(ParserMessages::lpdSubsetDeclaration,
357 StringMessageArg(syntax().reservedName(name)));
361 case Syntax::rUSEMAP:
363 result = parseUsemapDecl();
365 message(ParserMessages::lpdSubsetDeclaration,
366 StringMessageArg(syntax().reservedName(name)));
372 message(ParserMessages::dtdSubsetDeclaration,
373 StringMessageArg(syntax().reservedName(name)));
377 result = parseLinkDecl();
379 case Syntax::rIDLINK:
381 message(ParserMessages::dtdSubsetDeclaration,
382 StringMessageArg(syntax().reservedName(name)));
386 result = parseIdlinkDecl();
388 case Syntax::rDOCTYPE:
389 case Syntax::rLINKTYPE:
390 case Syntax::rUSELINK:
393 ? ParserMessages::dtdSubsetDeclaration
394 : ParserMessages::lpdSubsetDeclaration,
395 StringMessageArg(syntax().reservedName(name)));
399 message(ParserMessages::noSuchDeclarationType,
400 StringMessageArg(syntax().reservedName(name)));
407 declSubsetRecover(startLevel);
409 case tokenMdoMdc: // empty comment declaration
413 case tokenMdoCom: // comment declaration
414 if (!parseCommentDecl())
415 declSubsetRecover(startLevel);
417 case tokenMdoDso: // marked section declaration
418 if (!parseMarkedSectionDeclStart())
419 declSubsetRecover(startLevel);
422 handleMarkedSectionEnd();
424 case tokenPeroGrpo: // parameter entity reference with name group
425 message(ParserMessages::peroGrpoProlog);
427 case tokenPeroNameStart: // parameter entity reference
429 ConstPtr<Entity> entity;
430 Ptr<EntityOrigin> origin;
431 if (parseEntityReference(1, token == tokenPeroGrpo, entity, origin)) {
432 if (!entity.isNull())
433 entity->dsReference(*this, origin);
436 declSubsetRecover(startLevel);
439 case tokenPio: // processing instruction
440 if (!parseProcessingInstruction())
441 declSubsetRecover(startLevel);
443 case tokenS: // white space
444 if (eventsWanted().wantPrologMarkup()) {
446 eventHandler().sSep(new (eventAllocator())
447 SSepEvent(currentInput()->currentTokenStart(),
448 currentInput()->currentTokenLength(),
453 case tokenIgnoredChar:
454 // from an ignored marked section
455 if (eventsWanted().wantPrologMarkup())
456 eventHandler().ignoredChars(new (eventAllocator())
457 IgnoredCharsEvent(currentInput()->currentTokenStart(),
458 currentInput()->currentTokenLength(),
465 case tokenCroNameStart:
466 case tokenEroNameStart:
469 // these can occur in a cdata or rcdata marked section
470 message(ParserMessages::dataMarkedSectionDeclSubset);
471 declSubsetRecover(startLevel);
476 } while (eventQueueEmpty());
479 void Parser::declSubsetRecover(unsigned startLevel)
482 Token token = getToken(currentMode());
484 case tokenUnrecognized:
488 if (inputLevel() <= startLevel)
494 case tokenMdoNameStart:
499 if (inputLevel() == startLevel) {
500 currentInput()->ungetToken();
510 Boolean Parser::lookingAtStartTag(StringC &gi)
512 // This is harder than might be expected since we may not have compiled
513 // the recognizers for the instance yet.
514 const StringC &stago = instanceSyntax().delimGeneral(Syntax::dSTAGO);
515 for (size_t i = currentInput()->currentTokenLength();
518 if (currentInput()->tokenChar(messenger()) == InputSource::eE)
521 getCurrentToken(instanceSyntax().generalSubstTable(), delim);
524 Xchar c = currentInput()->tokenChar(messenger());
525 if (!instanceSyntax().isNameStartCharacter(c))
529 c = currentInput()->tokenChar(messenger());
530 } while (instanceSyntax().isNameCharacter(c));
534 Boolean Parser::parseDeclarationName(Syntax::ReservedName *result,
537 currentInput()->discardInitial();
538 extendNameToken(syntax().namelen(), ParserMessages::nameLength);
539 StringC &name = nameBuffer();
540 getCurrentToken(syntax().generalSubstTable(), name);
541 if (!syntax().lookupReservedName(name, result)) {
542 if (allowAfdr && name == sd().execToDoc("AFDR")) {
543 *result = Syntax::rANY;
545 currentMarkup()->addName(currentInput());
548 message(ParserMessages::noSuchDeclarationType, StringMessageArg(name));
552 else if (currentMarkup())
553 currentMarkup()->addReservedName(*result, currentInput());
557 Boolean Parser::parseElementDecl()
559 unsigned declInputLevel = inputLevel();
561 if (!parseParam(allowNameNameGroup, declInputLevel, parm))
563 Vector<NameToken> nameVector;
564 if (parm.type == Param::nameGroup)
565 parm.nameTokenVector.swap(nameVector);
567 nameVector.resize(1);
568 parm.token.swap(nameVector[0].name);
571 allowRankOmissionContent(Param::number,
572 Param::reservedName + Syntax::rO,
574 Param::reservedName + Syntax::rCDATA,
575 Param::reservedName + Syntax::rRCDATA,
576 Param::reservedName + Syntax::rEMPTY,
577 Param::reservedName + Syntax::rANY,
579 if (!parseParam(allowRankOmissionContent, declInputLevel, parm))
582 Vector<ElementType *> elements(nameVector.size());
583 Vector<RankStem *> rankStems;
584 Vector<const RankStem *> constRankStems;
586 if (parm.type == Param::number) {
587 parm.token.swap(rankSuffix);
588 rankStems.resize(nameVector.size());
589 constRankStems.resize(nameVector.size());
590 for (i = 0; i < elements.size(); i++) {
591 StringC name(nameVector[i].name);
593 if (name.size() > syntax().namelen()
594 && nameVector[i].name.size() <= syntax().namelen())
595 message(ParserMessages::genericIdentifierLength,
596 NumberMessageArg(syntax().namelen()));
597 elements[i] = lookupCreateElement(name);
598 rankStems[i] = lookupCreateRankStem(nameVector[i].name);
599 constRankStems[i] = rankStems[i];
602 allowOmissionContent(Param::reservedName + Syntax::rO,
604 Param::reservedName + Syntax::rCDATA,
605 Param::reservedName + Syntax::rRCDATA,
606 Param::reservedName + Syntax::rEMPTY,
607 Param::reservedName + Syntax::rANY,
609 Token token = getToken(mdMinusMode);
610 if (token == tokenNameStart)
611 message(ParserMessages::psRequired);
612 currentInput()->ungetToken();
613 if (!parseParam(allowOmissionContent, declInputLevel, parm))
617 for (i = 0; i < elements.size(); i++)
618 elements[i] = lookupCreateElement(nameVector[i].name);
620 for (i = 0; i < elements.size(); i++)
621 if (defDtd().lookupRankStem(elements[i]->name()))
622 message(ParserMessages::rankStemGenericIdentifier,
623 StringMessageArg(elements[i]->name()));
624 unsigned char omitFlags = 0;
625 if (parm.type == Param::minus
626 || parm.type == Param::reservedName + Syntax::rO) {
627 omitFlags |= ElementDefinition::omitSpec;
628 if (parm.type != Param::minus)
629 omitFlags |= ElementDefinition::omitStart;
630 static AllowedParams allowOmission(Param::reservedName + Syntax::rO,
632 if (!parseParam(allowOmission, declInputLevel, parm))
634 if (parm.type != Param::minus)
635 omitFlags |= ElementDefinition::omitEnd;
636 static AllowedParams allowContent(Param::reservedName + Syntax::rCDATA,
637 Param::reservedName + Syntax::rRCDATA,
638 Param::reservedName + Syntax::rEMPTY,
639 Param::reservedName + Syntax::rANY,
641 if (!parseParam(allowContent, declInputLevel, parm))
646 message(ParserMessages::missingTagMinimization);
648 Ptr<ElementDefinition> def;
650 case Param::reservedName + Syntax::rCDATA:
651 def = new ElementDefinition(markupLocation(),
652 defDtd().allocElementDefinitionIndex(),
654 ElementDefinition::cdata);
655 if (!parseParam(allowMdc, declInputLevel, parm))
658 case Param::reservedName + Syntax::rRCDATA:
659 def = new ElementDefinition(markupLocation(),
660 defDtd().allocElementDefinitionIndex(),
662 ElementDefinition::rcdata);
663 if (!parseParam(allowMdc, declInputLevel, parm))
666 case Param::reservedName + Syntax::rEMPTY:
667 def = new ElementDefinition(markupLocation(),
668 defDtd().allocElementDefinitionIndex(),
670 ElementDefinition::empty);
671 if ((omitFlags & ElementDefinition::omitSpec)
672 && !(omitFlags & ElementDefinition::omitEnd)
673 && options().warnShould)
674 message(ParserMessages::emptyOmitEndTag);
675 if (!parseParam(allowMdc, declInputLevel, parm))
678 case Param::reservedName + Syntax::rANY:
679 def = new ElementDefinition(markupLocation(),
680 defDtd().allocElementDefinitionIndex(),
682 ElementDefinition::any);
683 if (!parseExceptions(declInputLevel, def))
686 case Param::modelGroup:
688 unsigned long cnt = parm.modelGroupPtr->grpgtcnt();
689 // The outermost model group isn't formally a content token.
690 if (cnt - 1 > syntax().grpgtcnt())
691 message(ParserMessages::grpgtcnt, NumberMessageArg(syntax().grpgtcnt()));
692 Owner<CompiledModelGroup>
693 modelGroup(new CompiledModelGroup(parm.modelGroupPtr));
694 Vector<ContentModelAmbiguity> ambiguities;
695 Boolean pcdataUnreachable;
696 modelGroup->compile(currentDtd().nElementTypeIndex(), ambiguities,
698 if (pcdataUnreachable && options().warnMixedContent)
699 message(ParserMessages::pcdataUnreachable);
700 for (i = 0; i < ambiguities.size(); i++) {
701 const ContentModelAmbiguity &a = ambiguities[i];
702 reportAmbiguity(a.from, a.to1, a.to2, a.andDepth);
704 def = new ElementDefinition(markupLocation(),
705 defDtd().allocElementDefinitionIndex(),
707 ElementDefinition::modelGroup,
709 if (!parseExceptions(declInputLevel, def))
714 if (rankSuffix.size() > 0)
715 def->setRank(rankSuffix, constRankStems);
716 ConstPtr<ElementDefinition> constDef(def);
717 for (i = 0; i < elements.size(); i++) {
718 if (elements[i]->definition() != 0)
719 message(ParserMessages::duplicateElementDefinition,
720 StringMessageArg(elements[i]->name()));
722 elements[i]->setElementDefinition(constDef, i);
723 if (!elements[i]->attributeDef().isNull())
724 checkElementAttribute(elements[i]);
726 if (rankStems.size() > 0)
727 rankStems[i]->addDefinition(constDef);
729 if (currentMarkup()) {
730 Vector<const ElementType *> v(elements.size());
731 for (i = 0; i < elements.size(); i++)
733 eventHandler().elementDecl(new (eventAllocator())
734 ElementDeclEvent(v, currentDtdPointer(),
741 void Parser::reportAmbiguity(const LeafContentToken *from,
742 const LeafContentToken *to1,
743 const LeafContentToken *to2,
744 unsigned ambigAndDepth)
747 const ElementType *toType = to1->elementType();
749 toName = toType->name();
751 toName = syntax().delimGeneral(Syntax::dRNI);
752 toName += syntax().reservedName(Syntax::rPCDATA);
754 unsigned to1Index = to1->typeIndex() + 1;
755 unsigned to2Index = to2->typeIndex() + 1;
756 if (from->isInitial())
757 message(ParserMessages::ambiguousModelInitial,
758 StringMessageArg(toName),
759 OrdinalMessageArg(to1Index),
760 OrdinalMessageArg(to2Index));
763 const ElementType *fromType = from->elementType();
765 fromName = fromType->name();
767 fromName = syntax().delimGeneral(Syntax::dRNI);
768 fromName += syntax().reservedName(Syntax::rPCDATA);
770 unsigned fromIndex = from->typeIndex() + 1;
771 unsigned andMatches = from->andDepth() - ambigAndDepth;
773 message(ParserMessages::ambiguousModel,
774 StringMessageArg(fromName),
775 OrdinalMessageArg(fromIndex),
776 StringMessageArg(toName),
777 OrdinalMessageArg(to1Index),
778 OrdinalMessageArg(to2Index));
779 else if (andMatches == 1)
780 message(ParserMessages::ambiguousModelSingleAnd,
781 StringMessageArg(fromName),
782 OrdinalMessageArg(fromIndex),
783 StringMessageArg(toName),
784 OrdinalMessageArg(to1Index),
785 OrdinalMessageArg(to2Index));
787 message(ParserMessages::ambiguousModelMultipleAnd,
788 StringMessageArg(fromName),
789 OrdinalMessageArg(fromIndex),
790 NumberMessageArg(andMatches),
791 StringMessageArg(toName),
792 OrdinalMessageArg(to1Index),
793 OrdinalMessageArg(to2Index));
798 // Check the compatibility of the attribute definition with
799 // the element definition.
801 void Parser::checkElementAttribute(const ElementType *e, size_t checkFrom)
803 const AttributeDefinitionList *attDef = e->attributeDef().pointer();
806 const ElementDefinition *edef = e->definition();
809 size_t attDefLength = attDef->size();
810 for (size_t i = checkFrom; i < attDefLength; i++) {
811 const AttributeDefinition *p = attDef->def(i);
815 && edef->declaredContent() == ElementDefinition::empty)
816 message(ParserMessages::notationEmpty, StringMessageArg(e->name()));
820 if (edef->omittedTagSpec() && !edef->canOmitEndTag()
821 && options().warnShould)
822 message(ParserMessages::conrefOmitEndTag, StringMessageArg(e->name()));
824 if (edef->declaredContent() == ElementDefinition::empty)
825 message(ParserMessages::conrefEmpty, StringMessageArg(e->name()));
829 ElementType *Parser::lookupCreateElement(const StringC &name)
831 ElementType *e = defDtd().lookupElementType(name);
834 message(ParserMessages::noSuchSourceElement, StringMessageArg(name));
836 e = new ElementType(name, defDtd().nElementTypeIndex());
837 defDtd().insertElementType(e);
843 RankStem *Parser::lookupCreateRankStem(const StringC &name)
845 RankStem *r = defDtd().lookupRankStem(name);
847 r = new RankStem(name, defDtd().nRankStem());
848 defDtd().insertRankStem(r);
849 const ElementType *e = defDtd().lookupElementType(name);
850 if (e && e->definition() != 0)
851 message(ParserMessages::rankStemGenericIdentifier, StringMessageArg(name));
856 Boolean Parser::parseExceptions(unsigned declInputLevel,
857 Ptr<ElementDefinition> &def)
861 allowExceptionsMdc(Param::mdc, Param::exclusions, Param::inclusions);
862 if (!parseParam(allowExceptionsMdc, declInputLevel, parm))
864 if (parm.type == Param::exclusions) {
865 def->setExclusions(parm.elementVector);
866 static AllowedParams allowInclusionsMdc(Param::mdc, Param::inclusions);
867 if (!parseParam(allowInclusionsMdc, declInputLevel, parm))
870 if (parm.type == Param::inclusions) {
871 def->setInclusions(parm.elementVector);
872 size_t nI = def->nInclusions();
873 size_t nE = def->nExclusions();
875 for (size_t i = 0; i < nI; i++) {
876 const ElementType *e = def->inclusion(i);
877 for (size_t j = 0; j < nE; j++)
878 if (def->exclusion(j) == e)
879 message(ParserMessages::excludeIncludeSame,
880 StringMessageArg(e->name()));
883 if (!parseParam(allowMdc, declInputLevel, parm))
889 Boolean Parser::parseAttlistDecl()
891 unsigned declInputLevel = inputLevel();
894 size_t idIndex = size_t(-1);
895 size_t notationIndex = size_t(-1);
896 Boolean anyCurrent = 0;
899 Vector<Attributed *> attributed;
900 if (!parseAttributed(declInputLevel, parm, attributed, isNotation))
902 Vector<CopyOwner<AttributeDefinition> > defs;
903 if (!parseParam(allowName, declInputLevel, parm))
906 StringC attributeName;
907 parm.token.swap(attributeName);
909 Boolean duplicate = 0;
911 for (i = 0; i < defs.size(); i++)
912 if (defs[i]->name() == attributeName) {
913 message(ParserMessages::duplicateAttributeDef,
914 StringMessageArg(attributeName));
918 Owner<DeclaredValue> declaredValue;
919 if (!parseDeclaredValue(declInputLevel, isNotation, parm, declaredValue))
922 if (declaredValue->isId()) {
923 if (idIndex != size_t(-1))
924 message(ParserMessages::multipleIdAttributes,
925 StringMessageArg(defs[idIndex]->name()));
926 idIndex = defs.size();
928 else if (declaredValue->isNotation()) {
929 if (notationIndex != size_t(-1))
930 message(ParserMessages::multipleNotationAttributes,
931 StringMessageArg(defs[notationIndex]->name()));
932 notationIndex = defs.size();
935 const Vector<StringC> *tokensPtr = declaredValue->getTokens();
937 size_t nTokens = tokensPtr->size();
938 Vector<StringC>::const_iterator tokens = tokensPtr->begin();
939 for (i = 0; i < nTokens; i++) {
940 for (size_t j = 0; j < defs.size(); j++)
941 if (defs[j]->containsToken(tokens[i])) {
942 message(ParserMessages::duplicateAttributeToken,
943 StringMessageArg(tokens[i]));
949 Owner<AttributeDefinition> def;
950 if (!parseDefaultValue(declInputLevel, isNotation, parm, attributeName,
951 declaredValue, def, anyCurrent))
953 if (haveDefLpd() && defLpd().type() == Lpd::simpleLink && !def->isFixed())
954 message(ParserMessages::simpleLinkFixedAttribute);
956 defs.resize(defs.size() + 1);
957 defs.back() = def.extract();
959 static AllowedParams allowNameMdc(Param::name, Param::mdc);
960 if (!parseParam(allowNameMdc, declInputLevel, parm))
962 } while (parm.type != Param::mdc);
963 if (attcnt > syntax().attcnt())
964 message(ParserMessages::attcnt,
965 NumberMessageArg(attcnt),
966 NumberMessageArg(syntax().attcnt()));
967 if (haveDefLpd() && !isNotation) {
968 if (defLpd().type() == Lpd::simpleLink) {
969 for (size_t i = 0; i < attributed.size(); i++) {
970 const ElementType *e = (const ElementType *)attributed[i];
972 if (e->name() == defLpd().sourceDtd()->name()) {
973 SimpleLpd &lpd = (SimpleLpd &)defLpd();
974 if (lpd.attributeDef().isNull())
975 lpd.setAttributeDef(new AttributeDefinitionList(defs, 0));
977 message(ParserMessages::duplicateAttlistElement,
978 StringMessageArg(e->name()));
981 message(ParserMessages::simpleLinkAttlistElement,
982 StringMessageArg(e->name()));
987 Ptr<AttributeDefinitionList>
988 adl(new AttributeDefinitionList(defs,
990 .allocAttributeDefinitionListIndex()));
991 for (size_t i = 0; i < attributed.size(); i++) {
992 const ElementType *e = (const ElementType *)attributed[i];
994 if (defComplexLpd().attributeDef(e).isNull())
995 defComplexLpd().setAttributeDef(e, adl);
997 message(ParserMessages::duplicateAttlistElement,
998 StringMessageArg(e->name()));
1004 Ptr<AttributeDefinitionList>
1005 adl(new AttributeDefinitionList(defs,
1007 .allocAttributeDefinitionListIndex(),
1011 for (size_t i = 0; i < attributed.size(); i++) {
1012 if (attributed[i]->attributeDef().isNull()) {
1013 attributed[i]->setAttributeDef(adl);
1015 ElementType *e = (ElementType *)attributed[i];
1016 if (e->definition() != 0)
1017 checkElementAttribute(e);
1020 else if (options().errorAfdr) {
1021 if (!hadAfdrDecl()) {
1022 message(ParserMessages::missingAfdrDecl);
1026 message(ParserMessages::duplicateAttlistNotation,
1027 StringMessageArg(((Notation *)attributed[i])->name()));
1029 message(ParserMessages::duplicateAttlistElement,
1030 StringMessageArg(((ElementType *)attributed[i])->name()));
1033 AttributeDefinitionList *curAdl;
1035 // Use block to make sure temporary gets destroyed.
1036 curAdl = attributed[i]->attributeDef().pointer();
1038 size_t oldSize = curAdl->size();
1039 if (curAdl->count() != 1) {
1040 Vector<CopyOwner<AttributeDefinition> > copy(oldSize);
1041 for (size_t j = 0; j < oldSize; j++)
1042 copy[j] = curAdl->def(j)->copy();
1043 Ptr<AttributeDefinitionList> adlCopy
1044 = new AttributeDefinitionList(copy,
1045 defDtd().allocAttributeDefinitionListIndex(),
1046 curAdl->anyCurrent(),
1048 curAdl->notationIndex());
1049 attributed[i]->setAttributeDef(adlCopy);
1050 curAdl = adlCopy.pointer();
1052 // FIXME check for multiple ID and NOTATION attributes
1053 for (size_t j = 0; j < adl->size(); j++) {
1055 if (!curAdl->attributeIndex(adl->def(j)->name(), tem))
1056 curAdl->append(adl->def(j)->copy());
1059 ElementType *e = (ElementType *)attributed[i];
1060 if (e->definition() != 0)
1061 checkElementAttribute(e, oldSize);
1066 if (currentMarkup()) {
1068 Vector<ConstPtr<Notation> > v(attributed.size());
1069 for (size_t i = 0; i < attributed.size(); i++)
1070 v[i] = (Notation *)attributed[i];
1072 .attlistNotationDecl(new (eventAllocator())
1073 AttlistNotationDeclEvent(v,
1078 Vector<const ElementType *> v(attributed.size());
1079 for (size_t i = 0; i < attributed.size(); i++)
1080 v[i] = (ElementType *)attributed[i];
1083 .linkAttlistDecl(new (eventAllocator())
1084 LinkAttlistDeclEvent(v,
1089 eventHandler().attlistDecl(new (eventAllocator())
1091 currentDtdPointer(),
1097 Dtd::EntityIter entityIter(defDtd().generalEntityIter());
1099 Ptr<Entity> entity(entityIter.next());
1100 if (entity.isNull())
1102 const ExternalDataEntity *external = entity->asExternalDataEntity();
1104 const Notation *entityNotation = external->notation();
1105 for (size_t i = 0; i < attributed.size(); i++)
1106 if ((Notation *)attributed[i] == entityNotation) {
1107 AttributeList attributes(entityNotation->attributeDef());
1108 attributes.finish(*this);
1109 ((ExternalDataEntity *)entity.pointer())
1110 ->setNotation((Notation *)attributed[i], attributes);
1119 Boolean Parser::parseAttributed(unsigned declInputLevel,
1121 Vector<Attributed *> &attributed,
1122 Boolean &isNotation)
1124 // There's a hack in getIndicatedReservedName allows #ALL as #ANY.
1125 static AllowedParams
1126 allowNameGroupNotation(Param::name,
1128 Param::indicatedReservedName + Syntax::rNOTATION);
1129 static AllowedParams
1130 allowNameGroupNotationAll(Param::name,
1132 Param::indicatedReservedName
1133 + Syntax::rNOTATION,
1134 Param::indicatedReservedName
1136 if (!parseParam(options().errorAfdr || haveDefLpd()
1137 ? allowNameGroupNotation
1138 : allowNameGroupNotationAll,
1139 declInputLevel, parm))
1141 if (parm.type == Param::indicatedReservedName + Syntax::rNOTATION) {
1143 static AllowedParams
1144 allowNameGroupAll(Param::name,
1146 Param::indicatedReservedName + Syntax::rANY);
1147 if (!parseParam(options().errorAfdr || haveDefLpd()
1148 ? allowNameNameGroup
1149 : allowNameGroupAll,
1150 declInputLevel, parm))
1152 if (parm.type == Param::nameGroup) {
1153 attributed.resize(parm.nameTokenVector.size());
1154 for (size_t i = 0; i < attributed.size(); i++)
1155 attributed[i] = lookupCreateNotation(parm.nameTokenVector[i].name);
1158 if (parm.type != Param::name && !hadAfdrDecl()) {
1159 message(ParserMessages::missingAfdrDecl);
1162 attributed.resize(1);
1164 = lookupCreateNotation(parm.type == Param::name
1166 : syntax().rniReservedName(Syntax::rANY));
1171 if (parm.type == Param::nameGroup) {
1172 attributed.resize(parm.nameTokenVector.size());
1173 for (size_t i = 0; i < attributed.size(); i++)
1174 attributed[i] = lookupCreateElement(parm.nameTokenVector[i].name);
1177 if (parm.type != Param::name && !hadAfdrDecl()) {
1178 message(ParserMessages::missingAfdrDecl);
1181 attributed.resize(1);
1183 = lookupCreateElement(parm.type == Param::name
1185 : syntax().rniReservedName(Syntax::rANY));
1191 Boolean Parser::parseDeclaredValue(unsigned declInputLevel,
1194 Owner<DeclaredValue> &declaredValue)
1196 static Param::Type declaredValues[] = {
1197 Param::reservedName + Syntax::rCDATA,
1198 Param::reservedName + Syntax::rENTITY,
1199 Param::reservedName + Syntax::rENTITIES,
1200 Param::reservedName + Syntax::rID,
1201 Param::reservedName + Syntax::rIDREF,
1202 Param::reservedName + Syntax::rIDREFS,
1203 Param::reservedName + Syntax::rNAME,
1204 Param::reservedName + Syntax::rNAMES,
1205 Param::reservedName + Syntax::rNMTOKEN,
1206 Param::reservedName + Syntax::rNMTOKENS,
1207 Param::reservedName + Syntax::rNUMBER,
1208 Param::reservedName + Syntax::rNUMBERS,
1209 Param::reservedName + Syntax::rNUTOKEN,
1210 Param::reservedName + Syntax::rNUTOKENS,
1211 Param::reservedName + Syntax::rNOTATION,
1212 Param::nameTokenGroup
1214 static AllowedParams allowDeclaredValue(declaredValues,
1215 SIZEOF(declaredValues));
1216 if (!parseParam(allowDeclaredValue, declInputLevel, parm))
1218 enum { asDataAttribute = 01, asLinkAttribute = 02 };
1219 unsigned allowedFlags = asDataAttribute|asLinkAttribute;
1220 switch (parm.type) {
1221 case Param::reservedName + Syntax::rCDATA:
1222 declaredValue = new CdataDeclaredValue;
1224 case Param::reservedName + Syntax::rENTITY:
1225 declaredValue = new EntityDeclaredValue(0);
1226 allowedFlags = asLinkAttribute;
1228 case Param::reservedName + Syntax::rENTITIES:
1229 declaredValue = new EntityDeclaredValue(1);
1230 allowedFlags = asLinkAttribute;
1232 case Param::reservedName + Syntax::rID:
1233 declaredValue = new IdDeclaredValue;
1236 case Param::reservedName + Syntax::rIDREF:
1237 declaredValue = new IdrefDeclaredValue(0);
1240 case Param::reservedName + Syntax::rIDREFS:
1241 declaredValue = new IdrefDeclaredValue(1);
1244 case Param::reservedName + Syntax::rNAME:
1246 = new TokenizedDeclaredValue(TokenizedDeclaredValue::name, 0);
1248 case Param::reservedName + Syntax::rNAMES:
1250 = new TokenizedDeclaredValue(TokenizedDeclaredValue::name, 1);
1252 case Param::reservedName + Syntax::rNMTOKEN:
1254 = new TokenizedDeclaredValue(TokenizedDeclaredValue::nameToken, 0);
1256 case Param::reservedName + Syntax::rNMTOKENS:
1258 = new TokenizedDeclaredValue(TokenizedDeclaredValue::nameToken, 1);
1260 case Param::reservedName + Syntax::rNUMBER:
1262 = new TokenizedDeclaredValue(TokenizedDeclaredValue::number, 0);
1264 case Param::reservedName + Syntax::rNUMBERS:
1266 = new TokenizedDeclaredValue(TokenizedDeclaredValue::number, 1);
1268 case Param::reservedName + Syntax::rNUTOKEN:
1270 = new TokenizedDeclaredValue(TokenizedDeclaredValue::numberToken, 0);
1272 case Param::reservedName + Syntax::rNUTOKENS:
1274 = new TokenizedDeclaredValue(TokenizedDeclaredValue::numberToken, 1);
1276 case Param::reservedName + Syntax::rNOTATION:
1278 static AllowedParams allowNameGroup(Param::nameGroup);
1279 if (!parseParam(allowNameGroup, declInputLevel, parm))
1281 Vector<StringC> group(parm.nameTokenVector.size());
1282 for (size_t i = 0; i < group.size(); i++)
1283 parm.nameTokenVector[i].name.swap(group[i]);
1284 declaredValue = new NotationDeclaredValue(group);
1288 case Param::nameTokenGroup:
1290 Vector<StringC> group(parm.nameTokenVector.size());
1291 for (size_t i = 0; i < group.size(); i++)
1292 parm.nameTokenVector[i].name.swap(group[i]);
1293 declaredValue = new NameTokenGroupDeclaredValue(group);
1300 if (!(allowedFlags & asDataAttribute))
1301 message(ParserMessages::dataAttributeDeclaredValue);
1303 else if (haveDefLpd() && !isNotation && !(allowedFlags & asLinkAttribute))
1304 message(ParserMessages::linkAttributeDeclaredValue);
1308 Boolean Parser::parseDefaultValue(unsigned declInputLevel,
1311 const StringC &attributeName,
1312 Owner<DeclaredValue> &declaredValue,
1313 Owner<AttributeDefinition> &def,
1314 Boolean &anyCurrent)
1317 static AllowedParams
1318 allowDefaultValue(Param::indicatedReservedName + Syntax::rFIXED,
1319 Param::indicatedReservedName + Syntax::rREQUIRED,
1320 Param::indicatedReservedName + Syntax::rCURRENT,
1321 Param::indicatedReservedName + Syntax::rCONREF,
1322 Param::indicatedReservedName + Syntax::rIMPLIED,
1323 Param::attributeValue,
1324 Param::attributeValueLiteral);
1325 static AllowedParams
1326 allowTokenDefaultValue(Param::indicatedReservedName + Syntax::rFIXED,
1327 Param::indicatedReservedName + Syntax::rREQUIRED,
1328 Param::indicatedReservedName + Syntax::rCURRENT,
1329 Param::indicatedReservedName + Syntax::rCONREF,
1330 Param::indicatedReservedName + Syntax::rIMPLIED,
1331 Param::attributeValue,
1332 Param::tokenizedAttributeValueLiteral);
1333 if (!parseParam(declaredValue->tokenized()
1334 ? allowTokenDefaultValue
1335 : allowDefaultValue, declInputLevel, parm))
1337 switch (parm.type) {
1338 case Param::indicatedReservedName + Syntax::rFIXED:
1340 static AllowedParams allowValue(Param::attributeValue,
1341 Param::attributeValueLiteral);
1342 static AllowedParams
1343 allowTokenValue(Param::attributeValue,
1344 Param::tokenizedAttributeValueLiteral);
1345 if (!parseParam(declaredValue->tokenized()
1347 : allowValue, declInputLevel, parm))
1349 unsigned specLength = 0;
1350 AttributeValue *value = declaredValue->makeValue(parm.literalText,
1354 if (declaredValue->isId())
1355 message(ParserMessages::idDeclaredValue);
1356 def = new FixedAttributeDefinition(attributeName,
1357 declaredValue.extract(),
1361 case Param::attributeValue:
1362 case Param::attributeValueLiteral:
1363 case Param::tokenizedAttributeValueLiteral:
1365 unsigned specLength = 0;
1366 AttributeValue *value = declaredValue->makeValue(parm.literalText,
1370 if (declaredValue->isId())
1371 message(ParserMessages::idDeclaredValue);
1372 def = new DefaultAttributeDefinition(attributeName,
1373 declaredValue.extract(),
1377 case Param::indicatedReservedName + Syntax::rREQUIRED:
1378 def = new RequiredAttributeDefinition(attributeName,
1379 declaredValue.extract());
1381 case Param::indicatedReservedName + Syntax::rCURRENT:
1383 if (declaredValue->isId())
1384 message(ParserMessages::idDeclaredValue);
1385 def = new CurrentAttributeDefinition(attributeName,
1386 declaredValue.extract(),
1387 defDtd().allocCurrentAttributeIndex());
1389 message(ParserMessages::dataAttributeDefaultValue);
1390 else if (haveDefLpd())
1391 message(ParserMessages::linkAttributeDefaultValue);
1393 case Param::indicatedReservedName + Syntax::rCONREF:
1394 if (declaredValue->isId())
1395 message(ParserMessages::idDeclaredValue);
1396 def = new ConrefAttributeDefinition(attributeName,
1397 declaredValue.extract());
1399 message(ParserMessages::dataAttributeDefaultValue);
1400 else if (haveDefLpd())
1401 message(ParserMessages::linkAttributeDefaultValue);
1403 case Param::indicatedReservedName + Syntax::rIMPLIED:
1404 def = new ImpliedAttributeDefinition(attributeName,
1405 declaredValue.extract());
1413 // parm contains either system or public
1415 Boolean Parser::parseExternalId(const AllowedParams &sysidAllow,
1416 const AllowedParams &endAllow,
1417 unsigned declInputLevel,
1421 id.setLocation(currentLocation());
1422 if (parm.type == Param::reservedName + Syntax::rPUBLIC) {
1423 static AllowedParams allowMinimumLiteral(Param::minimumLiteral);
1424 if (!parseParam(allowMinimumLiteral, declInputLevel, parm))
1426 const MessageType1 *err;
1427 if (!id.setPublic(parm.literalText, sd().docCharset(), syntax().space(),
1431 StringMessageArg(*id.publicIdString()));
1433 if (!parseParam(sysidAllow, declInputLevel, parm))
1435 if (parm.type == Param::systemIdentifier) {
1436 id.setSystem(parm.literalText);
1437 if (!parseParam(endAllow, declInputLevel, parm))
1443 Boolean Parser::parseNotationDecl()
1445 unsigned declInputLevel = inputLevel();
1447 if (!parseParam(allowName, declInputLevel, parm))
1449 Notation *nt = lookupCreateNotation(parm.token);
1451 message(ParserMessages::duplicateNotationDeclaration,
1452 StringMessageArg(parm.token));
1453 static AllowedParams
1454 allowPublicSystem(Param::reservedName + Syntax::rPUBLIC,
1455 Param::reservedName + Syntax::rSYSTEM);
1456 if (!parseParam(allowPublicSystem, declInputLevel, parm))
1460 static AllowedParams allowSystemIdentifierMdc(Param::systemIdentifier,
1464 if (!parseExternalId(allowSystemIdentifierMdc, allowMdc,
1465 declInputLevel, parm, id))
1467 if (sd().formal()) {
1468 PublicId::TextClass textClass;
1469 const PublicId *publicId = id.publicId();
1471 && publicId->getTextClass(textClass)
1472 && textClass != PublicId::NOTATION)
1473 message(ParserMessages::notationIdentifierTextClass);
1475 if (!nt->defined()) {
1476 nt->setExternalId(id, markupLocation());
1477 nt->generateSystemId(*this);
1478 if (currentMarkup())
1479 eventHandler().notationDecl(new (eventAllocator())
1480 NotationDeclEvent(nt, markupLocation(),
1486 Boolean Parser::parseEntityDecl()
1488 unsigned declInputLevel = inputLevel();
1491 static AllowedParams
1492 allowEntityNamePero(Param::entityName,
1493 Param::indicatedReservedName + Syntax::rDEFAULT,
1496 if (!parseParam(allowEntityNamePero, declInputLevel, parm))
1499 Entity::DeclType declType;
1500 StringC name; // empty for default entity
1501 if (parm.type == Param::pero) {
1502 declType = Entity::parameterEntity;
1503 static AllowedParams allowParamEntityName(Param::paramEntityName);
1504 if (!parseParam(allowParamEntityName, declInputLevel, parm))
1506 parm.token.swap(name);
1509 declType = Entity::generalEntity;
1510 if (parm.type == Param::entityName)
1511 parm.token.swap(name);
1513 static AllowedParams
1514 allowEntityTextType(Param::paramLiteral,
1515 Param::reservedName + Syntax::rCDATA,
1516 Param::reservedName + Syntax::rSDATA,
1517 Param::reservedName + Syntax::rPI,
1518 Param::reservedName + Syntax::rSTARTTAG,
1519 Param::reservedName + Syntax::rENDTAG,
1520 Param::reservedName + Syntax::rMS,
1521 Param::reservedName + Syntax::rMD,
1522 Param::reservedName + Syntax::rSYSTEM,
1523 Param::reservedName + Syntax::rPUBLIC);
1525 if (!parseParam(allowEntityTextType, declInputLevel, parm))
1527 Location typeLocation(currentLocation());
1528 Entity::DataType dataType = Entity::sgmlText;
1529 InternalTextEntity::Bracketed bracketed = InternalTextEntity::none;
1530 switch (parm.type) {
1531 case Param::reservedName + Syntax::rSYSTEM:
1532 case Param::reservedName + Syntax::rPUBLIC:
1533 return parseExternalEntity(name, declType, declInputLevel, parm);
1534 case Param::reservedName + Syntax::rCDATA:
1535 dataType = Entity::cdata;
1537 case Param::reservedName + Syntax::rSDATA:
1538 dataType = Entity::sdata;
1540 case Param::reservedName + Syntax::rPI:
1541 dataType = Entity::pi;
1543 case Param::reservedName + Syntax::rSTARTTAG:
1544 bracketed = InternalTextEntity::starttag;
1546 case Param::reservedName + Syntax::rENDTAG:
1547 bracketed = InternalTextEntity::endtag;
1549 case Param::reservedName + Syntax::rMS:
1550 bracketed = InternalTextEntity::ms;
1552 case Param::reservedName + Syntax::rMD:
1553 bracketed = InternalTextEntity::md;
1556 if (parm.type != Param::paramLiteral) {
1557 if (!parseParam(allowParamLiteral, declInputLevel, parm))
1561 parm.literalText.swap(text);
1562 if (bracketed != InternalTextEntity::none) {
1565 switch (bracketed) {
1566 case InternalTextEntity::starttag:
1567 open = syntax().delimGeneral(Syntax::dSTAGO);
1568 close = syntax().delimGeneral(Syntax::dTAGC);
1570 case InternalTextEntity::endtag:
1571 open = syntax().delimGeneral(Syntax::dETAGO);
1572 close = syntax().delimGeneral(Syntax::dTAGC);
1574 case InternalTextEntity::ms:
1575 open = syntax().delimGeneral(Syntax::dMDO);
1576 open += syntax().delimGeneral(Syntax::dDSO);
1577 close = syntax().delimGeneral(Syntax::dMSC);
1578 close += syntax().delimGeneral(Syntax::dMDC);
1580 case InternalTextEntity::md:
1581 open = syntax().delimGeneral(Syntax::dMDO);
1582 close = syntax().delimGeneral(Syntax::dMDC);
1587 text.insertChars(open, Location(new BracketOrigin(typeLocation,
1588 BracketOrigin::open),
1590 text.addChars(close, Location(new BracketOrigin(typeLocation,
1591 BracketOrigin::close),
1593 if (text.size() > syntax().litlen()
1594 && text.size() - open.size() - close.size() <= syntax().litlen())
1595 message(ParserMessages::bracketedLitlen,
1596 NumberMessageArg(syntax().litlen()));
1598 if (!parseParam(allowMdc, declInputLevel, parm))
1600 if (declType == Entity::parameterEntity
1601 && (dataType == Entity::cdata || dataType == Entity::sdata)) {
1602 message(ParserMessages::internalParameterDataEntity,
1603 StringMessageArg(name));
1609 entity = new InternalCdataEntity(name, markupLocation(), text);
1612 entity = new InternalSdataEntity(name, markupLocation(), text);
1615 entity = new PiEntity(name, declType, markupLocation(), text);
1617 case Entity::sgmlText:
1618 entity = new InternalTextEntity(name, declType, markupLocation(), text, bracketed);
1624 maybeDefineEntity(entity);
1628 Boolean Parser::parseExternalEntity(StringC &name,
1629 Entity::DeclType declType,
1630 unsigned declInputLevel,
1633 static AllowedParams
1634 allowSystemIdentifierEntityTypeMdc(Param::systemIdentifier,
1635 Param::reservedName + Syntax::rSUBDOC,
1636 Param::reservedName + Syntax::rCDATA,
1637 Param::reservedName + Syntax::rSDATA,
1638 Param::reservedName + Syntax::rNDATA,
1640 static AllowedParams
1641 allowEntityTypeMdc(Param::reservedName + Syntax::rSUBDOC,
1642 Param::reservedName + Syntax::rCDATA,
1643 Param::reservedName + Syntax::rSDATA,
1644 Param::reservedName + Syntax::rNDATA,
1648 if (!parseExternalId(allowSystemIdentifierEntityTypeMdc, allowEntityTypeMdc,
1649 declInputLevel, parm, id))
1651 if (parm.type == Param::mdc) {
1652 maybeDefineEntity(new ExternalTextEntity(name, declType, markupLocation(),
1657 if (parm.type == Param::reservedName + Syntax::rSUBDOC) {
1658 if (sd().subdoc() == 0)
1659 message(ParserMessages::subdocEntity, StringMessageArg(name));
1660 if (!parseParam(allowMdc, declInputLevel, parm))
1662 entity = new SubdocEntity(name, markupLocation(), id);
1665 Entity::DataType dataType;
1666 switch (parm.type) {
1667 case Param::reservedName + Syntax::rCDATA:
1668 dataType = Entity::cdata;
1670 case Param::reservedName + Syntax::rSDATA:
1671 dataType = Entity::sdata;
1673 case Param::reservedName + Syntax::rNDATA:
1674 dataType = Entity::ndata;
1679 if (!parseParam(allowName, declInputLevel, parm))
1681 ConstPtr<Notation> notation(lookupCreateNotation(parm.token));
1682 if (!parseParam(allowDsoMdc, declInputLevel, parm))
1684 AttributeList attributes(notation->attributeDef());
1685 if (parm.type == Param::dso) {
1686 if (attributes.size() == 0)
1687 message(ParserMessages::notationNoAttributes,
1688 StringMessageArg(notation->name()));
1689 Boolean netEnabling;
1690 if (!parseAttributeSpec(1, attributes, netEnabling))
1692 if (attributes.nSpec() == 0)
1693 message(ParserMessages::emptyDataAttributeSpec);
1694 if (!parseParam(allowMdc, declInputLevel, parm))
1698 attributes.finish(*this);
1699 entity = new ExternalDataEntity(name, dataType, markupLocation(), id, notation,
1702 if (declType == Entity::parameterEntity) {
1703 message(ParserMessages::externalParameterDataSubdocEntity,
1704 StringMessageArg(name));
1707 maybeDefineEntity(entity);
1711 Notation *Parser::lookupCreateNotation(const StringC &name)
1713 Ptr<Notation> nt = defDtd().lookupNotation(name);
1715 nt = new Notation(name, defDtd().namePointer(), defDtd().isBase());
1716 defDtd().insertNotation(nt);
1718 return nt.pointer();
1721 void Parser::maybeDefineEntity(const Ptr<Entity> &entity)
1723 Dtd &dtd = defDtd();
1725 entity->setDeclIn(dtd.namePointer(),
1727 defLpd().namePointer(),
1730 entity->setDeclIn(dtd.namePointer(), dtd.isBase());
1731 Boolean ignored = 0;
1732 if (entity->name().size() == 0) {
1733 const Entity *oldEntity = dtd.defaultEntity().pointer();
1735 || (!oldEntity->declInActiveLpd() && entity->declInActiveLpd()))
1736 dtd.setDefaultEntity(entity, *this);
1739 if (options().warnDuplicateEntity)
1740 message(ParserMessages::duplicateEntityDeclaration,
1741 StringMessageArg(syntax().rniReservedName(Syntax::rDEFAULT)));
1745 Ptr<Entity> oldEntity = dtd.insertEntity(entity);
1746 if (oldEntity.isNull())
1747 entity->generateSystemId(*this);
1748 else if (oldEntity->defaulted()) {
1749 dtd.insertEntity(entity, 1);
1750 message(ParserMessages::defaultedEntityDefined,
1751 StringMessageArg(entity->name()));
1752 entity->generateSystemId(*this);
1755 if (entity->declInActiveLpd() && !oldEntity->declInActiveLpd()) {
1756 dtd.insertEntity(entity, 1);
1757 entity->generateSystemId(*this);
1761 if (options().warnDuplicateEntity)
1762 message(entity->declType() == Entity::parameterEntity
1763 ? ParserMessages::duplicateParameterEntityDeclaration
1764 : ParserMessages::duplicateEntityDeclaration,
1765 StringMessageArg(entity->name()));
1769 if (currentMarkup())
1770 eventHandler().entityDecl(new (eventAllocator())
1771 EntityDeclEvent(entity, ignored,
1776 Boolean Parser::parseShortrefDecl()
1778 if (!defDtd().isBase())
1779 message(ParserMessages::shortrefOnlyInBaseDtd);
1781 unsigned declInputLevel = inputLevel();
1784 if (!parseParam(allowName, declInputLevel, parm))
1786 ShortReferenceMap *map = lookupCreateMap(parm.token);
1788 if (map->defined()) {
1789 message(ParserMessages::duplicateShortrefDeclaration,
1790 StringMessageArg(parm.token),
1791 map->defLocation());
1795 map->setDefLocation(markupLocation());
1796 if (!parseParam(allowParamLiteral, declInputLevel, parm))
1798 Vector<StringC> vec;
1800 StringC delim(parm.literalText.string());
1801 const SubstTable<Char> *table = instanceSyntax().generalSubstTable();
1802 for (size_t i = 0; i < delim.size(); i++)
1803 table->subst(delim[i]);
1805 if (!defDtd().shortrefIndex(delim, instanceSyntax(), srIndex)) {
1806 message(ParserMessages::unknownShortrefDelim,
1807 StringMessageArg(prettifyDelim(delim)));
1810 static AllowedParams allowEntityName(Param::entityName);
1811 if (!parseParam(allowEntityName, declInputLevel, parm))
1814 if (srIndex >= vec.size())
1815 vec.resize(srIndex + 1);
1816 if (vec[srIndex].size() > 0) {
1817 message(ParserMessages::delimDuplicateMap,
1818 StringMessageArg(prettifyDelim(delim)));
1822 parm.token.swap(vec[srIndex]);
1824 static AllowedParams allowParamLiteralMdc(Param::paramLiteral, Param::mdc);
1825 if (!parseParam(allowParamLiteralMdc, declInputLevel, parm))
1827 } while (parm.type != Param::mdc);
1829 map->setNameMap(vec);
1830 if (currentMarkup())
1831 eventHandler().shortrefDecl(new (eventAllocator())
1832 ShortrefDeclEvent(map,
1833 currentDtdPointer(),
1840 StringC Parser::prettifyDelim(const StringC &delim)
1842 StringC prettyDelim;
1843 for (size_t i = 0; i < delim.size(); i++) {
1844 const StringC *nameP;
1845 if (syntax().charFunctionName(delim[i], nameP)) {
1846 prettyDelim += syntax().delimGeneral(Syntax::dCRO);
1847 prettyDelim += *nameP;
1848 prettyDelim += syntax().delimGeneral(Syntax::dREFC);
1851 prettyDelim += delim[i];
1856 ShortReferenceMap *Parser::lookupCreateMap(const StringC &name)
1858 ShortReferenceMap *map = defDtd().lookupShortReferenceMap(name);
1860 map = new ShortReferenceMap(name);
1861 defDtd().insertShortReferenceMap(map);
1866 Boolean Parser::parseUsemapDecl()
1868 if (!inInstance() && !defDtd().isBase())
1869 message(ParserMessages::usemapOnlyInBaseDtd);
1871 unsigned declInputLevel = inputLevel();
1873 static AllowedParams
1874 allowNameEmpty(Param::name,
1875 Param::indicatedReservedName + Syntax::rEMPTY);
1876 if (!parseParam(allowNameEmpty, declInputLevel, parm))
1878 const ShortReferenceMap *map;
1879 if (parm.type == Param::name) {
1881 map = currentDtd().lookupShortReferenceMap(parm.token);
1883 message(ParserMessages::undefinedShortrefMapInstance,
1884 StringMessageArg(parm.token));
1887 ShortReferenceMap *tem = lookupCreateMap(parm.token);
1894 static AllowedParams
1895 allowNameNameGroupMdc(Param::name, Param::nameGroup, Param::mdc);
1896 if (!parseParam(allowNameNameGroupMdc, declInputLevel, parm))
1898 if (parm.type != Param::mdc) {
1900 message(ParserMessages::usemapAssociatedElementTypeInstance);
1901 if (!parseParam(allowMdc, declInputLevel, parm))
1905 Vector<const ElementType *> v;
1906 if (parm.type == Param::name) {
1907 ElementType *e = lookupCreateElement(parm.token);
1913 v.resize(parm.nameTokenVector.size());
1914 for (size_t i = 0; i < parm.nameTokenVector.size(); i++) {
1916 = lookupCreateElement(parm.nameTokenVector[i].name);
1922 if (!parseParam(allowMdc, declInputLevel, parm))
1924 if (currentMarkup())
1925 eventHandler().usemap(new (eventAllocator())
1927 currentDtdPointer(),
1934 message(ParserMessages::usemapAssociatedElementTypeDtd);
1936 if (map != &theEmptyMap && !map->defined())
1937 message(ParserMessages::undefinedShortrefMapInstance,
1938 StringMessageArg(map->name()));
1940 if (currentMarkup()) {
1941 Vector<const ElementType *> v;
1942 eventHandler().usemap(new (eventAllocator())
1944 currentDtdPointer(),
1948 currentElement().setMap(map);
1955 Boolean Parser::parseDoctypeDeclStart()
1957 if (hadDtd() && !sd().concur() && !sd().explicitLink())
1958 message(ParserMessages::multipleDtds);
1960 message(ParserMessages::dtdAfterLpd);
1961 unsigned declInputLevel = inputLevel();
1964 if (!parseParam(allowName, declInputLevel, parm))
1967 parm.token.swap(name);
1968 if (!lookupDtd(name).isNull())
1969 message(ParserMessages::duplicateDtd, StringMessageArg(name));
1970 static AllowedParams
1971 allowPublicSystemDsoMdc(Param::reservedName + Syntax::rPUBLIC,
1972 Param::reservedName + Syntax::rSYSTEM,
1975 if (!parseParam(allowPublicSystemDsoMdc, declInputLevel, parm))
1977 ConstPtr<Entity> entity;
1978 if (parm.type == Param::reservedName + Syntax::rPUBLIC
1979 || parm.type == Param::reservedName + Syntax::rSYSTEM) {
1980 static AllowedParams allowSystemIdentifierDsoMdc(Param::systemIdentifier,
1981 Param::dso, Param::mdc);
1983 if (!parseExternalId(allowSystemIdentifierDsoMdc, allowDsoMdc,
1984 declInputLevel, parm, id))
1987 = new ExternalTextEntity(name, Entity::doctype, markupLocation(), id);
1988 tem->generateSystemId(*this);
1992 .externalEntityDecl(new (eventAllocator())
1993 ExternalEntityDeclEvent(entity, 0));
1996 else if (parm.type == Param::mdc) {
1997 message(ParserMessages::noDtdSubset, StringMessageArg(name));
2000 // Discard mdc or dso
2001 if (currentMarkup())
2002 currentMarkup()->resize(currentMarkup()->size() - 1);
2003 eventHandler().startDtd(new (eventAllocator())
2004 StartDtdEvent(name, entity, parm.type == Param::dso,
2008 if (parm.type == Param::mdc) {
2010 currentInput()->ungetToken();
2011 // reference the entity
2012 Ptr<EntityOrigin> origin
2013 = new (internalAllocator()) EntityOrigin(entity, currentLocation());
2014 entity->dsReference(*this, origin);
2015 if (inputLevel() == 1) { // reference failed
2016 (void)parseDoctypeDeclEnd();
2020 else if (!entity.isNull())
2021 setDsEntity(entity);
2022 setPhase(declSubsetPhase);
2026 Boolean Parser::implyDtd(const StringC &gi)
2029 // The null location indicates that this is a fake entity.
2030 ConstPtr<Entity> entity(new ExternalTextEntity(gi,
2034 // Don't use Entity::generateSystemId because we don't want an error
2038 if (!entityCatalog().lookup(*entity, syntax(), sd().docCharset(),
2039 messenger(), str)) {
2040 if (!entityCatalog().defaultDoctype(sd().docCharset(),
2045 for (size_t i = 0; i < name.size(); i++)
2046 syntax().generalSubstTable()->subst(name[i]);
2050 id.setEffectiveSystem(str);
2051 entity = new ExternalTextEntity(name,
2056 declStr += syntax().delimGeneral(Syntax::dMDO);
2057 declStr += syntax().reservedName(Syntax::rDOCTYPE);
2058 declStr += syntax().space();
2060 declStr += syntax().space();
2061 declStr += syntax().reservedName(Syntax::rSYSTEM);
2062 declStr += syntax().delimGeneral(Syntax::dMDC);
2063 message(ParserMessages::implyingDtd, StringMessageArg(declStr));
2064 Ptr<EntityOrigin> origin
2065 = new (internalAllocator()) EntityOrigin(entity, currentLocation());
2066 startMarkup(eventsWanted().wantPrologMarkup(), Location());
2067 if (currentMarkup()) {
2068 currentMarkup()->addDelim(Syntax::dMDO);
2069 currentMarkup()->addReservedName(Syntax::rDOCTYPE,
2070 syntax().reservedName(Syntax::rDOCTYPE));
2071 currentMarkup()->addS(syntax().space());
2072 currentMarkup()->addName(name.data(), name.size());
2073 currentMarkup()->addS(syntax().space());
2074 currentMarkup()->addReservedName(Syntax::rSYSTEM,
2075 syntax().reservedName(Syntax::rSYSTEM));
2077 eventHandler().startDtd(new (eventAllocator())
2078 StartDtdEvent(name, entity, 0,
2082 entity->dsReference(*this, origin);
2083 if (inputLevel() == 1) {
2084 parseDoctypeDeclEnd(1);
2087 setPhase(declSubsetPhase);
2091 Boolean Parser::parseDoctypeDeclEnd(Boolean fake)
2094 Ptr<Dtd> tem(defDtdPointer());
2097 startMarkup(eventsWanted().wantPrologMarkup(), Location());
2098 if (currentMarkup())
2099 currentMarkup()->addDelim(Syntax::dMDC);
2102 startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2104 // End DTD before parsing final param so parameter entity reference
2105 // not allowed between ] and >.
2106 if (!parseParam(allowMdc, inputLevel(), parm))
2109 eventHandler().endDtd(new (eventAllocator()) EndDtdEvent(tem,
2113 Char c = syntax().standardFunction(Syntax::fRE);
2114 eventHandler().sSep(new (eventAllocator())
2115 SSepEvent(&c, 1, Location(), 1));
2120 void Parser::checkDtd(Dtd &dtd)
2123 addNeededShortrefs(dtd, instanceSyntax());
2124 if (!options().errorAfdr)
2125 addCommonAttributes(dtd);
2126 Dtd::ElementTypeIter elementIter(dtd.elementTypeIter());
2128 ConstPtr<ElementDefinition> def;
2130 while ((p = elementIter.next()) != 0) {
2131 if (p->definition() == 0) {
2132 if (p->name() == dtd.name())
2133 message(ParserMessages::documentElementUndefined);
2134 else if (options().warnUndefinedElement)
2135 message(ParserMessages::dtdUndefinedElement, StringMessageArg(p->name()));
2137 def = new ElementDefinition(currentLocation(),
2138 ElementDefinition::undefinedIndex,
2139 (ElementDefinition::omitStart
2140 |ElementDefinition::omitEnd),
2141 ElementDefinition::any);
2142 p->setElementDefinition(def, i++);
2144 const ShortReferenceMap *map = p->map();
2145 if (map != 0 && map != &theEmptyMap && !map->defined()) {
2146 message(ParserMessages::undefinedShortrefMapDtd,
2147 StringMessageArg(map->name()),
2148 StringMessageArg(p->name()));
2152 Dtd::ConstEntityIter entityIter(((const Dtd &)dtd).generalEntityIter());
2154 ConstPtr<Entity> entity(entityIter.next());
2155 if (entity.isNull())
2157 const ExternalDataEntity *external = entity->asExternalDataEntity();
2159 const Notation *notation = external->notation();
2160 if (!notation->defined()) {
2161 setNextLocation(external->defLocation());
2162 message(ParserMessages::entityNotationUndefined,
2163 StringMessageArg(notation->name()),
2164 StringMessageArg(external->name()));
2168 Dtd::NotationIter notationIter(dtd.notationIter());
2170 ConstPtr<Notation> notation(notationIter.next());
2171 if (notation.isNull())
2173 if (!notation->defined() && !notation->attributeDef().isNull())
2174 message(ParserMessages::attlistNotationUndefined,
2175 StringMessageArg(notation->name()));
2177 Dtd::ShortReferenceMapIter mapIter(dtd.shortReferenceMapIter());
2178 int nShortref = dtd.nShortref();
2180 ShortReferenceMap *map = mapIter.next();
2183 Vector<ConstPtr<Entity> > entityMap(nShortref);
2184 for (i = 0; i < nShortref; i++) {
2185 const StringC *entityName = map->entityName(i);
2187 ConstPtr<Entity> entity
2188 = lookupEntity(0, *entityName, map->defLocation(), 0);
2189 if (entity.isNull()) {
2190 setNextLocation(map->defLocation());
2191 message(ParserMessages::mapEntityUndefined,
2192 StringMessageArg(*entityName),
2193 StringMessageArg(map->name()));
2196 if (entity->defaulted() && options().warnDefaultEntityReference) {
2197 setNextLocation(map->defLocation());
2198 message(ParserMessages::mapDefaultEntity,
2199 StringMessageArg(*entityName),
2200 StringMessageArg(map->name()));
2202 entityMap[i] = entity;
2206 map->setEntityMap(entityMap);
2207 if (options().warnUnusedMap && !map->used()) {
2208 setNextLocation(map->defLocation());
2209 message(ParserMessages::unusedMap, StringMessageArg(map->name()));
2212 if (options().warnUnusedParam) {
2213 Dtd::ConstEntityIter entityIter(((const Dtd &)dtd).parameterEntityIter());
2215 ConstPtr<Entity> entity(entityIter.next());
2216 if (entity.isNull())
2218 if (!entity->used() && !maybeStatusKeyword(*entity)) {
2219 setNextLocation(entity->defLocation());
2220 message(ParserMessages::unusedParamEntity,
2221 StringMessageArg(entity->name()));
2227 void Parser::addCommonAttributes(Dtd &dtd)
2229 Ptr<AttributeDefinitionList> commonAdl[2];
2231 ElementType *e = dtd.removeElementType(syntax()
2232 .rniReservedName(Syntax::rANY));
2234 commonAdl[0] = e->attributeDef();
2239 Ptr<Notation> allNotation
2240 = dtd.removeNotation(syntax().rniReservedName(Syntax::rANY));
2241 if (!allNotation.isNull())
2242 commonAdl[1] = allNotation->attributeDef();
2244 Dtd::ElementTypeIter elementIter(dtd.elementTypeIter());
2245 Dtd::NotationIter notationIter(dtd.notationIter());
2246 Vector<PackedBoolean> doneAdl(dtd.nAttributeDefinitionList(),
2248 for (int isNotation = 0; isNotation < 2; isNotation++) {
2249 if (!commonAdl[isNotation].isNull()) {
2250 doneAdl[commonAdl[isNotation]->index()] = 1;
2254 a = elementIter.next();
2256 a = notationIter.next().pointer();
2259 Ptr<AttributeDefinitionList> adl = a->attributeDef();
2261 a->setAttributeDef(commonAdl[isNotation]);
2262 else if (!doneAdl[adl->index()]) {
2263 doneAdl[adl->index()] = 1;
2264 for (size_t j = 0; j < commonAdl[isNotation]->size(); j++) {
2266 if (!adl->attributeIndex(commonAdl[isNotation]->def(j)->name(),
2268 adl->append(commonAdl[isNotation]->def(j)->copy());
2276 Boolean Parser::maybeStatusKeyword(const Entity &entity)
2278 const InternalEntity *internal = entity.asInternalEntity();
2281 const StringC &text = internal->string();
2282 static const Syntax::ReservedName statusKeywords[] = {
2283 Syntax::rINCLUDE, Syntax::rIGNORE
2285 for (size_t i = 0; i < SIZEOF(statusKeywords); i++) {
2286 const StringC &keyword = instanceSyntax().reservedName(statusKeywords[i]);
2288 while (j < text.size() && instanceSyntax().isS(text[j]))
2291 while (j < text.size()
2292 && k < keyword.size()
2293 && ((*instanceSyntax().generalSubstTable())[text[j]]
2296 if (k == keyword.size()) {
2297 while (j < text.size() && instanceSyntax().isS(text[j]))
2299 if (j == text.size())
2306 Boolean Parser::parseLinktypeDeclStart()
2308 if (baseDtd().isNull())
2309 message(ParserMessages::lpdBeforeBaseDtd);
2310 unsigned declInputLevel = inputLevel();
2313 if (!parseParam(allowName, declInputLevel, parm))
2316 parm.token.swap(name);
2317 if (!lookupDtd(name).isNull())
2318 message(ParserMessages::duplicateDtdLpd, StringMessageArg(name));
2319 else if (!lookupLpd(name).isNull())
2320 message(ParserMessages::duplicateLpd, StringMessageArg(name));
2321 static AllowedParams
2322 allowSimpleName(Param::indicatedReservedName + Syntax::rSIMPLE,
2324 if (!parseParam(allowSimpleName, declInputLevel, parm))
2328 if (parm.type == Param::indicatedReservedName + Syntax::rSIMPLE) {
2330 sourceDtd = baseDtd();
2331 if (sourceDtd.isNull())
2332 sourceDtd = new Dtd(StringC(), 1);
2336 sourceDtd = lookupDtd(parm.token);
2337 if (sourceDtd.isNull()) {
2338 message(ParserMessages::noSuchDtd, StringMessageArg(parm.token));
2339 sourceDtd = new Dtd(parm.token, 0);
2342 static AllowedParams
2343 allowImpliedName(Param::indicatedReservedName + Syntax::rIMPLIED,
2345 if (!parseParam(allowImpliedName, declInputLevel, parm))
2348 Boolean implied = 0;
2349 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2351 if (!sd().simpleLink())
2352 message(ParserMessages::simpleLinkFeature);
2356 if (!sd().implicitLink())
2357 message(ParserMessages::implicitLinkFeature);
2362 message(ParserMessages::simpleLinkResultNotImplied);
2364 if (!sd().explicitLink())
2365 message(ParserMessages::explicitLinkFeature);
2366 resultDtd = lookupDtd(parm.token);
2367 if (resultDtd.isNull())
2368 message(ParserMessages::noSuchDtd, StringMessageArg(parm.token));
2371 static AllowedParams
2372 allowPublicSystemDsoMdc(Param::reservedName + Syntax::rPUBLIC,
2373 Param::reservedName + Syntax::rSYSTEM,
2376 if (!parseParam(allowPublicSystemDsoMdc, declInputLevel, parm))
2378 ConstPtr<Entity> entity;
2379 if (parm.type == Param::reservedName + Syntax::rPUBLIC
2380 || parm.type == Param::reservedName + Syntax::rSYSTEM) {
2381 static AllowedParams allowSystemIdentifierDsoMdc(Param::systemIdentifier,
2382 Param::dso, Param::mdc);
2384 if (!parseExternalId(allowSystemIdentifierDsoMdc, allowDsoMdc,
2385 declInputLevel, parm, id))
2388 = new ExternalTextEntity(name, Entity::linktype, markupLocation(), id);
2389 tem->generateSystemId(*this);
2393 .externalEntityDecl(new (eventAllocator())
2394 ExternalEntityDeclEvent(entity, 0));
2399 lpd = new SimpleLpd(name, markupLocation(), sourceDtd);
2401 lpd = new ComplexLpd(name,
2402 implied ? Lpd::implicitLink : Lpd::explicitLink,
2407 if (!baseDtd().isNull() && shouldActivateLink(name)) {
2408 size_t nActive = nActiveLink();
2411 for (size_t i = 0; i < nActive; i++)
2412 if (activeLpd(i).type() == Lpd::simpleLink)
2414 if (nSimple == sd().simpleLink())
2415 message(ParserMessages::simpleLinkCount,
2416 NumberMessageArg(sd().simpleLink()));
2420 Boolean haveImplicit = 0;
2421 Boolean haveExplicit = 0;
2423 for (i = 0; i < nActive; i++) {
2424 if (activeLpd(i).type() == Lpd::implicitLink)
2426 else if (activeLpd(i).type() == Lpd::explicitLink)
2429 const Dtd *sourceDtd = lpd->sourceDtd().pointer();
2430 if (implied && haveImplicit)
2431 message(ParserMessages::oneImplicitLink);
2432 else if (sd().explicitLink() <= 1 && sourceDtd != baseDtd().pointer())
2433 message(sd().explicitLink() == 0
2434 ? ParserMessages::explicitNoRequiresSourceTypeBase
2435 : ParserMessages::explicit1RequiresSourceTypeBase,
2436 StringMessageArg(lpd->name()));
2437 else if (sd().explicitLink() == 1 && haveExplicit && !implied)
2438 message(ParserMessages::duplicateExplicitChain);
2439 else if (haveExplicit || haveImplicit
2440 || sourceDtd != baseDtd().pointer())
2441 message(ParserMessages::sorryLink, StringMessageArg(lpd->name()));
2446 // Discard mdc or dso
2447 if (currentMarkup())
2448 currentMarkup()->resize(currentMarkup()->size() - 1);
2449 eventHandler().startLpd(new (eventAllocator())
2450 StartLpdEvent(lpd->active(),
2453 parm.type == Param::dso,
2457 if (parm.type == Param::mdc) {
2459 currentInput()->ungetToken();
2460 if (entity.isNull()) {
2461 message(ParserMessages::noLpdSubset, StringMessageArg(name));
2462 (void)parseLinktypeDeclEnd();
2465 // reference the entity
2466 Ptr<EntityOrigin> origin
2467 = new (internalAllocator()) EntityOrigin(entity, currentLocation());
2468 entity->dsReference(*this, origin);
2469 if (inputLevel() == 1) { // reference failed
2470 (void)parseLinktypeDeclEnd();
2474 else if (!entity.isNull())
2475 setDsEntity(entity);
2476 setPhase(declSubsetPhase);
2480 Boolean Parser::parseLinktypeDeclEnd()
2483 if (defLpd().type() != Lpd::simpleLink) {
2484 if (!defComplexLpd().initialLinkSet()->defined())
2485 message(ParserMessages::noInitialLinkSet,
2486 StringMessageArg(defLpd().name()));
2487 ComplexLpd::ConstLinkSetIter iter = defComplexLpd().linkSetIter();
2488 const LinkSet *linkSet;
2489 while ((linkSet = iter.next()) != 0)
2490 if (!linkSet->defined())
2491 message(ParserMessages::undefinedLinkSet, StringMessageArg(linkSet->name()));
2493 ConstPtr<Lpd> tem(defLpdPointer());
2495 startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2497 Boolean result = parseParam(allowMdc, inputLevel(), parm);
2498 eventHandler().endLpd(new (eventAllocator()) EndLpdEvent(tem,
2504 Boolean Parser::parseLinkDecl()
2506 return parseLinkSet(0);
2509 Boolean Parser::parseIdlinkDecl()
2511 return parseLinkSet(1);
2514 // This will only get called if we're defining a complex lpd.
2516 Boolean Parser::parseLinkSet(Boolean idlink)
2518 if (defLpd().type() == Lpd::simpleLink) {
2519 message(idlink ? ParserMessages::idlinkDeclSimple : ParserMessages::linkDeclSimple);
2523 if (defComplexLpd().hadIdLinkSet())
2524 message(ParserMessages::duplicateIdLinkSet);
2526 defComplexLpd().setHadIdLinkSet();
2528 unsigned declInputLevel = inputLevel();
2531 Boolean isExplicit = (defLpd().type() == Lpd::explicitLink);
2534 if (!parseParam(allowName, declInputLevel, parm))
2539 static AllowedParams
2540 allowNameInitial(Param::name,
2541 Param::indicatedReservedName + Syntax::rINITIAL);
2542 if (!parseParam(allowNameInitial, declInputLevel, parm))
2544 if (parm.type == Param::name)
2545 linkSet = lookupCreateLinkSet(parm.token);
2547 linkSet = defComplexLpd().initialLinkSet();
2548 if (linkSet->defined())
2549 message(ParserMessages::duplicateLinkSet, StringMessageArg(linkSet->name()));
2550 static AllowedParams
2551 allowExplicitLinkRule(Param::name,
2553 Param::indicatedReservedName + Syntax::rIMPLIED);
2554 if (!parseParam(isExplicit ? allowExplicitLinkRule : allowNameNameGroup,
2555 declInputLevel, parm))
2562 parm.token.swap(id);
2563 if (!parseParam(isExplicit ? allowExplicitLinkRuleMdc : allowNameNameGroupMdc,
2564 declInputLevel, parm))
2567 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2568 if (!parseParam(allowName, declInputLevel, parm))
2570 Boolean resultImplied;
2571 const ElementType *resultType;
2572 AttributeList resultAttributes;
2573 if (!parseResultElementSpec(declInputLevel,
2581 const AttributeList *dummy;
2582 if (linkSet->impliedResultAttributes(resultType, dummy))
2583 message(ParserMessages::duplicateImpliedResult,
2584 StringMessageArg(resultType->name()));
2586 linkSet->addImplied(resultType, resultAttributes);
2590 SourceLinkRule *linkRule = 0;
2591 IdLinkRule idLinkRule;
2592 Ptr<SourceLinkRuleResource> linkRuleResource;
2594 linkRule = &idLinkRule;
2596 linkRuleResource = new SourceLinkRuleResource;
2597 linkRule = linkRuleResource.pointer();
2599 Vector<const ElementType *> assocElementTypes;
2600 if (parm.type == Param::name) {
2601 assocElementTypes.resize(1);
2602 assocElementTypes[0] = lookupCreateElement(parm.token);
2605 assocElementTypes.resize(parm.nameTokenVector.size());
2606 for (size_t i = 0; i < assocElementTypes.size(); i++)
2607 assocElementTypes[i]
2608 = lookupCreateElement(parm.nameTokenVector[i].name);
2610 static AllowedParams
2611 allow2i(Param::indicatedReservedName + Syntax::rUSELINK,
2612 Param::indicatedReservedName + Syntax::rPOSTLINK,
2617 static AllowedParams
2618 allow2id(Param::indicatedReservedName + Syntax::rUSELINK,
2619 Param::indicatedReservedName + Syntax::rPOSTLINK,
2623 static AllowedParams
2624 allow2e(Param::indicatedReservedName + Syntax::rUSELINK,
2625 Param::indicatedReservedName + Syntax::rPOSTLINK,
2628 Param::indicatedReservedName + Syntax::rIMPLIED);
2630 if (!parseParam(isExplicit
2632 : (idlink ? allow2id : allow2i), declInputLevel, parm))
2634 if (parm.type == Param::indicatedReservedName + Syntax::rUSELINK) {
2635 static AllowedParams
2636 allowLinkSetEmpty(Param::name,
2637 Param::indicatedReservedName + Syntax::rINITIAL,
2638 Param::indicatedReservedName + Syntax::rEMPTY);
2639 if (!parseParam(allowLinkSetEmpty, declInputLevel, parm))
2641 const LinkSet *uselink;
2642 if (parm.type == Param::name)
2643 uselink = lookupCreateLinkSet(parm.token);
2644 else if (parm.type == Param::indicatedReservedName + Syntax::rINITIAL)
2645 uselink = defComplexLpd().initialLinkSet();
2647 uselink = defComplexLpd().emptyLinkSet();
2648 linkRule->setUselink(uselink);
2649 static AllowedParams
2650 allow3i(Param::indicatedReservedName + Syntax::rPOSTLINK,
2655 static AllowedParams
2656 allow3id(Param::indicatedReservedName + Syntax::rPOSTLINK,
2660 static AllowedParams
2661 allow3e(Param::indicatedReservedName + Syntax::rPOSTLINK,
2664 Param::indicatedReservedName + Syntax::rIMPLIED);
2666 if (!parseParam(isExplicit
2668 : (idlink ? allow3id : allow3i),
2669 declInputLevel, parm))
2672 if (parm.type == Param::indicatedReservedName + Syntax::rPOSTLINK) {
2673 if (!parseParam(allowLinkSetSpec, declInputLevel, parm))
2675 const LinkSet *postlink;
2676 if (parm.type == Param::indicatedReservedName + Syntax::rRESTORE)
2677 linkRule->setPostlinkRestore();
2679 if (parm.type == Param::name)
2680 postlink = lookupCreateLinkSet(parm.token);
2682 == Param::indicatedReservedName + Syntax::rINITIAL)
2683 postlink = defComplexLpd().initialLinkSet();
2685 postlink = defComplexLpd().emptyLinkSet();
2686 linkRule->setPostlink(postlink);
2688 static AllowedParams
2693 static AllowedParams
2694 allow4id(Param::dso,
2697 static AllowedParams
2700 Param::indicatedReservedName + Syntax::rIMPLIED);
2701 if (!parseParam(isExplicit
2703 : (idlink ? allow4id : allow4i),
2704 declInputLevel, parm))
2707 AttributeList attributes;
2708 ConstPtr<AttributeDefinitionList> attDef;
2709 for (size_t i = 0; i < assocElementTypes.size(); i++) {
2710 const ElementType *e = assocElementTypes[i];
2713 attDef = defComplexLpd().attributeDef(e);
2714 else if (attDef != defComplexLpd().attributeDef(e))
2715 message(ParserMessages::assocElementDifferentAtts);
2716 // FIXME recover from this
2719 attributes.init(attDef);
2721 if (parm.type == Param::dso) {
2722 Boolean netEnabling;
2723 if (!parseAttributeSpec(1, attributes, netEnabling))
2725 static AllowedParams
2726 allow5e(Param::name,
2727 Param::indicatedReservedName + Syntax::rIMPLIED);
2728 if (!parseParam(isExplicit
2730 : (idlink ? allowNameMdc : allowNameNameGroupMdc),
2731 declInputLevel, parm))
2735 attributes.finish(*this);
2736 linkRule->setLinkAttributes(attributes);
2738 Boolean resultImplied;
2739 const ElementType *resultType;
2740 AttributeList resultAttributes;
2741 if (!parseResultElementSpec(declInputLevel,
2749 linkRule->setResult(resultType, resultAttributes);
2751 // Install the link rule.
2753 idLinkRule.setAssocElementTypes(assocElementTypes);
2754 addIdLinkRule(id, idLinkRule);
2757 if (!linkSet->defined()) {
2758 for (size_t i = 0; i < assocElementTypes.size(); i++)
2759 if (assocElementTypes[i])
2760 addLinkRule(linkSet, assocElementTypes[i], linkRuleResource);
2764 } while (parm.type != Param::mdc);
2766 linkSet->setDefined();
2767 if (currentMarkup()) {
2769 eventHandler().idLinkDecl(new (eventAllocator())
2770 IdLinkDeclEvent(defComplexLpdPointer(),
2774 eventHandler().linkDecl(new (eventAllocator())
2775 LinkDeclEvent(linkSet,
2776 defComplexLpdPointer(),
2783 void Parser::addIdLinkRule(const StringC &id,
2786 IdLinkRuleGroup *group = defComplexLpd().lookupCreateIdLink(id);
2787 size_t nRules = group->nLinkRules();
2788 if ((nRules == 1 && group->linkRule(0).attributes().nSpec() == 0)
2789 || nRules >= 1 && rule.attributes().nSpec() == 0)
2790 message(ParserMessages::multipleIdLinkRuleAttribute,
2791 StringMessageArg(id));
2792 group->addLinkRule(rule);
2795 void Parser::addLinkRule(LinkSet *linkSet,
2796 const ElementType *sourceElement,
2797 const ConstPtr<SourceLinkRuleResource> &linkRule)
2799 size_t nRules = linkSet->nLinkRules(sourceElement);
2801 && linkSet->linkRule(sourceElement, 0).attributes().nSpec() == 0)
2802 || nRules >= 1 && linkRule->attributes().nSpec() == 0)
2803 message(ParserMessages::multipleLinkRuleAttribute,
2804 StringMessageArg(sourceElement->name()));
2805 linkSet->addLinkRule(sourceElement, linkRule);
2808 class ResultAttributeSpecModeSetter {
2810 ResultAttributeSpecModeSetter(ParserState *state) : state_(state) {
2811 state_->setResultAttributeSpecMode();
2813 ~ResultAttributeSpecModeSetter() { clear(); }
2816 state_->clearResultAttributeSpecMode();
2821 ParserState *state_;
2824 Boolean Parser::parseResultElementSpec(unsigned declInputLevel,
2828 const ElementType *&resultType,
2829 AttributeList &attributes)
2831 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2832 if (!parseParam(idlink ? allowNameMdc : allowExplicitLinkRuleMdc,
2833 declInputLevel, parm))
2839 resultType = lookupResultElementType(parm.token);
2840 static AllowedParams
2845 Param::indicatedReservedName + Syntax::rIMPLIED);
2846 static AllowedParams
2847 allowNameDsoMdc(Param::dso,
2850 if (!parseParam(idlink ? allowNameDsoMdc : allow,
2851 declInputLevel, parm))
2853 ConstPtr<AttributeDefinitionList> attDef;
2855 attDef = resultType->attributeDef();
2856 attributes.init(attDef);
2857 if (parm.type == Param::dso) {
2858 ResultAttributeSpecModeSetter modeSetter(this);
2859 Boolean netEnabling;
2860 if (!parseAttributeSpec(1, attributes, netEnabling))
2863 if (attributes.nSpec() == 0)
2864 message(ParserMessages::emptyResultAttributeSpec);
2865 if (!parseParam(idlink ? allowNameMdc : allowExplicitLinkRuleMdc,
2866 declInputLevel, parm))
2870 // For entity and notation attributes.
2871 ResultAttributeSpecModeSetter modeSetter(this);
2872 attributes.finish(*this);
2879 const ElementType *Parser::lookupResultElementType(const StringC &name)
2881 const Dtd *dtd = defComplexLpd().resultDtd().pointer();
2884 const ElementType *e = dtd->lookupElementType(name);
2886 message(ParserMessages::noSuchResultElement, StringMessageArg(name));
2890 Boolean Parser::parseUselinkDecl()
2892 unsigned declInputLevel = inputLevel();
2894 if (!parseParam(allowLinkSetSpec, declInputLevel, parm))
2897 if (!parseParam(allowName, declInputLevel, parm2))
2900 parm2.token.swap(linkType);
2901 if (!parseParam(allowMdc, declInputLevel, parm2))
2903 ConstPtr<Lpd> lpd = lookupLpd(linkType);
2905 message(ParserMessages::uselinkBadLinkType, StringMessageArg(linkType));
2906 else if (lpd->type() == Lpd::simpleLink)
2907 message(ParserMessages::uselinkSimpleLpd, StringMessageArg(linkType));
2909 const ComplexLpd *complexLpd = (const ComplexLpd *)lpd.pointer();
2910 const LinkSet *linkSet;
2911 Boolean restore = 0;
2912 if (parm.type == Param::name) {
2913 linkSet = complexLpd->lookupLinkSet(parm.token);
2915 message(ParserMessages::uselinkBadLinkSet,
2916 StringMessageArg(complexLpd->name()),
2917 StringMessageArg(parm.token));
2921 else if (parm.type == Param::indicatedReservedName + Syntax::rINITIAL)
2922 linkSet = complexLpd->initialLinkSet();
2923 else if (parm.type == Param::indicatedReservedName + Syntax::rEMPTY)
2924 linkSet = complexLpd->emptyLinkSet();
2930 eventHandler().uselink(new (eventAllocator())
2931 UselinkEvent(lpd, linkSet,
2932 restore, markupLocation(),
2935 eventHandler().ignoredMarkup(new (eventAllocator())
2936 IgnoredMarkupEvent(markupLocation(),
2942 LinkSet *Parser::lookupCreateLinkSet(const StringC &name)
2944 LinkSet *linkSet = defComplexLpd().lookupLinkSet(name);
2946 linkSet = new LinkSet(name, defComplexLpd().sourceDtd().pointer());
2947 defComplexLpd().insertLinkSet(linkSet);
2952 Boolean Parser::parseMarkedSectionDeclStart()
2954 if (markedSectionLevel() == syntax().taglvl())
2955 message(ParserMessages::markedSectionLevel,
2956 NumberMessageArg(syntax().taglvl()));
2957 if (markedSectionSpecialLevel() > 0) {
2958 startMarkedSection(markupLocation());
2960 ? eventsWanted().wantMarkedSections()
2961 : eventsWanted().wantPrologMarkup())
2962 eventHandler().ignoredChars(new (eventAllocator())
2963 IgnoredCharsEvent(currentInput()->currentTokenStart(),
2964 currentInput()->currentTokenLength(),
2970 if (startMarkup(inInstance()
2971 ? eventsWanted().wantMarkedSections()
2972 : eventsWanted().wantPrologMarkup(),
2973 currentLocation())) {
2974 currentMarkup()->addDelim(Syntax::dMDO);
2975 currentMarkup()->addDelim(Syntax::dDSO);
2977 unsigned declInputLevel = inputLevel();
2978 static AllowedParams allowStatusDso(Param::dso,
2979 Param::reservedName + Syntax::rCDATA,
2980 Param::reservedName + Syntax::rRCDATA,
2981 Param::reservedName + Syntax::rIGNORE,
2982 Param::reservedName + Syntax::rINCLUDE,
2983 Param::reservedName + Syntax::rTEMP);
2985 MarkedSectionEvent::Status status = MarkedSectionEvent::include;
2987 if (!parseParam(allowStatusDso, declInputLevel, parm))
2989 if (parm.type == Param::dso)
2991 switch (parm.type) {
2992 case Param::reservedName + Syntax::rCDATA:
2993 if (status < MarkedSectionEvent::cdata)
2994 status = MarkedSectionEvent::cdata;
2996 case Param::reservedName + Syntax::rRCDATA:
2997 if (status < MarkedSectionEvent::rcdata)
2998 status = MarkedSectionEvent::rcdata;
3000 case Param::reservedName + Syntax::rIGNORE:
3001 if (status < MarkedSectionEvent::ignore)
3002 status = MarkedSectionEvent::ignore;
3006 // FIXME this disallows
3007 // <!entity % e "include [ stuff ">
3010 // which I think is legal.
3012 if (inputLevel() > declInputLevel)
3013 message(ParserMessages::parameterEntityNotEnded);
3015 case MarkedSectionEvent::include:
3016 startMarkedSection(markupLocation());
3018 case MarkedSectionEvent::cdata:
3019 startSpecialMarkedSection(cmsMode, markupLocation());
3021 case MarkedSectionEvent::rcdata:
3022 startSpecialMarkedSection(rcmsMode, markupLocation());
3024 case MarkedSectionEvent::ignore:
3025 startSpecialMarkedSection(imsMode, markupLocation());
3028 if (currentMarkup())
3029 eventHandler().markedSectionStart(new (eventAllocator())
3030 MarkedSectionStartEvent(status,
3036 void Parser::handleMarkedSectionEnd()
3038 if (markedSectionLevel() == 0)
3039 message(ParserMessages::markedSectionEnd);
3042 ? eventsWanted().wantMarkedSections()
3043 : eventsWanted().wantPrologMarkup()) {
3044 if (markedSectionSpecialLevel() > 1)
3045 eventHandler().ignoredChars(new (eventAllocator())
3046 IgnoredCharsEvent(currentInput()->currentTokenStart(),
3047 currentInput()->currentTokenLength(),
3051 MarkedSectionEvent::Status status;
3052 switch (currentMode()) {
3054 status = MarkedSectionEvent::cdata;
3057 status = MarkedSectionEvent::rcdata;
3060 status = MarkedSectionEvent::ignore;
3063 status = MarkedSectionEvent::include;
3066 startMarkup(1, currentLocation());
3067 currentMarkup()->addDelim(Syntax::dMSC);
3068 currentMarkup()->addDelim(Syntax::dMDC);
3069 eventHandler().markedSectionEnd(new (eventAllocator())
3070 MarkedSectionEndEvent(status,
3079 void Parser::emptyCommentDecl()
3081 if (startMarkup(eventsWanted().wantCommentDecls(), currentLocation())) {
3082 currentMarkup()->addDelim(Syntax::dMDO);
3083 currentMarkup()->addDelim(Syntax::dMDC);
3084 eventHandler().commentDecl(new (eventAllocator())
3085 CommentDeclEvent(markupLocation(),
3090 Boolean Parser::parseCommentDecl()
3092 if (startMarkup(inInstance()
3093 ? eventsWanted().wantCommentDecls()
3094 : eventsWanted().wantPrologMarkup(),
3096 currentMarkup()->addDelim(Syntax::dMDO);
3097 if (!parseComment(comMode))
3100 Token token = getToken(mdMode);
3103 if (currentMarkup())
3104 currentMarkup()->addS(currentChar());
3107 if (!parseComment(comMode))
3111 if (currentMarkup())
3112 currentMarkup()->addDelim(Syntax::dMDC);
3115 message(ParserMessages::declarationLevel);
3117 case tokenUnrecognized:
3118 if (reportNonSgmlCharacter())
3120 // braces to work round Sun C++ 4.0 bug
3122 message(ParserMessages::commentDeclarationCharacter,
3123 StringMessageArg(currentToken()),
3128 // braces to work round Sun C++ 4.0 bug
3130 message(ParserMessages::commentDeclInvalidToken,
3131 TokenMessageArg(token, mdMode, syntaxPointer(), sdPointer()),
3138 if (currentMarkup())
3139 eventHandler().commentDecl(new (eventAllocator())
3140 CommentDeclEvent(markupLocation(),
3145 Boolean Parser::parseAfdrDecl()
3147 unsigned declInputLevel = inputLevel();
3148 static AllowedParams allowMinimumLiteral(Param::minimumLiteral);
3151 if (!parseParam(allowMinimumLiteral, declInputLevel, parm))
3153 if (parm.literalText.string() != sd().execToDoc("ISO/IEC 10744:1992"))
3154 message(ParserMessages::afdrVersion,
3155 StringMessageArg(parm.literalText.string()));
3156 if (!parseParam(allowMdc, declInputLevel, parm))
3158 eventHandler().ignoredMarkup(new (eventAllocator())
3159 IgnoredMarkupEvent(markupLocation(),