1 // Copyright (c) 1994, 1995 James Clark
2 // See the file COPYING for copying permission.
4 // Prolog, dtd and declaration parsing.
10 #include "ParserMessages.h"
11 #include "MessageArg.h"
12 #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();
69 if (++tries >= maxTries) {
70 message(ParserMessages::notSgml);
74 message(ParserMessages::prologCharacter, StringMessageArg(currentToken()));
82 message(ParserMessages::documentEndProlog);
90 if (!parseCommentDecl())
93 case tokenMdoNameStart:
95 if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation()))
96 currentMarkup()->addDelim(Syntax::dMDO);
97 Syntax::ReservedName name;
98 if (parseDeclarationName(&name)) {
100 case Syntax::rDOCTYPE:
101 if (!parseDoctypeDeclStart())
104 case Syntax::rLINKTYPE:
105 if (!parseLinktypeDeclStart())
108 case Syntax::rELEMENT:
109 case Syntax::rATTLIST:
110 case Syntax::rENTITY:
111 case Syntax::rNOTATION:
112 case Syntax::rSHORTREF:
113 case Syntax::rUSEMAP:
114 case Syntax::rUSELINK:
116 case Syntax::rIDLINK:
117 message(ParserMessages::prologDeclaration,
118 StringMessageArg(syntax().reservedName(name)));
124 message(ParserMessages::noSuchDeclarationType,
125 StringMessageArg(syntax().reservedName(name)));
134 if (!parseProcessingInstruction())
138 if (eventsWanted().wantPrologMarkup()) {
140 eventHandler().sSep(new (eventAllocator())
141 SSepEvent(currentInput()->currentTokenStart(),
142 currentInput()->currentTokenLength(),
150 } while (eventQueueEmpty());
153 void Parser::endProlog()
155 if (baseDtd().isNull()
157 || 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(currentDtdPointer(),
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()->entityDecl();
263 && (e->declType() == EntityDecl::doctype
264 || e->declType() == EntityDecl::linktype)) {
265 // popInputStack may destroy e
266 Boolean fake = e->defLocation().origin().isNull();
269 ? parseDoctypeDeclEnd(fake)
270 : parseLinktypeDeclEnd()))
272 setPhase(prologPhase);
276 if (inputLevel() == 1) {
277 if (finalPhase() == declSubsetPhase) {
282 // Give message before popping stack.
284 ? ParserMessages::documentEndDtdSubset
285 : ParserMessages::documentEndLpdSubset);
292 case tokenDsc: // end of declaration subset
293 // FIXME what's the right location?
294 if (!referenceDsEntity(currentLocation())) {
295 if (!(inDtd ? parseDoctypeDeclEnd() : parseLinktypeDeclEnd()))
297 setPhase(prologPhase);
300 case tokenMdoNameStart: // named markup declaration
301 if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation()))
302 currentMarkup()->addDelim(Syntax::dMDO);
303 Syntax::ReservedName name;
305 if (parseDeclarationName(&name,
306 inDtd && !options().errorAfdr)) {
308 case Syntax::rANY: // used for <!AFDR
309 result = parseAfdrDecl();
311 case Syntax::rELEMENT:
313 result = parseElementDecl();
315 message(ParserMessages::lpdSubsetDeclaration,
316 StringMessageArg(syntax().reservedName(name)));
320 case Syntax::rATTLIST:
321 result = parseAttlistDecl();
323 case Syntax::rENTITY:
324 result = parseEntityDecl();
326 case Syntax::rNOTATION:
327 result = parseNotationDecl();
328 if (!inDtd && !sd().www())
329 message(ParserMessages::lpdSubsetDeclaration,
330 StringMessageArg(syntax().reservedName(name)));
332 case Syntax::rSHORTREF:
334 result = parseShortrefDecl();
336 message(ParserMessages::lpdSubsetDeclaration,
337 StringMessageArg(syntax().reservedName(name)));
341 case Syntax::rUSEMAP:
343 result = parseUsemapDecl();
345 message(ParserMessages::lpdSubsetDeclaration,
346 StringMessageArg(syntax().reservedName(name)));
352 message(ParserMessages::dtdSubsetDeclaration,
353 StringMessageArg(syntax().reservedName(name)));
357 result = parseLinkDecl();
359 case Syntax::rIDLINK:
361 message(ParserMessages::dtdSubsetDeclaration,
362 StringMessageArg(syntax().reservedName(name)));
366 result = parseIdlinkDecl();
368 case Syntax::rDOCTYPE:
369 case Syntax::rLINKTYPE:
370 case Syntax::rUSELINK:
373 ? ParserMessages::dtdSubsetDeclaration
374 : ParserMessages::lpdSubsetDeclaration,
375 StringMessageArg(syntax().reservedName(name)));
379 message(ParserMessages::noSuchDeclarationType,
380 StringMessageArg(syntax().reservedName(name)));
387 declSubsetRecover(startLevel);
389 case tokenMdoMdc: // empty comment declaration
393 case tokenMdoCom: // comment declaration
394 if (!parseCommentDecl())
395 declSubsetRecover(startLevel);
397 case tokenMdoDso: // marked section declaration
398 if (!parseMarkedSectionDeclStart())
399 declSubsetRecover(startLevel);
402 handleMarkedSectionEnd();
404 case tokenPeroGrpo: // parameter entity reference with name group
405 message(ParserMessages::peroGrpoProlog);
407 case tokenPeroNameStart: // parameter entity reference
409 ConstPtr<Entity> entity;
410 Ptr<EntityOrigin> origin;
411 if (parseEntityReference(1, token == tokenPeroGrpo, entity, origin)) {
412 if (!entity.isNull())
413 entity->dsReference(*this, origin);
416 declSubsetRecover(startLevel);
419 case tokenPio: // processing instruction
420 if (!parseProcessingInstruction())
421 declSubsetRecover(startLevel);
423 case tokenS: // white space
424 if (eventsWanted().wantPrologMarkup()) {
426 eventHandler().sSep(new (eventAllocator())
427 SSepEvent(currentInput()->currentTokenStart(),
428 currentInput()->currentTokenLength(),
433 case tokenIgnoredChar:
434 // from an ignored marked section
435 if (eventsWanted().wantPrologMarkup())
436 eventHandler().ignoredChars(new (eventAllocator())
437 IgnoredCharsEvent(currentInput()->currentTokenStart(),
438 currentInput()->currentTokenLength(),
444 case tokenCroNameStart:
446 case tokenHcroHexDigit:
447 case tokenEroNameStart:
450 // these can occur in a cdata or rcdata marked section
451 message(ParserMessages::dataMarkedSectionDeclSubset);
452 declSubsetRecover(startLevel);
457 } while (eventQueueEmpty());
460 void Parser::declSubsetRecover(unsigned startLevel)
463 Token token = getToken(currentMode());
465 case tokenUnrecognized:
469 if (inputLevel() <= startLevel)
475 case tokenMdoNameStart:
480 if (inputLevel() == startLevel) {
481 currentInput()->ungetToken();
491 Boolean Parser::lookingAtStartTag(StringC &gi)
493 // This is harder than might be expected since we may not have compiled
494 // the recognizers for the instance yet.
495 const StringC &stago = instanceSyntax().delimGeneral(Syntax::dSTAGO);
496 for (size_t i = currentInput()->currentTokenLength();
499 if (currentInput()->tokenChar(messenger()) == InputSource::eE)
502 getCurrentToken(instanceSyntax().generalSubstTable(), delim);
505 Xchar c = currentInput()->tokenChar(messenger());
506 if (!instanceSyntax().isNameStartCharacter(c))
509 gi += (*instanceSyntax().generalSubstTable())[(Char)c];
510 c = currentInput()->tokenChar(messenger());
511 } while (instanceSyntax().isNameCharacter(c));
515 Boolean Parser::parseDeclarationName(Syntax::ReservedName *result,
518 currentInput()->discardInitial();
519 extendNameToken(syntax().namelen(), ParserMessages::nameLength);
520 StringC &name = nameBuffer();
521 getCurrentToken(syntax().generalSubstTable(), name);
522 if (!syntax().lookupReservedName(name, result)) {
523 if (allowAfdr && name == sd().execToInternal("AFDR")) {
524 *result = Syntax::rANY;
526 currentMarkup()->addName(currentInput());
529 message(ParserMessages::noSuchDeclarationType, StringMessageArg(name));
533 else if (currentMarkup())
534 currentMarkup()->addReservedName(*result, currentInput());
538 Boolean Parser::parseElementDecl()
540 unsigned declInputLevel = inputLevel();
542 if (!parseParam(allowNameNameGroup, declInputLevel, parm))
544 Vector<NameToken> nameVector;
545 if (parm.type == Param::nameGroup) {
546 parm.nameTokenVector.swap(nameVector);
547 if (options().warnElementGroupDecl)
548 message(ParserMessages::elementGroupDecl);
551 nameVector.resize(1);
552 parm.token.swap(nameVector[0].name);
553 parm.origToken.swap(nameVector[0].origName);
556 allowRankOmissionContent(Param::number,
557 Param::reservedName + Syntax::rO,
559 Param::reservedName + Syntax::rCDATA,
560 Param::reservedName + Syntax::rRCDATA,
561 Param::reservedName + Syntax::rEMPTY,
562 Param::reservedName + Syntax::rANY,
564 if (!parseParam(allowRankOmissionContent, declInputLevel, parm))
567 Vector<ElementType *> elements(nameVector.size());
568 Vector<RankStem *> rankStems;
569 Vector<const RankStem *> constRankStems;
571 if (parm.type == Param::number) {
572 if (options().warnRank)
573 message(ParserMessages::rank);
574 parm.token.swap(rankSuffix);
575 rankStems.resize(nameVector.size());
576 constRankStems.resize(nameVector.size());
577 for (i = 0; i < elements.size(); i++) {
578 StringC name(nameVector[i].name);
580 if (name.size() > syntax().namelen()
581 && nameVector[i].name.size() <= syntax().namelen())
582 message(ParserMessages::genericIdentifierLength,
583 NumberMessageArg(syntax().namelen()));
584 elements[i] = lookupCreateElement(name);
585 rankStems[i] = lookupCreateRankStem(nameVector[i].name);
586 constRankStems[i] = rankStems[i];
589 allowOmissionContent(Param::reservedName + Syntax::rO,
591 Param::reservedName + Syntax::rCDATA,
592 Param::reservedName + Syntax::rRCDATA,
593 Param::reservedName + Syntax::rEMPTY,
594 Param::reservedName + Syntax::rANY,
596 Token token = getToken(mdMinusMode);
597 if (token == tokenNameStart)
598 message(ParserMessages::psRequired);
599 currentInput()->ungetToken();
600 if (!parseParam(allowOmissionContent, declInputLevel, parm))
604 for (i = 0; i < elements.size(); i++) {
605 // StringC *origName;
606 // origName = new StringC(nameVector[i].origName);
607 elements[i] = lookupCreateElement(nameVector[i].name);
608 elements[i]->setOrigName(nameVector[i].origName);
611 for (i = 0; i < elements.size(); i++)
612 if (defDtd().lookupRankStem(elements[i]->name()) && validate())
613 message(ParserMessages::rankStemGenericIdentifier,
614 StringMessageArg(elements[i]->name()));
615 unsigned char omitFlags = 0;
616 if (parm.type == Param::minus
617 || parm.type == Param::reservedName + Syntax::rO) {
618 if (options().warnMinimizationParam)
619 message(ParserMessages::minimizationParam);
620 omitFlags |= ElementDefinition::omitSpec;
621 if (parm.type != Param::minus)
622 omitFlags |= ElementDefinition::omitStart;
623 static AllowedParams allowOmission(Param::reservedName + Syntax::rO,
625 if (!parseParam(allowOmission, declInputLevel, parm))
627 if (parm.type != Param::minus)
628 omitFlags |= ElementDefinition::omitEnd;
629 static AllowedParams allowContent(Param::reservedName + Syntax::rCDATA,
630 Param::reservedName + Syntax::rRCDATA,
631 Param::reservedName + Syntax::rEMPTY,
632 Param::reservedName + Syntax::rANY,
634 if (!parseParam(allowContent, declInputLevel, parm))
639 message(ParserMessages::missingTagMinimization);
641 Ptr<ElementDefinition> def;
643 case Param::reservedName + Syntax::rCDATA:
644 def = new ElementDefinition(markupLocation(),
645 defDtd().allocElementDefinitionIndex(),
647 ElementDefinition::cdata);
648 if (!parseParam(allowMdc, declInputLevel, parm))
650 if (options().warnCdataContent)
651 message(ParserMessages::cdataContent);
653 case Param::reservedName + Syntax::rRCDATA:
654 def = new ElementDefinition(markupLocation(),
655 defDtd().allocElementDefinitionIndex(),
657 ElementDefinition::rcdata);
658 if (!parseParam(allowMdc, declInputLevel, parm))
660 if (options().warnRcdataContent)
661 message(ParserMessages::rcdataContent);
663 case Param::reservedName + Syntax::rEMPTY:
664 def = new ElementDefinition(markupLocation(),
665 defDtd().allocElementDefinitionIndex(),
667 ElementDefinition::empty);
668 if ((omitFlags & ElementDefinition::omitSpec)
669 && !(omitFlags & ElementDefinition::omitEnd)
670 && options().warnShould)
671 message(ParserMessages::emptyOmitEndTag);
672 if (!parseParam(allowMdc, declInputLevel, parm))
675 case Param::reservedName + Syntax::rANY:
676 def = new ElementDefinition(markupLocation(),
677 defDtd().allocElementDefinitionIndex(),
679 ElementDefinition::any);
680 if (!parseExceptions(declInputLevel, def))
683 case Param::modelGroup:
685 unsigned long cnt = parm.modelGroupPtr->grpgtcnt();
686 // The outermost model group isn't formally a content token.
687 if (cnt - 1 > syntax().grpgtcnt())
688 message(ParserMessages::grpgtcnt, NumberMessageArg(syntax().grpgtcnt()));
689 Owner<CompiledModelGroup>
690 modelGroup(new CompiledModelGroup(parm.modelGroupPtr));
691 Vector<ContentModelAmbiguity> ambiguities;
692 Boolean pcdataUnreachable;
693 modelGroup->compile(currentDtd().nElementTypeIndex(), ambiguities,
695 if (pcdataUnreachable && options().warnMixedContent)
696 message(ParserMessages::pcdataUnreachable);
698 for (i = 0; i < ambiguities.size(); i++) {
699 const ContentModelAmbiguity &a = ambiguities[i];
700 reportAmbiguity(a.from, a.to1, a.to2, a.andDepth);
703 def = new ElementDefinition(markupLocation(),
704 defDtd().allocElementDefinitionIndex(),
706 ElementDefinition::modelGroup,
708 if (!parseExceptions(declInputLevel, def))
713 if (rankSuffix.size() > 0)
714 def->setRank(rankSuffix, constRankStems);
715 ConstPtr<ElementDefinition> constDef(def);
716 for (i = 0; i < elements.size(); i++) {
717 if (elements[i]->definition() != 0) {
719 message(ParserMessages::duplicateElementDefinition,
720 StringMessageArg(elements[i]->name()));
723 elements[i]->setElementDefinition(constDef, i);
724 if (!elements[i]->attributeDef().isNull())
725 checkElementAttribute(elements[i]);
727 if (rankStems.size() > 0)
728 rankStems[i]->addDefinition(constDef);
730 if (currentMarkup()) {
731 Vector<const ElementType *> v(elements.size());
732 for (i = 0; i < elements.size(); i++)
734 eventHandler().elementDecl(new (eventAllocator())
735 ElementDeclEvent(v, currentDtdPointer(),
742 void Parser::reportAmbiguity(const LeafContentToken *from,
743 const LeafContentToken *to1,
744 const LeafContentToken *to2,
745 unsigned ambigAndDepth)
748 const ElementType *toType = to1->elementType();
750 toName = toType->name();
752 toName = syntax().delimGeneral(Syntax::dRNI);
753 toName += syntax().reservedName(Syntax::rPCDATA);
755 unsigned to1Index = to1->typeIndex() + 1;
756 unsigned to2Index = to2->typeIndex() + 1;
757 if (from->isInitial())
758 message(ParserMessages::ambiguousModelInitial,
759 StringMessageArg(toName),
760 OrdinalMessageArg(to1Index),
761 OrdinalMessageArg(to2Index));
764 const ElementType *fromType = from->elementType();
766 fromName = fromType->name();
768 fromName = syntax().delimGeneral(Syntax::dRNI);
769 fromName += syntax().reservedName(Syntax::rPCDATA);
771 unsigned fromIndex = from->typeIndex() + 1;
772 unsigned andMatches = from->andDepth() - ambigAndDepth;
774 message(ParserMessages::ambiguousModel,
775 StringMessageArg(fromName),
776 OrdinalMessageArg(fromIndex),
777 StringMessageArg(toName),
778 OrdinalMessageArg(to1Index),
779 OrdinalMessageArg(to2Index));
780 else if (andMatches == 1)
781 message(ParserMessages::ambiguousModelSingleAnd,
782 StringMessageArg(fromName),
783 OrdinalMessageArg(fromIndex),
784 StringMessageArg(toName),
785 OrdinalMessageArg(to1Index),
786 OrdinalMessageArg(to2Index));
788 message(ParserMessages::ambiguousModelMultipleAnd,
789 StringMessageArg(fromName),
790 OrdinalMessageArg(fromIndex),
791 NumberMessageArg(andMatches),
792 StringMessageArg(toName),
793 OrdinalMessageArg(to1Index),
794 OrdinalMessageArg(to2Index));
799 // Check the compatibility of the attribute definition with
800 // the element definition.
802 void Parser::checkElementAttribute(const ElementType *e, size_t checkFrom)
806 const AttributeDefinitionList *attDef = e->attributeDef().pointer();
809 const ElementDefinition *edef = e->definition();
812 size_t attDefLength = attDef->size();
813 for (size_t i = checkFrom; i < attDefLength; i++) {
814 const AttributeDefinition *p = attDef->def(i);
818 && edef->declaredContent() == ElementDefinition::empty)
819 message(ParserMessages::notationEmpty, StringMessageArg(e->name()));
823 if (edef->omittedTagSpec() && !edef->canOmitEndTag()
824 && options().warnShould)
825 message(ParserMessages::conrefOmitEndTag, StringMessageArg(e->name()));
827 if (edef->declaredContent() == ElementDefinition::empty)
828 message(ParserMessages::conrefEmpty, StringMessageArg(e->name()));
832 ElementType *Parser::lookupCreateElement(const StringC &name)
834 ElementType *e = defDtd().lookupElementType(name);
837 message(ParserMessages::noSuchSourceElement, StringMessageArg(name));
839 e = new ElementType(name, defDtd().allocElementTypeIndex());
840 defDtd().insertElementType(e);
846 RankStem *Parser::lookupCreateRankStem(const StringC &name)
848 RankStem *r = defDtd().lookupRankStem(name);
850 r = new RankStem(name, defDtd().nRankStem());
851 defDtd().insertRankStem(r);
852 const ElementType *e = defDtd().lookupElementType(name);
853 if (e && e->definition() != 0)
854 message(ParserMessages::rankStemGenericIdentifier, StringMessageArg(name));
859 Boolean Parser::parseExceptions(unsigned declInputLevel,
860 Ptr<ElementDefinition> &def)
864 allowExceptionsMdc(Param::mdc, Param::exclusions, Param::inclusions);
865 if (!parseParam(allowExceptionsMdc, declInputLevel, parm))
867 if (parm.type == Param::exclusions) {
868 if (options().warnExclusion)
869 message(ParserMessages::exclusion);
870 def->setExclusions(parm.elementVector);
871 static AllowedParams allowInclusionsMdc(Param::mdc, Param::inclusions);
872 if (!parseParam(allowInclusionsMdc, declInputLevel, parm))
875 if (parm.type == Param::inclusions) {
876 if (options().warnInclusion)
877 message(ParserMessages::inclusion);
878 def->setInclusions(parm.elementVector);
879 size_t nI = def->nInclusions();
880 size_t nE = def->nExclusions();
882 for (size_t i = 0; i < nI; i++) {
883 const ElementType *e = def->inclusion(i);
884 for (size_t j = 0; j < nE; j++)
885 if (def->exclusion(j) == e)
886 message(ParserMessages::excludeIncludeSame,
887 StringMessageArg(e->name()));
890 if (!parseParam(allowMdc, declInputLevel, parm))
896 Boolean Parser::parseAttlistDecl()
898 unsigned declInputLevel = inputLevel();
901 size_t idIndex = size_t(-1);
902 size_t notationIndex = size_t(-1);
903 Boolean anyCurrent = 0;
906 Vector<Attributed *> attributed;
907 if (!parseAttributed(declInputLevel, parm, attributed, isNotation))
909 Vector<CopyOwner<AttributeDefinition> > defs;
910 if (!parseParam(sd().www() ? allowNameMdc : allowName, declInputLevel, parm))
912 while (parm.type != Param::mdc) {
913 StringC attributeName;
914 StringC origAttributeName;
915 parm.token.swap(attributeName);
916 parm.origToken.swap(origAttributeName);
918 Boolean duplicate = 0;
920 for (i = 0; i < defs.size(); i++)
921 if (defs[i]->name() == attributeName) {
922 message(ParserMessages::duplicateAttributeDef,
923 StringMessageArg(attributeName));
927 Owner<DeclaredValue> declaredValue;
928 if (!parseDeclaredValue(declInputLevel, isNotation, parm, declaredValue))
931 if (declaredValue->isId()) {
932 if (idIndex != size_t(-1))
933 message(ParserMessages::multipleIdAttributes,
934 StringMessageArg(defs[idIndex]->name()));
935 idIndex = defs.size();
937 else if (declaredValue->isNotation()) {
938 if (notationIndex != size_t(-1))
939 message(ParserMessages::multipleNotationAttributes,
940 StringMessageArg(defs[notationIndex]->name()));
941 notationIndex = defs.size();
944 const Vector<StringC> *tokensPtr = declaredValue->getTokens();
946 size_t nTokens = tokensPtr->size();
948 Vector<StringC>::const_iterator tokens = tokensPtr->begin();
949 for (i = 0; i < nTokens; i++) {
950 for (size_t j = 0; j < defs.size(); j++)
951 if (defs[j]->containsToken(tokens[i])) {
952 message(ParserMessages::duplicateAttributeToken,
953 StringMessageArg(tokens[i]));
960 Owner<AttributeDefinition> def;
961 if (!parseDefaultValue(declInputLevel, isNotation, parm, attributeName,
962 declaredValue, def, anyCurrent))
964 if (haveDefLpd() && defLpd().type() == Lpd::simpleLink && !def->isFixed())
965 message(ParserMessages::simpleLinkFixedAttribute);
966 def->setOrigName(origAttributeName);
968 defs.resize(defs.size() + 1);
969 defs.back() = def.extract();
971 static AllowedParams allowNameMdc(Param::name, Param::mdc);
972 if (!parseParam(allowNameMdc, declInputLevel, parm))
975 if (attcnt > syntax().attcnt())
976 message(ParserMessages::attcnt,
977 NumberMessageArg(attcnt),
978 NumberMessageArg(syntax().attcnt()));
979 if (haveDefLpd() && !isNotation) {
980 if (defLpd().type() == Lpd::simpleLink) {
981 for (size_t i = 0; i < attributed.size(); i++) {
982 const ElementType *e = (const ElementType *)attributed[i];
984 if (e->name() == defLpd().sourceDtd()->name()) {
985 SimpleLpd &lpd = (SimpleLpd &)defLpd();
986 if (lpd.attributeDef().isNull())
987 lpd.setAttributeDef(new AttributeDefinitionList(defs, 0));
989 message(ParserMessages::duplicateAttlistElement,
990 StringMessageArg(e->name()));
993 message(ParserMessages::simpleLinkAttlistElement,
994 StringMessageArg(e->name()));
999 Ptr<AttributeDefinitionList>
1000 adl(new AttributeDefinitionList(defs,
1002 .allocAttributeDefinitionListIndex()));
1003 for (size_t i = 0; i < attributed.size(); i++) {
1004 const ElementType *e = (const ElementType *)attributed[i];
1006 if (defComplexLpd().attributeDef(e).isNull())
1007 defComplexLpd().setAttributeDef(e, adl);
1009 message(ParserMessages::duplicateAttlistElement,
1010 StringMessageArg(e->name()));
1016 Ptr<AttributeDefinitionList>
1017 adl(new AttributeDefinitionList(defs,
1019 .allocAttributeDefinitionListIndex(),
1023 for (size_t i = 0; i < attributed.size(); i++) {
1024 if (attributed[i]->attributeDef().isNull()) {
1025 attributed[i]->setAttributeDef(adl);
1027 ElementType *e = (ElementType *)attributed[i];
1028 if (e->definition() != 0)
1029 checkElementAttribute(e);
1032 else if (options().errorAfdr && !sd().www()) {
1034 message(ParserMessages::duplicateAttlistNotation,
1035 StringMessageArg(((Notation *)attributed[i])->name()));
1037 message(ParserMessages::duplicateAttlistElement,
1038 StringMessageArg(((ElementType *)attributed[i])->name()));
1041 if (!hadAfdrDecl() && !sd().www()) {
1042 message(ParserMessages::missingAfdrDecl);
1045 AttributeDefinitionList *curAdl;
1047 // Use block to make sure temporary gets destroyed.
1048 curAdl = attributed[i]->attributeDef().pointer();
1050 size_t oldSize = curAdl->size();
1051 if (curAdl->count() != 1) {
1052 Vector<CopyOwner<AttributeDefinition> > copy(oldSize);
1053 for (size_t j = 0; j < oldSize; j++)
1054 copy[j] = curAdl->def(j)->copy();
1055 Ptr<AttributeDefinitionList> adlCopy
1056 = new AttributeDefinitionList(copy,
1057 defDtd().allocAttributeDefinitionListIndex(),
1058 curAdl->anyCurrent(),
1060 curAdl->notationIndex());
1061 attributed[i]->setAttributeDef(adlCopy);
1062 curAdl = adlCopy.pointer();
1064 for (size_t j = 0; j < adl->size(); j++) {
1066 if (!curAdl->attributeIndex(adl->def(j)->name(), index)) {
1067 index = curAdl->idIndex();
1068 if (index != -1 && adl->def(j)->isId())
1069 message(ParserMessages::multipleIdAttributes,
1070 StringMessageArg(curAdl->def(index)->name()));
1071 index = curAdl->notationIndex();
1072 if (index != -1 && adl->def(j)->isNotation())
1073 message(ParserMessages::multipleNotationAttributes,
1074 StringMessageArg(curAdl->def(index)->name()));
1075 curAdl->append(adl->def(j)->copy());
1079 if (curAdl->def(index)->isSpecified(tem))
1080 message(ParserMessages::specifiedAttributeRedeclared,
1081 StringMessageArg(adl->def(j)->name()));
1085 ElementType *e = (ElementType *)attributed[i];
1086 if (e->definition() != 0)
1087 checkElementAttribute(e, oldSize);
1092 if (currentMarkup()) {
1094 Vector<ConstPtr<Notation> > v(attributed.size());
1095 for (size_t i = 0; i < attributed.size(); i++)
1096 v[i] = (Notation *)attributed[i];
1098 .attlistNotationDecl(new (eventAllocator())
1099 AttlistNotationDeclEvent(v,
1104 Vector<const ElementType *> v(attributed.size());
1105 for (size_t i = 0; i < attributed.size(); i++)
1106 v[i] = (ElementType *)attributed[i];
1109 .linkAttlistDecl(new (eventAllocator())
1110 LinkAttlistDeclEvent(v,
1115 eventHandler().attlistDecl(new (eventAllocator())
1117 currentDtdPointer(),
1123 Dtd::EntityIter entityIter(defDtd().generalEntityIter());
1125 Ptr<Entity> entity(entityIter.next());
1126 if (entity.isNull())
1128 const ExternalDataEntity *external = entity->asExternalDataEntity();
1130 const Notation *entityNotation = external->notation();
1131 for (size_t i = 0; i < attributed.size(); i++)
1132 if ((Notation *)attributed[i] == entityNotation) {
1133 AttributeList attributes(entityNotation->attributeDef());
1134 attributes.finish(*this);
1135 ((ExternalDataEntity *)entity.pointer())
1136 ->setNotation((Notation *)attributed[i], attributes);
1145 Boolean Parser::parseAttributed(unsigned declInputLevel,
1147 Vector<Attributed *> &attributed,
1148 Boolean &isNotation)
1150 static AllowedParams
1151 allowNameGroupNotation(Param::name,
1153 Param::indicatedReservedName + Syntax::rNOTATION);
1154 static AllowedParams
1155 allowNameGroupNotationAll(Param::name,
1157 Param::indicatedReservedName
1158 + Syntax::rNOTATION,
1159 Param::indicatedReservedName
1161 Param::indicatedReservedName
1162 + Syntax::rIMPLICIT);
1163 if (!parseParam(haveDefLpd()
1164 ? allowNameGroupNotation
1165 : allowNameGroupNotationAll,
1166 declInputLevel, parm))
1168 if (parm.type == Param::indicatedReservedName + Syntax::rNOTATION) {
1169 if (options().warnDataAttributes)
1170 message(ParserMessages::dataAttributes);
1172 static AllowedParams
1173 allowNameGroupAll(Param::name,
1175 Param::indicatedReservedName + Syntax::rALL,
1176 Param::indicatedReservedName + Syntax::rIMPLICIT);
1177 if (!parseParam(haveDefLpd()
1178 ? allowNameNameGroup
1179 : allowNameGroupAll,
1180 declInputLevel, parm))
1182 if (parm.type == Param::nameGroup) {
1183 attributed.resize(parm.nameTokenVector.size());
1184 for (size_t i = 0; i < attributed.size(); i++)
1185 attributed[i] = lookupCreateNotation(parm.nameTokenVector[i].name);
1188 if (parm.type != Param::name && !hadAfdrDecl() && !sd().www()) {
1189 message(ParserMessages::missingAfdrDecl);
1192 attributed.resize(1);
1194 = lookupCreateNotation(parm.type == Param::name
1196 : syntax().rniReservedName(Syntax::ReservedName(parm.type - Param::indicatedReservedName)));
1201 if (parm.type == Param::nameGroup) {
1202 if (options().warnAttlistGroupDecl)
1203 message(ParserMessages::attlistGroupDecl);
1204 attributed.resize(parm.nameTokenVector.size());
1205 for (size_t i = 0; i < attributed.size(); i++)
1206 attributed[i] = lookupCreateElement(parm.nameTokenVector[i].name);
1209 if (parm.type != Param::name && !hadAfdrDecl() && !sd().www()) {
1210 message(ParserMessages::missingAfdrDecl);
1213 attributed.resize(1);
1215 = lookupCreateElement(parm.type == Param::name
1217 : syntax().rniReservedName(Syntax::ReservedName(parm.type - Param::indicatedReservedName)));
1223 Boolean Parser::parseDeclaredValue(unsigned declInputLevel,
1226 Owner<DeclaredValue> &declaredValue)
1228 static Param::Type declaredValues[] = {
1229 Param::reservedName + Syntax::rCDATA,
1230 Param::reservedName + Syntax::rENTITY,
1231 Param::reservedName + Syntax::rENTITIES,
1232 Param::reservedName + Syntax::rID,
1233 Param::reservedName + Syntax::rIDREF,
1234 Param::reservedName + Syntax::rIDREFS,
1235 Param::reservedName + Syntax::rNAME,
1236 Param::reservedName + Syntax::rNAMES,
1237 Param::reservedName + Syntax::rNMTOKEN,
1238 Param::reservedName + Syntax::rNMTOKENS,
1239 Param::reservedName + Syntax::rNUMBER,
1240 Param::reservedName + Syntax::rNUMBERS,
1241 Param::reservedName + Syntax::rNUTOKEN,
1242 Param::reservedName + Syntax::rNUTOKENS,
1243 Param::reservedName + Syntax::rNOTATION,
1244 Param::nameTokenGroup,
1245 Param::reservedName + Syntax::rDATA
1247 static AllowedParams allowDeclaredValue(declaredValues,
1248 SIZEOF(declaredValues) - 1);
1249 static AllowedParams allowDeclaredValueData(declaredValues,
1250 SIZEOF(declaredValues));
1251 if (!parseParam(sd().www() ? allowDeclaredValueData : allowDeclaredValue,
1252 declInputLevel, parm))
1254 enum { asDataAttribute = 01, asLinkAttribute = 02 };
1255 unsigned allowedFlags = asDataAttribute|asLinkAttribute;
1256 switch (parm.type) {
1257 case Param::reservedName + Syntax::rCDATA:
1258 declaredValue = new CdataDeclaredValue;
1260 case Param::reservedName + Syntax::rENTITY:
1261 declaredValue = new EntityDeclaredValue(0);
1262 allowedFlags = asLinkAttribute;
1264 case Param::reservedName + Syntax::rENTITIES:
1265 declaredValue = new EntityDeclaredValue(1);
1266 allowedFlags = asLinkAttribute;
1268 case Param::reservedName + Syntax::rID:
1269 declaredValue = new IdDeclaredValue;
1272 case Param::reservedName + Syntax::rIDREF:
1273 declaredValue = new IdrefDeclaredValue(0);
1276 case Param::reservedName + Syntax::rIDREFS:
1277 declaredValue = new IdrefDeclaredValue(1);
1280 case Param::reservedName + Syntax::rNAME:
1282 = new TokenizedDeclaredValue(TokenizedDeclaredValue::name, 0);
1283 if (options().warnNameDeclaredValue)
1284 message(ParserMessages::nameDeclaredValue);
1286 case Param::reservedName + Syntax::rNAMES:
1288 = new TokenizedDeclaredValue(TokenizedDeclaredValue::name, 1);
1289 if (options().warnNameDeclaredValue)
1290 message(ParserMessages::nameDeclaredValue);
1292 case Param::reservedName + Syntax::rNMTOKEN:
1294 = new TokenizedDeclaredValue(TokenizedDeclaredValue::nameToken, 0);
1296 case Param::reservedName + Syntax::rNMTOKENS:
1298 = new TokenizedDeclaredValue(TokenizedDeclaredValue::nameToken, 1);
1300 case Param::reservedName + Syntax::rNUMBER:
1302 = new TokenizedDeclaredValue(TokenizedDeclaredValue::number, 0);
1303 if (options().warnNumberDeclaredValue)
1304 message(ParserMessages::numberDeclaredValue);
1306 case Param::reservedName + Syntax::rNUMBERS:
1308 = new TokenizedDeclaredValue(TokenizedDeclaredValue::number, 1);
1309 if (options().warnNumberDeclaredValue)
1310 message(ParserMessages::numberDeclaredValue);
1312 case Param::reservedName + Syntax::rNUTOKEN:
1314 = new TokenizedDeclaredValue(TokenizedDeclaredValue::numberToken, 0);
1315 if (options().warnNutokenDeclaredValue)
1316 message(ParserMessages::nutokenDeclaredValue);
1318 case Param::reservedName + Syntax::rNUTOKENS:
1320 = new TokenizedDeclaredValue(TokenizedDeclaredValue::numberToken, 1);
1321 if (options().warnNutokenDeclaredValue)
1322 message(ParserMessages::nutokenDeclaredValue);
1324 case Param::reservedName + Syntax::rNOTATION:
1326 static AllowedParams allowNameGroup(Param::nameGroup);
1327 if (!parseParam(allowNameGroup, declInputLevel, parm))
1329 Vector<StringC> group(parm.nameTokenVector.size());
1330 for (size_t i = 0; i < group.size(); i++)
1331 parm.nameTokenVector[i].name.swap(group[i]);
1332 declaredValue = new NotationDeclaredValue(group);
1336 case Param::nameTokenGroup:
1338 Vector<StringC> group(parm.nameTokenVector.size());
1339 Vector<StringC> origGroup(parm.nameTokenVector.size());
1340 for (size_t i = 0; i < group.size(); i++) {
1341 parm.nameTokenVector[i].name.swap(group[i]);
1342 parm.nameTokenVector[i].origName.swap(origGroup[i]);
1344 GroupDeclaredValue *grpVal = new NameTokenGroupDeclaredValue(group);
1345 grpVal->setOrigAllowedValues(origGroup);
1346 declaredValue = grpVal;
1349 case Param::reservedName + Syntax::rDATA:
1351 if (!parseParam(allowName, declInputLevel, parm))
1353 Ptr<Notation> notation(lookupCreateNotation(parm.token));
1354 static AllowedParams allowDsoSilentValue(Param::dso, Param::silent);
1355 AttributeList attributes(notation->attributeDef());
1356 if (parseParam(allowDsoSilentValue, declInputLevel, parm)
1357 && parm.type == Param::dso) {
1358 if (attributes.size() == 0 && !sd().www())
1359 message(ParserMessages::notationNoAttributes,
1360 StringMessageArg(notation->name()));
1361 Boolean netEnabling;
1362 Ptr<AttributeDefinitionList> newAttDef;
1363 if (!parseAttributeSpec(asMode, attributes, netEnabling, newAttDef))
1365 if (!newAttDef.isNull()) {
1366 newAttDef->setIndex(defDtd().allocAttributeDefinitionListIndex());
1367 notation->setAttributeDef(newAttDef);
1369 if (attributes.nSpec() == 0)
1370 message(ParserMessages::emptyDataAttributeSpec);
1373 attributes.finish(*this);
1374 // unget the first token of the default value
1375 currentInput()->ungetToken();
1377 ConstPtr<Notation> nt(notation.pointer());
1378 declaredValue = new DataDeclaredValue(nt, attributes);
1385 if (!(allowedFlags & asDataAttribute))
1386 message(ParserMessages::dataAttributeDeclaredValue);
1388 else if (haveDefLpd() && !isNotation && !(allowedFlags & asLinkAttribute))
1389 message(ParserMessages::linkAttributeDeclaredValue);
1393 Boolean Parser::parseDefaultValue(unsigned declInputLevel,
1396 const StringC &attributeName,
1397 Owner<DeclaredValue> &declaredValue,
1398 Owner<AttributeDefinition> &def,
1399 Boolean &anyCurrent)
1402 static AllowedParams
1403 allowDefaultValue(Param::indicatedReservedName + Syntax::rFIXED,
1404 Param::indicatedReservedName + Syntax::rREQUIRED,
1405 Param::indicatedReservedName + Syntax::rCURRENT,
1406 Param::indicatedReservedName + Syntax::rCONREF,
1407 Param::indicatedReservedName + Syntax::rIMPLIED,
1408 Param::attributeValue,
1409 Param::attributeValueLiteral);
1410 static AllowedParams
1411 allowTokenDefaultValue(Param::indicatedReservedName + Syntax::rFIXED,
1412 Param::indicatedReservedName + Syntax::rREQUIRED,
1413 Param::indicatedReservedName + Syntax::rCURRENT,
1414 Param::indicatedReservedName + Syntax::rCONREF,
1415 Param::indicatedReservedName + Syntax::rIMPLIED,
1416 Param::attributeValue,
1417 Param::tokenizedAttributeValueLiteral);
1418 if (!parseParam(declaredValue->tokenized()
1419 ? allowTokenDefaultValue
1420 : allowDefaultValue, declInputLevel, parm))
1422 switch (parm.type) {
1423 case Param::indicatedReservedName + Syntax::rFIXED:
1425 static AllowedParams allowValue(Param::attributeValue,
1426 Param::attributeValueLiteral);
1427 static AllowedParams
1428 allowTokenValue(Param::attributeValue,
1429 Param::tokenizedAttributeValueLiteral);
1430 if (!parseParam(declaredValue->tokenized()
1432 : allowValue, declInputLevel, parm))
1434 unsigned specLength = 0;
1435 AttributeValue *value = declaredValue->makeValue(parm.literalText,
1439 if (declaredValue->isId())
1440 message(ParserMessages::idDeclaredValue);
1441 def = new FixedAttributeDefinition(attributeName,
1442 declaredValue.extract(),
1446 case Param::attributeValue:
1447 if (options().warnAttributeValueNotLiteral)
1448 message(ParserMessages::attributeValueNotLiteral);
1450 case Param::attributeValueLiteral:
1451 case Param::tokenizedAttributeValueLiteral:
1453 unsigned specLength = 0;
1454 AttributeValue *value = declaredValue->makeValue(parm.literalText,
1458 if (declaredValue->isId())
1459 message(ParserMessages::idDeclaredValue);
1460 def = new DefaultAttributeDefinition(attributeName,
1461 declaredValue.extract(),
1465 case Param::indicatedReservedName + Syntax::rREQUIRED:
1466 def = new RequiredAttributeDefinition(attributeName,
1467 declaredValue.extract());
1469 case Param::indicatedReservedName + Syntax::rCURRENT:
1471 if (declaredValue->isId())
1472 message(ParserMessages::idDeclaredValue);
1473 def = new CurrentAttributeDefinition(attributeName,
1474 declaredValue.extract(),
1475 defDtd().allocCurrentAttributeIndex());
1477 message(ParserMessages::dataAttributeDefaultValue);
1478 else if (haveDefLpd())
1479 message(ParserMessages::linkAttributeDefaultValue);
1480 else if (options().warnCurrent)
1481 message(ParserMessages::currentAttribute);
1483 case Param::indicatedReservedName + Syntax::rCONREF:
1484 if (declaredValue->isId())
1485 message(ParserMessages::idDeclaredValue);
1486 if (declaredValue->isNotation())
1487 message(ParserMessages::notationConref);
1488 def = new ConrefAttributeDefinition(attributeName,
1489 declaredValue.extract());
1491 message(ParserMessages::dataAttributeDefaultValue);
1492 else if (haveDefLpd())
1493 message(ParserMessages::linkAttributeDefaultValue);
1494 else if (options().warnConref)
1495 message(ParserMessages::conrefAttribute);
1497 case Param::indicatedReservedName + Syntax::rIMPLIED:
1498 def = new ImpliedAttributeDefinition(attributeName,
1499 declaredValue.extract());
1507 // parm contains either system or public
1509 Boolean Parser::parseExternalId(const AllowedParams &sysidAllow,
1510 const AllowedParams &endAllow,
1511 Boolean maybeWarnMissingSystemId,
1512 unsigned declInputLevel,
1516 id.setLocation(currentLocation());
1517 if (parm.type == Param::reservedName + Syntax::rPUBLIC) {
1518 static AllowedParams allowMinimumLiteral(Param::minimumLiteral);
1519 if (!parseParam(allowMinimumLiteral, declInputLevel, parm))
1521 const MessageType1 *fpierr;
1522 const MessageType1 *urnerr;
1523 switch (id.setPublic(parm.literalText, sd().internalCharset(),
1524 syntax().space(), fpierr, urnerr)) {
1527 PublicId::TextClass textClass;
1528 if (sd().formal() && id.publicId()->getTextClass(textClass) && textClass == PublicId::SD)
1529 message(ParserMessages::wwwRequired);
1530 if (sd().urn() && !sd().formal())
1531 message(*urnerr, StringMessageArg(*id.publicIdString()));
1535 if (sd().formal() && !sd().urn())
1536 message(*fpierr, StringMessageArg(*id.publicIdString()));
1538 case PublicId::informal:
1540 message(*fpierr, StringMessageArg(*id.publicIdString()));
1542 message(*urnerr, StringMessageArg(*id.publicIdString()));
1546 if (!parseParam(sysidAllow, declInputLevel, parm))
1548 if (parm.type == Param::systemIdentifier) {
1549 id.setSystem(parm.literalText);
1550 if (!parseParam(endAllow, declInputLevel, parm))
1553 else if (options().warnMissingSystemId && maybeWarnMissingSystemId)
1554 message(ParserMessages::missingSystemId);
1558 Boolean Parser::parseNotationDecl()
1560 unsigned declInputLevel = inputLevel();
1562 if (!parseParam(allowName, declInputLevel, parm))
1564 Notation *nt = lookupCreateNotation(parm.token);
1565 if (validate() && nt->defined())
1566 message(ParserMessages::duplicateNotationDeclaration,
1567 StringMessageArg(parm.token));
1568 AttributeDefinitionList *atts = nt->attributeDef().pointer();
1570 for (size_t i = 0; i < atts->size(); i++) {
1572 if (atts->def(i)->isSpecified(implicit) && implicit) {
1573 message(ParserMessages::notationMustNotBeDeclared,
1574 StringMessageArg(parm.token));
1578 static AllowedParams
1579 allowPublicSystem(Param::reservedName + Syntax::rPUBLIC,
1580 Param::reservedName + Syntax::rSYSTEM);
1581 if (!parseParam(allowPublicSystem, declInputLevel, parm))
1585 static AllowedParams allowSystemIdentifierMdc(Param::systemIdentifier,
1589 if (!parseExternalId(allowSystemIdentifierMdc, allowMdc,
1590 parm.type == Param::reservedName + Syntax::rSYSTEM,
1591 declInputLevel, parm, id))
1593 if (validate() && sd().formal()) {
1594 PublicId::TextClass textClass;
1595 const PublicId *publicId = id.publicId();
1597 && publicId->getTextClass(textClass)
1598 && textClass != PublicId::NOTATION)
1599 message(ParserMessages::notationIdentifierTextClass);
1601 if (!nt->defined()) {
1602 nt->setExternalId(id, markupLocation());
1603 nt->generateSystemId(*this);
1604 if (currentMarkup())
1605 eventHandler().notationDecl(new (eventAllocator())
1606 NotationDeclEvent(nt, markupLocation(),
1612 Boolean Parser::parseEntityDecl()
1614 unsigned declInputLevel = inputLevel();
1617 static AllowedParams
1618 allowEntityNamePero(Param::entityName,
1619 Param::indicatedReservedName + Syntax::rDEFAULT,
1622 if (!parseParam(allowEntityNamePero, declInputLevel, parm))
1625 Entity::DeclType declType;
1626 StringC name; // empty for default entity
1627 if (parm.type == Param::pero) {
1628 declType = Entity::parameterEntity;
1629 static AllowedParams allowParamEntityName(Param::paramEntityName);
1630 if (!parseParam(allowParamEntityName, declInputLevel, parm))
1632 parm.token.swap(name);
1635 declType = Entity::generalEntity;
1636 if (parm.type == Param::entityName)
1637 parm.token.swap(name);
1638 else if (sd().implydefEntity())
1639 message(ParserMessages::implydefEntityDefault);
1640 else if (options().warnDefaultEntityDecl)
1641 message(ParserMessages::defaultEntityDecl);
1643 static AllowedParams
1644 allowEntityTextType(Param::paramLiteral,
1645 Param::reservedName + Syntax::rCDATA,
1646 Param::reservedName + Syntax::rSDATA,
1647 Param::reservedName + Syntax::rPI,
1648 Param::reservedName + Syntax::rSTARTTAG,
1649 Param::reservedName + Syntax::rENDTAG,
1650 Param::reservedName + Syntax::rMS,
1651 Param::reservedName + Syntax::rMD,
1652 Param::reservedName + Syntax::rSYSTEM,
1653 Param::reservedName + Syntax::rPUBLIC);
1655 if (!parseParam(allowEntityTextType, declInputLevel, parm))
1657 Location typeLocation(currentLocation());
1658 Entity::DataType dataType = Entity::sgmlText;
1659 InternalTextEntity::Bracketed bracketed = InternalTextEntity::none;
1660 switch (parm.type) {
1661 case Param::reservedName + Syntax::rSYSTEM:
1662 case Param::reservedName + Syntax::rPUBLIC:
1663 return parseExternalEntity(name, declType, declInputLevel, parm);
1664 case Param::reservedName + Syntax::rCDATA:
1665 dataType = Entity::cdata;
1666 if (options().warnInternalCdataEntity)
1667 message(ParserMessages::internalCdataEntity);
1669 case Param::reservedName + Syntax::rSDATA:
1670 dataType = Entity::sdata;
1671 if (options().warnInternalSdataEntity)
1672 message(ParserMessages::internalSdataEntity);
1674 case Param::reservedName + Syntax::rPI:
1675 dataType = Entity::pi;
1676 if (options().warnPiEntity)
1677 message(ParserMessages::piEntity);
1679 case Param::reservedName + Syntax::rSTARTTAG:
1680 bracketed = InternalTextEntity::starttag;
1681 if (options().warnBracketEntity)
1682 message(ParserMessages::bracketEntity);
1684 case Param::reservedName + Syntax::rENDTAG:
1685 bracketed = InternalTextEntity::endtag;
1686 if (options().warnBracketEntity)
1687 message(ParserMessages::bracketEntity);
1689 case Param::reservedName + Syntax::rMS:
1690 bracketed = InternalTextEntity::ms;
1691 if (options().warnBracketEntity)
1692 message(ParserMessages::bracketEntity);
1694 case Param::reservedName + Syntax::rMD:
1695 bracketed = InternalTextEntity::md;
1696 if (options().warnBracketEntity)
1697 message(ParserMessages::bracketEntity);
1700 if (parm.type != Param::paramLiteral) {
1701 if (!parseParam(allowParamLiteral, declInputLevel, parm))
1705 parm.literalText.swap(text);
1706 if (bracketed != InternalTextEntity::none) {
1709 switch (bracketed) {
1710 case InternalTextEntity::starttag:
1711 open = instanceSyntax().delimGeneral(Syntax::dSTAGO);
1712 close = instanceSyntax().delimGeneral(Syntax::dTAGC);
1714 case InternalTextEntity::endtag:
1715 open = instanceSyntax().delimGeneral(Syntax::dETAGO);
1716 close = instanceSyntax().delimGeneral(Syntax::dTAGC);
1718 case InternalTextEntity::ms: {
1720 (declType == Entity::parameterEntity) ? syntax() : instanceSyntax();
1721 open = syn.delimGeneral(Syntax::dMDO);
1722 open += syn.delimGeneral(Syntax::dDSO);
1723 close = syn.delimGeneral(Syntax::dMSC);
1724 close += syn.delimGeneral(Syntax::dMDC);
1727 case InternalTextEntity::md: {
1729 (declType == Entity::parameterEntity) ? syntax() : instanceSyntax();
1730 open = syn.delimGeneral(Syntax::dMDO);
1731 close = syn.delimGeneral(Syntax::dMDC);
1737 text.insertChars(open, Location(new BracketOrigin(typeLocation,
1738 BracketOrigin::open),
1740 text.addChars(close, Location(new BracketOrigin(typeLocation,
1741 BracketOrigin::close),
1743 if (text.size() > syntax().litlen()
1744 && text.size() - open.size() - close.size() <= syntax().litlen())
1745 message(ParserMessages::bracketedLitlen,
1746 NumberMessageArg(syntax().litlen()));
1748 if (!parseParam(allowMdc, declInputLevel, parm))
1750 if (declType == Entity::parameterEntity
1751 && (dataType == Entity::cdata || dataType == Entity::sdata)) {
1752 message(ParserMessages::internalParameterDataEntity,
1753 StringMessageArg(name));
1759 entity = new InternalCdataEntity(name, markupLocation(), text);
1762 entity = new InternalSdataEntity(name, markupLocation(), text);
1765 entity = new PiEntity(name, declType, markupLocation(), text);
1767 case Entity::sgmlText:
1768 entity = new InternalTextEntity(name, declType, markupLocation(), text, bracketed);
1774 maybeDefineEntity(entity);
1778 Boolean Parser::parseExternalEntity(StringC &name,
1779 Entity::DeclType declType,
1780 unsigned declInputLevel,
1783 static AllowedParams
1784 allowSystemIdentifierEntityTypeMdc(Param::systemIdentifier,
1785 Param::reservedName + Syntax::rSUBDOC,
1786 Param::reservedName + Syntax::rCDATA,
1787 Param::reservedName + Syntax::rSDATA,
1788 Param::reservedName + Syntax::rNDATA,
1790 static AllowedParams
1791 allowEntityTypeMdc(Param::reservedName + Syntax::rSUBDOC,
1792 Param::reservedName + Syntax::rCDATA,
1793 Param::reservedName + Syntax::rSDATA,
1794 Param::reservedName + Syntax::rNDATA,
1798 if (!parseExternalId(allowSystemIdentifierEntityTypeMdc, allowEntityTypeMdc,
1799 1, declInputLevel, parm, id))
1801 if (parm.type == Param::mdc) {
1802 maybeDefineEntity(new ExternalTextEntity(name, declType, markupLocation(),
1807 if (parm.type == Param::reservedName + Syntax::rSUBDOC) {
1808 if (sd().subdoc() == 0)
1809 message(ParserMessages::subdocEntity, StringMessageArg(name));
1810 if (!parseParam(allowMdc, declInputLevel, parm))
1812 entity = new SubdocEntity(name, markupLocation(), id);
1815 Entity::DataType dataType;
1816 switch (parm.type) {
1817 case Param::reservedName + Syntax::rCDATA:
1818 dataType = Entity::cdata;
1819 if (options().warnExternalCdataEntity)
1820 message(ParserMessages::externalCdataEntity);
1822 case Param::reservedName + Syntax::rSDATA:
1823 dataType = Entity::sdata;
1824 if (options().warnExternalSdataEntity)
1825 message(ParserMessages::externalSdataEntity);
1827 case Param::reservedName + Syntax::rNDATA:
1828 dataType = Entity::ndata;
1833 if (!parseParam(allowName, declInputLevel, parm))
1835 Ptr<Notation> notation(lookupCreateNotation(parm.token));
1836 if (!parseParam(allowDsoMdc, declInputLevel, parm))
1838 AttributeList attributes(notation->attributeDef());
1839 if (parm.type == Param::dso) {
1840 if (attributes.size() == 0 && !sd().www())
1841 message(ParserMessages::notationNoAttributes,
1842 StringMessageArg(notation->name()));
1843 Boolean netEnabling;
1844 Ptr<AttributeDefinitionList> newAttDef;
1845 if (!parseAttributeSpec(asMode, attributes, netEnabling, newAttDef))
1847 if (!newAttDef.isNull()) {
1848 newAttDef->setIndex(defDtd().allocAttributeDefinitionListIndex());
1849 notation->setAttributeDef(newAttDef);
1851 if (attributes.nSpec() == 0)
1852 message(ParserMessages::emptyDataAttributeSpec);
1853 if (!parseParam(allowMdc, declInputLevel, parm))
1857 attributes.finish(*this);
1858 entity = new ExternalDataEntity(name, dataType, markupLocation(), id,
1859 notation, attributes,
1860 declType == Entity::parameterEntity
1861 ? Entity::parameterEntity
1862 : Entity::generalEntity);
1864 if (declType == Entity::parameterEntity && !sd().www()) {
1865 message(ParserMessages::externalParameterDataSubdocEntity,
1866 StringMessageArg(name));
1869 maybeDefineEntity(entity);
1873 Notation *Parser::lookupCreateNotation(const StringC &name)
1875 Ptr<Notation> nt = defDtd().lookupNotation(name);
1877 nt = new Notation(name, defDtd().namePointer(), defDtd().isBase());
1878 defDtd().insertNotation(nt);
1880 return nt.pointer();
1883 void Parser::maybeDefineEntity(const Ptr<Entity> &entity)
1885 Dtd &dtd = defDtd();
1887 entity->setDeclIn(dtd.namePointer(),
1889 defLpd().namePointer(),
1892 entity->setDeclIn(dtd.namePointer(), dtd.isBase());
1893 Boolean ignored = 0;
1894 if (entity->name().size() == 0) {
1895 const Entity *oldEntity = dtd.defaultEntity().pointer();
1897 || (!oldEntity->declInActiveLpd() && entity->declInActiveLpd()))
1898 dtd.setDefaultEntity(entity, *this);
1901 if (options().warnDuplicateEntity)
1902 message(ParserMessages::duplicateEntityDeclaration,
1903 StringMessageArg(syntax().rniReservedName(Syntax::rDEFAULT)));
1907 Ptr<Entity> oldEntity = dtd.insertEntity(entity);
1908 if (oldEntity.isNull())
1909 entity->generateSystemId(*this);
1910 else if (oldEntity->defaulted()) {
1911 dtd.insertEntity(entity, 1);
1912 message(ParserMessages::defaultedEntityDefined,
1913 StringMessageArg(entity->name()));
1914 entity->generateSystemId(*this);
1917 if (entity->declInActiveLpd() && !oldEntity->declInActiveLpd()) {
1918 dtd.insertEntity(entity, 1);
1919 entity->generateSystemId(*this);
1923 if (options().warnDuplicateEntity)
1924 message(entity->declType() == Entity::parameterEntity
1925 ? ParserMessages::duplicateParameterEntityDeclaration
1926 : ParserMessages::duplicateEntityDeclaration,
1927 StringMessageArg(entity->name()));
1931 if (currentMarkup())
1932 eventHandler().entityDecl(new (eventAllocator())
1933 EntityDeclEvent(entity, ignored,
1938 Boolean Parser::parseShortrefDecl()
1940 if (!defDtd().isBase())
1941 message(ParserMessages::shortrefOnlyInBaseDtd);
1943 unsigned declInputLevel = inputLevel();
1946 if (!parseParam(allowName, declInputLevel, parm))
1948 ShortReferenceMap *map = lookupCreateMap(parm.token);
1950 if (map->defined()) {
1951 message(ParserMessages::duplicateShortrefDeclaration,
1952 StringMessageArg(parm.token),
1953 map->defLocation());
1957 map->setDefLocation(markupLocation());
1958 if (!parseParam(allowParamLiteral, declInputLevel, parm))
1960 Vector<StringC> vec;
1962 StringC delim(parm.literalText.string());
1963 instanceSyntax().generalSubstTable()->subst(delim);
1965 if (!defDtd().shortrefIndex(delim, instanceSyntax(), srIndex)) {
1966 message(ParserMessages::unknownShortrefDelim,
1967 StringMessageArg(prettifyDelim(delim)));
1970 static AllowedParams allowEntityName(Param::entityName);
1971 if (!parseParam(allowEntityName, declInputLevel, parm))
1974 if (srIndex >= vec.size())
1975 vec.resize(srIndex + 1);
1976 if (vec[srIndex].size() > 0) {
1977 message(ParserMessages::delimDuplicateMap,
1978 StringMessageArg(prettifyDelim(delim)));
1982 parm.token.swap(vec[srIndex]);
1984 static AllowedParams allowParamLiteralMdc(Param::paramLiteral, Param::mdc);
1985 if (!parseParam(allowParamLiteralMdc, declInputLevel, parm))
1987 } while (parm.type != Param::mdc);
1989 map->setNameMap(vec);
1990 if (currentMarkup())
1991 eventHandler().shortrefDecl(new (eventAllocator())
1992 ShortrefDeclEvent(map,
1993 currentDtdPointer(),
2000 StringC Parser::prettifyDelim(const StringC &delim)
2002 StringC prettyDelim;
2003 for (size_t i = 0; i < delim.size(); i++) {
2004 const StringC *nameP;
2005 if (syntax().charFunctionName(delim[i], nameP)) {
2006 prettyDelim += syntax().delimGeneral(Syntax::dCRO);
2007 prettyDelim += *nameP;
2008 prettyDelim += syntax().delimGeneral(Syntax::dREFC);
2011 prettyDelim += delim[i];
2016 ShortReferenceMap *Parser::lookupCreateMap(const StringC &name)
2018 ShortReferenceMap *map = defDtd().lookupShortReferenceMap(name);
2020 map = new ShortReferenceMap(name);
2021 defDtd().insertShortReferenceMap(map);
2026 Boolean Parser::parseUsemapDecl()
2028 if (!inInstance() && !defDtd().isBase())
2029 message(ParserMessages::usemapOnlyInBaseDtd);
2031 unsigned declInputLevel = inputLevel();
2033 static AllowedParams
2034 allowNameEmpty(Param::name,
2035 Param::indicatedReservedName + Syntax::rEMPTY);
2036 if (!parseParam(allowNameEmpty, declInputLevel, parm))
2038 const ShortReferenceMap *map;
2039 if (parm.type == Param::name) {
2041 map = currentDtd().lookupShortReferenceMap(parm.token);
2043 message(ParserMessages::undefinedShortrefMapInstance,
2044 StringMessageArg(parm.token));
2047 ShortReferenceMap *tem = lookupCreateMap(parm.token);
2054 static AllowedParams
2055 allowNameNameGroupMdc(Param::name, Param::nameGroup, Param::mdc);
2056 if (!parseParam(allowNameNameGroupMdc, declInputLevel, parm))
2058 if (parm.type != Param::mdc) {
2060 message(ParserMessages::usemapAssociatedElementTypeInstance);
2061 if (!parseParam(allowMdc, declInputLevel, parm))
2065 Vector<const ElementType *> v;
2066 if (parm.type == Param::name) {
2067 ElementType *e = lookupCreateElement(parm.token);
2073 v.resize(parm.nameTokenVector.size());
2074 for (size_t i = 0; i < parm.nameTokenVector.size(); i++) {
2076 = lookupCreateElement(parm.nameTokenVector[i].name);
2082 if (!parseParam(allowMdc, declInputLevel, parm))
2084 if (currentMarkup())
2085 eventHandler().usemap(new (eventAllocator())
2087 currentDtdPointer(),
2094 message(ParserMessages::usemapAssociatedElementTypeDtd);
2096 if (map != &theEmptyMap && !map->defined())
2097 message(ParserMessages::undefinedShortrefMapInstance,
2098 StringMessageArg(map->name()));
2100 if (currentMarkup()) {
2101 Vector<const ElementType *> v;
2102 eventHandler().usemap(new (eventAllocator())
2104 currentDtdPointer(),
2108 currentElement().setMap(map);
2115 Boolean Parser::parseDoctypeDeclStart()
2117 if (hadDtd() && !sd().concur() && !sd().explicitLink())
2118 message(ParserMessages::multipleDtds);
2120 message(ParserMessages::dtdAfterLpd);
2121 unsigned declInputLevel = inputLevel();
2123 static AllowedParams
2124 allowImpliedName(Param::indicatedReservedName + Syntax::rIMPLIED,
2126 if (!parseParam(sd().www() ? allowImpliedName : allowName, declInputLevel, parm))
2128 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2129 if (sd().concur() > 0 || sd().explicitLink() > 0)
2130 message(ParserMessages::impliedDoctypeConcurLink);
2131 message(ParserMessages::sorryImpliedDoctype);
2135 parm.token.swap(name);
2136 if (!lookupDtd(name).isNull())
2137 message(ParserMessages::duplicateDtd, StringMessageArg(name));
2138 static AllowedParams
2139 allowPublicSystemDsoMdc(Param::reservedName + Syntax::rPUBLIC,
2140 Param::reservedName + Syntax::rSYSTEM,
2143 if (!parseParam(allowPublicSystemDsoMdc, declInputLevel, parm))
2145 ConstPtr<Entity> entity;
2147 EntityDecl::DataType data;
2149 if (parm.type == Param::reservedName + Syntax::rPUBLIC
2150 || parm.type == Param::reservedName + Syntax::rSYSTEM) {
2151 static AllowedParams allowSystemIdentifierDsoMdc(Param::systemIdentifier,
2152 Param::dso, Param::mdc);
2153 static AllowedParams
2154 allowSystemIdentifierDsoMdcData(Param::systemIdentifier,
2155 Param::dso, Param::mdc,
2156 Param::reservedName + Syntax::rCDATA,
2157 Param::reservedName + Syntax::rSDATA,
2158 Param::reservedName + Syntax::rNDATA);
2159 static AllowedParams allowDsoMdcData(Param::dso, Param::mdc,
2160 Param::reservedName + Syntax::rCDATA,
2161 Param::reservedName + Syntax::rSDATA,
2162 Param::reservedName + Syntax::rNDATA);
2163 if (!parseExternalId(sd().www() ? allowSystemIdentifierDsoMdcData :
2164 allowSystemIdentifierDsoMdc,
2165 sd().www() ? allowDsoMdcData : allowDsoMdc,
2166 1, declInputLevel, parm, id))
2168 switch (parm.type) {
2169 case Param::reservedName + Syntax::rCDATA:
2170 data = Entity::cdata;
2172 case Param::reservedName + Syntax::rSDATA:
2173 data = Entity::sdata;
2175 case Param::reservedName + Syntax::rNDATA:
2176 data = Entity::ndata;
2179 data = Entity::sgmlText;
2182 if (data == Entity::sgmlText) {
2184 = new ExternalTextEntity(name, Entity::doctype, markupLocation(), id);
2185 tem->generateSystemId(*this);
2190 .externalEntityDecl(new (eventAllocator())
2191 ExternalEntityDeclEvent(entity, 0));
2194 // external subset uses some DTD notation
2195 if (!parseParam(allowName, declInputLevel, parm))
2197 parm.token.swap(notation);
2198 if (!parseParam(allowDsoMdc, declInputLevel, parm))
2203 // no external subset specified
2204 if (sd().implydefDoctype()) {
2205 // FIXME this fails for #IMPLIED, since name isn't yet known
2207 = new ExternalTextEntity(name, Entity::doctype, markupLocation(), id);
2208 tem->generateSystemId(*this);
2211 else if (parm.type == Param::mdc) {
2212 if (sd().implydefElement() == Sd::implydefElementNo) {
2213 message(ParserMessages::noDtdSubset);
2217 // Discard mdc or dso
2218 if (currentMarkup())
2219 currentMarkup()->resize(currentMarkup()->size() - 1);
2220 eventHandler().startDtd(new (eventAllocator())
2221 StartDtdEvent(name, entity, parm.type == Param::dso,
2225 if (notation.size() > 0) {
2226 // FIXME this case has the wrong entity in the event
2227 // this should be fixed by moving startDtd() call and this code up
2228 ConstPtr<Notation> nt(lookupCreateNotation(notation));
2230 AttributeList attrs(nt->attributeDef());
2231 attrs.finish(*this);
2233 = new ExternalDataEntity(name, data, markupLocation(), id, nt, attrs,
2235 tem->generateSystemId(*this);
2236 // FIXME This is a hack; we need the entity to have the doctype name to
2237 // have generateSytemId() work properly, but have an empty name to add
2238 // it as a parameter entity, which is needed to check the notation
2240 tem->setName(entname);
2241 defDtd().insertEntity(tem);
2244 if (parm.type == Param::mdc) {
2246 currentInput()->ungetToken();
2247 if (entity.isNull()) {
2248 (void)parseDoctypeDeclEnd();
2251 // reference the entity
2252 Ptr<EntityOrigin> origin
2253 = EntityOrigin::make(internalAllocator(), entity, currentLocation());
2254 entity->dsReference(*this, origin);
2255 if (inputLevel() == 1) { // reference failed
2256 (void)parseDoctypeDeclEnd();
2260 else if (!entity.isNull())
2261 setDsEntity(entity);
2262 setPhase(declSubsetPhase);
2266 void Parser::implyDtd(const StringC &gi)
2268 startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2270 if (currentMarkup()) {
2271 currentMarkup()->addDelim(Syntax::dMDO);
2272 currentMarkup()->addReservedName(Syntax::rDOCTYPE,
2273 syntax().reservedName(Syntax::rDOCTYPE));
2274 currentMarkup()->addS(syntax().space());
2275 currentMarkup()->addName(gi.data(), gi.size());
2278 if (sd().concur() > 0 || sd().explicitLink() > 0
2279 || (sd().implydefElement() == Sd::implydefElementNo
2280 && !sd().implydefDoctype()))
2281 message(ParserMessages::omittedProlog);
2283 if ((sd().implydefElement() != Sd::implydefElementNo) && !sd().implydefDoctype()) {
2284 eventHandler().startDtd(new (eventAllocator())
2285 StartDtdEvent(gi, ConstPtr<Entity>(), 0,
2289 parseDoctypeDeclEnd(1);
2293 // The null location indicates that this is a fake entity.
2294 Entity *tem = new ExternalTextEntity(gi, Entity::doctype, Location(), id);
2295 ConstPtr<Entity> entity(tem);
2296 if (sd().implydefDoctype())
2297 tem->generateSystemId(*this);
2299 // Don't use Entity::generateSystemId because we don't want an error
2302 if (!entityCatalog().lookup(*entity, syntax(), sd().internalCharset(),
2303 messenger(), str)) {
2304 message(ParserMessages::noDtd);
2306 eventHandler().startDtd(new (eventAllocator())
2307 StartDtdEvent(gi, ConstPtr<Entity>(), 0,
2311 parseDoctypeDeclEnd(1);
2314 id.setEffectiveSystem(str);
2316 if (currentMarkup()) {
2317 currentMarkup()->addS(syntax().space());
2318 currentMarkup()->addReservedName(Syntax::rSYSTEM,
2319 syntax().reservedName(Syntax::rSYSTEM));
2322 entity = new ExternalTextEntity(gi,
2327 declStr += syntax().delimGeneral(Syntax::dMDO);
2328 declStr += syntax().reservedName(Syntax::rDOCTYPE);
2329 declStr += syntax().space();
2331 declStr += syntax().space();
2332 declStr += syntax().reservedName(Syntax::rSYSTEM);
2333 declStr += syntax().delimGeneral(Syntax::dMDC);
2334 message(ParserMessages::implyingDtd, StringMessageArg(declStr));
2336 Ptr<EntityOrigin> origin
2337 = EntityOrigin::make(internalAllocator(), entity, currentLocation());
2338 eventHandler().startDtd(new (eventAllocator())
2339 StartDtdEvent(gi, entity, 0,
2343 entity->dsReference(*this, origin);
2344 if (inputLevel() == 1)
2345 parseDoctypeDeclEnd(1);
2347 setPhase(declSubsetPhase);
2350 Boolean Parser::parseDoctypeDeclEnd(Boolean fake)
2353 Ptr<Dtd> tem(defDtdPointer());
2356 startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2358 if (currentMarkup())
2359 currentMarkup()->addDelim(Syntax::dMDC);
2363 startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2365 // End DTD before parsing final param so parameter entity reference
2366 // not allowed between ] and >.
2367 if (!parseParam(allowMdc, inputLevel(), parm))
2370 eventHandler().endDtd(new (eventAllocator()) EndDtdEvent(tem,
2375 Char c = syntax().standardFunction(Syntax::fRE);
2376 eventHandler().sSep(new (eventAllocator())
2377 SSepEvent(&c, 1, Location(), 1));
2383 void Parser::checkDtd(Dtd &dtd)
2386 addNeededShortrefs(dtd, instanceSyntax());
2387 if (sd().www() || !options().errorAfdr)
2388 addCommonAttributes(dtd);
2389 Dtd::ElementTypeIter elementIter(dtd.elementTypeIter());
2391 ConstPtr<ElementDefinition> def;
2393 while ((p = elementIter.next()) != 0) {
2394 if (p->definition() == 0) {
2395 if (p->name() == dtd.name()) {
2396 if (validate() && (implydefElement() == Sd::implydefElementNo))
2397 message(ParserMessages::documentElementUndefined);
2399 else if (options().warnUndefinedElement)
2400 message(ParserMessages::dtdUndefinedElement, StringMessageArg(p->name()));
2402 def = new ElementDefinition(currentLocation(),
2403 size_t(ElementDefinition::undefinedIndex),
2404 ElementDefinition::omitEnd,
2405 ElementDefinition::any,
2406 (implydefElement() != Sd::implydefElementAnyother));
2407 p->setElementDefinition(def, i++);
2409 const ShortReferenceMap *map = p->map();
2410 if (map != 0 && map != &theEmptyMap && !map->defined()) {
2412 message(ParserMessages::undefinedShortrefMapDtd,
2413 StringMessageArg(map->name()),
2414 StringMessageArg(p->name()));
2418 Dtd::ShortReferenceMapIter mapIter(dtd.shortReferenceMapIter());
2419 int nShortref = dtd.nShortref();
2421 ShortReferenceMap *map = mapIter.next();
2424 Vector<ConstPtr<Entity> > entityMap(nShortref);
2425 for (i = 0; i < nShortref; i++) {
2426 const StringC *entityName = map->entityName(i);
2428 ConstPtr<Entity> entity
2429 = lookupEntity(0, *entityName, map->defLocation(), 0);
2430 if (entity.isNull()) {
2431 setNextLocation(map->defLocation());
2432 message(ParserMessages::mapEntityUndefined,
2433 StringMessageArg(*entityName),
2434 StringMessageArg(map->name()));
2437 if (entity->defaulted() && options().warnDefaultEntityReference) {
2438 setNextLocation(map->defLocation());
2439 message(ParserMessages::mapDefaultEntity,
2440 StringMessageArg(*entityName),
2441 StringMessageArg(map->name()));
2443 entityMap[i] = entity;
2447 map->setEntityMap(entityMap);
2448 if (options().warnUnusedMap && !map->used()) {
2449 setNextLocation(map->defLocation());
2450 message(ParserMessages::unusedMap, StringMessageArg(map->name()));
2453 if (options().warnUnusedParam) {
2454 Dtd::ConstEntityIter entityIter(((const Dtd &)dtd).parameterEntityIter());
2456 ConstPtr<Entity> entity(entityIter.next());
2457 if (entity.isNull())
2459 if (!entity->used() && !maybeStatusKeyword(*entity)) {
2460 setNextLocation(entity->defLocation());
2461 message(ParserMessages::unusedParamEntity,
2462 StringMessageArg(entity->name()));
2466 Dtd::ConstEntityIter gEntityIter(((const Dtd &)dtd).generalEntityIter());
2467 Dtd::ConstEntityIter pEntityIter(((const Dtd &)dtd).parameterEntityIter());
2468 for (i = 0; i < (sd().www() ? 2 : 1); i++) {
2470 ConstPtr<Entity> entity(i == 0 ? gEntityIter.next() : pEntityIter.next());
2471 if (entity.isNull())
2473 const ExternalDataEntity *external = entity->asExternalDataEntity();
2475 Notation *notation = (Notation *)external->notation();
2476 if (!notation->defined()) {
2477 if (sd().implydefNotation()) {
2479 notation->setExternalId(id, Location());
2480 notation->generateSystemId(*this);
2482 else if (validate()) {
2483 setNextLocation(external->defLocation());
2484 switch (external->declType()) {
2485 case Entity::parameterEntity:
2486 message(ParserMessages::parameterEntityNotationUndefined,
2487 StringMessageArg(notation->name()),
2488 StringMessageArg(external->name()));
2490 case Entity::doctype:
2491 message(ParserMessages::dsEntityNotationUndefined,
2492 StringMessageArg(notation->name()));
2495 message(ParserMessages::entityNotationUndefined,
2496 StringMessageArg(notation->name()),
2497 StringMessageArg(external->name()));
2505 Dtd::NotationIter notationIter(dtd.notationIter());
2507 Ptr<Notation> notation(notationIter.next());
2508 if (notation.isNull())
2510 if (!notation->defined() && !notation->attributeDef().isNull()) {
2511 if (sd().implydefNotation()) {
2513 notation->setExternalId(id, Location());
2514 notation->generateSystemId(*this);
2516 else if (validate())
2517 message(ParserMessages::attlistNotationUndefined,
2518 StringMessageArg(notation->name()));
2524 void Parser::addCommonAttributes(Dtd &dtd)
2526 Ptr<AttributeDefinitionList> commonAdl[2];
2528 ElementType *e = dtd.removeElementType(syntax()
2529 .rniReservedName(Syntax::rALL));
2531 commonAdl[0] = e->attributeDef();
2533 lookupCreateElement(syntax().rniReservedName(Syntax::rIMPLICIT));
2537 Ptr<Notation> allNotation
2538 = dtd.removeNotation(syntax().rniReservedName(Syntax::rALL));
2539 if (!allNotation.isNull()) {
2540 commonAdl[1] = allNotation->attributeDef();
2541 lookupCreateNotation(syntax().rniReservedName(Syntax::rIMPLICIT));
2544 Dtd::ElementTypeIter elementIter(dtd.elementTypeIter());
2545 Dtd::NotationIter notationIter(dtd.notationIter());
2546 Vector<PackedBoolean> doneAdl(dtd.nAttributeDefinitionList(),
2548 for (int isNotation = 0; isNotation < 2; isNotation++) {
2549 if (!commonAdl[isNotation].isNull()) {
2550 doneAdl[commonAdl[isNotation]->index()] = 1;
2554 a = elementIter.next();
2556 a = notationIter.next().pointer();
2559 Ptr<AttributeDefinitionList> adl = a->attributeDef();
2561 a->setAttributeDef(commonAdl[isNotation]);
2562 else if (!doneAdl[adl->index()]) {
2563 doneAdl[adl->index()] = 1;
2564 for (size_t j = 0; j < commonAdl[isNotation]->size(); j++) {
2566 if (!adl->attributeIndex(commonAdl[isNotation]->def(j)->name(),
2568 adl->append(commonAdl[isNotation]->def(j)->copy());
2575 ElementType *e = dtd.removeElementType(syntax()
2576 .rniReservedName(Syntax::rIMPLICIT));
2578 dtd.setImplicitElementAttributeDef(e->attributeDef());
2583 = dtd.removeNotation(syntax().rniReservedName(Syntax::rIMPLICIT));
2585 dtd.setImplicitNotationAttributeDef(n->attributeDef());
2589 void Parser::addCommonAttributes(Dtd &dtd)
2591 // These are #implicit, #all, #notation #implicit, #notation #all
2592 Ptr<AttributeDefinitionList> commonAdl[4];
2594 ElementType *e = lookupCreateElement(syntax()
2595 .rniReservedName(Syntax::rIMPLICIT));
2596 commonAdl[0] = e->attributeDef();
2597 e = dtd.removeElementType(syntax().rniReservedName(Syntax::rALL));
2599 commonAdl[1] = e->attributeDef();
2604 = lookupCreateNotation(syntax().rniReservedName(Syntax::rIMPLICIT));
2605 commonAdl[2] = nt->attributeDef();
2606 nt = dtd.removeNotation(syntax().rniReservedName(Syntax::rALL));
2608 commonAdl[3] = nt->attributeDef();
2610 Dtd::ElementTypeIter elementIter(dtd.elementTypeIter());
2611 Dtd::ElementTypeIter element2Iter(dtd.elementTypeIter());
2612 Dtd::NotationIter notationIter(dtd.notationIter());
2613 Dtd::NotationIter notation2Iter(dtd.notationIter());
2614 Vector<PackedBoolean> done1Adl(dtd.nAttributeDefinitionList(),
2616 Vector<PackedBoolean> done2Adl(dtd.nAttributeDefinitionList(),
2618 // we do 2 passes over element types and notations,
2619 // first merging #implicit attributes for implicit element types/notations
2620 // next merging #all attributes for all element types/notations
2621 for (int i = 0; i < 4; i++) {
2622 if (!commonAdl[i].isNull()) {
2624 done1Adl[commonAdl[i]->index()] = 1;
2626 done2Adl[commonAdl[i]->index()] = 1;
2633 ElementType *e = elementIter.next();
2635 skip = (e && e->definition()); // don't merge #implicit
2636 // attributes if e is defined
2640 a = element2Iter.next();
2641 skip = 0; // always merge #all attributes
2645 Notation *nt = notationIter.next().pointer();
2647 skip = (nt && nt->defined()); // don't merge #implicit
2648 // attributes if nt is defined
2652 a = notation2Iter.next().pointer();
2653 skip = 0; // always merge #all attributes
2660 Ptr<AttributeDefinitionList> adl = a->attributeDef();
2663 a->setAttributeDef(commonAdl[i]);
2665 else if (((i % 2) && !done1Adl[adl->index()])
2666 ||(!(i % 2) && !done2Adl[adl->index()])) {
2668 done1Adl[adl->index()] = 1;
2670 done2Adl[adl->index()] = 1;
2672 for (size_t j = 0; j < commonAdl[i]->size(); j++) {
2674 if (!adl->attributeIndex(commonAdl[i]->def(j)->name(),
2676 adl->append(commonAdl[i]->def(j)->copy());
2678 // Give an error if an #ALL data attribute was
2679 // specified and is later redeclared as #IMPLICIT
2681 if (adl->def(index)->isSpecified(implicit) && !implicit)
2682 message(ParserMessages::specifiedAttributeRedeclared,
2683 StringMessageArg(adl->def(index)->name()));
2691 ElementType *e = dtd.removeElementType(syntax()
2692 .rniReservedName(Syntax::rIMPLICIT));
2694 dtd.setImplicitElementAttributeDef(e->attributeDef());
2699 = dtd.removeNotation(syntax().rniReservedName(Syntax::rIMPLICIT));
2701 dtd.setImplicitNotationAttributeDef(n->attributeDef());
2707 Boolean Parser::maybeStatusKeyword(const Entity &entity)
2709 const InternalEntity *internal = entity.asInternalEntity();
2712 const StringC &text = internal->string();
2713 static const Syntax::ReservedName statusKeywords[] = {
2714 Syntax::rINCLUDE, Syntax::rIGNORE
2716 for (size_t i = 0; i < SIZEOF(statusKeywords); i++) {
2717 const StringC &keyword = instanceSyntax().reservedName(statusKeywords[i]);
2719 while (j < text.size() && instanceSyntax().isS(text[j]))
2722 while (j < text.size()
2723 && k < keyword.size()
2724 && ((*instanceSyntax().generalSubstTable())[text[j]]
2727 if (k == keyword.size()) {
2728 while (j < text.size() && instanceSyntax().isS(text[j]))
2730 if (j == text.size())
2737 Boolean Parser::parseLinktypeDeclStart()
2739 if (baseDtd().isNull())
2740 message(ParserMessages::lpdBeforeBaseDtd);
2741 unsigned declInputLevel = inputLevel();
2744 if (!parseParam(allowName, declInputLevel, parm))
2747 parm.token.swap(name);
2748 if (!lookupDtd(name).isNull())
2749 message(ParserMessages::duplicateDtdLpd, StringMessageArg(name));
2750 else if (!lookupLpd(name).isNull())
2751 message(ParserMessages::duplicateLpd, StringMessageArg(name));
2752 static AllowedParams
2753 allowSimpleName(Param::indicatedReservedName + Syntax::rSIMPLE,
2755 if (!parseParam(allowSimpleName, declInputLevel, parm))
2759 if (parm.type == Param::indicatedReservedName + Syntax::rSIMPLE) {
2761 sourceDtd = baseDtd();
2762 if (sourceDtd.isNull())
2763 sourceDtd = new Dtd(StringC(), 1);
2767 sourceDtd = lookupDtd(parm.token);
2768 if (sourceDtd.isNull()) {
2769 message(ParserMessages::noSuchDtd, StringMessageArg(parm.token));
2770 sourceDtd = new Dtd(parm.token, 0);
2773 static AllowedParams
2774 allowImpliedName(Param::indicatedReservedName + Syntax::rIMPLIED,
2776 if (!parseParam(allowImpliedName, declInputLevel, parm))
2779 Boolean implied = 0;
2780 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2782 if (!sd().simpleLink())
2783 message(ParserMessages::simpleLinkFeature);
2787 if (!sd().implicitLink())
2788 message(ParserMessages::implicitLinkFeature);
2793 message(ParserMessages::simpleLinkResultNotImplied);
2795 if (!sd().explicitLink())
2796 message(ParserMessages::explicitLinkFeature);
2797 resultDtd = lookupDtd(parm.token);
2798 if (resultDtd.isNull())
2799 message(ParserMessages::noSuchDtd, StringMessageArg(parm.token));
2802 static AllowedParams
2803 allowPublicSystemDsoMdc(Param::reservedName + Syntax::rPUBLIC,
2804 Param::reservedName + Syntax::rSYSTEM,
2807 if (!parseParam(allowPublicSystemDsoMdc, declInputLevel, parm))
2809 ConstPtr<Entity> entity;
2810 if (parm.type == Param::reservedName + Syntax::rPUBLIC
2811 || parm.type == Param::reservedName + Syntax::rSYSTEM) {
2812 static AllowedParams allowSystemIdentifierDsoMdc(Param::systemIdentifier,
2813 Param::dso, Param::mdc);
2815 if (!parseExternalId(allowSystemIdentifierDsoMdc, allowDsoMdc,
2816 1, declInputLevel, parm, id))
2819 = new ExternalTextEntity(name, Entity::linktype, markupLocation(), id);
2820 tem->generateSystemId(*this);
2824 .externalEntityDecl(new (eventAllocator())
2825 ExternalEntityDeclEvent(entity, 0));
2830 lpd = new SimpleLpd(name, markupLocation(), sourceDtd);
2832 lpd = new ComplexLpd(name,
2833 implied ? Lpd::implicitLink : Lpd::explicitLink,
2838 if (!baseDtd().isNull() && shouldActivateLink(name)) {
2839 size_t nActive = nActiveLink();
2842 for (size_t i = 0; i < nActive; i++)
2843 if (activeLpd(i).type() == Lpd::simpleLink)
2845 if (nSimple == sd().simpleLink())
2846 message(ParserMessages::simpleLinkCount,
2847 NumberMessageArg(sd().simpleLink()));
2851 Boolean haveImplicit = 0;
2852 Boolean haveExplicit = 0;
2854 for (i = 0; i < nActive; i++) {
2855 if (activeLpd(i).type() == Lpd::implicitLink)
2857 else if (activeLpd(i).type() == Lpd::explicitLink)
2860 const Dtd *sourceDtd = lpd->sourceDtd().pointer();
2861 if (implied && haveImplicit)
2862 message(ParserMessages::oneImplicitLink);
2863 else if (sd().explicitLink() <= 1 && sourceDtd != baseDtd().pointer())
2864 message(sd().explicitLink() == 0
2865 ? ParserMessages::explicitNoRequiresSourceTypeBase
2866 : ParserMessages::explicit1RequiresSourceTypeBase,
2867 StringMessageArg(lpd->name()));
2868 else if (sd().explicitLink() == 1 && haveExplicit && !implied)
2869 message(ParserMessages::duplicateExplicitChain);
2870 else if (haveExplicit || haveImplicit
2871 || sourceDtd != baseDtd().pointer())
2872 message(ParserMessages::sorryLink, StringMessageArg(lpd->name()));
2877 // Discard mdc or dso
2878 if (currentMarkup())
2879 currentMarkup()->resize(currentMarkup()->size() - 1);
2880 eventHandler().startLpd(new (eventAllocator())
2881 StartLpdEvent(lpd->active(),
2884 parm.type == Param::dso,
2888 if (parm.type == Param::mdc) {
2890 currentInput()->ungetToken();
2891 if (entity.isNull()) {
2892 message(ParserMessages::noLpdSubset, StringMessageArg(name));
2893 (void)parseLinktypeDeclEnd();
2896 // reference the entity
2897 Ptr<EntityOrigin> origin
2898 = EntityOrigin::make(internalAllocator(), entity, currentLocation());
2899 entity->dsReference(*this, origin);
2900 if (inputLevel() == 1) { // reference failed
2901 (void)parseLinktypeDeclEnd();
2905 else if (!entity.isNull())
2906 setDsEntity(entity);
2907 setPhase(declSubsetPhase);
2911 Boolean Parser::parseLinktypeDeclEnd()
2914 if (defLpd().type() != Lpd::simpleLink) {
2915 if (!defComplexLpd().initialLinkSet()->defined())
2916 message(ParserMessages::noInitialLinkSet,
2917 StringMessageArg(defLpd().name()));
2918 ComplexLpd::ConstLinkSetIter iter = defComplexLpd().linkSetIter();
2919 const LinkSet *linkSet;
2920 while ((linkSet = iter.next()) != 0)
2921 if (!linkSet->defined())
2922 message(ParserMessages::undefinedLinkSet, StringMessageArg(linkSet->name()));
2924 ConstPtr<Lpd> tem(defLpdPointer());
2926 startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2928 Boolean result = parseParam(allowMdc, inputLevel(), parm);
2929 eventHandler().endLpd(new (eventAllocator()) EndLpdEvent(tem,
2935 Boolean Parser::parseLinkDecl()
2937 return parseLinkSet(0);
2940 Boolean Parser::parseIdlinkDecl()
2942 return parseLinkSet(1);
2945 // This will only get called if we're defining a complex lpd.
2947 Boolean Parser::parseLinkSet(Boolean idlink)
2949 if (defLpd().type() == Lpd::simpleLink) {
2950 message(idlink ? ParserMessages::idlinkDeclSimple : ParserMessages::linkDeclSimple);
2954 if (defComplexLpd().hadIdLinkSet())
2955 message(ParserMessages::duplicateIdLinkSet);
2957 defComplexLpd().setHadIdLinkSet();
2959 unsigned declInputLevel = inputLevel();
2962 Boolean isExplicit = (defLpd().type() == Lpd::explicitLink);
2965 if (!parseParam(allowName, declInputLevel, parm))
2970 static AllowedParams
2971 allowNameInitial(Param::name,
2972 Param::indicatedReservedName + Syntax::rINITIAL);
2973 if (!parseParam(allowNameInitial, declInputLevel, parm))
2975 if (parm.type == Param::name)
2976 linkSet = lookupCreateLinkSet(parm.token);
2978 linkSet = defComplexLpd().initialLinkSet();
2979 if (linkSet->defined())
2980 message(ParserMessages::duplicateLinkSet, StringMessageArg(linkSet->name()));
2981 static AllowedParams
2982 allowExplicitLinkRule(Param::name,
2984 Param::indicatedReservedName + Syntax::rIMPLIED);
2985 if (!parseParam(isExplicit ? allowExplicitLinkRule : allowNameNameGroup,
2986 declInputLevel, parm))
2993 parm.token.swap(id);
2994 if (!parseParam(isExplicit ? allowExplicitLinkRuleMdc : allowNameNameGroupMdc,
2995 declInputLevel, parm))
2998 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2999 if (!parseParam(allowName, declInputLevel, parm))
3001 Boolean resultImplied;
3002 const ElementType *resultType;
3003 AttributeList resultAttributes;
3004 if (!parseResultElementSpec(declInputLevel,
3012 const AttributeList *dummy;
3013 if (linkSet->impliedResultAttributes(resultType, dummy))
3014 message(ParserMessages::duplicateImpliedResult,
3015 StringMessageArg(resultType->name()));
3017 linkSet->addImplied(resultType, resultAttributes);
3021 SourceLinkRule *linkRule = 0;
3022 IdLinkRule idLinkRule;
3023 Ptr<SourceLinkRuleResource> linkRuleResource;
3025 linkRule = &idLinkRule;
3027 linkRuleResource = new SourceLinkRuleResource;
3028 linkRule = linkRuleResource.pointer();
3030 Vector<const ElementType *> assocElementTypes;
3031 if (parm.type == Param::name) {
3032 assocElementTypes.resize(1);
3033 assocElementTypes[0] = lookupCreateElement(parm.token);
3036 assocElementTypes.resize(parm.nameTokenVector.size());
3037 for (size_t i = 0; i < assocElementTypes.size(); i++)
3038 assocElementTypes[i]
3039 = lookupCreateElement(parm.nameTokenVector[i].name);
3041 static AllowedParams
3042 allow2i(Param::indicatedReservedName + Syntax::rUSELINK,
3043 Param::indicatedReservedName + Syntax::rPOSTLINK,
3048 static AllowedParams
3049 allow2id(Param::indicatedReservedName + Syntax::rUSELINK,
3050 Param::indicatedReservedName + Syntax::rPOSTLINK,
3054 static AllowedParams
3055 allow2e(Param::indicatedReservedName + Syntax::rUSELINK,
3056 Param::indicatedReservedName + Syntax::rPOSTLINK,
3059 Param::indicatedReservedName + Syntax::rIMPLIED);
3061 if (!parseParam(isExplicit
3063 : (idlink ? allow2id : allow2i), declInputLevel, parm))
3065 if (parm.type == Param::indicatedReservedName + Syntax::rUSELINK) {
3066 static AllowedParams
3067 allowLinkSetEmpty(Param::name,
3068 Param::indicatedReservedName + Syntax::rINITIAL,
3069 Param::indicatedReservedName + Syntax::rEMPTY);
3070 if (!parseParam(allowLinkSetEmpty, declInputLevel, parm))
3072 const LinkSet *uselink;
3073 if (parm.type == Param::name)
3074 uselink = lookupCreateLinkSet(parm.token);
3075 else if (parm.type == Param::indicatedReservedName + Syntax::rINITIAL)
3076 uselink = defComplexLpd().initialLinkSet();
3078 uselink = defComplexLpd().emptyLinkSet();
3079 linkRule->setUselink(uselink);
3080 static AllowedParams
3081 allow3i(Param::indicatedReservedName + Syntax::rPOSTLINK,
3086 static AllowedParams
3087 allow3id(Param::indicatedReservedName + Syntax::rPOSTLINK,
3091 static AllowedParams
3092 allow3e(Param::indicatedReservedName + Syntax::rPOSTLINK,
3095 Param::indicatedReservedName + Syntax::rIMPLIED);
3097 if (!parseParam(isExplicit
3099 : (idlink ? allow3id : allow3i),
3100 declInputLevel, parm))
3103 if (parm.type == Param::indicatedReservedName + Syntax::rPOSTLINK) {
3104 if (!parseParam(allowLinkSetSpec, declInputLevel, parm))
3106 const LinkSet *postlink;
3107 if (parm.type == Param::indicatedReservedName + Syntax::rRESTORE)
3108 linkRule->setPostlinkRestore();
3110 if (parm.type == Param::name)
3111 postlink = lookupCreateLinkSet(parm.token);
3113 == Param::indicatedReservedName + Syntax::rINITIAL)
3114 postlink = defComplexLpd().initialLinkSet();
3116 postlink = defComplexLpd().emptyLinkSet();
3117 linkRule->setPostlink(postlink);
3119 static AllowedParams
3124 static AllowedParams
3125 allow4id(Param::dso,
3128 static AllowedParams
3131 Param::indicatedReservedName + Syntax::rIMPLIED);
3132 if (!parseParam(isExplicit
3134 : (idlink ? allow4id : allow4i),
3135 declInputLevel, parm))
3138 AttributeList attributes;
3139 ConstPtr<AttributeDefinitionList> attDef;
3140 for (size_t i = 0; i < assocElementTypes.size(); i++) {
3141 const ElementType *e = assocElementTypes[i];
3144 attDef = defComplexLpd().attributeDef(e);
3145 else if (attDef != defComplexLpd().attributeDef(e))
3146 message(ParserMessages::assocElementDifferentAtts);
3147 // FIXME recover from this
3150 attributes.init(attDef);
3152 if (parm.type == Param::dso) {
3153 Boolean netEnabling;
3154 Ptr<AttributeDefinitionList> newAttDef;
3155 if (!parseAttributeSpec(asMode, attributes, netEnabling, newAttDef))
3157 if (!newAttDef.isNull()) {
3158 newAttDef->setIndex(defComplexLpd().allocAttributeDefinitionListIndex());
3159 for (size_t i = 0; i < assocElementTypes.size(); i++) {
3160 const ElementType *e = assocElementTypes[i];
3161 if (e && defComplexLpd().attributeDef(e) == attDef)
3162 defComplexLpd().setAttributeDef(e, newAttDef);
3165 static AllowedParams
3166 allow5e(Param::name,
3167 Param::indicatedReservedName + Syntax::rIMPLIED);
3168 if (!parseParam(isExplicit
3170 : (idlink ? allowNameMdc : allowNameNameGroupMdc),
3171 declInputLevel, parm))
3175 attributes.finish(*this);
3176 linkRule->setLinkAttributes(attributes);
3178 Boolean resultImplied;
3179 const ElementType *resultType;
3180 AttributeList resultAttributes;
3181 if (!parseResultElementSpec(declInputLevel,
3189 linkRule->setResult(resultType, resultAttributes);
3191 // Install the link rule.
3193 idLinkRule.setAssocElementTypes(assocElementTypes);
3194 addIdLinkRule(id, idLinkRule);
3197 if (!linkSet->defined()) {
3198 for (size_t i = 0; i < assocElementTypes.size(); i++)
3199 if (assocElementTypes[i])
3200 addLinkRule(linkSet, assocElementTypes[i], linkRuleResource);
3204 } while (parm.type != Param::mdc);
3206 linkSet->setDefined();
3207 if (currentMarkup()) {
3209 eventHandler().idLinkDecl(new (eventAllocator())
3210 IdLinkDeclEvent(defComplexLpdPointer(),
3214 eventHandler().linkDecl(new (eventAllocator())
3215 LinkDeclEvent(linkSet,
3216 defComplexLpdPointer(),
3223 void Parser::addIdLinkRule(const StringC &id,
3226 IdLinkRuleGroup *group = defComplexLpd().lookupCreateIdLink(id);
3227 size_t nRules = group->nLinkRules();
3228 if ((nRules == 1 && group->linkRule(0).attributes().nSpec() == 0)
3229 || nRules >= 1 && rule.attributes().nSpec() == 0)
3230 message(ParserMessages::multipleIdLinkRuleAttribute,
3231 StringMessageArg(id));
3232 group->addLinkRule(rule);
3235 void Parser::addLinkRule(LinkSet *linkSet,
3236 const ElementType *sourceElement,
3237 const ConstPtr<SourceLinkRuleResource> &linkRule)
3239 size_t nRules = linkSet->nLinkRules(sourceElement);
3241 && linkSet->linkRule(sourceElement, 0).attributes().nSpec() == 0)
3242 || nRules >= 1 && linkRule->attributes().nSpec() == 0)
3243 message(ParserMessages::multipleLinkRuleAttribute,
3244 StringMessageArg(sourceElement->name()));
3245 linkSet->addLinkRule(sourceElement, linkRule);
3248 class ResultAttributeSpecModeSetter {
3250 ResultAttributeSpecModeSetter(ParserState *state) : state_(state) {
3251 state_->setResultAttributeSpecMode();
3253 ~ResultAttributeSpecModeSetter() { clear(); }
3256 state_->clearResultAttributeSpecMode();
3261 ParserState *state_;
3264 Boolean Parser::parseResultElementSpec(unsigned declInputLevel,
3268 const ElementType *&resultType,
3269 AttributeList &attributes)
3271 if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
3272 if (!parseParam(idlink ? allowNameMdc : allowExplicitLinkRuleMdc,
3273 declInputLevel, parm))
3279 ElementType *e = lookupResultElementType(parm.token);
3281 static AllowedParams
3286 Param::indicatedReservedName + Syntax::rIMPLIED);
3287 static AllowedParams
3288 allowNameDsoMdc(Param::dso,
3291 if (!parseParam(idlink ? allowNameDsoMdc : allow,
3292 declInputLevel, parm))
3294 ConstPtr<AttributeDefinitionList> attDef;
3296 attDef = e->attributeDef();
3297 attributes.init(attDef);
3298 if (parm.type == Param::dso) {
3299 ResultAttributeSpecModeSetter modeSetter(this);
3300 Boolean netEnabling;
3301 Ptr<AttributeDefinitionList> newAttDef;
3302 if (!parseAttributeSpec(asMode, attributes, netEnabling, newAttDef))
3304 if (!newAttDef.isNull()) {
3305 Ptr<Dtd> r(defComplexLpd().resultDtd());
3307 newAttDef->setIndex(r->allocAttributeDefinitionListIndex());
3309 e->setAttributeDef(newAttDef);
3313 if (attributes.nSpec() == 0)
3314 message(ParserMessages::emptyResultAttributeSpec);
3315 if (!parseParam(idlink ? allowNameMdc : allowExplicitLinkRuleMdc,
3316 declInputLevel, parm))
3320 // For entity and notation attributes.
3321 ResultAttributeSpecModeSetter modeSetter(this);
3322 attributes.finish(*this);
3329 ElementType *Parser::lookupResultElementType(const StringC &name)
3331 Dtd *dtd = defComplexLpd().resultDtd().pointer();
3334 ElementType *e = dtd->lookupElementType(name);
3336 message(ParserMessages::noSuchResultElement, StringMessageArg(name));
3340 Boolean Parser::parseUselinkDecl()
3342 unsigned declInputLevel = inputLevel();
3344 if (!parseParam(allowLinkSetSpec, declInputLevel, parm))
3347 if (!parseParam(allowName, declInputLevel, parm2))
3350 parm2.token.swap(linkType);
3351 if (!parseParam(allowMdc, declInputLevel, parm2))
3353 ConstPtr<Lpd> lpd = lookupLpd(linkType);
3355 message(ParserMessages::uselinkBadLinkType, StringMessageArg(linkType));
3356 else if (lpd->type() == Lpd::simpleLink)
3357 message(ParserMessages::uselinkSimpleLpd, StringMessageArg(linkType));
3359 const ComplexLpd *complexLpd = (const ComplexLpd *)lpd.pointer();
3360 const LinkSet *linkSet;
3361 Boolean restore = 0;
3362 if (parm.type == Param::name) {
3363 linkSet = complexLpd->lookupLinkSet(parm.token);
3365 message(ParserMessages::uselinkBadLinkSet,
3366 StringMessageArg(complexLpd->name()),
3367 StringMessageArg(parm.token));
3371 else if (parm.type == Param::indicatedReservedName + Syntax::rINITIAL)
3372 linkSet = complexLpd->initialLinkSet();
3373 else if (parm.type == Param::indicatedReservedName + Syntax::rEMPTY)
3374 linkSet = complexLpd->emptyLinkSet();
3380 eventHandler().uselink(new (eventAllocator())
3381 UselinkEvent(lpd, linkSet,
3382 restore, markupLocation(),
3385 eventHandler().ignoredMarkup(new (eventAllocator())
3386 IgnoredMarkupEvent(markupLocation(),
3392 LinkSet *Parser::lookupCreateLinkSet(const StringC &name)
3394 LinkSet *linkSet = defComplexLpd().lookupLinkSet(name);
3396 linkSet = new LinkSet(name, defComplexLpd().sourceDtd().pointer());
3397 defComplexLpd().insertLinkSet(linkSet);
3402 Boolean Parser::parseMarkedSectionDeclStart()
3404 if (markedSectionLevel() == syntax().taglvl())
3405 message(ParserMessages::markedSectionLevel,
3406 NumberMessageArg(syntax().taglvl()));
3408 && options().warnInternalSubsetMarkedSection
3409 && inputLevel() == 1)
3410 message(ParserMessages::internalSubsetMarkedSection);
3411 if (markedSectionSpecialLevel() > 0) {
3412 startMarkedSection(markupLocation());
3414 ? eventsWanted().wantMarkedSections()
3415 : eventsWanted().wantPrologMarkup())
3416 eventHandler().ignoredChars(new (eventAllocator())
3417 IgnoredCharsEvent(currentInput()->currentTokenStart(),
3418 currentInput()->currentTokenLength(),
3424 Boolean discardMarkup;
3425 if (startMarkup(inInstance()
3426 ? eventsWanted().wantMarkedSections()
3427 : eventsWanted().wantPrologMarkup(),
3428 currentLocation())) {
3429 currentMarkup()->addDelim(Syntax::dMDO);
3430 currentMarkup()->addDelim(Syntax::dDSO);
3433 else if (options().warnInstanceStatusKeywordSpecS && inInstance()) {
3434 startMarkup(1, currentLocation());
3437 unsigned declInputLevel = inputLevel();
3438 static AllowedParams allowStatusDso(Param::dso,
3439 Param::reservedName + Syntax::rCDATA,
3440 Param::reservedName + Syntax::rRCDATA,
3441 Param::reservedName + Syntax::rIGNORE,
3442 Param::reservedName + Syntax::rINCLUDE,
3443 Param::reservedName + Syntax::rTEMP);
3445 MarkedSectionEvent::Status status = MarkedSectionEvent::include;
3446 if (!parseParam(allowStatusDso, declInputLevel, parm))
3448 if (options().warnMissingStatusKeyword && parm.type == Param::dso)
3449 message(ParserMessages::missingStatusKeyword);
3450 while (parm.type != Param::dso) {
3451 switch (parm.type) {
3452 case Param::reservedName + Syntax::rCDATA:
3453 if (status < MarkedSectionEvent::cdata)
3454 status = MarkedSectionEvent::cdata;
3456 case Param::reservedName + Syntax::rRCDATA:
3457 if (status < MarkedSectionEvent::rcdata)
3458 status = MarkedSectionEvent::rcdata;
3459 if (options().warnRcdataMarkedSection)
3460 message(ParserMessages::rcdataMarkedSection);
3462 case Param::reservedName + Syntax::rIGNORE:
3463 if (status < MarkedSectionEvent::ignore)
3464 status = MarkedSectionEvent::ignore;
3465 if (inInstance() && options().warnInstanceIgnoreMarkedSection)
3466 message(ParserMessages::instanceIgnoreMarkedSection);
3468 case Param::reservedName + Syntax::rINCLUDE:
3469 if (inInstance() && options().warnInstanceIncludeMarkedSection)
3470 message(ParserMessages::instanceIncludeMarkedSection);
3472 case Param::reservedName + Syntax::rTEMP:
3473 if (options().warnTempMarkedSection)
3474 message(ParserMessages::tempMarkedSection);
3477 if (!parseParam(allowStatusDso, declInputLevel, parm))
3479 if (options().warnMultipleStatusKeyword
3480 && parm.type != Param::dso)
3481 message(ParserMessages::multipleStatusKeyword);
3483 // FIXME this disallows
3484 // <!entity % e "include [ stuff ">
3487 // which I think is legal.
3489 if (inputLevel() > declInputLevel)
3490 message(ParserMessages::parameterEntityNotEnded);
3492 case MarkedSectionEvent::include:
3493 startMarkedSection(markupLocation());
3495 case MarkedSectionEvent::cdata:
3496 startSpecialMarkedSection(cmsMode, markupLocation());
3498 case MarkedSectionEvent::rcdata:
3499 startSpecialMarkedSection(rcmsMode, markupLocation());
3501 case MarkedSectionEvent::ignore:
3502 startSpecialMarkedSection(imsMode, markupLocation());
3505 if (currentMarkup()) {
3506 if (options().warnInstanceStatusKeywordSpecS && inInstance()) {
3507 Location loc(markupLocation());
3508 for (MarkupIter iter(*currentMarkup()); iter.valid(); iter.advance(loc, syntaxPointer())) {
3509 if (iter.type() == Markup::s) {
3510 setNextLocation(loc);
3511 message(ParserMessages::instanceStatusKeywordSpecS);
3515 startMarkup(0, markupLocation());
3517 eventHandler().markedSectionStart(new (eventAllocator())
3518 MarkedSectionStartEvent(status,
3525 void Parser::handleMarkedSectionEnd()
3527 if (markedSectionLevel() == 0)
3528 message(ParserMessages::markedSectionEnd);
3531 ? eventsWanted().wantMarkedSections()
3532 : eventsWanted().wantPrologMarkup()) {
3533 if (markedSectionSpecialLevel() > 1)
3534 eventHandler().ignoredChars(new (eventAllocator())
3535 IgnoredCharsEvent(currentInput()->currentTokenStart(),
3536 currentInput()->currentTokenLength(),
3540 MarkedSectionEvent::Status status;
3541 switch (currentMode()) {
3543 status = MarkedSectionEvent::cdata;
3546 status = MarkedSectionEvent::rcdata;
3549 status = MarkedSectionEvent::ignore;
3552 status = MarkedSectionEvent::include;
3555 startMarkup(1, currentLocation());
3556 currentMarkup()->addDelim(Syntax::dMSC);
3557 currentMarkup()->addDelim(Syntax::dMDC);
3558 eventHandler().markedSectionEnd(new (eventAllocator())
3559 MarkedSectionEndEvent(status,
3568 void Parser::emptyCommentDecl()
3570 if (startMarkup(eventsWanted().wantCommentDecls(), currentLocation())) {
3571 currentMarkup()->addDelim(Syntax::dMDO);
3572 currentMarkup()->addDelim(Syntax::dMDC);
3573 eventHandler().commentDecl(new (eventAllocator())
3574 CommentDeclEvent(markupLocation(),
3577 if (options().warnEmptyCommentDecl)
3578 message(ParserMessages::emptyCommentDecl);
3581 Boolean Parser::parseCommentDecl()
3583 if (startMarkup(inInstance()
3584 ? eventsWanted().wantCommentDecls()
3585 : eventsWanted().wantPrologMarkup(),
3587 currentMarkup()->addDelim(Syntax::dMDO);
3588 if (!parseComment(comMode))
3591 Token token = getToken(mdMode);
3594 if (currentMarkup())
3595 currentMarkup()->addS(currentChar());
3596 if (options().warnCommentDeclS)
3597 message(ParserMessages::commentDeclS);
3600 if (!parseComment(comMode))
3602 if (options().warnCommentDeclMultiple)
3603 message(ParserMessages::commentDeclMultiple);
3606 if (currentMarkup())
3607 currentMarkup()->addDelim(Syntax::dMDC);
3610 message(ParserMessages::declarationLevel);
3612 case tokenUnrecognized:
3613 if (reportNonSgmlCharacter())
3615 // braces to work round Sun C++ 4.0 bug
3617 message(ParserMessages::commentDeclarationCharacter,
3618 StringMessageArg(currentToken()),
3623 // braces to work round Sun C++ 4.0 bug
3625 message(ParserMessages::commentDeclInvalidToken,
3626 TokenMessageArg(token, mdMode, syntaxPointer(), sdPointer()),
3633 if (currentMarkup())
3634 eventHandler().commentDecl(new (eventAllocator())
3635 CommentDeclEvent(markupLocation(),
3640 Boolean Parser::parseAfdrDecl()
3642 unsigned declInputLevel = inputLevel();
3643 static AllowedParams allowMinimumLiteral(Param::minimumLiteral);
3646 if (!parseParam(allowMinimumLiteral, declInputLevel, parm))
3648 if (parm.literalText.string() != sd().execToInternal("ISO/IEC 10744:1997"))
3649 message(ParserMessages::afdrVersion,
3650 StringMessageArg(parm.literalText.string()));
3651 if (!parseParam(allowMdc, declInputLevel, parm))
3653 eventHandler().ignoredMarkup(new (eventAllocator())
3654 IgnoredMarkupEvent(markupLocation(),