1 /* $XConsortium: parseDecl.C /main/1 1996/07/29 17:09:16 cde-hp $ */
2 // Copyright (c) 1994, 1995 James Clark
3 // See the file COPYING for copying permission.
5 // Prolog, dtd and declaration parsing.
11 #include "ParserMessages.h"
12 #include "MessageArg.h"
13 #include "TokenMessageArg.h"
18 namespace SP_NAMESPACE {
21 static const AllowedParams allowMdc(Param::mdc);
22 static const AllowedParams allowName(Param::name);
23 static const AllowedParams allowParamLiteral(Param::paramLiteral);
24 static const AllowedParams allowNameNameGroup(Param::name, Param::nameGroup);
25 static const AllowedParams allowDsoMdc(Param::dso, Param::mdc);
26 static AllowedParams allowNameMdc(Param::name, Param::mdc);
28 allowExplicitLinkRuleMdc(Param::mdc,
31 Param::indicatedReservedName + Syntax::rIMPLIED);
33 allowNameNameGroupMdc(Param::name, Param::nameGroup, Param::mdc);
35 static const AllowedParams
36 allowLinkSetSpec(Param::name,
37 Param::indicatedReservedName + Syntax::rINITIAL,
38 Param::indicatedReservedName + Syntax::rEMPTY,
39 Param::indicatedReservedName + Syntax::rRESTORE);
41 void Parser::doProlog()
43 const unsigned maxTries = 10;
50 Token token = getToken(proMode);
52 case tokenUnrecognized:
53 if (reportNonSgmlCharacter())
56 currentInput()->ungetToken();
62 if (lookingAtStartTag(gi)) {
63 currentInput()->ungetToken();
65 message(ParserMessages::noDtd);
72 if (++tries >= maxTries) {
73 message(ParserMessages::noDtd);
77 message(ParserMessages::prologCharacter, StringMessageArg(currentToken()));
85 message(ParserMessages::documentEndProlog);
93 if (!parseCommentDecl())
96 case tokenMdoNameStart:
98 if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation()))
99 currentMarkup()->addDelim(Syntax::dMDO);
100 Syntax::ReservedName name;
101 if (parseDeclarationName(&name)) {
103 case Syntax::rDOCTYPE:
104 if (!parseDoctypeDeclStart())
107 case Syntax::rLINKTYPE:
108 if (!parseLinktypeDeclStart())
111 case Syntax::rELEMENT:
112 case Syntax::rATTLIST:
113 case Syntax::rENTITY:
114 case Syntax::rNOTATION:
115 case Syntax::rSHORTREF:
116 case Syntax::rUSEMAP:
117 case Syntax::rUSELINK:
119 case Syntax::rIDLINK:
120 message(ParserMessages::prologDeclaration,
121 StringMessageArg(syntax().reservedName(name)));
127 message(ParserMessages::noSuchDeclarationType,
128 StringMessageArg(syntax().reservedName(name)));
137 if (!parseProcessingInstruction())
141 if (eventsWanted().wantPrologMarkup()) {
143 eventHandler().sSep(new (eventAllocator())
144 SSepEvent(currentInput()->currentTokenStart(),
145 currentInput()->currentTokenLength(),
153 } while (eventQueueEmpty());
156 void Parser::endProlog()
158 if (baseDtd().isNull()
159 || baseDtd()->documentElementType()->definition()->undefined()) {
160 // We could continue, but there's not a lot of point.
164 if (maybeStartPass2())
165 setPhase(prologPhase);
167 if (inputLevel() == 0) {
172 checkEntityStability();
173 setPhase(instanceStartPhase);
175 ConstPtr<ComplexLpd> lpd;
176 Vector<AttributeList> simpleLinkAtts;
177 Vector<StringC> simpleLinkNames;
178 for (size_t i = 0; i < nActiveLink(); i++)
179 if (activeLpd(i).type() == Lpd::simpleLink) {
180 const SimpleLpd &lpd = (SimpleLpd &)activeLpd(i);
181 simpleLinkNames.push_back(lpd.name());
182 simpleLinkAtts.resize(simpleLinkAtts.size() + 1);
183 simpleLinkAtts.back().init(lpd.attributeDef());
184 simpleLinkAtts.back().finish(*this);
187 lpd = (ComplexLpd *)&activeLpd(i);
188 eventHandler().endProlog(new (eventAllocator())
189 EndPrologEvent(baseDtd(),
197 void Parser::prologRecover()
199 unsigned skipCount = 0;
200 const unsigned skipMax = 250;
202 Token token = getToken(proMode);
204 if (token == tokenUnrecognized) {
205 token = getToken(mdMode);
206 if (token == tokenMdc) {
207 token = getToken(proMode);
213 case tokenUnrecognized:
220 case tokenMdoNameStart:
222 currentInput()->ungetToken();
225 if (currentChar() == syntax().standardFunction(Syntax::fRE)
226 && skipCount >= skipMax)
234 void Parser::doDeclSubset()
241 Token token = getToken(currentMode());
242 unsigned startLevel = inputLevel();
243 Boolean inDtd = !haveDefLpd();
245 case tokenUnrecognized:
246 if (reportNonSgmlCharacter())
248 message(ParserMessages::declSubsetCharacter, StringMessageArg(currentToken()));
249 declSubsetRecover(startLevel);
252 if (inputLevel() == specialParseInputLevel()) {
253 // FIXME have separate messages for each type of special parse
254 message(ParserMessages::specialParseEntityEnd);
256 if (eventsWanted().wantPrologMarkup())
257 eventHandler().entityEnd(new (eventAllocator())
258 EntityEndEvent(currentLocation()));
259 if (inputLevel() == 2) {
261 = currentLocation().origin()->asEntityOrigin()->entity();
263 && (e->declType() == Entity::doctype
264 || e->declType() == Entity::linktype)) {
267 ? parseDoctypeDeclEnd(e->defLocation().origin().isNull())
268 : parseLinktypeDeclEnd()))
270 setPhase(prologPhase);
274 if (inputLevel() == 1) {
275 if (finalPhase() == declSubsetPhase) {
280 // Give message before popping stack.
282 ? ParserMessages::documentEndDtdSubset
283 : ParserMessages::documentEndLpdSubset);
290 case tokenDsc: // end of declaration subset
291 // FIXME what's the right location?
292 if (!referenceDsEntity(currentLocation())) {
293 if (!(inDtd ? parseDoctypeDeclEnd() : parseLinktypeDeclEnd()))
295 setPhase(prologPhase);
298 case tokenMdoNameStart: // named markup declaration
299 if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation()))
300 currentMarkup()->addDelim(Syntax::dMDO);
301 Syntax::ReservedName name;
303 if (parseDeclarationName(&name,
304 inDtd && !options().errorAfdr)) {
306 case Syntax::rANY: // used for <!AFDR
307 result = parseAfdrDecl();
309 case Syntax::rELEMENT:
311 result = parseElementDecl();
313 message(ParserMessages::lpdSubsetDeclaration,
314 StringMessageArg(syntax().reservedName(name)));
318 case Syntax::rATTLIST:
319 result = parseAttlistDecl();
321 case Syntax::rENTITY:
322 result = parseEntityDecl();
324 case Syntax::rNOTATION:
325 result = parseNotationDecl();
326 if (!inDtd && options().errorLpdNotation)
327 message(ParserMessages::lpdSubsetDeclaration,
328 StringMessageArg(syntax().reservedName(name)));
330 case Syntax::rSHORTREF:
332 result = parseShortrefDecl();
334 message(ParserMessages::lpdSubsetDeclaration,
335 StringMessageArg(syntax().reservedName(name)));
339 case Syntax::rUSEMAP:
341 result = parseUsemapDecl();
343 message(ParserMessages::lpdSubsetDeclaration,
344 StringMessageArg(syntax().reservedName(name)));
350 message(ParserMessages::dtdSubsetDeclaration,
351 StringMessageArg(syntax().reservedName(name)));
355 result = parseLinkDecl();
357 case Syntax::rIDLINK:
359 message(ParserMessages::dtdSubsetDeclaration,
360 StringMessageArg(syntax().reservedName(name)));
364 result = parseIdlinkDecl();
366 case Syntax::rDOCTYPE:
367 case Syntax::rLINKTYPE:
368 case Syntax::rUSELINK:
371 ? ParserMessages::dtdSubsetDeclaration
372 : ParserMessages::lpdSubsetDeclaration,
373 StringMessageArg(syntax().reservedName(name)));
377 message(ParserMessages::noSuchDeclarationType,
378 StringMessageArg(syntax().reservedName(name)));
385 declSubsetRecover(startLevel);
387 case tokenMdoMdc: // empty comment declaration
391 case tokenMdoCom: // comment declaration
392 if (!parseCommentDecl())
393 declSubsetRecover(startLevel);
395 case tokenMdoDso: // marked section declaration
396 if (!parseMarkedSectionDeclStart())
397 declSubsetRecover(startLevel);
400 handleMarkedSectionEnd();
402 case tokenPeroGrpo: // parameter entity reference with name group
403 message(ParserMessages::peroGrpoProlog);
405 case tokenPeroNameStart: // parameter entity reference
407 ConstPtr<Entity> entity;
408 Ptr<EntityOrigin> origin;
409 if (parseEntityReference(1, token == tokenPeroGrpo, entity, origin)) {
410 if (!entity.isNull())
411 entity->dsReference(*this, origin);
414 declSubsetRecover(startLevel);
417 case tokenPio: // processing instruction
418 if (!parseProcessingInstruction())
419 declSubsetRecover(startLevel);
421 case tokenS: // white space
422 if (eventsWanted().wantPrologMarkup()) {
424 eventHandler().sSep(new (eventAllocator())
425 SSepEvent(currentInput()->currentTokenStart(),
426 currentInput()->currentTokenLength(),
431 case tokenIgnoredChar:
432 // from an ignored marked section
433 if (eventsWanted().wantPrologMarkup())
434 eventHandler().ignoredChars(new (eventAllocator())
435 IgnoredCharsEvent(currentInput()->currentTokenStart(),
436 currentInput()->currentTokenLength(),
443 case tokenCroNameStart:
444 case tokenEroNameStart:
447 // these can occur in a cdata or rcdata marked section
448 message(ParserMessages::dataMarkedSectionDeclSubset);
449 declSubsetRecover(startLevel);
454 } while (eventQueueEmpty());
457 void Parser::declSubsetRecover(unsigned startLevel)
460 Token token = getToken(currentMode());
462 case tokenUnrecognized:
466 if (inputLevel() <= startLevel)
472 case tokenMdoNameStart:
477 if (inputLevel() == startLevel) {
478 currentInput()->ungetToken();
488 Boolean Parser::lookingAtStartTag(StringC &gi)
490 // This is harder than might be expected since we may not have compiled
491 // the recognizers for the instance yet.
492 const StringC &stago = instanceSyntax().delimGeneral(Syntax::dSTAGO);
493 for (size_t i = currentInput()->currentTokenLength();
496 if (currentInput()->tokenChar(messenger()) == InputSource::eE)
499 getCurrentToken(instanceSyntax().generalSubstTable(), delim);
502 Xchar c = currentInput()->tokenChar(messenger());
503 if (!instanceSyntax().isNameStartCharacter(c))
507 c = currentInput()->tokenChar(messenger());
508 } while (instanceSyntax().isNameCharacter(c));
512 Boolean Parser::parseDeclarationName(Syntax::ReservedName *result,
515 currentInput()->discardInitial();
516 extendNameToken(syntax().namelen(), ParserMessages::nameLength);
517 StringC &name = nameBuffer();
518 getCurrentToken(syntax().generalSubstTable(), name);
519 if (!syntax().lookupReservedName(name, result)) {
520 if (allowAfdr && name == sd().execToDoc("AFDR")) {
521 *result = Syntax::rANY;
523 currentMarkup()->addName(currentInput());
526 message(ParserMessages::noSuchDeclarationType, StringMessageArg(name));
530 else if (currentMarkup())
531 currentMarkup()->addReservedName(*result, currentInput());
535 Boolean Parser::parseElementDecl()
537 unsigned declInputLevel = inputLevel();
539 if (!parseParam(allowNameNameGroup, declInputLevel, parm))
541 Vector<NameToken> nameVector;
542 if (parm.type == Param::nameGroup)
543 parm.nameTokenVector.swap(nameVector);
545 nameVector.resize(1);
546 parm.token.swap(nameVector[0].name);
549 allowRankOmissionContent(Param::number,
550 Param::reservedName + Syntax::rO,
552 Param::reservedName + Syntax::rCDATA,
553 Param::reservedName + Syntax::rRCDATA,
554 Param::reservedName + Syntax::rEMPTY,
555 Param::reservedName + Syntax::rANY,
557 if (!parseParam(allowRankOmissionContent, declInputLevel, parm))
560 Vector<ElementType *> elements(nameVector.size());
561 Vector<RankStem *> rankStems;
562 Vector<const RankStem *> constRankStems;
564 if (parm.type == Param::number) {
565 parm.token.swap(rankSuffix);
566 rankStems.resize(nameVector.size());
567 constRankStems.resize(nameVector.size());
568 for (i = 0; i < elements.size(); i++) {
569 StringC name(nameVector[i].name);
571 if (name.size() > syntax().namelen()
572 && nameVector[i].name.size() <= syntax().namelen())
573 message(ParserMessages::genericIdentifierLength,
574 NumberMessageArg(syntax().namelen()));
575 elements[i] = lookupCreateElement(name);
576 rankStems[i] = lookupCreateRankStem(nameVector[i].name);
577 constRankStems[i] = rankStems[i];
580 allowOmissionContent(Param::reservedName + Syntax::rO,
582 Param::reservedName + Syntax::rCDATA,
583 Param::reservedName + Syntax::rRCDATA,
584 Param::reservedName + Syntax::rEMPTY,
585 Param::reservedName + Syntax::rANY,
587 Token token = getToken(mdMinusMode);
588 if (token == tokenNameStart)
589 message(ParserMessages::psRequired);
590 currentInput()->ungetToken();
591 if (!parseParam(allowOmissionContent, declInputLevel, parm))
595 for (i = 0; i < elements.size(); i++)
596 elements[i] = lookupCreateElement(nameVector[i].name);
598 for (i = 0; i < elements.size(); i++)
599 if (defDtd().lookupRankStem(elements[i]->name()))
600 message(ParserMessages::rankStemGenericIdentifier,
601 StringMessageArg(elements[i]->name()));
602 unsigned char omitFlags = 0;
603 if (parm.type == Param::minus
604 || parm.type == Param::reservedName + Syntax::rO) {
605 omitFlags |= ElementDefinition::omitSpec;
606 if (parm.type != Param::minus)
607 omitFlags |= ElementDefinition::omitStart;
608 static AllowedParams allowOmission(Param::reservedName + Syntax::rO,
610 if (!parseParam(allowOmission, declInputLevel, parm))
612 if (parm.type != Param::minus)
613 omitFlags |= ElementDefinition::omitEnd;
614 static AllowedParams allowContent(Param::reservedName + Syntax::rCDATA,
615 Param::reservedName + Syntax::rRCDATA,
616 Param::reservedName + Syntax::rEMPTY,
617 Param::reservedName + Syntax::rANY,
619 if (!parseParam(allowContent, declInputLevel, parm))
624 message(ParserMessages::missingTagMinimization);
626 Ptr<ElementDefinition> def;
628 case Param::reservedName + Syntax::rCDATA:
629 def = new ElementDefinition(markupLocation(),
630 defDtd().allocElementDefinitionIndex(),
632 ElementDefinition::cdata);
633 if (!parseParam(allowMdc, declInputLevel, parm))
636 case Param::reservedName + Syntax::rRCDATA:
637 def = new ElementDefinition(markupLocation(),
638 defDtd().allocElementDefinitionIndex(),
640 ElementDefinition::rcdata);
641 if (!parseParam(allowMdc, declInputLevel, parm))
644 case Param::reservedName + Syntax::rEMPTY:
645 def = new ElementDefinition(markupLocation(),
646 defDtd().allocElementDefinitionIndex(),
648 ElementDefinition::empty);
649 if ((omitFlags & ElementDefinition::omitSpec)
650 && !(omitFlags & ElementDefinition::omitEnd)
651 && options().warnShould)
652 message(ParserMessages::emptyOmitEndTag);
653 if (!parseParam(allowMdc, declInputLevel, parm))
656 case Param::reservedName + Syntax::rANY:
657 def = new ElementDefinition(markupLocation(),
658 defDtd().allocElementDefinitionIndex(),
660 ElementDefinition::any);
661 if (!parseExceptions(declInputLevel, def))
664 case Param::modelGroup:
666 unsigned long cnt = parm.modelGroupPtr->grpgtcnt();
667 // The outermost model group isn't formally a content token.
668 if (cnt - 1 > syntax().grpgtcnt())
669 message(ParserMessages::grpgtcnt, NumberMessageArg(syntax().grpgtcnt()));
670 Owner<CompiledModelGroup>
671 modelGroup(new CompiledModelGroup(parm.modelGroupPtr));
672 Vector<ContentModelAmbiguity> ambiguities;
673 Boolean pcdataUnreachable;
674 modelGroup->compile(currentDtd().nElementTypeIndex(), ambiguities,
676 if (pcdataUnreachable && options().warnMixedContent)
677 message(ParserMessages::pcdataUnreachable);
678 for (i = 0; i < ambiguities.size(); i++) {
679 const ContentModelAmbiguity &a = ambiguities[i];
680 reportAmbiguity(a.from, a.to1, a.to2, a.andDepth);
682 def = new ElementDefinition(markupLocation(),
683 defDtd().allocElementDefinitionIndex(),
685 ElementDefinition::modelGroup,
687 if (!parseExceptions(declInputLevel, def))
692 if (rankSuffix.size() > 0)
693 def->setRank(rankSuffix, constRankStems);
694 ConstPtr<ElementDefinition> constDef(def);
695 for (i = 0; i < elements.size(); i++) {
696 if (elements[i]->definition() != 0)
697 message(ParserMessages::duplicateElementDefinition,
698 StringMessageArg(elements[i]->name()));
700 elements[i]->setElementDefinition(constDef, i);
701 if (!elements[i]->attributeDef().isNull())
702 checkElementAttribute(elements[i]);
704 if (rankStems.size() > 0)
705 rankStems[i]->addDefinition(constDef);
707 if (currentMarkup()) {
708 Vector<const ElementType *> v(elements.size());
709 for (i = 0; i < elements.size(); i++)
711 eventHandler().elementDecl(new (eventAllocator())
712 ElementDeclEvent(v, currentDtdPointer(),
719 void Parser::reportAmbiguity(const LeafContentToken *from,
720 const LeafContentToken *to1,
721 const LeafContentToken *to2,
722 unsigned ambigAndDepth)
725 const ElementType *toType = to1->elementType();
727 toName = toType->name();
729 toName = syntax().delimGeneral(Syntax::dRNI);
730 toName += syntax().reservedName(Syntax::rPCDATA);
732 unsigned to1Index = to1->typeIndex() + 1;
733 unsigned to2Index = to2->typeIndex() + 1;
734 if (from->isInitial())
735 message(ParserMessages::ambiguousModelInitial,
736 StringMessageArg(toName),
737 OrdinalMessageArg(to1Index),
738 OrdinalMessageArg(to2Index));
741 const ElementType *fromType = from->elementType();
743 fromName = fromType->name();
745 fromName = syntax().delimGeneral(Syntax::dRNI);
746 fromName += syntax().reservedName(Syntax::rPCDATA);
748 unsigned fromIndex = from->typeIndex() + 1;
749 unsigned andMatches = from->andDepth() - ambigAndDepth;
751 message(ParserMessages::ambiguousModel,
752 StringMessageArg(fromName),
753 OrdinalMessageArg(fromIndex),
754 StringMessageArg(toName),
755 OrdinalMessageArg(to1Index),
756 OrdinalMessageArg(to2Index));
757 else if (andMatches == 1)
758 message(ParserMessages::ambiguousModelSingleAnd,
759 StringMessageArg(fromName),
760 OrdinalMessageArg(fromIndex),
761 StringMessageArg(toName),
762 OrdinalMessageArg(to1Index),
763 OrdinalMessageArg(to2Index));
765 message(ParserMessages::ambiguousModelMultipleAnd,
766 StringMessageArg(fromName),
767 OrdinalMessageArg(fromIndex),
768 NumberMessageArg(andMatches),
769 StringMessageArg(toName),
770 OrdinalMessageArg(to1Index),
771 OrdinalMessageArg(to2Index));
776 // Check the compatibility of the attribute definition with
777 // the element definition.
779 void Parser::checkElementAttribute(const ElementType *e, size_t checkFrom)
781 const AttributeDefinitionList *attDef = e->attributeDef().pointer();
784 const ElementDefinition *edef = e->definition();
787 size_t attDefLength = attDef->size();
788 for (size_t i = checkFrom; i < attDefLength; i++) {
789 const AttributeDefinition *p = attDef->def(i);
793 && edef->declaredContent() == ElementDefinition::empty)
794 message(ParserMessages::notationEmpty, StringMessageArg(e->name()));
798 if (edef->omittedTagSpec() && !edef->canOmitEndTag()
799 && options().warnShould)
800 message(ParserMessages::conrefOmitEndTag, StringMessageArg(e->name()));
802 if (edef->declaredContent() == ElementDefinition::empty)
803 message(ParserMessages::conrefEmpty, StringMessageArg(e->name()));
807 ElementType *Parser::lookupCreateElement(const StringC &name)
809 ElementType *e = defDtd().lookupElementType(name);
812 message(ParserMessages::noSuchSourceElement, StringMessageArg(name));
814 e = new ElementType(name, defDtd().nElementTypeIndex());
815 defDtd().insertElementType(e);
821 RankStem *Parser::lookupCreateRankStem(const StringC &name)
823 RankStem *r = defDtd().lookupRankStem(name);
825 r = new RankStem(name, defDtd().nRankStem());
826 defDtd().insertRankStem(r);
827 const ElementType *e = defDtd().lookupElementType(name);
828 if (e && e->definition() != 0)
829 message(ParserMessages::rankStemGenericIdentifier, StringMessageArg(name));
834 Boolean Parser::parseExceptions(unsigned declInputLevel,
835 Ptr<ElementDefinition> &def)
839 allowExceptionsMdc(Param::mdc, Param::exclusions, Param::inclusions);
840 if (!parseParam(allowExceptionsMdc, declInputLevel, parm))
842 if (parm.type == Param::exclusions) {
843 def->setExclusions(parm.elementVector);
844 static AllowedParams allowInclusionsMdc(Param::mdc, Param::inclusions);
845 if (!parseParam(allowInclusionsMdc, declInputLevel, parm))
848 if (parm.type == Param::inclusions) {
849 def->setInclusions(parm.elementVector);
850 size_t nI = def->nInclusions();
851 size_t nE = def->nExclusions();
853 for (size_t i = 0; i < nI; i++) {
854 const ElementType *e = def->inclusion(i);
855 for (size_t j = 0; j < nE; j++)
856 if (def->exclusion(j) == e)
857 message(ParserMessages::excludeIncludeSame,
858 StringMessageArg(e->name()));
861 if (!parseParam(allowMdc, declInputLevel, parm))
867 Boolean Parser::parseAttlistDecl()
869 unsigned declInputLevel = inputLevel();
872 size_t idIndex = size_t(-1);
873 size_t notationIndex = size_t(-1);
874 Boolean anyCurrent = 0;
877 Vector<Attributed *> attributed;
878 if (!parseAttributed(declInputLevel, parm, attributed, isNotation))
880 Vector<CopyOwner<AttributeDefinition> > defs;
881 if (!parseParam(allowName, declInputLevel, parm))
884 StringC attributeName;
885 parm.token.swap(attributeName);
887 Boolean duplicate = 0;
889 for (i = 0; i < defs.size(); i++)
890 if (defs[i]->name() == attributeName) {
891 message(ParserMessages::duplicateAttributeDef,
892 StringMessageArg(attributeName));
896 Owner<DeclaredValue> declaredValue;
897 if (!parseDeclaredValue(declInputLevel, isNotation, parm, declaredValue))
900 if (declaredValue->isId()) {
901 if (idIndex != size_t(-1))
902 message(ParserMessages::multipleIdAttributes,
903 StringMessageArg(defs[idIndex]->name()));
904 idIndex = defs.size();
906 else if (declaredValue->isNotation()) {
907 if (notationIndex != size_t(-1))
908 message(ParserMessages::multipleNotationAttributes,
909 StringMessageArg(defs[notationIndex]->name()));
910 notationIndex = defs.size();
913 const Vector<StringC> *tokensPtr = declaredValue->getTokens();
915 size_t nTokens = tokensPtr->size();
916 Vector<StringC>::const_iterator tokens = tokensPtr->begin();
917 for (i = 0; i < nTokens; i++) {
918 for (size_t j = 0; j < defs.size(); j++)
919 if (defs[j]->containsToken(tokens[i])) {
920 message(ParserMessages::duplicateAttributeToken,
921 StringMessageArg(tokens[i]));
927 Owner<AttributeDefinition> def;
928 if (!parseDefaultValue(declInputLevel, isNotation, parm, attributeName,
929 declaredValue, def, anyCurrent))
931 if (haveDefLpd() && defLpd().type() == Lpd::simpleLink && !def->isFixed())
932 message(ParserMessages::simpleLinkFixedAttribute);
934 defs.resize(defs.size() + 1);
935 defs.back() = def.extract();
937 static AllowedParams allowNameMdc(Param::name, Param::mdc);
938 if (!parseParam(allowNameMdc, declInputLevel, parm))
940 } while (parm.type != Param::mdc);
941 if (attcnt > syntax().attcnt())
942 message(ParserMessages::attcnt,
943 NumberMessageArg(attcnt),
944 NumberMessageArg(syntax().attcnt()));
945 if (haveDefLpd() && !isNotation) {
946 if (defLpd().type() == Lpd::simpleLink) {
947 for (size_t i = 0; i < attributed.size(); i++) {
948 const ElementType *e = (const ElementType *)attributed[i];
950 if (e->name() == defLpd().sourceDtd()->name()) {
951 SimpleLpd &lpd = (SimpleLpd &)defLpd();
952 if (lpd.attributeDef().isNull())
953 lpd.setAttributeDef(new AttributeDefinitionList(defs, 0));
955 message(ParserMessages::duplicateAttlistElement,
956 StringMessageArg(e->name()));
959 message(ParserMessages::simpleLinkAttlistElement,
960 StringMessageArg(e->name()));
965 Ptr<AttributeDefinitionList>
966 adl(new AttributeDefinitionList(defs,
968 .allocAttributeDefinitionListIndex()));
969 for (size_t i = 0; i < attributed.size(); i++) {
970 const ElementType *e = (const ElementType *)attributed[i];
972 if (defComplexLpd().attributeDef(e).isNull())
973 defComplexLpd().setAttributeDef(e, adl);
975 message(ParserMessages::duplicateAttlistElement,
976 StringMessageArg(e->name()));
982 Ptr<AttributeDefinitionList>
983 adl(new AttributeDefinitionList(defs,
985 .allocAttributeDefinitionListIndex(),
989 for (size_t i = 0; i < attributed.size(); i++) {
990 if (attributed[i]->attributeDef().isNull()) {
991 attributed[i]->setAttributeDef(adl);
993 ElementType *e = (ElementType *)attributed[i];
994 if (e->definition() != 0)
995 checkElementAttribute(e);
998 else if (options().errorAfdr) {
999 if (!hadAfdrDecl()) {
1000 message(ParserMessages::missingAfdrDecl);
1004 message(ParserMessages::duplicateAttlistNotation,
1005 StringMessageArg(((Notation *)attributed[i])->name()));
1007 message(ParserMessages::duplicateAttlistElement,
1008 StringMessageArg(((ElementType *)attributed[i])->name()));
1011 AttributeDefinitionList *curAdl;
1013 // Use block to make sure temporary gets destroyed.
1014 curAdl = attributed[i]->attributeDef().pointer();
1016 size_t oldSize = curAdl->size();
1017 if (curAdl->count() != 1) {
1018 Vector<CopyOwner<AttributeDefinition> > copy(oldSize);
1019 for (size_t j = 0; j < oldSize; j++)
1020 copy[j] = curAdl->def(j)->copy();
1021 Ptr<AttributeDefinitionList> adlCopy
1022 = new AttributeDefinitionList(copy,
1023 defDtd().allocAttributeDefinitionListIndex(),
1024 curAdl->anyCurrent(),
1026 curAdl->notationIndex());
1027 attributed[i]->setAttributeDef(adlCopy);
1028 curAdl = adlCopy.pointer();
1030 // FIXME check for multiple ID and NOTATION attributes
1031 for (size_t j = 0; j < adl->size(); j++) {
1033 if (!curAdl->attributeIndex(adl->def(j)->name(), tem))
1034 curAdl->append(adl->def(j)->copy());
1037 ElementType *e = (ElementType *)attributed[i];
1038 if (e->definition() != 0)
1039 checkElementAttribute(e, oldSize);
1044 if (currentMarkup()) {
1046 Vector<ConstPtr<Notation> > v(attributed.size());
1047 for (size_t i = 0; i < attributed.size(); i++)
1048 v[i] = (Notation *)attributed[i];
1050 .attlistNotationDecl(new (eventAllocator())
1051 AttlistNotationDeclEvent(v,
1056 Vector<const ElementType *> v(attributed.size());
1057 for (size_t i = 0; i < attributed.size(); i++)
1058 v[i] = (ElementType *)attributed[i];
1061 .linkAttlistDecl(new (eventAllocator())
1062 LinkAttlistDeclEvent(v,
1067 eventHandler().attlistDecl(new (eventAllocator())
1069 currentDtdPointer(),
1075 Dtd::EntityIter entityIter(defDtd().generalEntityIter());
1077 Ptr<Entity> entity(entityIter.next());
1078 if (entity.isNull())
1080 const ExternalDataEntity *external = entity->asExternalDataEntity();
1082 const Notation *entityNotation = external->notation();
1083 for (size_t i = 0; i < attributed.size(); i++)
1084 if ((Notation *)attributed[i] == entityNotation) {
1085 AttributeList attributes(entityNotation->attributeDef());
1086 attributes.finish(*this);
1087 ((ExternalDataEntity *)entity.pointer())
1088 ->setNotation((Notation *)attributed[i], attributes);
1097 Boolean Parser::parseAttributed(unsigned declInputLevel,
1099 Vector<Attributed *> &attributed,
1100 Boolean &isNotation)
1102 // There's a hack in getIndicatedReservedName allows #ALL as #ANY.
1103 static AllowedParams
1104 allowNameGroupNotation(Param::name,
1106 Param::indicatedReservedName + Syntax::rNOTATION);
1107 static AllowedParams
1108 allowNameGroupNotationAll(Param::name,
1110 Param::indicatedReservedName
1111 + Syntax::rNOTATION,
1112 Param::indicatedReservedName
1114 if (!parseParam(options().errorAfdr || haveDefLpd()
1115 ? allowNameGroupNotation
1116 : allowNameGroupNotationAll,
1117 declInputLevel, parm))
1119 if (parm.type == Param::indicatedReservedName + Syntax::rNOTATION) {
1121 static AllowedParams
1122 allowNameGroupAll(Param::name,
1124 Param::indicatedReservedName + Syntax::rANY);
1125 if (!parseParam(options().errorAfdr || haveDefLpd()
1126 ? allowNameNameGroup
1127 : allowNameGroupAll,
1128 declInputLevel, parm))
1130 if (parm.type == Param::nameGroup) {
1131 attributed.resize(parm.nameTokenVector.size());
1132 for (size_t i = 0; i < attributed.size(); i++)
1133 attributed[i] = lookupCreateNotation(parm.nameTokenVector[i].name);
1136 if (parm.type != Param::name && !hadAfdrDecl()) {
1137 message(ParserMessages::missingAfdrDecl);
1140 attributed.resize(1);
1142 = lookupCreateNotation(parm.type == Param::name
1144 : syntax().rniReservedName(Syntax::rANY));
1149 if (parm.type == Param::nameGroup) {
1150 attributed.resize(parm.nameTokenVector.size());
1151 for (size_t i = 0; i < attributed.size(); i++)
1152 attributed[i] = lookupCreateElement(parm.nameTokenVector[i].name);
1155 if (parm.type != Param::name && !hadAfdrDecl()) {
1156 message(ParserMessages::missingAfdrDecl);
1159 attributed.resize(1);
1161 = lookupCreateElement(parm.type == Param::name
1163 : syntax().rniReservedName(Syntax::rANY));
1169 Boolean Parser::parseDeclaredValue(unsigned declInputLevel,
1172 Owner<DeclaredValue> &declaredValue)
1174 static Param::Type declaredValues[] = {
1175 Param::reservedName + Syntax::rCDATA,
1176 Param::reservedName + Syntax::rENTITY,
1177 Param::reservedName + Syntax::rENTITIES,
1178 Param::reservedName + Syntax::rID,
1179 Param::reservedName + Syntax::rIDREF,
1180 Param::reservedName + Syntax::rIDREFS,
1181 Param::reservedName + Syntax::rNAME,
1182 Param::reservedName + Syntax::rNAMES,
1183 Param::reservedName + Syntax::rNMTOKEN,
1184 Param::reservedName + Syntax::rNMTOKENS,
1185 Param::reservedName + Syntax::rNUMBER,
1186 Param::reservedName + Syntax::rNUMBERS,
1187 Param::reservedName + Syntax::rNUTOKEN,
1188 Param::reservedName + Syntax::rNUTOKENS,
1189 Param::reservedName + Syntax::rNOTATION,
1190 Param::nameTokenGroup
1192 static AllowedParams allowDeclaredValue(declaredValues,
1193 SIZEOF(declaredValues));
1194 if (!parseParam(allowDeclaredValue, declInputLevel, parm))
1196 enum { asDataAttribute = 01, asLinkAttribute = 02 };
1197 unsigned allowedFlags = asDataAttribute|asLinkAttribute;
1198 switch (parm.type) {
1199 case Param::reservedName + Syntax::rCDATA:
1200 declaredValue = new CdataDeclaredValue;
1202 case Param::reservedName + Syntax::rENTITY:
1203 declaredValue = new EntityDeclaredValue(0);
1204 allowedFlags = asLinkAttribute;
1206 case Param::reservedName + Syntax::rENTITIES:
1207 declaredValue = new EntityDeclaredValue(1);
1208 allowedFlags = asLinkAttribute;
1210 case Param::reservedName + Syntax::rID:
1211 declaredValue = new IdDeclaredValue;
1214 case Param::reservedName + Syntax::rIDREF:
1215 declaredValue = new IdrefDeclaredValue(0);
1218 case Param::reservedName + Syntax::rIDREFS:
1219 declaredValue = new IdrefDeclaredValue(1);
1222 case Param::reservedName + Syntax::rNAME:
1224 = new TokenizedDeclaredValue(TokenizedDeclaredValue::name, 0);
1226 case Param::reservedName + Syntax::rNAMES:
1228 = new TokenizedDeclaredValue(TokenizedDeclaredValue::name, 1);
1230 case Param::reservedName + Syntax::rNMTOKEN:
1232 = new TokenizedDeclaredValue(TokenizedDeclaredValue::nameToken, 0);
1234 case Param::reservedName + Syntax::rNMTOKENS:
1236 = new TokenizedDeclaredValue(TokenizedDeclaredValue::nameToken, 1);
1238 case Param::reservedName + Syntax::rNUMBER:
1240 = new TokenizedDeclaredValue(TokenizedDeclaredValue::number, 0);
1242 case Param::reservedName + Syntax::rNUMBERS:
1244 = new TokenizedDeclaredValue(TokenizedDeclaredValue::number, 1);
1246 case Param::reservedName + Syntax::rNUTOKEN:
1248 = new TokenizedDeclaredValue(TokenizedDeclaredValue::numberToken, 0);
1250 case Param::reservedName + Syntax::rNUTOKENS:
1252 = new TokenizedDeclaredValue(TokenizedDeclaredValue::numberToken, 1);
1254 case Param::reservedName + Syntax::rNOTATION:
1256 static AllowedParams allowNameGroup(Param::nameGroup);
1257 if (!parseParam(allowNameGroup, declInputLevel, parm))
1259 Vector<StringC> group(parm.nameTokenVector.size());
1260 for (size_t i = 0; i < group.size(); i++)
1261 parm.nameTokenVector[i].name.swap(group[i]);
1262 declaredValue = new NotationDeclaredValue(group);
1266 case Param::nameTokenGroup:
1268 Vector<StringC> group(parm.nameTokenVector.size());
1269 for (size_t i = 0; i < group.size(); i++)
1270 parm.nameTokenVector[i].name.swap(group[i]);
1271 declaredValue = new NameTokenGroupDeclaredValue(group);
1278 if (!(allowedFlags & asDataAttribute))
1279 message(ParserMessages::dataAttributeDeclaredValue);
1281 else if (haveDefLpd() && !isNotation && !(allowedFlags & asLinkAttribute))
1282 message(ParserMessages::linkAttributeDeclaredValue);
1286 Boolean Parser::parseDefaultValue(unsigned declInputLevel,
1289 const StringC &attributeName,
1290 Owner<DeclaredValue> &declaredValue,
1291 Owner<AttributeDefinition> &def,
1292 Boolean &anyCurrent)
1295 static AllowedParams
1296 allowDefaultValue(Param::indicatedReservedName + Syntax::rFIXED,
1297 Param::indicatedReservedName + Syntax::rREQUIRED,
1298 Param::indicatedReservedName + Syntax::rCURRENT,
1299 Param::indicatedReservedName + Syntax::rCONREF,
1300 Param::indicatedReservedName + Syntax::rIMPLIED,
1301 Param::attributeValue,
1302 Param::attributeValueLiteral);
1303 static AllowedParams
1304 allowTokenDefaultValue(Param::indicatedReservedName + Syntax::rFIXED,
1305 Param::indicatedReservedName + Syntax::rREQUIRED,
1306 Param::indicatedReservedName + Syntax::rCURRENT,
1307 Param::indicatedReservedName + Syntax::rCONREF,
1308 Param::indicatedReservedName + Syntax::rIMPLIED,
1309 Param::attributeValue,
1310 Param::tokenizedAttributeValueLiteral);
1311 if (!parseParam(declaredValue->tokenized()
1312 ? allowTokenDefaultValue
1313 : allowDefaultValue, declInputLevel, parm))
1315 switch (parm.type) {
1316 case Param::indicatedReservedName + Syntax::rFIXED:
1318 static AllowedParams allowValue(Param::attributeValue,
1319 Param::attributeValueLiteral);
1320 static AllowedParams
1321 allowTokenValue(Param::attributeValue,
1322 Param::tokenizedAttributeValueLiteral);
1323 if (!parseParam(declaredValue->tokenized()
1325 : allowValue, declInputLevel, parm))
1327 unsigned specLength = 0;
1328 AttributeValue *value = declaredValue->makeValue(parm.literalText,
1332 if (declaredValue->isId())
1333 message(ParserMessages::idDeclaredValue);
1334 def = new FixedAttributeDefinition(attributeName,
1335 declaredValue.extract(),
1339 case Param::attributeValue:
1340 case Param::attributeValueLiteral:
1341 case Param::tokenizedAttributeValueLiteral:
1343 unsigned specLength = 0;
1344 AttributeValue *value = declaredValue->makeValue(parm.literalText,
1348 if (declaredValue->isId())
1349 message(ParserMessages::idDeclaredValue);
1350 def = new DefaultAttributeDefinition(attributeName,
1351 declaredValue.extract(),
1355 case Param::indicatedReservedName + Syntax::rREQUIRED:
1356 def = new RequiredAttributeDefinition(attributeName,
1357 declaredValue.extract());
1359 case Param::indicatedReservedName + Syntax::rCURRENT:
1361 if (declaredValue->isId())
1362 message(ParserMessages::idDeclaredValue);
1363 def = new CurrentAttributeDefinition(attributeName,
1364 declaredValue.extract(),
1365 defDtd().allocCurrentAttributeIndex());
1367 message(ParserMessages::dataAttributeDefaultValue);
1368 else if (haveDefLpd())
1369 message(ParserMessages::linkAttributeDefaultValue);
1371 case Param::indicatedReservedName + Syntax::rCONREF:
1372 if (declaredValue->isId())
1373 message(ParserMessages::idDeclaredValue);
1374 def = new ConrefAttributeDefinition(attributeName,
1375 declaredValue.extract());
1377 message(ParserMessages::dataAttributeDefaultValue);
1378 else if (haveDefLpd())
1379 message(ParserMessages::linkAttributeDefaultValue);
1381 case Param::indicatedReservedName + Syntax::rIMPLIED:
1382 def = new ImpliedAttributeDefinition(attributeName,
1383 declaredValue.extract());
1391 // parm contains either system or public
1393 Boolean Parser::parseExternalId(const AllowedParams &sysidAllow,
1394 const AllowedParams &endAllow,
1395 unsigned declInputLevel,
1399 id.setLocation(currentLocation());
1400 if (parm.type == Param::reservedName + Syntax::rPUBLIC) {
1401 static AllowedParams allowMinimumLiteral(Param::minimumLiteral);
1402 if (!parseParam(allowMinimumLiteral, declInputLevel, parm))
1404 const MessageType1 *err;
1405 if (!id.setPublic(parm.literalText, sd().docCharset(), syntax().space(),
1409 StringMessageArg(*id.publicIdString()));
1411 if (!parseParam(sysidAllow, declInputLevel, parm))
1413 if (parm.type == Param::systemIdentifier) {
1414 id.setSystem(parm.literalText);
1415 if (!parseParam(endAllow, declInputLevel, parm))
1421 Boolean Parser::parseNotationDecl()
1423 unsigned declInputLevel = inputLevel();
1425 if (!parseParam(allowName, declInputLevel, parm))
1427 Notation *nt = lookupCreateNotation(parm.token);
1429 message(ParserMessages::duplicateNotationDeclaration,
1430 StringMessageArg(parm.token));
1431 static AllowedParams
1432 allowPublicSystem(Param::reservedName + Syntax::rPUBLIC,
1433 Param::reservedName + Syntax::rSYSTEM);
1434 if (!parseParam(allowPublicSystem, declInputLevel, parm))
1438 static AllowedParams allowSystemIdentifierMdc(Param::systemIdentifier,
1442 if (!parseExternalId(allowSystemIdentifierMdc, allowMdc,
1443 declInputLevel, parm, id))
1445 if (sd().formal()) {
1446 PublicId::TextClass textClass;
1447 const PublicId *publicId = id.publicId();
1449 && publicId->getTextClass(textClass)
1450 && textClass != PublicId::NOTATION)
1451 message(ParserMessages::notationIdentifierTextClass);
1453 if (!nt->defined()) {
1454 nt->setExternalId(id, markupLocation());
1455 nt->generateSystemId(*this);
1456 if (currentMarkup())
1457 eventHandler().notationDecl(new (eventAllocator())
1458 NotationDeclEvent(nt, markupLocation(),
1464 Boolean Parser::parseEntityDecl()
1466 unsigned declInputLevel = inputLevel();
1469 static AllowedParams
1470 allowEntityNamePero(Param::entityName,
1471 Param::indicatedReservedName + Syntax::rDEFAULT,
1474 if (!parseParam(allowEntityNamePero, declInputLevel, parm))
1477 Entity::DeclType declType;
1478 StringC name; // empty for default entity
1479 if (parm.type == Param::pero) {
1480 declType = Entity::parameterEntity;
1481 static AllowedParams allowParamEntityName(Param::paramEntityName);
1482 if (!parseParam(allowParamEntityName, declInputLevel, parm))
1484 parm.token.swap(name);
1487 declType = Entity::generalEntity;
1488 if (parm.type == Param::entityName)
1489 parm.token.swap(name);
1491 static AllowedParams
1492 allowEntityTextType(Param::paramLiteral,
1493 Param::reservedName + Syntax::rCDATA,
1494 Param::reservedName + Syntax::rSDATA,
1495 Param::reservedName + Syntax::rPI,
1496 Param::reservedName + Syntax::rSTARTTAG,
1497 Param::reservedName + Syntax::rENDTAG,
1498 Param::reservedName + Syntax::rMS,
1499 Param::reservedName + Syntax::rMD,
1500 Param::reservedName + Syntax::rSYSTEM,
1501 Param::reservedName + Syntax::rPUBLIC);
1503 if (!parseParam(allowEntityTextType, declInputLevel, parm))
1505 Location typeLocation(currentLocation());
1506 Entity::DataType dataType = Entity::sgmlText;
1507 InternalTextEntity::Bracketed bracketed = InternalTextEntity::none;
1508 switch (parm.type) {
1509 case Param::reservedName + Syntax::rSYSTEM:
1510 case Param::reservedName + Syntax::rPUBLIC:
1511 return parseExternalEntity(name, declType, declInputLevel, parm);
1512 case Param::reservedName + Syntax::rCDATA:
1513 dataType = Entity::cdata;
1515 case Param::reservedName + Syntax::rSDATA:
1516 dataType = Entity::sdata;
1518 case Param::reservedName + Syntax::rPI:
1519 dataType = Entity::pi;
1521 case Param::reservedName + Syntax::rSTARTTAG:
1522 bracketed = InternalTextEntity::starttag;
1524 case Param::reservedName + Syntax::rENDTAG:
1525 bracketed = InternalTextEntity::endtag;
1527 case Param::reservedName + Syntax::rMS:
1528 bracketed = InternalTextEntity::ms;
1530 case Param::reservedName + Syntax::rMD:
1531 bracketed = InternalTextEntity::md;
1534 if (parm.type != Param::paramLiteral) {
1535 if (!parseParam(allowParamLiteral, declInputLevel, parm))
1539 parm.literalText.swap(text);
1540 if (bracketed != InternalTextEntity::none) {
1543 switch (bracketed) {
1544 case InternalTextEntity::starttag:
1545 open = syntax().delimGeneral(Syntax::dSTAGO);
1546 close = syntax().delimGeneral(Syntax::dTAGC);
1548 case InternalTextEntity::endtag:
1549 open = syntax().delimGeneral(Syntax::dETAGO);
1550 close = syntax().delimGeneral(Syntax::dTAGC);
1552 case InternalTextEntity::ms:
1553 open = syntax().delimGeneral(Syntax::dMDO);
1554 open += syntax().delimGeneral(Syntax::dDSO);
1555 close = syntax().delimGeneral(Syntax::dMSC);
1556 close += syntax().delimGeneral(Syntax::dMDC);
1558 case InternalTextEntity::md:
1559 open = syntax().delimGeneral(Syntax::dMDO);
1560 close = syntax().delimGeneral(Syntax::dMDC);
1565 text.insertChars(open, Location(new BracketOrigin(typeLocation,
1566 BracketOrigin::open),
1568 text.addChars(close, Location(new BracketOrigin(typeLocation,
1569 BracketOrigin::close),
1571 if (text.size() > syntax().litlen()
1572 && text.size() - open.size() - close.size() <= syntax().litlen())
1573 message(ParserMessages::bracketedLitlen,
1574 NumberMessageArg(syntax().litlen()));
1576 if (!parseParam(allowMdc, declInputLevel, parm))
1578 if (declType == Entity::parameterEntity
1579 && (dataType == Entity::cdata || dataType == Entity::sdata)) {
1580 message(ParserMessages::internalParameterDataEntity,
1581 StringMessageArg(name));
1587 entity = new InternalCdataEntity(name, markupLocation(), text);
1590 entity = new InternalSdataEntity(name, markupLocation(), text);
1593 entity = new PiEntity(name, declType, markupLocation(), text);
1595 case Entity::sgmlText:
1596 entity = new InternalTextEntity(name, declType, markupLocation(), text, bracketed);
1602 maybeDefineEntity(entity);
1606 Boolean Parser::parseExternalEntity(StringC &name,
1607 Entity::DeclType declType,
1608 unsigned declInputLevel,
1611 static AllowedParams
1612 allowSystemIdentifierEntityTypeMdc(Param::systemIdentifier,
1613 Param::reservedName + Syntax::rSUBDOC,
1614 Param::reservedName + Syntax::rCDATA,
1615 Param::reservedName + Syntax::rSDATA,
1616 Param::reservedName + Syntax::rNDATA,
1618 static AllowedParams
1619 allowEntityTypeMdc(Param::reservedName + Syntax::rSUBDOC,
1620 Param::reservedName + Syntax::rCDATA,
1621 Param::reservedName + Syntax::rSDATA,
1622 Param::reservedName + Syntax::rNDATA,
1626 if (!parseExternalId(allowSystemIdentifierEntityTypeMdc, allowEntityTypeMdc,
1627 declInputLevel, parm, id))
1629 if (parm.type == Param::mdc) {
1630 maybeDefineEntity(new ExternalTextEntity(name, declType, markupLocation(),
1635 if (parm.type == Param::reservedName + Syntax::rSUBDOC) {
1636 if (sd().subdoc() == 0)
1637 message(ParserMessages::subdocEntity, StringMessageArg(name));
1638 if (!parseParam(allowMdc, declInputLevel, parm))
1640 entity = new SubdocEntity(name, markupLocation(), id);
1643 Entity::DataType dataType;
1644 switch (parm.type) {
1645 case Param::reservedName + Syntax::rCDATA:
1646 dataType = Entity::cdata;
1648 case Param::reservedName + Syntax::rSDATA:
1649 dataType = Entity::sdata;
1651 case Param::reservedName + Syntax::rNDATA:
1652 dataType = Entity::ndata;
1657 if (!parseParam(allowName, declInputLevel, parm))
1659 ConstPtr<Notation> notation(lookupCreateNotation(parm.token));
1660 if (!parseParam(allowDsoMdc, declInputLevel, parm))
1662 AttributeList attributes(notation->attributeDef());
1663 if (parm.type == Param::dso) {
1664 if (attributes.size() == 0)
1665 message(ParserMessages::notationNoAttributes,
1666 StringMessageArg(notation->name()));
1667 Boolean netEnabling;
1668 if (!parseAttributeSpec(1, attributes, netEnabling))
1670 if (attributes.nSpec() == 0)
1671 message(ParserMessages::emptyDataAttributeSpec);
1672 if (!parseParam(allowMdc, declInputLevel, parm))
1676 attributes.finish(*this);
1677 entity = new ExternalDataEntity(name, dataType, markupLocation(), id, notation,
1680 if (declType == Entity::parameterEntity) {
1681 message(ParserMessages::externalParameterDataSubdocEntity,
1682 StringMessageArg(name));
1685 maybeDefineEntity(entity);
1689 Notation *Parser::lookupCreateNotation(const StringC &name)
1691 Ptr<Notation> nt = defDtd().lookupNotation(name);
1693 nt = new Notation(name, defDtd().namePointer(), defDtd().isBase());
1694 defDtd().insertNotation(nt);
1696 return nt.pointer();
1699 void Parser::maybeDefineEntity(const Ptr<Entity> &entity)
1701 Dtd &dtd = defDtd();
1703 entity->setDeclIn(dtd.namePointer(),
1705 defLpd().namePointer(),
1708 entity->setDeclIn(dtd.namePointer(), dtd.isBase());
1709 Boolean ignored = 0;
1710 if (entity->name().size() == 0) {
1711 const Entity *oldEntity = dtd.defaultEntity().pointer();
1713 || (!oldEntity->declInActiveLpd() && entity->declInActiveLpd()))
1714 dtd.setDefaultEntity(entity, *this);
1717 if (options().warnDuplicateEntity)
1718 message(ParserMessages::duplicateEntityDeclaration,
1719 StringMessageArg(syntax().rniReservedName(Syntax::rDEFAULT)));
1723 Ptr<Entity> oldEntity = dtd.insertEntity(entity);
1724 if (oldEntity.isNull())
1725 entity->generateSystemId(*this);
1726 else if (oldEntity->defaulted()) {
1727 dtd.insertEntity(entity, 1);
1728 message(ParserMessages::defaultedEntityDefined,
1729 StringMessageArg(entity->name()));
1730 entity->generateSystemId(*this);
1733 if (entity->declInActiveLpd() && !oldEntity->declInActiveLpd()) {
1734 dtd.insertEntity(entity, 1);
1735 entity->generateSystemId(*this);
1739 if (options().warnDuplicateEntity)
1740 message(entity->declType() == Entity::parameterEntity
1741 ? ParserMessages::duplicateParameterEntityDeclaration
1742 : ParserMessages::duplicateEntityDeclaration,
1743 StringMessageArg(entity->name()));
1747 if (currentMarkup())
1748 eventHandler().entityDecl(new (eventAllocator())
1749 EntityDeclEvent(entity, ignored,
1754 Boolean Parser::parseShortrefDecl()
1756 if (!defDtd().isBase())
1757 message(ParserMessages::shortrefOnlyInBaseDtd);
1759 unsigned declInputLevel = inputLevel();
1762 if (!parseParam(allowName, declInputLevel, parm))
1764 ShortReferenceMap *map = lookupCreateMap(parm.token);
1766 if (map->defined()) {
1767 message(ParserMessages::duplicateShortrefDeclaration,
1768 StringMessageArg(parm.token),
1769 map->defLocation());
1773 map->setDefLocation(markupLocation());
1774 if (!parseParam(allowParamLiteral, declInputLevel, parm))
1776 Vector<StringC> vec;
1778 StringC delim(parm.literalText.string());
1779 const SubstTable<Char> *table = instanceSyntax().generalSubstTable();
1780 for (size_t i = 0; i < delim.size(); i++)
1781 table->subst(delim[i]);
1783 if (!defDtd().shortrefIndex(delim, instanceSyntax(), srIndex)) {
1784 message(ParserMessages::unknownShortrefDelim,
1785 StringMessageArg(prettifyDelim(delim)));
1788 static AllowedParams allowEntityName(Param::entityName);
1789 if (!parseParam(allowEntityName, declInputLevel, parm))
1792 if (srIndex >= vec.size())
1793 vec.resize(srIndex + 1);
1794 if (vec[srIndex].size() > 0) {
1795 message(ParserMessages::delimDuplicateMap,
1796 StringMessageArg(prettifyDelim(delim)));
1800 parm.token.swap(vec[srIndex]);
1802 static AllowedParams allowParamLiteralMdc(Param::paramLiteral, Param::mdc);
1803 if (!parseParam(allowParamLiteralMdc, declInputLevel, parm))
1805 } while (parm.type != Param::mdc);
1807 map->setNameMap(vec);
1808 if (currentMarkup())
1809 eventHandler().shortrefDecl(new (eventAllocator())
1810 ShortrefDeclEvent(map,
1811 currentDtdPointer(),
1818 StringC Parser::prettifyDelim(const StringC &delim)
1820 StringC prettyDelim;
1821 for (size_t i = 0; i < delim.size(); i++) {
1822 const StringC *nameP;
1823 if (syntax().charFunctionName(delim[i], nameP)) {
1824 prettyDelim += syntax().delimGeneral(Syntax::dCRO);
1825 prettyDelim += *nameP;
1826 prettyDelim += syntax().delimGeneral(Syntax::dREFC);
1829 prettyDelim += delim[i];
1834 ShortReferenceMap *Parser::lookupCreateMap(const StringC &name)
1836 ShortReferenceMap *map = defDtd().lookupShortReferenceMap(name);
1838 map = new ShortReferenceMap(name);
1839 defDtd().insertShortReferenceMap(map);
1844 Boolean Parser::parseUsemapDecl()
1846 if (!inInstance() && !defDtd().isBase())
1847 message(ParserMessages::usemapOnlyInBaseDtd);
1849 unsigned declInputLevel = inputLevel();
1851 static AllowedParams
1852 allowNameEmpty(Param::name,
1853 Param::indicatedReservedName + Syntax::rEMPTY);
1854 if (!parseParam(allowNameEmpty, declInputLevel, parm))
1856 const ShortReferenceMap *map;
1857 if (parm.type == Param::name) {
1859 map = currentDtd().lookupShortReferenceMap(parm.token);
1861 message(ParserMessages::undefinedShortrefMapInstance,
1862 StringMessageArg(parm.token));
1865 ShortReferenceMap *tem = lookupCreateMap(parm.token);
1872 static AllowedParams
1873 allowNameNameGroupMdc(Param::name, Param::nameGroup, Param::mdc);
1874 if (!parseParam(allowNameNameGroupMdc, declInputLevel, parm))
1876 if (parm.type != Param::mdc) {
1878 message(ParserMessages::usemapAssociatedElementTypeInstance);
1879 if (!parseParam(allowMdc, declInputLevel, parm))
1883 Vector<const ElementType *> v;
1884 if (parm.type == Param::name) {
1885 ElementType *e = lookupCreateElement(parm.token);
1891 v.resize(parm.nameTokenVector.size());
1892 for (size_t i = 0; i < parm.nameTokenVector.size(); i++) {
1894 = lookupCreateElement(parm.nameTokenVector[i].name);
1900 if (!parseParam(allowMdc, declInputLevel, parm))
1902 if (currentMarkup())
1903 eventHandler().usemap(new (eventAllocator())
1905 currentDtdPointer(),
1912 message(ParserMessages::usemapAssociatedElementTypeDtd);
1914 if (map != &theEmptyMap && !map->defined())
1915 message(ParserMessages::undefinedShortrefMapInstance,
1916 StringMessageArg(map->name()));
1918 if (currentMarkup()) {
1919 Vector<const ElementType *> v;
1920 eventHandler().usemap(new (eventAllocator())
1922 currentDtdPointer(),
1926 currentElement().setMap(map);
1933 Boolean Parser::parseDoctypeDeclStart()
1935 if (hadDtd() && !sd().concur() && !sd().explicitLink())
1936 message(ParserMessages::multipleDtds);
1938 message(ParserMessages::dtdAfterLpd);
1939 unsigned declInputLevel = inputLevel();
1942 if (!parseParam(allowName, declInputLevel, parm))
1945 parm.token.swap(name);
1946 if (!lookupDtd(name).isNull())
1947 message(ParserMessages::duplicateDtd, StringMessageArg(name));
1948 static AllowedParams
1949 allowPublicSystemDsoMdc(Param::reservedName + Syntax::rPUBLIC,
1950 Param::reservedName + Syntax::rSYSTEM,
1953 if (!parseParam(allowPublicSystemDsoMdc, declInputLevel, parm))
1955 ConstPtr<Entity> entity;
1956 if (parm.type == Param::reservedName + Syntax::rPUBLIC
1957 || parm.type == Param::reservedName + Syntax::rSYSTEM) {
1958 static AllowedParams allowSystemIdentifierDsoMdc(Param::systemIdentifier,
1959 Param::dso, Param::mdc);
1961 if (!parseExternalId(allowSystemIdentifierDsoMdc, allowDsoMdc,
1962 declInputLevel, parm, id))
1965 = new ExternalTextEntity(name, Entity::doctype, markupLocation(), id);
1966 tem->generateSystemId(*this);
1970 .externalEntityDecl(new (eventAllocator())
1971 ExternalEntityDeclEvent(entity, 0));
1974 else if (parm.type == Param::mdc) {
1975 message(ParserMessages::noDtdSubset, StringMessageArg(name));
1978 // Discard mdc or dso
1979 if (currentMarkup())
1980 currentMarkup()->resize(currentMarkup()->size() - 1);
1981 eventHandler().startDtd(new (eventAllocator())
1982 StartDtdEvent(name, entity, parm.type == Param::dso,
1986 if (parm.type == Param::mdc) {
1988 currentInput()->ungetToken();
1989 // reference the entity
1990 Ptr<EntityOrigin> origin
1991 = new (internalAllocator()) EntityOrigin(entity, currentLocation());
1992 entity->dsReference(*this, origin);
1993 if (inputLevel() == 1) { // reference failed
1994 (void)parseDoctypeDeclEnd();
1998 else if (!entity.isNull())
1999 setDsEntity(entity);
2000 setPhase(declSubsetPhase);
2004 Boolean Parser::implyDtd(const StringC &gi)
2007 // The null location indicates that this is a fake entity.
2008 ConstPtr<Entity> entity(new ExternalTextEntity(gi,
2012 // Don't use Entity::generateSystemId because we don't want an error
2016 if (!entityCatalog().lookup(*entity, syntax(), sd().docCharset(),
2017 messenger(), str)) {
2018 if (!entityCatalog().defaultDoctype(sd().docCharset(),
2023 for (size_t i = 0; i < name.size(); i++)
2024 syntax().generalSubstTable()->subst(name[i]);
2028 id.setEffectiveSystem(str);
2029 entity = new ExternalTextEntity(name,
2034 declStr += syntax().delimGeneral(Syntax::dMDO);
2035 declStr += syntax().reservedName(Syntax::rDOCTYPE);
2036 declStr += syntax().space();
2038 declStr += syntax().space();
2039 declStr += syntax().reservedName(Syntax::rSYSTEM);
2040 declStr += syntax().delimGeneral(Syntax::dMDC);
2041 message(ParserMessages::implyingDtd, StringMessageArg(declStr));
2042 Ptr<EntityOrigin> origin
2043 = new (internalAllocator()) EntityOrigin(entity, currentLocation());
2044 startMarkup(eventsWanted().wantPrologMarkup(), Location());
2045 if (currentMarkup()) {
2046 currentMarkup()->addDelim(Syntax::dMDO);
2047 currentMarkup()->addReservedName(Syntax::rDOCTYPE,
2048 syntax().reservedName(Syntax::rDOCTYPE));
2049 currentMarkup()->addS(syntax().space());
2050 currentMarkup()->addName(name.data(), name.size());
2051 currentMarkup()->addS(syntax().space());
2052 currentMarkup()->addReservedName(Syntax::rSYSTEM,
2053 syntax().reservedName(Syntax::rSYSTEM));
2055 eventHandler().startDtd(new (eventAllocator())
2056 StartDtdEvent(name, entity, 0,
2060 entity->dsReference(*this, origin);
2061 if (inputLevel() == 1) {
2062 parseDoctypeDeclEnd(1);
2065 setPhase(declSubsetPhase);
2069 Boolean Parser::parseDoctypeDeclEnd(Boolean fake)
2072 Ptr<Dtd> tem(defDtdPointer());
2075 startMarkup(eventsWanted().wantPrologMarkup(), Location());
2076 if (currentMarkup())
2077 currentMarkup()->addDelim(Syntax::dMDC);
2080 startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2082 // End DTD before parsing final param so parameter entity reference
2083 // not allowed between ] and >.
2084 if (!parseParam(allowMdc, inputLevel(), parm))
2087 eventHandler().endDtd(new (eventAllocator()) EndDtdEvent(tem,
2091 Char c = syntax().standardFunction(Syntax::fRE);
2092 eventHandler().sSep(new (eventAllocator())
2093 SSepEvent(&c, 1, Location(), 1));
2098 void Parser::checkDtd(Dtd &dtd)
2101 addNeededShortrefs(dtd, instanceSyntax());
2102 if (!options().errorAfdr)
2103 addCommonAttributes(dtd);
2104 Dtd::ElementTypeIter elementIter(dtd.elementTypeIter());
2106 ConstPtr<ElementDefinition> def;
2108 while ((p = elementIter.next()) != 0) {
2109 if (p->definition() == 0) {
2110 if (p->name() == dtd.name())
2111 message(ParserMessages::documentElementUndefined);
2112 else if (options().warnUndefinedElement)
2113 message(ParserMessages::dtdUndefinedElement, StringMessageArg(p->name()));
2115 def = new ElementDefinition(currentLocation(),
2116 ElementDefinition::undefinedIndex,
2117 (ElementDefinition::omitStart
2118 |ElementDefinition::omitEnd),
2119 ElementDefinition::any);
2120 p->setElementDefinition(def, i++);
2122 const ShortReferenceMap *map = p->map();
2123 if (map != 0 && map != &theEmptyMap && !map->defined()) {
2124 message(ParserMessages::undefinedShortrefMapDtd,
2125 StringMessageArg(map->name()),
2126 StringMessageArg(p->name()));
2130 Dtd::ConstEntityIter entityIter(((const Dtd &)dtd).generalEntityIter());
2132 ConstPtr<Entity> entity(entityIter.next());
2133 if (entity.isNull())
2135 const ExternalDataEntity *external = entity->asExternalDataEntity();
2137 const Notation *notation = external->notation();
2138 if (!notation->defined()) {
2139 setNextLocation(external->defLocation());
2140 message(ParserMessages::entityNotationUndefined,
2141 StringMessageArg(notation->name()),
2142 StringMessageArg(external->name()));
2146 Dtd::NotationIter notationIter(dtd.notationIter());
2148 ConstPtr<Notation> notation(notationIter.next());
2149 if (notation.isNull())
2151 if (!notation->defined() && !notation->attributeDef().isNull())
2152 message(ParserMessages::attlistNotationUndefined,
2153 StringMessageArg(notation->name()));
2155 Dtd::ShortReferenceMapIter mapIter(dtd.shortReferenceMapIter());
2156 int nShortref = dtd.nShortref();
2158 ShortReferenceMap *map = mapIter.next();
2161 Vector<ConstPtr<Entity> > entityMap(nShortref);
2162 for (i = 0; i < nShortref; i++) {
2163 const StringC *entityName = map->entityName(i);
2165 ConstPtr<Entity> entity
2166 = lookupEntity(0, *entityName, map->defLocation(), 0);
2167 if (entity.isNull()) {
2168 setNextLocation(map->defLocation());
2169 message(ParserMessages::mapEntityUndefined,
2170 StringMessageArg(*entityName),
2171 StringMessageArg(map->name()));
2174 if (entity->defaulted() && options().warnDefaultEntityReference) {
2175 setNextLocation(map->defLocation());
2176 message(ParserMessages::mapDefaultEntity,
2177 StringMessageArg(*entityName),
2178 StringMessageArg(map->name()));
2180 entityMap[i] = entity;
2184 map->setEntityMap(entityMap);
2185 if (options().warnUnusedMap && !map->used()) {
2186 setNextLocation(map->defLocation());
2187 message(ParserMessages::unusedMap, StringMessageArg(map->name()));
2190 if (options().warnUnusedParam) {
2191 Dtd::ConstEntityIter entityIter(((const Dtd &)dtd).parameterEntityIter());
2193 ConstPtr<Entity> entity(entityIter.next());
2194 if (entity.isNull())
2196 if (!entity->used() && !maybeStatusKeyword(*entity)) {
2197 setNextLocation(entity->defLocation());
2198 message(ParserMessages::unusedParamEntity,
2199 StringMessageArg(entity->name()));
2205 void Parser::addCommonAttributes(Dtd &dtd)
2207 Ptr<AttributeDefinitionList> commonAdl[2];
2209 ElementType *e = dtd.removeElementType(syntax()
2210 .rniReservedName(Syntax::rANY));
2212 commonAdl[0] = e->attributeDef();
2217 Ptr<Notation> allNotation
2218 = dtd.removeNotation(syntax().rniReservedName(Syntax::rANY));
2219 if (!allNotation.isNull())
2220 commonAdl[1] = allNotation->attributeDef();
2222 Dtd::ElementTypeIter elementIter(dtd.elementTypeIter());
2223 Dtd::NotationIter notationIter(dtd.notationIter());
2224 Vector<PackedBoolean> doneAdl(dtd.nAttributeDefinitionList(),
2226 for (int isNotation = 0; isNotation < 2; isNotation++) {
2227 if (!commonAdl[isNotation].isNull()) {
2228 doneAdl[commonAdl[isNotation]->index()] = 1;
2232 a = elementIter.next();
2234 a = notationIter.next().pointer();
2237 Ptr<AttributeDefinitionList> adl = a->attributeDef();
2239 a->setAttributeDef(commonAdl[isNotation]);
2240 else if (!doneAdl[adl->index()]) {
2241 doneAdl[adl->index()] = 1;
2242 for (size_t j = 0; j < commonAdl[isNotation]->size(); j++) {
2244 if (!adl->attributeIndex(commonAdl[isNotation]->def(j)->name(),
2246 adl->append(commonAdl[isNotation]->def(j)->copy());
2254 Boolean Parser::maybeStatusKeyword(const Entity &entity)
2256 const InternalEntity *internal = entity.asInternalEntity();
2259 const StringC &text = internal->string();
2260 static const Syntax::ReservedName statusKeywords[] = {
2261 Syntax::rINCLUDE, Syntax::rIGNORE
2263 for (size_t i = 0; i < SIZEOF(statusKeywords); i++) {
2264 const StringC &keyword = instanceSyntax().reservedName(statusKeywords[i]);
2266 while (j < text.size() && instanceSyntax().isS(text[j]))
2269 while (j < text.size()
2270 && k < keyword.size()
2271 && ((*instanceSyntax().generalSubstTable())[text[j]]
2274 if (k == keyword.size()) {
2275 while (j < text.size() && instanceSyntax().isS(text[j]))
2277 if (j == text.size())
2284 Boolean Parser::parseLinktypeDeclStart()
2286 if (baseDtd().isNull())
2287 message(ParserMessages::lpdBeforeBaseDtd);
2288 unsigned declInputLevel = inputLevel();
2291 if (!parseParam(allowName, declInputLevel, parm))
2294 parm.token.swap(name);
2295 if (!lookupDtd(name).isNull())
2296 message(ParserMessages::duplicateDtdLpd, StringMessageArg(name));
2297 else if (!lookupLpd(name).isNull())
2298 message(ParserMessages::duplicateLpd, StringMessageArg(name));
2299 static AllowedParams
2300 allowSimpleName(Param::indicatedReservedName + Syntax::rSIMPLE,
2302 if (!parseParam(allowSimpleName, declInputLevel, parm))
2306 if (parm.type == Param::indicatedReservedName + Syntax::rSIMPLE) {
2308 sourceDtd = baseDtd();
2309 if (sourceDtd.isNull())
2310 sourceDtd = new Dtd(StringC(), 1);
2314 sourceDtd = lookupDtd(parm.token);
2315 if (sourceDtd.isNull()) {
2316 message(ParserMessages::noSuchDtd, StringMessageArg(parm.token));
2317 sourceDtd = new Dtd(parm.token, 0);
2320 static AllowedParams
2321 allowImpliedName(Param::indicatedReservedName + Syntax::rIMPLIED,
2323 if (!parseParam(allowImpliedName, declInputLevel, parm))
2326 Boolean implied = 0;
2327 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2329 if (!sd().simpleLink())
2330 message(ParserMessages::simpleLinkFeature);
2334 if (!sd().implicitLink())
2335 message(ParserMessages::implicitLinkFeature);
2340 message(ParserMessages::simpleLinkResultNotImplied);
2342 if (!sd().explicitLink())
2343 message(ParserMessages::explicitLinkFeature);
2344 resultDtd = lookupDtd(parm.token);
2345 if (resultDtd.isNull())
2346 message(ParserMessages::noSuchDtd, StringMessageArg(parm.token));
2349 static AllowedParams
2350 allowPublicSystemDsoMdc(Param::reservedName + Syntax::rPUBLIC,
2351 Param::reservedName + Syntax::rSYSTEM,
2354 if (!parseParam(allowPublicSystemDsoMdc, declInputLevel, parm))
2356 ConstPtr<Entity> entity;
2357 if (parm.type == Param::reservedName + Syntax::rPUBLIC
2358 || parm.type == Param::reservedName + Syntax::rSYSTEM) {
2359 static AllowedParams allowSystemIdentifierDsoMdc(Param::systemIdentifier,
2360 Param::dso, Param::mdc);
2362 if (!parseExternalId(allowSystemIdentifierDsoMdc, allowDsoMdc,
2363 declInputLevel, parm, id))
2366 = new ExternalTextEntity(name, Entity::linktype, markupLocation(), id);
2367 tem->generateSystemId(*this);
2371 .externalEntityDecl(new (eventAllocator())
2372 ExternalEntityDeclEvent(entity, 0));
2377 lpd = new SimpleLpd(name, markupLocation(), sourceDtd);
2379 lpd = new ComplexLpd(name,
2380 implied ? Lpd::implicitLink : Lpd::explicitLink,
2385 if (!baseDtd().isNull() && shouldActivateLink(name)) {
2386 size_t nActive = nActiveLink();
2389 for (size_t i = 0; i < nActive; i++)
2390 if (activeLpd(i).type() == Lpd::simpleLink)
2392 if (nSimple == sd().simpleLink())
2393 message(ParserMessages::simpleLinkCount,
2394 NumberMessageArg(sd().simpleLink()));
2398 Boolean haveImplicit = 0;
2399 Boolean haveExplicit = 0;
2401 for (i = 0; i < nActive; i++) {
2402 if (activeLpd(i).type() == Lpd::implicitLink)
2404 else if (activeLpd(i).type() == Lpd::explicitLink)
2407 const Dtd *sourceDtd = lpd->sourceDtd().pointer();
2408 if (implied && haveImplicit)
2409 message(ParserMessages::oneImplicitLink);
2410 else if (sd().explicitLink() <= 1 && sourceDtd != baseDtd().pointer())
2411 message(sd().explicitLink() == 0
2412 ? ParserMessages::explicitNoRequiresSourceTypeBase
2413 : ParserMessages::explicit1RequiresSourceTypeBase,
2414 StringMessageArg(lpd->name()));
2415 else if (sd().explicitLink() == 1 && haveExplicit && !implied)
2416 message(ParserMessages::duplicateExplicitChain);
2417 else if (haveExplicit || haveImplicit
2418 || sourceDtd != baseDtd().pointer())
2419 message(ParserMessages::sorryLink, StringMessageArg(lpd->name()));
2424 // Discard mdc or dso
2425 if (currentMarkup())
2426 currentMarkup()->resize(currentMarkup()->size() - 1);
2427 eventHandler().startLpd(new (eventAllocator())
2428 StartLpdEvent(lpd->active(),
2431 parm.type == Param::dso,
2435 if (parm.type == Param::mdc) {
2437 currentInput()->ungetToken();
2438 if (entity.isNull()) {
2439 message(ParserMessages::noLpdSubset, StringMessageArg(name));
2440 (void)parseLinktypeDeclEnd();
2443 // reference the entity
2444 Ptr<EntityOrigin> origin
2445 = new (internalAllocator()) EntityOrigin(entity, currentLocation());
2446 entity->dsReference(*this, origin);
2447 if (inputLevel() == 1) { // reference failed
2448 (void)parseLinktypeDeclEnd();
2452 else if (!entity.isNull())
2453 setDsEntity(entity);
2454 setPhase(declSubsetPhase);
2458 Boolean Parser::parseLinktypeDeclEnd()
2461 if (defLpd().type() != Lpd::simpleLink) {
2462 if (!defComplexLpd().initialLinkSet()->defined())
2463 message(ParserMessages::noInitialLinkSet,
2464 StringMessageArg(defLpd().name()));
2465 ComplexLpd::ConstLinkSetIter iter = defComplexLpd().linkSetIter();
2466 const LinkSet *linkSet;
2467 while ((linkSet = iter.next()) != 0)
2468 if (!linkSet->defined())
2469 message(ParserMessages::undefinedLinkSet, StringMessageArg(linkSet->name()));
2471 ConstPtr<Lpd> tem(defLpdPointer());
2473 startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2475 Boolean result = parseParam(allowMdc, inputLevel(), parm);
2476 eventHandler().endLpd(new (eventAllocator()) EndLpdEvent(tem,
2482 Boolean Parser::parseLinkDecl()
2484 return parseLinkSet(0);
2487 Boolean Parser::parseIdlinkDecl()
2489 return parseLinkSet(1);
2492 // This will only get called if we're defining a complex lpd.
2494 Boolean Parser::parseLinkSet(Boolean idlink)
2496 if (defLpd().type() == Lpd::simpleLink) {
2497 message(idlink ? ParserMessages::idlinkDeclSimple : ParserMessages::linkDeclSimple);
2501 if (defComplexLpd().hadIdLinkSet())
2502 message(ParserMessages::duplicateIdLinkSet);
2504 defComplexLpd().setHadIdLinkSet();
2506 unsigned declInputLevel = inputLevel();
2509 Boolean isExplicit = (defLpd().type() == Lpd::explicitLink);
2512 if (!parseParam(allowName, declInputLevel, parm))
2517 static AllowedParams
2518 allowNameInitial(Param::name,
2519 Param::indicatedReservedName + Syntax::rINITIAL);
2520 if (!parseParam(allowNameInitial, declInputLevel, parm))
2522 if (parm.type == Param::name)
2523 linkSet = lookupCreateLinkSet(parm.token);
2525 linkSet = defComplexLpd().initialLinkSet();
2526 if (linkSet->defined())
2527 message(ParserMessages::duplicateLinkSet, StringMessageArg(linkSet->name()));
2528 static AllowedParams
2529 allowExplicitLinkRule(Param::name,
2531 Param::indicatedReservedName + Syntax::rIMPLIED);
2532 if (!parseParam(isExplicit ? allowExplicitLinkRule : allowNameNameGroup,
2533 declInputLevel, parm))
2540 parm.token.swap(id);
2541 if (!parseParam(isExplicit ? allowExplicitLinkRuleMdc : allowNameNameGroupMdc,
2542 declInputLevel, parm))
2545 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2546 if (!parseParam(allowName, declInputLevel, parm))
2548 Boolean resultImplied;
2549 const ElementType *resultType;
2550 AttributeList resultAttributes;
2551 if (!parseResultElementSpec(declInputLevel,
2559 const AttributeList *dummy;
2560 if (linkSet->impliedResultAttributes(resultType, dummy))
2561 message(ParserMessages::duplicateImpliedResult,
2562 StringMessageArg(resultType->name()));
2564 linkSet->addImplied(resultType, resultAttributes);
2568 SourceLinkRule *linkRule = 0;
2569 IdLinkRule idLinkRule;
2570 Ptr<SourceLinkRuleResource> linkRuleResource;
2572 linkRule = &idLinkRule;
2574 linkRuleResource = new SourceLinkRuleResource;
2575 linkRule = linkRuleResource.pointer();
2577 Vector<const ElementType *> assocElementTypes;
2578 if (parm.type == Param::name) {
2579 assocElementTypes.resize(1);
2580 assocElementTypes[0] = lookupCreateElement(parm.token);
2583 assocElementTypes.resize(parm.nameTokenVector.size());
2584 for (size_t i = 0; i < assocElementTypes.size(); i++)
2585 assocElementTypes[i]
2586 = lookupCreateElement(parm.nameTokenVector[i].name);
2588 static AllowedParams
2589 allow2i(Param::indicatedReservedName + Syntax::rUSELINK,
2590 Param::indicatedReservedName + Syntax::rPOSTLINK,
2595 static AllowedParams
2596 allow2id(Param::indicatedReservedName + Syntax::rUSELINK,
2597 Param::indicatedReservedName + Syntax::rPOSTLINK,
2601 static AllowedParams
2602 allow2e(Param::indicatedReservedName + Syntax::rUSELINK,
2603 Param::indicatedReservedName + Syntax::rPOSTLINK,
2606 Param::indicatedReservedName + Syntax::rIMPLIED);
2608 if (!parseParam(isExplicit
2610 : (idlink ? allow2id : allow2i), declInputLevel, parm))
2612 if (parm.type == Param::indicatedReservedName + Syntax::rUSELINK) {
2613 static AllowedParams
2614 allowLinkSetEmpty(Param::name,
2615 Param::indicatedReservedName + Syntax::rINITIAL,
2616 Param::indicatedReservedName + Syntax::rEMPTY);
2617 if (!parseParam(allowLinkSetEmpty, declInputLevel, parm))
2619 const LinkSet *uselink;
2620 if (parm.type == Param::name)
2621 uselink = lookupCreateLinkSet(parm.token);
2622 else if (parm.type == Param::indicatedReservedName + Syntax::rINITIAL)
2623 uselink = defComplexLpd().initialLinkSet();
2625 uselink = defComplexLpd().emptyLinkSet();
2626 linkRule->setUselink(uselink);
2627 static AllowedParams
2628 allow3i(Param::indicatedReservedName + Syntax::rPOSTLINK,
2633 static AllowedParams
2634 allow3id(Param::indicatedReservedName + Syntax::rPOSTLINK,
2638 static AllowedParams
2639 allow3e(Param::indicatedReservedName + Syntax::rPOSTLINK,
2642 Param::indicatedReservedName + Syntax::rIMPLIED);
2644 if (!parseParam(isExplicit
2646 : (idlink ? allow3id : allow3i),
2647 declInputLevel, parm))
2650 if (parm.type == Param::indicatedReservedName + Syntax::rPOSTLINK) {
2651 if (!parseParam(allowLinkSetSpec, declInputLevel, parm))
2653 const LinkSet *postlink;
2654 if (parm.type == Param::indicatedReservedName + Syntax::rRESTORE)
2655 linkRule->setPostlinkRestore();
2657 if (parm.type == Param::name)
2658 postlink = lookupCreateLinkSet(parm.token);
2660 == Param::indicatedReservedName + Syntax::rINITIAL)
2661 postlink = defComplexLpd().initialLinkSet();
2663 postlink = defComplexLpd().emptyLinkSet();
2664 linkRule->setPostlink(postlink);
2666 static AllowedParams
2671 static AllowedParams
2672 allow4id(Param::dso,
2675 static AllowedParams
2678 Param::indicatedReservedName + Syntax::rIMPLIED);
2679 if (!parseParam(isExplicit
2681 : (idlink ? allow4id : allow4i),
2682 declInputLevel, parm))
2685 AttributeList attributes;
2686 ConstPtr<AttributeDefinitionList> attDef;
2687 for (size_t i = 0; i < assocElementTypes.size(); i++) {
2688 const ElementType *e = assocElementTypes[i];
2691 attDef = defComplexLpd().attributeDef(e);
2692 else if (attDef != defComplexLpd().attributeDef(e))
2693 message(ParserMessages::assocElementDifferentAtts);
2694 // FIXME recover from this
2697 attributes.init(attDef);
2699 if (parm.type == Param::dso) {
2700 Boolean netEnabling;
2701 if (!parseAttributeSpec(1, attributes, netEnabling))
2703 static AllowedParams
2704 allow5e(Param::name,
2705 Param::indicatedReservedName + Syntax::rIMPLIED);
2706 if (!parseParam(isExplicit
2708 : (idlink ? allowNameMdc : allowNameNameGroupMdc),
2709 declInputLevel, parm))
2713 attributes.finish(*this);
2714 linkRule->setLinkAttributes(attributes);
2716 Boolean resultImplied;
2717 const ElementType *resultType;
2718 AttributeList resultAttributes;
2719 if (!parseResultElementSpec(declInputLevel,
2727 linkRule->setResult(resultType, resultAttributes);
2729 // Install the link rule.
2731 idLinkRule.setAssocElementTypes(assocElementTypes);
2732 addIdLinkRule(id, idLinkRule);
2735 if (!linkSet->defined()) {
2736 for (size_t i = 0; i < assocElementTypes.size(); i++)
2737 if (assocElementTypes[i])
2738 addLinkRule(linkSet, assocElementTypes[i], linkRuleResource);
2742 } while (parm.type != Param::mdc);
2744 linkSet->setDefined();
2745 if (currentMarkup()) {
2747 eventHandler().idLinkDecl(new (eventAllocator())
2748 IdLinkDeclEvent(defComplexLpdPointer(),
2752 eventHandler().linkDecl(new (eventAllocator())
2753 LinkDeclEvent(linkSet,
2754 defComplexLpdPointer(),
2761 void Parser::addIdLinkRule(const StringC &id,
2764 IdLinkRuleGroup *group = defComplexLpd().lookupCreateIdLink(id);
2765 size_t nRules = group->nLinkRules();
2766 if ((nRules == 1 && group->linkRule(0).attributes().nSpec() == 0)
2767 || nRules >= 1 && rule.attributes().nSpec() == 0)
2768 message(ParserMessages::multipleIdLinkRuleAttribute,
2769 StringMessageArg(id));
2770 group->addLinkRule(rule);
2773 void Parser::addLinkRule(LinkSet *linkSet,
2774 const ElementType *sourceElement,
2775 const ConstPtr<SourceLinkRuleResource> &linkRule)
2777 size_t nRules = linkSet->nLinkRules(sourceElement);
2779 && linkSet->linkRule(sourceElement, 0).attributes().nSpec() == 0)
2780 || nRules >= 1 && linkRule->attributes().nSpec() == 0)
2781 message(ParserMessages::multipleLinkRuleAttribute,
2782 StringMessageArg(sourceElement->name()));
2783 linkSet->addLinkRule(sourceElement, linkRule);
2786 class ResultAttributeSpecModeSetter {
2788 ResultAttributeSpecModeSetter(ParserState *state) : state_(state) {
2789 state_->setResultAttributeSpecMode();
2791 ~ResultAttributeSpecModeSetter() { clear(); }
2794 state_->clearResultAttributeSpecMode();
2799 ParserState *state_;
2802 Boolean Parser::parseResultElementSpec(unsigned declInputLevel,
2806 const ElementType *&resultType,
2807 AttributeList &attributes)
2809 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2810 if (!parseParam(idlink ? allowNameMdc : allowExplicitLinkRuleMdc,
2811 declInputLevel, parm))
2817 resultType = lookupResultElementType(parm.token);
2818 static AllowedParams
2823 Param::indicatedReservedName + Syntax::rIMPLIED);
2824 static AllowedParams
2825 allowNameDsoMdc(Param::dso,
2828 if (!parseParam(idlink ? allowNameDsoMdc : allow,
2829 declInputLevel, parm))
2831 ConstPtr<AttributeDefinitionList> attDef;
2833 attDef = resultType->attributeDef();
2834 attributes.init(attDef);
2835 if (parm.type == Param::dso) {
2836 ResultAttributeSpecModeSetter modeSetter(this);
2837 Boolean netEnabling;
2838 if (!parseAttributeSpec(1, attributes, netEnabling))
2841 if (attributes.nSpec() == 0)
2842 message(ParserMessages::emptyResultAttributeSpec);
2843 if (!parseParam(idlink ? allowNameMdc : allowExplicitLinkRuleMdc,
2844 declInputLevel, parm))
2848 // For entity and notation attributes.
2849 ResultAttributeSpecModeSetter modeSetter(this);
2850 attributes.finish(*this);
2857 const ElementType *Parser::lookupResultElementType(const StringC &name)
2859 const Dtd *dtd = defComplexLpd().resultDtd().pointer();
2862 const ElementType *e = dtd->lookupElementType(name);
2864 message(ParserMessages::noSuchResultElement, StringMessageArg(name));
2868 Boolean Parser::parseUselinkDecl()
2870 unsigned declInputLevel = inputLevel();
2872 if (!parseParam(allowLinkSetSpec, declInputLevel, parm))
2875 if (!parseParam(allowName, declInputLevel, parm2))
2878 parm2.token.swap(linkType);
2879 if (!parseParam(allowMdc, declInputLevel, parm2))
2881 ConstPtr<Lpd> lpd = lookupLpd(linkType);
2883 message(ParserMessages::uselinkBadLinkType, StringMessageArg(linkType));
2884 else if (lpd->type() == Lpd::simpleLink)
2885 message(ParserMessages::uselinkSimpleLpd, StringMessageArg(linkType));
2887 const ComplexLpd *complexLpd = (const ComplexLpd *)lpd.pointer();
2888 const LinkSet *linkSet;
2889 Boolean restore = 0;
2890 if (parm.type == Param::name) {
2891 linkSet = complexLpd->lookupLinkSet(parm.token);
2893 message(ParserMessages::uselinkBadLinkSet,
2894 StringMessageArg(complexLpd->name()),
2895 StringMessageArg(parm.token));
2899 else if (parm.type == Param::indicatedReservedName + Syntax::rINITIAL)
2900 linkSet = complexLpd->initialLinkSet();
2901 else if (parm.type == Param::indicatedReservedName + Syntax::rEMPTY)
2902 linkSet = complexLpd->emptyLinkSet();
2908 eventHandler().uselink(new (eventAllocator())
2909 UselinkEvent(lpd, linkSet,
2910 restore, markupLocation(),
2913 eventHandler().ignoredMarkup(new (eventAllocator())
2914 IgnoredMarkupEvent(markupLocation(),
2920 LinkSet *Parser::lookupCreateLinkSet(const StringC &name)
2922 LinkSet *linkSet = defComplexLpd().lookupLinkSet(name);
2924 linkSet = new LinkSet(name, defComplexLpd().sourceDtd().pointer());
2925 defComplexLpd().insertLinkSet(linkSet);
2930 Boolean Parser::parseMarkedSectionDeclStart()
2932 if (markedSectionLevel() == syntax().taglvl())
2933 message(ParserMessages::markedSectionLevel,
2934 NumberMessageArg(syntax().taglvl()));
2935 if (markedSectionSpecialLevel() > 0) {
2936 startMarkedSection(markupLocation());
2938 ? eventsWanted().wantMarkedSections()
2939 : eventsWanted().wantPrologMarkup())
2940 eventHandler().ignoredChars(new (eventAllocator())
2941 IgnoredCharsEvent(currentInput()->currentTokenStart(),
2942 currentInput()->currentTokenLength(),
2948 if (startMarkup(inInstance()
2949 ? eventsWanted().wantMarkedSections()
2950 : eventsWanted().wantPrologMarkup(),
2951 currentLocation())) {
2952 currentMarkup()->addDelim(Syntax::dMDO);
2953 currentMarkup()->addDelim(Syntax::dDSO);
2955 unsigned declInputLevel = inputLevel();
2956 static AllowedParams allowStatusDso(Param::dso,
2957 Param::reservedName + Syntax::rCDATA,
2958 Param::reservedName + Syntax::rRCDATA,
2959 Param::reservedName + Syntax::rIGNORE,
2960 Param::reservedName + Syntax::rINCLUDE,
2961 Param::reservedName + Syntax::rTEMP);
2963 MarkedSectionEvent::Status status = MarkedSectionEvent::include;
2965 if (!parseParam(allowStatusDso, declInputLevel, parm))
2967 if (parm.type == Param::dso)
2969 switch (parm.type) {
2970 case Param::reservedName + Syntax::rCDATA:
2971 if (status < MarkedSectionEvent::cdata)
2972 status = MarkedSectionEvent::cdata;
2974 case Param::reservedName + Syntax::rRCDATA:
2975 if (status < MarkedSectionEvent::rcdata)
2976 status = MarkedSectionEvent::rcdata;
2978 case Param::reservedName + Syntax::rIGNORE:
2979 if (status < MarkedSectionEvent::ignore)
2980 status = MarkedSectionEvent::ignore;
2984 // FIXME this disallows
2985 // <!entity % e "include [ stuff ">
2988 // which I think is legal.
2990 if (inputLevel() > declInputLevel)
2991 message(ParserMessages::parameterEntityNotEnded);
2993 case MarkedSectionEvent::include:
2994 startMarkedSection(markupLocation());
2996 case MarkedSectionEvent::cdata:
2997 startSpecialMarkedSection(cmsMode, markupLocation());
2999 case MarkedSectionEvent::rcdata:
3000 startSpecialMarkedSection(rcmsMode, markupLocation());
3002 case MarkedSectionEvent::ignore:
3003 startSpecialMarkedSection(imsMode, markupLocation());
3006 if (currentMarkup())
3007 eventHandler().markedSectionStart(new (eventAllocator())
3008 MarkedSectionStartEvent(status,
3014 void Parser::handleMarkedSectionEnd()
3016 if (markedSectionLevel() == 0)
3017 message(ParserMessages::markedSectionEnd);
3020 ? eventsWanted().wantMarkedSections()
3021 : eventsWanted().wantPrologMarkup()) {
3022 if (markedSectionSpecialLevel() > 1)
3023 eventHandler().ignoredChars(new (eventAllocator())
3024 IgnoredCharsEvent(currentInput()->currentTokenStart(),
3025 currentInput()->currentTokenLength(),
3029 MarkedSectionEvent::Status status;
3030 switch (currentMode()) {
3032 status = MarkedSectionEvent::cdata;
3035 status = MarkedSectionEvent::rcdata;
3038 status = MarkedSectionEvent::ignore;
3041 status = MarkedSectionEvent::include;
3044 startMarkup(1, currentLocation());
3045 currentMarkup()->addDelim(Syntax::dMSC);
3046 currentMarkup()->addDelim(Syntax::dMDC);
3047 eventHandler().markedSectionEnd(new (eventAllocator())
3048 MarkedSectionEndEvent(status,
3057 void Parser::emptyCommentDecl()
3059 if (startMarkup(eventsWanted().wantCommentDecls(), currentLocation())) {
3060 currentMarkup()->addDelim(Syntax::dMDO);
3061 currentMarkup()->addDelim(Syntax::dMDC);
3062 eventHandler().commentDecl(new (eventAllocator())
3063 CommentDeclEvent(markupLocation(),
3068 Boolean Parser::parseCommentDecl()
3070 if (startMarkup(inInstance()
3071 ? eventsWanted().wantCommentDecls()
3072 : eventsWanted().wantPrologMarkup(),
3074 currentMarkup()->addDelim(Syntax::dMDO);
3075 if (!parseComment(comMode))
3078 Token token = getToken(mdMode);
3081 if (currentMarkup())
3082 currentMarkup()->addS(currentChar());
3085 if (!parseComment(comMode))
3089 if (currentMarkup())
3090 currentMarkup()->addDelim(Syntax::dMDC);
3093 message(ParserMessages::declarationLevel);
3095 case tokenUnrecognized:
3096 if (reportNonSgmlCharacter())
3098 // braces to work round Sun C++ 4.0 bug
3100 message(ParserMessages::commentDeclarationCharacter,
3101 StringMessageArg(currentToken()),
3106 // braces to work round Sun C++ 4.0 bug
3108 message(ParserMessages::commentDeclInvalidToken,
3109 TokenMessageArg(token, mdMode, syntaxPointer(), sdPointer()),
3116 if (currentMarkup())
3117 eventHandler().commentDecl(new (eventAllocator())
3118 CommentDeclEvent(markupLocation(),
3123 Boolean Parser::parseAfdrDecl()
3125 unsigned declInputLevel = inputLevel();
3126 static AllowedParams allowMinimumLiteral(Param::minimumLiteral);
3129 if (!parseParam(allowMinimumLiteral, declInputLevel, parm))
3131 if (parm.literalText.string() != sd().execToDoc("ISO/IEC 10744:1992"))
3132 message(ParserMessages::afdrVersion,
3133 StringMessageArg(parm.literalText.string()));
3134 if (!parseParam(allowMdc, declInputLevel, parm))
3136 eventHandler().ignoredMarkup(new (eventAllocator())
3137 IgnoredMarkupEvent(markupLocation(),