TIVI-153: Add as dependency for iputils
[profile/ivi/opensp.git] / lib / parseDecl.cxx
1 // Copyright (c) 1994, 1995 James Clark
2 // See the file COPYING for copying permission.
3
4 // Prolog, dtd and declaration parsing.
5
6 #include "splib.h"
7 #include "Parser.h"
8 #include "Param.h"
9 #include "Markup.h"
10 #include "ParserMessages.h"
11 #include "MessageArg.h"
12 #include "TokenMessageArg.h"
13 #include "token.h"
14 #include "macros.h"
15 #include <stdio.h>
16
17 #ifdef SP_NAMESPACE
18 namespace SP_NAMESPACE {
19 #endif
20
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);
27 static AllowedParams
28   allowExplicitLinkRuleMdc(Param::mdc,
29                            Param::name,
30                            Param::nameGroup,
31                            Param::indicatedReservedName + Syntax::rIMPLIED);
32 static AllowedParams
33   allowNameNameGroupMdc(Param::name, Param::nameGroup, Param::mdc);
34
35 static const AllowedParams
36   allowLinkSetSpec(Param::name,
37                    Param::indicatedReservedName + Syntax::rINITIAL,
38                    Param::indicatedReservedName + Syntax::rEMPTY,
39                    Param::indicatedReservedName + Syntax::rRESTORE);
40
41 void Parser::doProlog()
42 {
43   const unsigned maxTries = 10;
44   unsigned tries = 0;
45   do {
46     if (cancelled()) {
47       allDone();
48       return;
49     }
50     Token token = getToken(proMode);
51     switch (token) {
52     case tokenUnrecognized:
53       if (reportNonSgmlCharacter())
54         break;
55       if (hadDtd()) {
56         currentInput()->ungetToken();
57         endProlog();
58         return;
59       }
60       {
61         StringC gi;
62         if (lookingAtStartTag(gi)) {
63           currentInput()->ungetToken();
64           implyDtd(gi);
65           return;
66         }
67       }
68             
69       if (++tries >= maxTries) {
70         message(ParserMessages::notSgml);
71         giveUp();
72         return;
73       }
74       message(ParserMessages::prologCharacter, StringMessageArg(currentToken()));
75       prologRecover();
76       break;
77     case tokenEe:
78       if (hadDtd()) {
79         endProlog();
80         return;
81       }
82       message(ParserMessages::documentEndProlog);
83       allDone();
84       return;
85     case tokenMdoMdc:
86       // empty comment
87       emptyCommentDecl();
88       break;
89     case tokenMdoCom:
90       if (!parseCommentDecl())
91         prologRecover();
92       break;
93     case tokenMdoNameStart:
94       setPass2Start();
95       if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation()))
96         currentMarkup()->addDelim(Syntax::dMDO);
97       Syntax::ReservedName name;
98       if (parseDeclarationName(&name)) {
99         switch (name) {
100         case Syntax::rDOCTYPE:
101           if (!parseDoctypeDeclStart())
102             giveUp();
103           return;
104         case Syntax::rLINKTYPE:
105           if (!parseLinktypeDeclStart())
106             giveUp();
107           return;
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:
115         case Syntax::rLINK:
116         case Syntax::rIDLINK:
117           message(ParserMessages::prologDeclaration,
118                   StringMessageArg(syntax().reservedName(name)));
119           if (!hadDtd())
120             tries++;
121           prologRecover();
122           break;
123         default:
124           message(ParserMessages::noSuchDeclarationType,
125                   StringMessageArg(syntax().reservedName(name)));
126           prologRecover();
127           break;
128         }
129       }
130       else
131         prologRecover();
132       break;
133     case tokenPio:
134       if (!parseProcessingInstruction())
135         prologRecover();
136       break;
137     case tokenS:
138       if (eventsWanted().wantPrologMarkup()) {
139         extendS();
140         eventHandler().sSep(new (eventAllocator())
141                             SSepEvent(currentInput()->currentTokenStart(),
142                                       currentInput()->currentTokenLength(),
143                                       currentLocation(),
144                                       1));
145       }
146       break;
147     default:
148       CANNOT_HAPPEN();
149     }
150   } while (eventQueueEmpty());
151 }
152
153 void Parser::endProlog()
154 {
155   if (baseDtd().isNull()
156 #if 0
157       || baseDtd()->documentElementType()->definition()->undefined()
158 #endif
159       ) {
160     // We could continue, but there's not a lot of point.
161     giveUp();
162     return;
163   }
164   if (maybeStartPass2())
165     setPhase(prologPhase);
166   else {
167     if (inputLevel() == 0) {
168       allDone();
169       return;
170     }
171     if (pass2())
172       checkEntityStability();
173     setPhase(instanceStartPhase);
174     startInstance();
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);
185       }
186       else 
187         lpd = (ComplexLpd *)&activeLpd(i);
188     eventHandler().endProlog(new (eventAllocator())
189                              EndPrologEvent(currentDtdPointer(),
190                                             lpd,
191                                             simpleLinkNames,
192                                             simpleLinkAtts,
193                                             currentLocation()));
194   }
195 }
196
197 void Parser::prologRecover()
198 {
199   unsigned skipCount = 0;
200   const unsigned skipMax = 250;
201   for (;;) {
202     Token token = getToken(proMode);
203     skipCount++;
204     if (token == tokenUnrecognized) {
205       token = getToken(mdMode);
206       if (token == tokenMdc) {
207         token = getToken(proMode);
208         if (token == tokenS)
209           return;
210       }
211     }
212     switch (token) {
213     case tokenUnrecognized:
214       (void)getChar();
215       break;
216     case tokenEe:
217       return;
218     case tokenMdoMdc:
219     case tokenMdoCom:
220     case tokenMdoNameStart:
221     case tokenPio:
222       currentInput()->ungetToken();
223       return;
224     case tokenS:
225       if (currentChar() == syntax().standardFunction(Syntax::fRE)
226           && skipCount >= skipMax)
227         return;
228     default:
229       break;
230     }
231   }
232 }
233
234 void Parser::doDeclSubset()
235 {
236   do {
237     if (cancelled()) {
238       allDone();
239       return;
240     }
241     Token token = getToken(currentMode());
242     unsigned startLevel = inputLevel();
243     Boolean inDtd = !haveDefLpd();
244     switch (token) {
245     case tokenUnrecognized:
246       if (reportNonSgmlCharacter())
247         break;
248       message(ParserMessages::declSubsetCharacter, StringMessageArg(currentToken()));
249       declSubsetRecover(startLevel);
250       break;
251     case tokenEe:
252       if (inputLevel() == specialParseInputLevel()) {
253         // FIXME have separate messages for each type of special parse
254         message(ParserMessages::specialParseEntityEnd);
255       }
256       if (eventsWanted().wantPrologMarkup())
257         eventHandler().entityEnd(new (eventAllocator())
258                                  EntityEndEvent(currentLocation()));
259       if (inputLevel() == 2) {
260         const EntityDecl *e
261           = currentLocation().origin()->entityDecl();
262         if (e
263             && (e->declType() == EntityDecl::doctype
264                 || e->declType() == EntityDecl::linktype)) {
265           // popInputStack may destroy e
266           Boolean fake = e->defLocation().origin().isNull();
267           popInputStack();
268           if (!(inDtd
269                 ? parseDoctypeDeclEnd(fake)
270                 : parseLinktypeDeclEnd()))
271             ;                   // FIXME recover
272           setPhase(prologPhase);
273           return;
274         }
275       }
276       if (inputLevel() == 1) {
277         if (finalPhase() == declSubsetPhase) {
278           checkDtd(defDtd());
279           endDtd();
280         }
281         else
282           // Give message before popping stack.
283           message(inDtd
284                   ? ParserMessages::documentEndDtdSubset
285                   : ParserMessages::documentEndLpdSubset);
286         popInputStack();
287         allDone();
288       }
289       else
290         popInputStack();
291       return;
292     case tokenDsc:              // end of declaration subset
293       // FIXME what's the right location?
294       if (!referenceDsEntity(currentLocation())) {
295         if (!(inDtd ? parseDoctypeDeclEnd() : parseLinktypeDeclEnd()))
296           ;                     // FIXME recover
297         setPhase(prologPhase);
298       }
299       return;
300     case tokenMdoNameStart:     // named markup declaration
301       if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation()))
302         currentMarkup()->addDelim(Syntax::dMDO);
303       Syntax::ReservedName name;
304       Boolean result;
305       if (parseDeclarationName(&name,
306                                inDtd && !options().errorAfdr)) {
307         switch (name) {
308         case Syntax::rANY:      // used for <!AFDR
309           result = parseAfdrDecl();
310           break;
311         case Syntax::rELEMENT:
312           if (inDtd)
313             result = parseElementDecl();
314           else {
315             message(ParserMessages::lpdSubsetDeclaration,
316                     StringMessageArg(syntax().reservedName(name)));
317             result = 0;
318           }
319           break;
320         case Syntax::rATTLIST:
321           result = parseAttlistDecl();
322           break;
323         case Syntax::rENTITY:
324           result = parseEntityDecl();
325           break;
326         case Syntax::rNOTATION:
327           result = parseNotationDecl();
328           if (!inDtd && !sd().www())
329             message(ParserMessages::lpdSubsetDeclaration,
330                     StringMessageArg(syntax().reservedName(name)));
331           break;
332         case Syntax::rSHORTREF:
333           if (inDtd)
334             result = parseShortrefDecl();
335           else {
336             message(ParserMessages::lpdSubsetDeclaration,
337                     StringMessageArg(syntax().reservedName(name)));
338             result = 0;
339           }
340           break;
341         case Syntax::rUSEMAP:
342           if (inDtd)
343             result = parseUsemapDecl();
344           else {
345             message(ParserMessages::lpdSubsetDeclaration,
346                     StringMessageArg(syntax().reservedName(name)));
347             result = 0;
348           }
349           break;
350         case Syntax::rLINK:
351           if (inDtd) {
352             message(ParserMessages::dtdSubsetDeclaration,
353                     StringMessageArg(syntax().reservedName(name)));
354             result = 0;
355           }
356           else
357             result = parseLinkDecl();
358           break;
359         case Syntax::rIDLINK:
360           if (inDtd) {
361             message(ParserMessages::dtdSubsetDeclaration,
362                     StringMessageArg(syntax().reservedName(name)));
363             result = 0;
364           }
365           else
366             result = parseIdlinkDecl();
367           break;
368         case Syntax::rDOCTYPE:
369         case Syntax::rLINKTYPE:
370         case Syntax::rUSELINK:
371           result = 0;
372           message(inDtd
373                   ? ParserMessages::dtdSubsetDeclaration
374                   : ParserMessages::lpdSubsetDeclaration,
375                   StringMessageArg(syntax().reservedName(name)));
376           break;
377         default:
378           result = 0;
379           message(ParserMessages::noSuchDeclarationType,
380                   StringMessageArg(syntax().reservedName(name)));
381           break;
382         }
383       }
384       else
385         result = 0;
386       if (!result)
387         declSubsetRecover(startLevel);
388       break;
389     case tokenMdoMdc:           // empty comment declaration
390       // empty comment
391       emptyCommentDecl();
392       break;
393     case tokenMdoCom:           // comment declaration
394       if (!parseCommentDecl())
395         declSubsetRecover(startLevel);
396       break;
397     case tokenMdoDso:           // marked section declaration
398       if (!parseMarkedSectionDeclStart())
399         declSubsetRecover(startLevel);
400       break;
401     case tokenMscMdc:
402       handleMarkedSectionEnd();
403       break;
404     case tokenPeroGrpo:         // parameter entity reference with name group
405       message(ParserMessages::peroGrpoProlog);
406       // fall through
407     case tokenPeroNameStart:    // parameter entity reference
408       {
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);
414         }
415         else
416           declSubsetRecover(startLevel);
417       }
418       break;
419     case tokenPio:              // processing instruction
420       if (!parseProcessingInstruction())
421         declSubsetRecover(startLevel);
422       break;
423     case tokenS:                // white space
424       if (eventsWanted().wantPrologMarkup()) {
425         extendS();
426         eventHandler().sSep(new (eventAllocator())
427                             SSepEvent(currentInput()->currentTokenStart(),
428                                       currentInput()->currentTokenLength(),
429                                       currentLocation(),
430                                       1));
431       }
432       break;
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(),
439                                                       currentLocation(),
440                                                       1));
441       break;
442     case tokenRe:
443     case tokenRs:
444     case tokenCroNameStart:
445     case tokenCroDigit:
446     case tokenHcroHexDigit:
447     case tokenEroNameStart:
448     case tokenEroGrpo:
449     case tokenChar:
450       // these can occur in a cdata or rcdata marked section
451       message(ParserMessages::dataMarkedSectionDeclSubset);
452       declSubsetRecover(startLevel);
453       break;
454     default:
455       CANNOT_HAPPEN();
456     }
457   } while (eventQueueEmpty());
458 }
459
460 void Parser::declSubsetRecover(unsigned startLevel)
461 {
462   for (;;) {
463     Token token = getToken(currentMode());
464     switch (token) {
465     case tokenUnrecognized:
466       (void)getChar();
467       break;
468     case tokenEe:
469       if (inputLevel() <= startLevel)
470         return;
471       popInputStack();
472       break;
473     case tokenMdoCom:
474     case tokenDsc:
475     case tokenMdoNameStart:
476     case tokenMdoMdc:
477     case tokenMdoDso:
478     case tokenMscMdc:
479     case tokenPio:
480       if (inputLevel() == startLevel) {
481         currentInput()->ungetToken();
482         return;
483       }
484       break;
485     default:
486       break;
487     }
488   }
489 }
490
491 Boolean Parser::lookingAtStartTag(StringC &gi)
492 {
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();
497        i < stago.size();
498        i++)
499     if (currentInput()->tokenChar(messenger()) == InputSource::eE)
500       return 0;
501   StringC delim;
502   getCurrentToken(instanceSyntax().generalSubstTable(), delim);
503   if (delim != stago)
504     return 0;
505   Xchar c = currentInput()->tokenChar(messenger());
506   if (!instanceSyntax().isNameStartCharacter(c))
507     return 0;
508   do {
509     gi += (*instanceSyntax().generalSubstTable())[(Char)c];
510     c = currentInput()->tokenChar(messenger());
511   } while (instanceSyntax().isNameCharacter(c));
512   return 1;
513 }
514
515 Boolean Parser::parseDeclarationName(Syntax::ReservedName *result,
516                                      Boolean allowAfdr)
517 {
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;
525       if (currentMarkup())
526         currentMarkup()->addName(currentInput());
527     }
528     else {
529       message(ParserMessages::noSuchDeclarationType, StringMessageArg(name));
530       return 0;
531     }
532   }
533   else if (currentMarkup())
534     currentMarkup()->addReservedName(*result, currentInput());
535   return 1;
536 }
537
538 Boolean Parser::parseElementDecl()
539 {
540   unsigned declInputLevel = inputLevel();
541   Param parm;
542   if (!parseParam(allowNameNameGroup, declInputLevel, parm))
543     return 0;
544   Vector<NameToken> nameVector;
545   if (parm.type == Param::nameGroup) {
546     parm.nameTokenVector.swap(nameVector);
547     if (options().warnElementGroupDecl)
548       message(ParserMessages::elementGroupDecl);
549   }
550   else {
551     nameVector.resize(1);
552     parm.token.swap(nameVector[0].name);
553     parm.origToken.swap(nameVector[0].origName);
554   }
555   static AllowedParams
556     allowRankOmissionContent(Param::number,
557                              Param::reservedName + Syntax::rO,
558                              Param::minus,
559                              Param::reservedName + Syntax::rCDATA,
560                              Param::reservedName + Syntax::rRCDATA,
561                              Param::reservedName + Syntax::rEMPTY,
562                              Param::reservedName + Syntax::rANY,
563                              Param::modelGroup);
564   if (!parseParam(allowRankOmissionContent, declInputLevel, parm))
565     return 0;
566   StringC rankSuffix;
567   Vector<ElementType *> elements(nameVector.size());
568   Vector<RankStem *> rankStems;
569   Vector<const RankStem *> constRankStems;
570   size_t i;
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);
579       name += rankSuffix;
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];
587     }
588     static AllowedParams
589       allowOmissionContent(Param::reservedName + Syntax::rO,
590                            Param::minus,
591                            Param::reservedName + Syntax::rCDATA,
592                            Param::reservedName + Syntax::rRCDATA,
593                            Param::reservedName + Syntax::rEMPTY,
594                            Param::reservedName + Syntax::rANY,
595                            Param::modelGroup);
596     Token token = getToken(mdMinusMode);
597     if (token == tokenNameStart)
598       message(ParserMessages::psRequired);
599     currentInput()->ungetToken();
600     if (!parseParam(allowOmissionContent, declInputLevel, parm))
601       return 0;
602   }
603   else {
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);
609     }
610   }
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,
624                                        Param::minus);
625     if (!parseParam(allowOmission, declInputLevel, parm))
626       return 0;
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,
633                                       Param::modelGroup);
634     if (!parseParam(allowContent, declInputLevel, parm))
635       return 0;
636   }
637   else {
638     if (sd().omittag())
639       message(ParserMessages::missingTagMinimization);
640   }
641   Ptr<ElementDefinition> def;
642   switch (parm.type) {
643   case Param::reservedName + Syntax::rCDATA:
644     def = new ElementDefinition(markupLocation(),
645                                 defDtd().allocElementDefinitionIndex(),
646                                 omitFlags,
647                                 ElementDefinition::cdata);
648     if (!parseParam(allowMdc, declInputLevel, parm))
649       return 0;
650     if (options().warnCdataContent)
651       message(ParserMessages::cdataContent);
652     break;
653   case Param::reservedName + Syntax::rRCDATA:
654     def = new ElementDefinition(markupLocation(),
655                                 defDtd().allocElementDefinitionIndex(),
656                                 omitFlags,
657                                 ElementDefinition::rcdata);
658     if (!parseParam(allowMdc, declInputLevel, parm))
659       return 0;
660     if (options().warnRcdataContent)
661       message(ParserMessages::rcdataContent);
662     break;
663   case Param::reservedName + Syntax::rEMPTY:
664     def = new ElementDefinition(markupLocation(),
665                                 defDtd().allocElementDefinitionIndex(),
666                                 omitFlags,
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))
673       return 0;
674     break;
675   case Param::reservedName + Syntax::rANY:
676     def = new ElementDefinition(markupLocation(),
677                                 defDtd().allocElementDefinitionIndex(),
678                                 omitFlags,
679                                 ElementDefinition::any);
680     if (!parseExceptions(declInputLevel, def))
681       return 0;
682     break;
683   case Param::modelGroup:
684     {
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,
694                           pcdataUnreachable);
695       if (pcdataUnreachable && options().warnMixedContent)
696         message(ParserMessages::pcdataUnreachable);
697       if (validate()) {
698         for (i = 0; i < ambiguities.size(); i++) {
699           const ContentModelAmbiguity &a = ambiguities[i];
700           reportAmbiguity(a.from, a.to1, a.to2, a.andDepth);
701         }
702       }
703       def = new ElementDefinition(markupLocation(),
704                                   defDtd().allocElementDefinitionIndex(),
705                                   omitFlags,
706                                   ElementDefinition::modelGroup,
707                                   modelGroup);
708       if (!parseExceptions(declInputLevel, def))
709         return 0;
710     }
711     break;
712   }
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) {
718       if (validate())
719         message(ParserMessages::duplicateElementDefinition,
720                 StringMessageArg(elements[i]->name()));
721     }
722     else {
723       elements[i]->setElementDefinition(constDef, i);
724       if (!elements[i]->attributeDef().isNull())
725         checkElementAttribute(elements[i]);
726     }
727     if (rankStems.size() > 0)
728       rankStems[i]->addDefinition(constDef);
729   }
730   if (currentMarkup()) {
731     Vector<const ElementType *> v(elements.size());
732     for (i = 0; i < elements.size(); i++)
733       v[i] = elements[i];
734     eventHandler().elementDecl(new (eventAllocator())
735                                ElementDeclEvent(v, currentDtdPointer(),
736                                                 markupLocation(),
737                                                 currentMarkup()));
738   }
739   return 1;
740 }
741
742 void Parser::reportAmbiguity(const LeafContentToken *from,
743                              const LeafContentToken *to1,
744                              const LeafContentToken *to2,
745                              unsigned ambigAndDepth)
746 {
747   StringC toName;
748   const ElementType *toType = to1->elementType();
749   if (toType)
750     toName = toType->name();
751   else {
752     toName = syntax().delimGeneral(Syntax::dRNI);
753     toName += syntax().reservedName(Syntax::rPCDATA);
754   }
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));
762   else {
763     StringC fromName;
764     const ElementType *fromType = from->elementType();
765     if (fromType)
766       fromName = fromType->name();
767     else {
768       fromName = syntax().delimGeneral(Syntax::dRNI);
769       fromName += syntax().reservedName(Syntax::rPCDATA);
770     }
771     unsigned fromIndex = from->typeIndex() + 1;
772     unsigned andMatches = from->andDepth() - ambigAndDepth;
773     if (andMatches == 0)
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));
787     else
788       message(ParserMessages::ambiguousModelMultipleAnd,
789               StringMessageArg(fromName),
790               OrdinalMessageArg(fromIndex),
791               NumberMessageArg(andMatches),
792               StringMessageArg(toName),
793               OrdinalMessageArg(to1Index),
794               OrdinalMessageArg(to2Index));
795   }
796 }
797
798
799 // Check the compatibility of the attribute definition with
800 // the element definition.
801
802 void Parser::checkElementAttribute(const ElementType *e, size_t checkFrom)
803 {
804   if (!validate())
805     return;
806   const AttributeDefinitionList *attDef = e->attributeDef().pointer();
807   Boolean conref = 0;
808   ASSERT(e != 0);
809   const ElementDefinition *edef = e->definition();
810   ASSERT(edef != 0);
811   ASSERT(attDef != 0);
812   size_t attDefLength = attDef->size();
813   for (size_t i = checkFrom; i < attDefLength; i++) {
814     const AttributeDefinition *p = attDef->def(i);
815     if (p->isConref())
816       conref = 1;
817     if (p->isNotation()
818         && edef->declaredContent() == ElementDefinition::empty)
819       message(ParserMessages::notationEmpty, StringMessageArg(e->name()));
820   }
821   if (conref) {
822 #if 0
823     if (edef->omittedTagSpec() && !edef->canOmitEndTag()
824         && options().warnShould)
825       message(ParserMessages::conrefOmitEndTag, StringMessageArg(e->name()));
826 #endif
827     if (edef->declaredContent() == ElementDefinition::empty)
828       message(ParserMessages::conrefEmpty, StringMessageArg(e->name()));
829   }
830 }
831
832 ElementType *Parser::lookupCreateElement(const StringC &name)
833 {
834   ElementType *e = defDtd().lookupElementType(name);
835   if (!e) {
836     if (haveDefLpd()) 
837       message(ParserMessages::noSuchSourceElement, StringMessageArg(name));
838     else {
839       e = new ElementType(name, defDtd().allocElementTypeIndex());
840       defDtd().insertElementType(e);
841     }
842   }
843   return e;
844 }
845
846 RankStem *Parser::lookupCreateRankStem(const StringC &name)
847 {
848   RankStem *r = defDtd().lookupRankStem(name);
849   if (!r) {
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));
855   }
856   return r;
857 }
858
859 Boolean Parser::parseExceptions(unsigned declInputLevel,
860                                 Ptr<ElementDefinition> &def)
861 {
862   Param parm;
863   static AllowedParams
864     allowExceptionsMdc(Param::mdc, Param::exclusions, Param::inclusions);
865   if (!parseParam(allowExceptionsMdc, declInputLevel, parm))
866     return 0;
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))
873       return 0;
874   }
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();
881     if (nE) {
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()));
888       }
889     }
890     if (!parseParam(allowMdc, declInputLevel, parm))
891       return 0;
892   }
893   return 1;
894 }
895
896 Boolean Parser::parseAttlistDecl()
897 {
898   unsigned declInputLevel = inputLevel();
899   Param parm;
900   size_t attcnt = 0;
901   size_t idIndex = size_t(-1);
902   size_t notationIndex = size_t(-1);
903   Boolean anyCurrent = 0;
904
905   Boolean isNotation;
906   Vector<Attributed *> attributed;
907   if (!parseAttributed(declInputLevel, parm, attributed, isNotation))
908     return 0;
909   Vector<CopyOwner<AttributeDefinition> > defs;
910   if (!parseParam(sd().www() ? allowNameMdc : allowName, declInputLevel, parm))
911     return 0;
912   while (parm.type != Param::mdc) {
913     StringC attributeName;
914     StringC origAttributeName;
915     parm.token.swap(attributeName);
916     parm.origToken.swap(origAttributeName);
917     attcnt++;
918     Boolean duplicate = 0;
919     size_t i;
920     for (i = 0; i < defs.size(); i++)
921       if (defs[i]->name() == attributeName) {
922         message(ParserMessages::duplicateAttributeDef,
923                 StringMessageArg(attributeName));
924         duplicate = 1;
925         break;
926       }
927     Owner<DeclaredValue> declaredValue;
928     if (!parseDeclaredValue(declInputLevel, isNotation, parm, declaredValue))
929       return 0;
930     if (!duplicate) {
931       if (declaredValue->isId()) {
932         if (idIndex != size_t(-1))
933           message(ParserMessages::multipleIdAttributes,
934                   StringMessageArg(defs[idIndex]->name()));
935         idIndex = defs.size();
936       }
937       else if (declaredValue->isNotation()) {
938         if (notationIndex != size_t(-1))
939           message(ParserMessages::multipleNotationAttributes,
940                   StringMessageArg(defs[notationIndex]->name()));
941         notationIndex = defs.size();
942       }
943     }
944     const Vector<StringC> *tokensPtr = declaredValue->getTokens();
945     if (tokensPtr) {
946       size_t nTokens = tokensPtr->size();
947       if (!sd().www()) {
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]));
954               break;
955             }
956         }
957       }
958       attcnt += nTokens;
959     }
960     Owner<AttributeDefinition> def;
961     if (!parseDefaultValue(declInputLevel, isNotation, parm, attributeName,
962                            declaredValue, def, anyCurrent))
963       return 0;
964     if (haveDefLpd() && defLpd().type() == Lpd::simpleLink && !def->isFixed())
965       message(ParserMessages::simpleLinkFixedAttribute);
966     def->setOrigName(origAttributeName);
967     if (!duplicate) {
968       defs.resize(defs.size() + 1);
969       defs.back() = def.extract();
970     }
971     static AllowedParams allowNameMdc(Param::name, Param::mdc);
972     if (!parseParam(allowNameMdc, declInputLevel, parm))
973       return 0;
974   }
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];
983         if (e) {
984           if (e->name() == defLpd().sourceDtd()->name()) {
985             SimpleLpd &lpd = (SimpleLpd &)defLpd();
986             if (lpd.attributeDef().isNull())
987               lpd.setAttributeDef(new AttributeDefinitionList(defs, 0));
988             else
989               message(ParserMessages::duplicateAttlistElement,
990                       StringMessageArg(e->name()));
991           }
992           else
993             message(ParserMessages::simpleLinkAttlistElement,
994                     StringMessageArg(e->name()));
995         }
996       }
997     }
998     else {
999       Ptr<AttributeDefinitionList>
1000         adl(new AttributeDefinitionList(defs,
1001                                         defComplexLpd()
1002                                         .allocAttributeDefinitionListIndex()));
1003       for (size_t i = 0; i < attributed.size(); i++) {
1004         const ElementType *e = (const ElementType *)attributed[i];
1005         if (e) {
1006           if (defComplexLpd().attributeDef(e).isNull())
1007             defComplexLpd().setAttributeDef(e, adl);
1008           else
1009             message(ParserMessages::duplicateAttlistElement,
1010                     StringMessageArg(e->name()));
1011         }
1012       }
1013     }
1014   }
1015   else {
1016     Ptr<AttributeDefinitionList>
1017       adl(new AttributeDefinitionList(defs,
1018                                       defDtd()
1019                                       .allocAttributeDefinitionListIndex(),
1020                                       anyCurrent,
1021                                       idIndex,
1022                                       notationIndex));
1023     for (size_t i = 0; i < attributed.size(); i++) {
1024       if (attributed[i]->attributeDef().isNull()) {
1025         attributed[i]->setAttributeDef(adl);
1026         if (!isNotation) {
1027           ElementType *e = (ElementType *)attributed[i];
1028           if (e->definition() != 0)
1029             checkElementAttribute(e);
1030         }
1031       }
1032       else if (options().errorAfdr && !sd().www()) {
1033         if (isNotation)
1034           message(ParserMessages::duplicateAttlistNotation,
1035                   StringMessageArg(((Notation *)attributed[i])->name()));
1036         else
1037           message(ParserMessages::duplicateAttlistElement,
1038                   StringMessageArg(((ElementType *)attributed[i])->name()));
1039       }
1040       else {
1041         if (!hadAfdrDecl() && !sd().www()) {
1042           message(ParserMessages::missingAfdrDecl);
1043           setHadAfdrDecl();
1044         }
1045         AttributeDefinitionList *curAdl;
1046         {
1047           // Use block to make sure temporary gets destroyed.
1048           curAdl = attributed[i]->attributeDef().pointer();
1049         }
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(),
1059                                           curAdl->idIndex(),
1060                                           curAdl->notationIndex());
1061           attributed[i]->setAttributeDef(adlCopy);
1062           curAdl = adlCopy.pointer();
1063         }
1064         for (size_t j = 0; j < adl->size(); j++) {
1065           unsigned index;
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());
1076           }
1077           else {
1078             Boolean tem;
1079             if (curAdl->def(index)->isSpecified(tem))
1080               message(ParserMessages::specifiedAttributeRedeclared,
1081                       StringMessageArg(adl->def(j)->name()));
1082           }
1083         }
1084         if (!isNotation) {
1085           ElementType *e = (ElementType *)attributed[i];
1086           if (e->definition() != 0)
1087             checkElementAttribute(e, oldSize);
1088         }
1089       }
1090     }
1091   }
1092   if (currentMarkup()) {
1093     if (isNotation) {
1094       Vector<ConstPtr<Notation> > v(attributed.size());
1095       for (size_t i = 0; i < attributed.size(); i++)
1096         v[i] = (Notation *)attributed[i];
1097       eventHandler()
1098         .attlistNotationDecl(new (eventAllocator())
1099                              AttlistNotationDeclEvent(v,
1100                                                       markupLocation(),
1101                                                       currentMarkup()));
1102     }
1103     else {
1104       Vector<const ElementType *> v(attributed.size());
1105       for (size_t i = 0; i < attributed.size(); i++)
1106         v[i] = (ElementType *)attributed[i];
1107       if (haveDefLpd())
1108         eventHandler()
1109           .linkAttlistDecl(new (eventAllocator())
1110                            LinkAttlistDeclEvent(v,
1111                                                 defLpdPointer(),
1112                                                 markupLocation(),
1113                                                 currentMarkup()));
1114       else
1115         eventHandler().attlistDecl(new (eventAllocator())
1116                                    AttlistDeclEvent(v,
1117                                                     currentDtdPointer(),
1118                                                     markupLocation(),
1119                                                     currentMarkup()));
1120     }
1121   }
1122   if (isNotation) {
1123     Dtd::EntityIter entityIter(defDtd().generalEntityIter());
1124     for (;;) {
1125       Ptr<Entity> entity(entityIter.next());
1126       if (entity.isNull())
1127         break;
1128       const ExternalDataEntity *external = entity->asExternalDataEntity();
1129       if (external) {
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);
1137           }
1138       }
1139     }
1140   }
1141   return 1;
1142 }
1143
1144
1145 Boolean Parser::parseAttributed(unsigned declInputLevel,
1146                                 Param &parm,
1147                                 Vector<Attributed *> &attributed,
1148                                 Boolean &isNotation)
1149 {
1150   static AllowedParams
1151     allowNameGroupNotation(Param::name,
1152                            Param::nameGroup,
1153                            Param::indicatedReservedName + Syntax::rNOTATION);
1154   static AllowedParams
1155     allowNameGroupNotationAll(Param::name,
1156                               Param::nameGroup,
1157                               Param::indicatedReservedName
1158                               + Syntax::rNOTATION,
1159                               Param::indicatedReservedName
1160                               + Syntax::rALL,
1161                               Param::indicatedReservedName
1162                               + Syntax::rIMPLICIT);
1163   if (!parseParam(haveDefLpd()
1164                   ? allowNameGroupNotation
1165                   : allowNameGroupNotationAll,
1166                   declInputLevel, parm))
1167     return 0;
1168   if (parm.type == Param::indicatedReservedName + Syntax::rNOTATION) {
1169     if (options().warnDataAttributes)
1170       message(ParserMessages::dataAttributes);
1171     isNotation = 1;
1172     static AllowedParams
1173       allowNameGroupAll(Param::name,
1174                         Param::nameGroup,
1175                         Param::indicatedReservedName + Syntax::rALL,
1176                         Param::indicatedReservedName + Syntax::rIMPLICIT);
1177     if (!parseParam(haveDefLpd()
1178                     ? allowNameNameGroup
1179                     : allowNameGroupAll,
1180                     declInputLevel, parm))
1181       return 0;
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);
1186     }
1187     else {
1188       if (parm.type != Param::name && !hadAfdrDecl() && !sd().www()) {
1189         message(ParserMessages::missingAfdrDecl);
1190         setHadAfdrDecl();
1191       }
1192       attributed.resize(1);
1193       attributed[0]
1194         = lookupCreateNotation(parm.type == Param::name
1195                                ? parm.token
1196                                : syntax().rniReservedName(Syntax::ReservedName(parm.type - Param::indicatedReservedName)));
1197     }
1198   }
1199   else {
1200     isNotation = 0;
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);
1207     }
1208     else {
1209       if (parm.type != Param::name && !hadAfdrDecl() && !sd().www()) {
1210         message(ParserMessages::missingAfdrDecl);
1211         setHadAfdrDecl();
1212       }
1213       attributed.resize(1);
1214       attributed[0]
1215         = lookupCreateElement(parm.type == Param::name
1216                               ? parm.token
1217                               : syntax().rniReservedName(Syntax::ReservedName(parm.type - Param::indicatedReservedName)));
1218     }
1219   }
1220   return 1;
1221 }
1222
1223 Boolean Parser::parseDeclaredValue(unsigned declInputLevel,
1224                                    Boolean isNotation,
1225                                    Param &parm,
1226                                    Owner<DeclaredValue> &declaredValue)
1227 {
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
1246     };
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))
1253     return 0;
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;
1259     break;
1260   case Param::reservedName + Syntax::rENTITY:
1261     declaredValue = new EntityDeclaredValue(0);
1262     allowedFlags = asLinkAttribute;
1263     break;
1264   case Param::reservedName + Syntax::rENTITIES:
1265     declaredValue = new EntityDeclaredValue(1);
1266     allowedFlags = asLinkAttribute;
1267     break;
1268   case Param::reservedName + Syntax::rID:
1269     declaredValue = new IdDeclaredValue;
1270     allowedFlags = 0;
1271     break;
1272   case Param::reservedName + Syntax::rIDREF:
1273     declaredValue = new IdrefDeclaredValue(0);
1274     allowedFlags = 0;
1275     break;
1276   case Param::reservedName + Syntax::rIDREFS:
1277     declaredValue = new IdrefDeclaredValue(1);
1278     allowedFlags = 0;
1279     break;
1280   case Param::reservedName + Syntax::rNAME:
1281     declaredValue
1282       = new TokenizedDeclaredValue(TokenizedDeclaredValue::name, 0);
1283     if (options().warnNameDeclaredValue)
1284       message(ParserMessages::nameDeclaredValue);
1285     break;
1286   case Param::reservedName + Syntax::rNAMES:
1287     declaredValue
1288       = new TokenizedDeclaredValue(TokenizedDeclaredValue::name, 1);
1289     if (options().warnNameDeclaredValue)
1290       message(ParserMessages::nameDeclaredValue);
1291     break;
1292   case Param::reservedName + Syntax::rNMTOKEN:
1293     declaredValue
1294       = new TokenizedDeclaredValue(TokenizedDeclaredValue::nameToken, 0);
1295     break;
1296   case Param::reservedName + Syntax::rNMTOKENS:
1297     declaredValue
1298       = new TokenizedDeclaredValue(TokenizedDeclaredValue::nameToken, 1);
1299     break;
1300   case Param::reservedName + Syntax::rNUMBER:
1301     declaredValue
1302       = new TokenizedDeclaredValue(TokenizedDeclaredValue::number, 0);
1303     if (options().warnNumberDeclaredValue)
1304       message(ParserMessages::numberDeclaredValue);
1305     break;
1306   case Param::reservedName + Syntax::rNUMBERS:
1307     declaredValue
1308       = new TokenizedDeclaredValue(TokenizedDeclaredValue::number, 1);
1309     if (options().warnNumberDeclaredValue)
1310       message(ParserMessages::numberDeclaredValue);
1311     break;
1312   case Param::reservedName + Syntax::rNUTOKEN:
1313     declaredValue
1314       = new TokenizedDeclaredValue(TokenizedDeclaredValue::numberToken, 0);
1315     if (options().warnNutokenDeclaredValue)
1316       message(ParserMessages::nutokenDeclaredValue);
1317     break;
1318   case Param::reservedName + Syntax::rNUTOKENS:
1319     declaredValue
1320       = new TokenizedDeclaredValue(TokenizedDeclaredValue::numberToken, 1);
1321     if (options().warnNutokenDeclaredValue)
1322       message(ParserMessages::nutokenDeclaredValue);
1323     break;
1324   case Param::reservedName + Syntax::rNOTATION:
1325     {
1326       static AllowedParams allowNameGroup(Param::nameGroup);
1327       if (!parseParam(allowNameGroup, declInputLevel, parm))
1328         return 0;
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);
1333       allowedFlags = 0;
1334     }
1335     break;
1336   case Param::nameTokenGroup:
1337     {
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]);
1343       }
1344       GroupDeclaredValue *grpVal = new NameTokenGroupDeclaredValue(group);
1345       grpVal->setOrigAllowedValues(origGroup);
1346       declaredValue = grpVal;
1347     }
1348     break;
1349   case Param::reservedName + Syntax::rDATA:
1350     {
1351       if (!parseParam(allowName, declInputLevel, parm))
1352         return 0;
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))
1364           return 0;
1365         if (!newAttDef.isNull()) {
1366           newAttDef->setIndex(defDtd().allocAttributeDefinitionListIndex());
1367           notation->setAttributeDef(newAttDef);
1368         }
1369         if (attributes.nSpec() == 0)
1370           message(ParserMessages::emptyDataAttributeSpec);
1371       }
1372       else {
1373         attributes.finish(*this);
1374         // unget the first token of the default value
1375         currentInput()->ungetToken();
1376       }
1377       ConstPtr<Notation> nt(notation.pointer());
1378       declaredValue = new DataDeclaredValue(nt, attributes);
1379     }
1380     break;
1381   default:
1382     CANNOT_HAPPEN();
1383   }
1384   if (isNotation) {
1385     if (!(allowedFlags & asDataAttribute))
1386       message(ParserMessages::dataAttributeDeclaredValue);
1387   }
1388   else if (haveDefLpd() && !isNotation && !(allowedFlags & asLinkAttribute))
1389     message(ParserMessages::linkAttributeDeclaredValue);
1390   return 1;
1391 }
1392
1393 Boolean Parser::parseDefaultValue(unsigned declInputLevel,
1394                                   Boolean isNotation,
1395                                   Param &parm,
1396                                   const StringC &attributeName,
1397                                   Owner<DeclaredValue> &declaredValue,
1398                                   Owner<AttributeDefinition> &def,
1399                                   Boolean &anyCurrent)
1400 {
1401   // default value
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))
1421     return 0;
1422   switch (parm.type) {
1423   case Param::indicatedReservedName + Syntax::rFIXED:
1424     {
1425       static AllowedParams allowValue(Param::attributeValue,
1426                                       Param::attributeValueLiteral);
1427       static AllowedParams
1428         allowTokenValue(Param::attributeValue,
1429                         Param::tokenizedAttributeValueLiteral);
1430       if (!parseParam(declaredValue->tokenized()
1431                       ? allowTokenValue
1432                       : allowValue, declInputLevel, parm))
1433         return 0;
1434       unsigned specLength = 0;
1435       AttributeValue *value = declaredValue->makeValue(parm.literalText,
1436                                                        *this,
1437                                                        attributeName,
1438                                                        specLength);
1439       if (declaredValue->isId())
1440         message(ParserMessages::idDeclaredValue);
1441       def = new FixedAttributeDefinition(attributeName,
1442                                          declaredValue.extract(),
1443                                          value);
1444     }
1445     break;
1446   case Param::attributeValue:
1447     if (options().warnAttributeValueNotLiteral)
1448       message(ParserMessages::attributeValueNotLiteral);
1449     // fall through
1450   case Param::attributeValueLiteral:
1451   case Param::tokenizedAttributeValueLiteral:
1452     {
1453       unsigned specLength = 0;
1454       AttributeValue *value = declaredValue->makeValue(parm.literalText,
1455                                                        *this,
1456                                                        attributeName,
1457                                                        specLength);
1458       if (declaredValue->isId())
1459         message(ParserMessages::idDeclaredValue);
1460       def = new DefaultAttributeDefinition(attributeName,
1461                                            declaredValue.extract(),
1462                                            value);
1463     }
1464     break;
1465   case Param::indicatedReservedName + Syntax::rREQUIRED:
1466     def = new RequiredAttributeDefinition(attributeName,
1467                                           declaredValue.extract());
1468     break;
1469   case Param::indicatedReservedName + Syntax::rCURRENT:
1470     anyCurrent = 1;
1471     if (declaredValue->isId())
1472       message(ParserMessages::idDeclaredValue);
1473     def = new CurrentAttributeDefinition(attributeName,
1474                                          declaredValue.extract(),
1475                                          defDtd().allocCurrentAttributeIndex());
1476     if (isNotation)
1477       message(ParserMessages::dataAttributeDefaultValue);
1478     else if (haveDefLpd())
1479       message(ParserMessages::linkAttributeDefaultValue);
1480     else if (options().warnCurrent)
1481       message(ParserMessages::currentAttribute);
1482     break;
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());
1490     if (isNotation)
1491       message(ParserMessages::dataAttributeDefaultValue);
1492     else if (haveDefLpd())
1493       message(ParserMessages::linkAttributeDefaultValue);
1494     else if (options().warnConref)
1495       message(ParserMessages::conrefAttribute);
1496     break;
1497   case Param::indicatedReservedName + Syntax::rIMPLIED:
1498     def = new ImpliedAttributeDefinition(attributeName,
1499                                          declaredValue.extract());
1500     break;
1501   default:
1502     CANNOT_HAPPEN();
1503   }
1504   return 1;
1505 }
1506
1507 // parm contains either system or public
1508
1509 Boolean Parser::parseExternalId(const AllowedParams &sysidAllow,
1510                                 const AllowedParams &endAllow,
1511                                 Boolean maybeWarnMissingSystemId,
1512                                 unsigned declInputLevel,
1513                                 Param &parm,
1514                                 ExternalId &id)
1515 {
1516   id.setLocation(currentLocation());
1517   if (parm.type == Param::reservedName + Syntax::rPUBLIC) {
1518     static AllowedParams allowMinimumLiteral(Param::minimumLiteral);
1519     if (!parseParam(allowMinimumLiteral, declInputLevel, parm))
1520       return 0;
1521     const MessageType1 *fpierr;
1522     const MessageType1 *urnerr;
1523     switch (id.setPublic(parm.literalText, sd().internalCharset(), 
1524                          syntax().space(), fpierr, urnerr)) {
1525     case PublicId::fpi: 
1526       {
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()));
1532       }
1533       break;
1534     case PublicId::urn:
1535       if (sd().formal() && !sd().urn()) 
1536         message(*fpierr, StringMessageArg(*id.publicIdString()));
1537       break;
1538     case PublicId::informal:
1539       if (sd().formal())
1540         message(*fpierr, StringMessageArg(*id.publicIdString()));
1541       if (sd().urn())
1542         message(*urnerr, StringMessageArg(*id.publicIdString()));
1543       break;
1544     }
1545   }
1546   if (!parseParam(sysidAllow, declInputLevel, parm))
1547     return 0;
1548   if (parm.type == Param::systemIdentifier) {
1549     id.setSystem(parm.literalText);
1550     if (!parseParam(endAllow, declInputLevel, parm))
1551       return 0;
1552   }
1553   else if (options().warnMissingSystemId && maybeWarnMissingSystemId)
1554     message(ParserMessages::missingSystemId);
1555   return 1;
1556 }
1557
1558 Boolean Parser::parseNotationDecl()
1559 {
1560   unsigned declInputLevel = inputLevel();
1561   Param parm;
1562   if (!parseParam(allowName, declInputLevel, parm))
1563     return 0;
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();
1569   if (atts) 
1570     for (size_t i = 0; i < atts->size(); i++) {
1571       Boolean implicit;
1572       if (atts->def(i)->isSpecified(implicit) && implicit) {
1573         message(ParserMessages::notationMustNotBeDeclared,
1574                 StringMessageArg(parm.token));
1575         break;
1576       }
1577     }
1578   static AllowedParams
1579     allowPublicSystem(Param::reservedName + Syntax::rPUBLIC,
1580                       Param::reservedName + Syntax::rSYSTEM);
1581   if (!parseParam(allowPublicSystem, declInputLevel, parm))
1582     return 0;
1583
1584
1585   static AllowedParams allowSystemIdentifierMdc(Param::systemIdentifier,
1586                                                 Param::mdc);
1587
1588   ExternalId id;
1589   if (!parseExternalId(allowSystemIdentifierMdc, allowMdc,
1590                        parm.type == Param::reservedName + Syntax::rSYSTEM,
1591                        declInputLevel, parm, id))
1592     return 0;
1593   if (validate() && sd().formal()) {
1594     PublicId::TextClass textClass;
1595     const PublicId *publicId = id.publicId();
1596     if (publicId
1597         && publicId->getTextClass(textClass)
1598         && textClass != PublicId::NOTATION)
1599       message(ParserMessages::notationIdentifierTextClass);
1600   }
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(),
1607                                                     currentMarkup()));
1608   }
1609   return 1;
1610 }
1611
1612 Boolean Parser::parseEntityDecl()
1613 {
1614   unsigned declInputLevel = inputLevel();
1615   Param parm;
1616
1617   static AllowedParams
1618     allowEntityNamePero(Param::entityName,
1619                         Param::indicatedReservedName + Syntax::rDEFAULT,
1620                         Param::pero);
1621
1622   if (!parseParam(allowEntityNamePero, declInputLevel, parm))
1623     return 0;
1624
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))
1631       return 0;
1632     parm.token.swap(name);
1633   }
1634   else {
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);
1642   }
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);
1654
1655   if (!parseParam(allowEntityTextType, declInputLevel, parm))
1656     return 0;
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);
1668     break;
1669   case Param::reservedName + Syntax::rSDATA:
1670     dataType = Entity::sdata;
1671     if (options().warnInternalSdataEntity)
1672       message(ParserMessages::internalSdataEntity);
1673     break;
1674   case Param::reservedName + Syntax::rPI:
1675     dataType = Entity::pi;
1676     if (options().warnPiEntity)
1677       message(ParserMessages::piEntity);
1678     break;
1679   case Param::reservedName + Syntax::rSTARTTAG:
1680     bracketed = InternalTextEntity::starttag;
1681     if (options().warnBracketEntity)
1682       message(ParserMessages::bracketEntity);
1683     break;
1684   case Param::reservedName + Syntax::rENDTAG:
1685     bracketed = InternalTextEntity::endtag;
1686     if (options().warnBracketEntity)
1687       message(ParserMessages::bracketEntity);
1688     break;
1689   case Param::reservedName + Syntax::rMS:
1690     bracketed = InternalTextEntity::ms;
1691     if (options().warnBracketEntity)
1692       message(ParserMessages::bracketEntity);
1693     break;
1694   case Param::reservedName + Syntax::rMD:
1695     bracketed = InternalTextEntity::md;
1696     if (options().warnBracketEntity)
1697       message(ParserMessages::bracketEntity);
1698     break;
1699   }
1700   if (parm.type != Param::paramLiteral) {
1701     if (!parseParam(allowParamLiteral, declInputLevel, parm))
1702       return 0;
1703   }
1704   Text text;
1705   parm.literalText.swap(text);
1706   if (bracketed != InternalTextEntity::none) {
1707     StringC open;
1708     StringC close;
1709     switch (bracketed) {
1710     case InternalTextEntity::starttag:
1711       open = instanceSyntax().delimGeneral(Syntax::dSTAGO);
1712       close = instanceSyntax().delimGeneral(Syntax::dTAGC);
1713       break;
1714     case InternalTextEntity::endtag:
1715       open = instanceSyntax().delimGeneral(Syntax::dETAGO);
1716       close = instanceSyntax().delimGeneral(Syntax::dTAGC);
1717       break;
1718     case InternalTextEntity::ms: {
1719       const Syntax &syn = 
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);
1725       break;
1726     }
1727     case InternalTextEntity::md: {
1728       const Syntax &syn = 
1729         (declType == Entity::parameterEntity) ? syntax() : instanceSyntax();
1730       open = syn.delimGeneral(Syntax::dMDO);
1731       close = syn.delimGeneral(Syntax::dMDC);
1732       break;
1733     }
1734     default:
1735       CANNOT_HAPPEN();
1736     }
1737     text.insertChars(open, Location(new BracketOrigin(typeLocation,
1738                                                       BracketOrigin::open),
1739                                     0));
1740     text.addChars(close, Location(new BracketOrigin(typeLocation,
1741                                                     BracketOrigin::close),
1742                                   0));
1743     if (text.size() > syntax().litlen()
1744         && text.size() - open.size() - close.size() <= syntax().litlen())
1745       message(ParserMessages::bracketedLitlen,
1746               NumberMessageArg(syntax().litlen()));
1747   }
1748   if (!parseParam(allowMdc, declInputLevel, parm))
1749     return 0;
1750   if (declType == Entity::parameterEntity
1751       && (dataType == Entity::cdata || dataType == Entity::sdata)) {
1752     message(ParserMessages::internalParameterDataEntity,
1753             StringMessageArg(name));
1754     return 1;
1755   }
1756   Ptr<Entity> entity;
1757   switch (dataType) {
1758   case Entity::cdata:
1759     entity = new InternalCdataEntity(name, markupLocation(), text);
1760     break;
1761   case Entity::sdata:
1762     entity = new InternalSdataEntity(name, markupLocation(), text);
1763     break;
1764   case Entity::pi:
1765     entity = new PiEntity(name, declType, markupLocation(), text);
1766     break;
1767   case Entity::sgmlText:
1768     entity = new InternalTextEntity(name, declType, markupLocation(), text, bracketed);
1769     break;
1770   default:
1771     CANNOT_HAPPEN();
1772     break;
1773   }
1774   maybeDefineEntity(entity);
1775   return 1;
1776 }
1777
1778 Boolean Parser::parseExternalEntity(StringC &name,
1779                                     Entity::DeclType declType,
1780                                     unsigned declInputLevel,
1781                                     Param &parm)
1782 {
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,
1789                                        Param::mdc);
1790   static AllowedParams
1791     allowEntityTypeMdc(Param::reservedName + Syntax::rSUBDOC,
1792                        Param::reservedName + Syntax::rCDATA,
1793                        Param::reservedName + Syntax::rSDATA,
1794                        Param::reservedName + Syntax::rNDATA,
1795                        Param::mdc);
1796   
1797   ExternalId id;
1798   if (!parseExternalId(allowSystemIdentifierEntityTypeMdc, allowEntityTypeMdc,
1799                        1, declInputLevel, parm, id))
1800     return 0;
1801   if (parm.type == Param::mdc) {
1802     maybeDefineEntity(new ExternalTextEntity(name, declType, markupLocation(),
1803                                              id));
1804     return 1;
1805   }
1806   Ptr<Entity> entity;
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))
1811       return 0;
1812     entity = new SubdocEntity(name, markupLocation(), id);
1813   }
1814   else {
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);
1821       break;
1822     case Param::reservedName + Syntax::rSDATA:
1823       dataType = Entity::sdata;
1824       if (options().warnExternalSdataEntity)
1825         message(ParserMessages::externalSdataEntity);
1826       break;
1827     case Param::reservedName + Syntax::rNDATA:
1828       dataType = Entity::ndata;
1829       break;
1830     default:
1831       CANNOT_HAPPEN();
1832     }
1833     if (!parseParam(allowName, declInputLevel, parm))
1834       return 0;
1835     Ptr<Notation> notation(lookupCreateNotation(parm.token));
1836     if (!parseParam(allowDsoMdc, declInputLevel, parm))
1837       return 0;
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))
1846         return 0;
1847       if (!newAttDef.isNull()) {
1848         newAttDef->setIndex(defDtd().allocAttributeDefinitionListIndex());
1849         notation->setAttributeDef(newAttDef);
1850       }
1851       if (attributes.nSpec() == 0)
1852         message(ParserMessages::emptyDataAttributeSpec);
1853       if (!parseParam(allowMdc, declInputLevel, parm))
1854         return 0;
1855     }
1856     else
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);
1863   }
1864   if (declType == Entity::parameterEntity && !sd().www()) {
1865     message(ParserMessages::externalParameterDataSubdocEntity,
1866             StringMessageArg(name));
1867     return 1;
1868   }
1869   maybeDefineEntity(entity);
1870   return 1;
1871 }
1872
1873 Notation *Parser::lookupCreateNotation(const StringC &name)
1874 {
1875   Ptr<Notation> nt = defDtd().lookupNotation(name);
1876   if (nt.isNull()) {
1877     nt = new Notation(name, defDtd().namePointer(), defDtd().isBase());
1878     defDtd().insertNotation(nt);
1879   }
1880   return nt.pointer();
1881 }
1882
1883 void Parser::maybeDefineEntity(const Ptr<Entity> &entity)
1884 {
1885   Dtd &dtd = defDtd();
1886   if (haveDefLpd())
1887     entity->setDeclIn(dtd.namePointer(),
1888                       dtd.isBase(),
1889                       defLpd().namePointer(),
1890                       defLpd().active());
1891   else
1892     entity->setDeclIn(dtd.namePointer(), dtd.isBase());
1893   Boolean ignored = 0;
1894   if (entity->name().size() == 0) {
1895     const Entity *oldEntity = dtd.defaultEntity().pointer();
1896     if (oldEntity == 0
1897         || (!oldEntity->declInActiveLpd() && entity->declInActiveLpd()))
1898       dtd.setDefaultEntity(entity, *this);
1899     else {
1900       ignored = 1;
1901       if (options().warnDuplicateEntity)
1902         message(ParserMessages::duplicateEntityDeclaration,
1903                 StringMessageArg(syntax().rniReservedName(Syntax::rDEFAULT)));
1904     }
1905   }
1906   else {
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);
1915     }
1916     else {
1917       if (entity->declInActiveLpd() && !oldEntity->declInActiveLpd()) {
1918         dtd.insertEntity(entity, 1);
1919         entity->generateSystemId(*this);
1920       }
1921       else {
1922         ignored = 1;
1923         if (options().warnDuplicateEntity)
1924           message(entity->declType() == Entity::parameterEntity
1925                   ? ParserMessages::duplicateParameterEntityDeclaration
1926                   : ParserMessages::duplicateEntityDeclaration,
1927                   StringMessageArg(entity->name()));
1928       }
1929     }
1930   }
1931   if (currentMarkup())
1932     eventHandler().entityDecl(new (eventAllocator())
1933                               EntityDeclEvent(entity, ignored,
1934                                               markupLocation(),
1935                                               currentMarkup()));
1936 }
1937
1938 Boolean Parser::parseShortrefDecl()
1939 {
1940   if (!defDtd().isBase())
1941     message(ParserMessages::shortrefOnlyInBaseDtd);
1942
1943   unsigned declInputLevel = inputLevel();
1944   Param parm;
1945
1946   if (!parseParam(allowName, declInputLevel, parm))
1947     return 0;
1948   ShortReferenceMap *map = lookupCreateMap(parm.token);
1949   int valid = 1;
1950   if (map->defined()) {
1951     message(ParserMessages::duplicateShortrefDeclaration,
1952             StringMessageArg(parm.token),
1953             map->defLocation());
1954     valid = 0;
1955   }
1956   else
1957     map->setDefLocation(markupLocation());
1958   if (!parseParam(allowParamLiteral, declInputLevel, parm))
1959     return 0;
1960   Vector<StringC> vec;
1961   do {
1962     StringC delim(parm.literalText.string());
1963     instanceSyntax().generalSubstTable()->subst(delim);
1964     size_t srIndex;
1965     if (!defDtd().shortrefIndex(delim, instanceSyntax(), srIndex)) {
1966       message(ParserMessages::unknownShortrefDelim,
1967               StringMessageArg(prettifyDelim(delim)));
1968       valid = 0;
1969     }
1970     static AllowedParams allowEntityName(Param::entityName);
1971     if (!parseParam(allowEntityName, declInputLevel, parm))
1972       return 0;
1973     if (valid) {
1974       if (srIndex >= vec.size())
1975         vec.resize(srIndex + 1);
1976       if (vec[srIndex].size() > 0) {
1977         message(ParserMessages::delimDuplicateMap,
1978                 StringMessageArg(prettifyDelim(delim)));
1979         valid = 0;
1980       }
1981       else
1982         parm.token.swap(vec[srIndex]);
1983     }
1984     static AllowedParams allowParamLiteralMdc(Param::paramLiteral, Param::mdc);
1985     if (!parseParam(allowParamLiteralMdc, declInputLevel, parm))
1986       return 0;
1987   } while (parm.type != Param::mdc);
1988   if (valid) {
1989     map->setNameMap(vec);
1990     if (currentMarkup())
1991       eventHandler().shortrefDecl(new (eventAllocator())
1992                                   ShortrefDeclEvent(map,
1993                                                     currentDtdPointer(),
1994                                                     markupLocation(),
1995                                                     currentMarkup()));
1996   }
1997   return 1;
1998 }
1999
2000 StringC Parser::prettifyDelim(const StringC &delim)
2001 {
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);
2009     }
2010     else
2011       prettyDelim += delim[i];
2012   }
2013   return prettyDelim;
2014 }
2015
2016 ShortReferenceMap *Parser::lookupCreateMap(const StringC &name)
2017 {
2018   ShortReferenceMap *map = defDtd().lookupShortReferenceMap(name);
2019   if (!map) {
2020     map = new ShortReferenceMap(name);
2021     defDtd().insertShortReferenceMap(map);
2022   }
2023   return map;
2024 }
2025
2026 Boolean Parser::parseUsemapDecl()
2027 {
2028   if (!inInstance() && !defDtd().isBase())
2029     message(ParserMessages::usemapOnlyInBaseDtd);
2030
2031   unsigned declInputLevel = inputLevel();
2032   Param parm;
2033   static AllowedParams
2034     allowNameEmpty(Param::name,
2035                    Param::indicatedReservedName + Syntax::rEMPTY);
2036   if (!parseParam(allowNameEmpty, declInputLevel, parm))
2037     return 0;
2038   const ShortReferenceMap *map;
2039   if (parm.type == Param::name) {
2040     if (inInstance()) {
2041       map = currentDtd().lookupShortReferenceMap(parm.token);
2042       if (!map)
2043         message(ParserMessages::undefinedShortrefMapInstance,
2044                 StringMessageArg(parm.token));
2045     }
2046     else {
2047       ShortReferenceMap *tem = lookupCreateMap(parm.token);
2048       tem->setUsed();
2049       map = tem;
2050     }
2051   }
2052   else
2053     map = &theEmptyMap;
2054   static AllowedParams
2055     allowNameNameGroupMdc(Param::name, Param::nameGroup, Param::mdc);
2056   if (!parseParam(allowNameNameGroupMdc, declInputLevel, parm))
2057     return 0;
2058   if (parm.type != Param::mdc) {
2059     if (inInstance()) {
2060       message(ParserMessages::usemapAssociatedElementTypeInstance);
2061       if (!parseParam(allowMdc, declInputLevel, parm))
2062         return 0;
2063     }
2064     else {
2065       Vector<const ElementType *> v;
2066       if (parm.type == Param::name) {
2067         ElementType *e = lookupCreateElement(parm.token);
2068         v.push_back(e);
2069         if (!e->map())
2070           e->setMap(map);
2071       }
2072       else {
2073         v.resize(parm.nameTokenVector.size());
2074         for (size_t i = 0; i < parm.nameTokenVector.size(); i++) {
2075           ElementType *e
2076             = lookupCreateElement(parm.nameTokenVector[i].name);
2077           v[i] = e;
2078           if (!e->map())
2079             e->setMap(map);
2080         }
2081       }
2082       if (!parseParam(allowMdc, declInputLevel, parm))
2083         return 0;
2084       if (currentMarkup())
2085         eventHandler().usemap(new (eventAllocator())
2086                               UsemapEvent(map, v,
2087                                           currentDtdPointer(),
2088                                           markupLocation(),
2089                                           currentMarkup()));
2090     }
2091   }
2092   else {
2093     if (!inInstance())
2094       message(ParserMessages::usemapAssociatedElementTypeDtd);
2095     else if (map) {
2096       if (map != &theEmptyMap && !map->defined())
2097         message(ParserMessages::undefinedShortrefMapInstance,
2098                 StringMessageArg(map->name()));
2099       else {
2100         if (currentMarkup()) {
2101           Vector<const ElementType *> v;
2102           eventHandler().usemap(new (eventAllocator())
2103                                 UsemapEvent(map, v,
2104                                             currentDtdPointer(),
2105                                             markupLocation(),
2106                                             currentMarkup()));
2107         }
2108         currentElement().setMap(map);
2109       }
2110     }
2111   }
2112   return 1;
2113 }
2114
2115 Boolean Parser::parseDoctypeDeclStart()
2116 {
2117   if (hadDtd() && !sd().concur() && !sd().explicitLink())
2118     message(ParserMessages::multipleDtds);
2119   if (hadLpd())
2120     message(ParserMessages::dtdAfterLpd);
2121   unsigned declInputLevel = inputLevel();
2122   Param parm;
2123   static AllowedParams
2124     allowImpliedName(Param::indicatedReservedName + Syntax::rIMPLIED,
2125                      Param::name);
2126   if (!parseParam(sd().www() ? allowImpliedName : allowName, declInputLevel, parm))
2127     return 0;
2128   if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2129     if (sd().concur() > 0 || sd().explicitLink() > 0)
2130       message(ParserMessages::impliedDoctypeConcurLink);
2131     message(ParserMessages::sorryImpliedDoctype);
2132     return 0;
2133   }
2134   StringC name;
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,
2141                             Param::dso,
2142                             Param::mdc);
2143   if (!parseParam(allowPublicSystemDsoMdc, declInputLevel, parm))
2144     return 0;
2145   ConstPtr<Entity> entity;
2146   StringC notation;
2147   EntityDecl::DataType data;
2148   ExternalId id;
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))
2167       return 0;
2168     switch (parm.type) {
2169     case Param::reservedName + Syntax::rCDATA:
2170       data = Entity::cdata;
2171       break; 
2172     case Param::reservedName + Syntax::rSDATA:
2173       data = Entity::sdata;
2174       break; 
2175     case Param::reservedName + Syntax::rNDATA:
2176       data = Entity::ndata;
2177       break; 
2178     default:
2179       data = Entity::sgmlText;
2180       break;
2181     }
2182     if (data == Entity::sgmlText) {
2183       Ptr<Entity> tem
2184         = new ExternalTextEntity(name, Entity::doctype, markupLocation(), id);
2185       tem->generateSystemId(*this);
2186       entity = tem;
2187     }
2188 #if 0
2189       eventHandler()
2190         .externalEntityDecl(new (eventAllocator())
2191                             ExternalEntityDeclEvent(entity, 0));
2192 #endif
2193     else {
2194       // external subset uses some DTD notation
2195       if (!parseParam(allowName, declInputLevel, parm))
2196         return 0;
2197       parm.token.swap(notation);
2198       if (!parseParam(allowDsoMdc, declInputLevel, parm))
2199         return 0;
2200     }
2201   }
2202   else 
2203   // no external subset specified
2204   if (sd().implydefDoctype()) {
2205     // FIXME this fails for #IMPLIED, since name isn't yet known
2206     Ptr<Entity> tem
2207       = new ExternalTextEntity(name, Entity::doctype, markupLocation(), id);
2208     tem->generateSystemId(*this);
2209     entity = tem;
2210   }
2211   else if (parm.type == Param::mdc) {
2212     if (sd().implydefElement() == Sd::implydefElementNo) {
2213       message(ParserMessages::noDtdSubset);
2214       enableImplydef();
2215     }
2216   }
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,
2222                                         markupLocation(),
2223                                         currentMarkup()));
2224   startDtd(name);
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)); 
2229     
2230     AttributeList attrs(nt->attributeDef());
2231     attrs.finish(*this); 
2232     Ptr<Entity> tem 
2233       = new ExternalDataEntity(name, data, markupLocation(), id, nt, attrs, 
2234                                Entity::doctype);
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
2239     StringC entname;
2240     tem->setName(entname);
2241     defDtd().insertEntity(tem);
2242     entity = tem;
2243   }
2244   if (parm.type == Param::mdc) {
2245     // unget the mdc
2246     currentInput()->ungetToken();
2247     if (entity.isNull()) {
2248       (void)parseDoctypeDeclEnd();
2249       return 1;
2250     }
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();
2257       return 1;
2258     }
2259   }
2260   else if (!entity.isNull())
2261     setDsEntity(entity);
2262   setPhase(declSubsetPhase);
2263   return 1;
2264 }
2265
2266 void Parser::implyDtd(const StringC &gi)
2267 {
2268   startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2269 #if 0
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());
2276   }
2277 #endif
2278   if (sd().concur() > 0 || sd().explicitLink() > 0
2279       || (sd().implydefElement() == Sd::implydefElementNo
2280           && !sd().implydefDoctype()))
2281     message(ParserMessages::omittedProlog);
2282
2283   if ((sd().implydefElement() != Sd::implydefElementNo) && !sd().implydefDoctype()) {
2284     eventHandler().startDtd(new (eventAllocator())
2285                                   StartDtdEvent(gi, ConstPtr<Entity>(), 0,
2286                                         markupLocation(),
2287                                         currentMarkup()));
2288     startDtd(gi);
2289     parseDoctypeDeclEnd(1);
2290     return;
2291   }
2292   ExternalId id;
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);
2298   else {
2299     // Don't use Entity::generateSystemId because we don't want an error
2300     // if it fails.
2301     StringC str;
2302     if (!entityCatalog().lookup(*entity, syntax(), sd().internalCharset(),
2303                                 messenger(), str)) {
2304       message(ParserMessages::noDtd);
2305       enableImplydef();
2306       eventHandler().startDtd(new (eventAllocator())
2307                                    StartDtdEvent(gi, ConstPtr<Entity>(), 0,
2308                                                  markupLocation(),
2309                                                  currentMarkup()));
2310       startDtd(gi);
2311       parseDoctypeDeclEnd(1);
2312       return;
2313     }
2314     id.setEffectiveSystem(str);
2315 #if 0
2316     if (currentMarkup()) {
2317       currentMarkup()->addS(syntax().space());
2318       currentMarkup()->addReservedName(Syntax::rSYSTEM,
2319                                        syntax().reservedName(Syntax::rSYSTEM));
2320     }
2321 #endif
2322     entity = new ExternalTextEntity(gi,
2323                                     Entity::doctype,
2324                                     Location(),
2325                                     id);
2326     StringC declStr;
2327     declStr += syntax().delimGeneral(Syntax::dMDO);
2328     declStr += syntax().reservedName(Syntax::rDOCTYPE);
2329     declStr += syntax().space();
2330     declStr += gi;
2331     declStr += syntax().space();
2332     declStr += syntax().reservedName(Syntax::rSYSTEM);
2333     declStr += syntax().delimGeneral(Syntax::dMDC);
2334     message(ParserMessages::implyingDtd, StringMessageArg(declStr));
2335   }
2336   Ptr<EntityOrigin> origin
2337     = EntityOrigin::make(internalAllocator(), entity, currentLocation());
2338   eventHandler().startDtd(new (eventAllocator())
2339                           StartDtdEvent(gi, entity, 0,
2340                                         markupLocation(),
2341                                         currentMarkup()));
2342   startDtd(gi);
2343   entity->dsReference(*this, origin);
2344   if (inputLevel() == 1)
2345     parseDoctypeDeclEnd(1);
2346   else
2347     setPhase(declSubsetPhase);
2348 }
2349
2350 Boolean Parser::parseDoctypeDeclEnd(Boolean fake)
2351 {
2352   checkDtd(defDtd());
2353   Ptr<Dtd> tem(defDtdPointer());
2354   endDtd();
2355   if (fake) {
2356     startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2357 #if 0
2358     if (currentMarkup())
2359       currentMarkup()->addDelim(Syntax::dMDC);
2360 #endif
2361   }
2362   else {
2363     startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2364     Param parm;
2365     // End DTD before parsing final param so parameter entity reference
2366     // not allowed between ] and >.
2367     if (!parseParam(allowMdc, inputLevel(), parm))
2368       return 0;
2369   }
2370   eventHandler().endDtd(new (eventAllocator()) EndDtdEvent(tem,
2371                                                            markupLocation(),
2372                                                            currentMarkup()));
2373 #if 0
2374   if (fake) {
2375     Char c = syntax().standardFunction(Syntax::fRE);
2376     eventHandler().sSep(new (eventAllocator())
2377                         SSepEvent(&c, 1, Location(), 1));
2378   }
2379 #endif
2380   return 1;
2381 }
2382
2383 void Parser::checkDtd(Dtd &dtd)
2384 {
2385   if (dtd.isBase())
2386     addNeededShortrefs(dtd, instanceSyntax());
2387   if (sd().www() || !options().errorAfdr)
2388     addCommonAttributes(dtd);
2389   Dtd::ElementTypeIter elementIter(dtd.elementTypeIter());
2390   ElementType *p;
2391   ConstPtr<ElementDefinition> def;
2392   int i = 0;
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);
2398       }
2399       else if (options().warnUndefinedElement)
2400         message(ParserMessages::dtdUndefinedElement, StringMessageArg(p->name()));
2401       if (def.isNull())
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++);
2408     }
2409     const ShortReferenceMap *map = p->map();
2410     if (map != 0 && map != &theEmptyMap && !map->defined()) {
2411       if (validate())
2412         message(ParserMessages::undefinedShortrefMapDtd,
2413                 StringMessageArg(map->name()),
2414                 StringMessageArg(p->name()));
2415       p->setMap(0);
2416     }
2417   }
2418   Dtd::ShortReferenceMapIter mapIter(dtd.shortReferenceMapIter());
2419   int nShortref = dtd.nShortref();
2420   for (;;) {
2421     ShortReferenceMap *map = mapIter.next();
2422     if (!map)
2423       break;
2424     Vector<ConstPtr<Entity> > entityMap(nShortref);
2425     for (i = 0; i < nShortref; i++) {
2426       const StringC *entityName = map->entityName(i);
2427       if (entityName) {
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()));
2435         }
2436         else {
2437           if (entity->defaulted() && options().warnDefaultEntityReference) {
2438             setNextLocation(map->defLocation());
2439             message(ParserMessages::mapDefaultEntity,
2440                     StringMessageArg(*entityName),
2441                     StringMessageArg(map->name()));
2442           }
2443           entityMap[i] = entity;
2444         }
2445       }
2446     }
2447     map->setEntityMap(entityMap);
2448     if (options().warnUnusedMap && !map->used()) {
2449       setNextLocation(map->defLocation());
2450       message(ParserMessages::unusedMap, StringMessageArg(map->name()));
2451     }
2452   }
2453   if (options().warnUnusedParam) {
2454     Dtd::ConstEntityIter entityIter(((const Dtd &)dtd).parameterEntityIter());
2455     for (;;) {
2456       ConstPtr<Entity> entity(entityIter.next());
2457       if (entity.isNull())
2458         break;
2459       if (!entity->used() && !maybeStatusKeyword(*entity)) {
2460         setNextLocation(entity->defLocation());
2461         message(ParserMessages::unusedParamEntity,
2462                 StringMessageArg(entity->name()));
2463       }
2464     }
2465   }
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++) {
2469     for (;;) {
2470       ConstPtr<Entity> entity(i == 0 ? gEntityIter.next() : pEntityIter.next());
2471       if (entity.isNull())
2472         break;
2473       const ExternalDataEntity *external = entity->asExternalDataEntity();
2474       if (external) {
2475         Notation *notation = (Notation *)external->notation();
2476         if (!notation->defined()) {
2477           if (sd().implydefNotation()) {
2478             ExternalId id;
2479             notation->setExternalId(id, Location());
2480             notation->generateSystemId(*this);
2481           } 
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()));
2489               break;
2490             case Entity::doctype:
2491               message(ParserMessages::dsEntityNotationUndefined,
2492                       StringMessageArg(notation->name()));
2493               break;
2494             default:
2495               message(ParserMessages::entityNotationUndefined,
2496                 StringMessageArg(notation->name()),
2497                 StringMessageArg(external->name()));
2498               break;
2499             }
2500           }
2501         }
2502       }
2503     }
2504   }
2505   Dtd::NotationIter notationIter(dtd.notationIter());
2506   for (;;) {
2507     Ptr<Notation> notation(notationIter.next());
2508     if (notation.isNull())
2509       break;
2510     if (!notation->defined() && !notation->attributeDef().isNull()) {
2511         if (sd().implydefNotation()) {
2512           ExternalId id;
2513           notation->setExternalId(id, Location());
2514           notation->generateSystemId(*this);                                   
2515         } 
2516         else if (validate())
2517           message(ParserMessages::attlistNotationUndefined,
2518                   StringMessageArg(notation->name()));
2519     }
2520   }
2521 }
2522
2523 #if 0
2524 void Parser::addCommonAttributes(Dtd &dtd)
2525 {
2526   Ptr<AttributeDefinitionList> commonAdl[2];
2527   {
2528     ElementType *e = dtd.removeElementType(syntax()
2529                                            .rniReservedName(Syntax::rALL));
2530     if (e) {
2531       commonAdl[0] = e->attributeDef();
2532       delete e;
2533       lookupCreateElement(syntax().rniReservedName(Syntax::rIMPLICIT));
2534     }
2535   }
2536   {
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));
2542     }
2543   }
2544   Dtd::ElementTypeIter elementIter(dtd.elementTypeIter());
2545   Dtd::NotationIter notationIter(dtd.notationIter());
2546   Vector<PackedBoolean> doneAdl(dtd.nAttributeDefinitionList(),
2547                                 PackedBoolean(0));
2548   for (int isNotation = 0; isNotation < 2; isNotation++) {
2549     if (!commonAdl[isNotation].isNull()) {
2550       doneAdl[commonAdl[isNotation]->index()] = 1;
2551       for (;;) {
2552         Attributed *a;
2553         if (!isNotation)
2554           a = elementIter.next();
2555         else
2556           a = notationIter.next().pointer();
2557         if (!a)
2558           break;
2559         Ptr<AttributeDefinitionList> adl = a->attributeDef();
2560         if (adl.isNull())
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++) {
2565             unsigned tem;
2566             if (!adl->attributeIndex(commonAdl[isNotation]->def(j)->name(),
2567                                      tem))
2568               adl->append(commonAdl[isNotation]->def(j)->copy());
2569           }
2570         }
2571       }
2572     }
2573   }
2574   {
2575     ElementType *e = dtd.removeElementType(syntax()
2576                                            .rniReservedName(Syntax::rIMPLICIT));
2577     if (e)
2578       dtd.setImplicitElementAttributeDef(e->attributeDef());
2579     delete e;
2580   }
2581   {
2582     Ptr<Notation> n
2583       = dtd.removeNotation(syntax().rniReservedName(Syntax::rIMPLICIT));
2584     if (!n.isNull())
2585       dtd.setImplicitNotationAttributeDef(n->attributeDef());
2586   }
2587 }
2588 #else
2589 void Parser::addCommonAttributes(Dtd &dtd)
2590 {
2591   // These are #implicit, #all, #notation #implicit, #notation #all
2592   Ptr<AttributeDefinitionList> commonAdl[4];
2593   {
2594     ElementType *e = lookupCreateElement(syntax()
2595                                        .rniReservedName(Syntax::rIMPLICIT));
2596     commonAdl[0] = e->attributeDef();
2597     e = dtd.removeElementType(syntax().rniReservedName(Syntax::rALL));
2598     if (e) 
2599       commonAdl[1] = e->attributeDef();
2600     delete e;
2601   }
2602   {
2603     Ptr<Notation> nt 
2604       = lookupCreateNotation(syntax().rniReservedName(Syntax::rIMPLICIT));
2605     commonAdl[2] = nt->attributeDef();
2606     nt = dtd.removeNotation(syntax().rniReservedName(Syntax::rALL));
2607     if (!nt.isNull()) 
2608       commonAdl[3] = nt->attributeDef();
2609   }
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(),
2615                                 PackedBoolean(0));
2616   Vector<PackedBoolean> done2Adl(dtd.nAttributeDefinitionList(),
2617                                 PackedBoolean(0));
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()) {
2623       if (i % 2) 
2624         done1Adl[commonAdl[i]->index()] = 1;
2625       else
2626         done2Adl[commonAdl[i]->index()] = 1;
2627       for (;;) {
2628         Boolean skip;
2629         Attributed *a;
2630         switch (i) {
2631         case 0: 
2632           {
2633             ElementType *e = elementIter.next();
2634             a = e;
2635             skip = (e && e->definition()); // don't merge #implicit 
2636                                            // attributes if e is defined
2637           }
2638           break;
2639         case 1:
2640           a = element2Iter.next();
2641           skip = 0;                        // always merge #all attributes
2642           break;
2643         case 2: 
2644           {
2645             Notation *nt = notationIter.next().pointer();
2646             a = nt;
2647             skip = (nt && nt->defined());  // don't merge #implicit 
2648                                            // attributes if nt is defined
2649           }
2650           break;
2651         case 3:
2652           a = notation2Iter.next().pointer();
2653           skip = 0;                        // always merge #all attributes
2654           break;
2655         default:
2656           CANNOT_HAPPEN();
2657         }
2658         if (!a)
2659           break;
2660         Ptr<AttributeDefinitionList> adl = a->attributeDef();
2661         if (adl.isNull()) {
2662           if (!skip)
2663             a->setAttributeDef(commonAdl[i]);
2664         }
2665         else if (((i % 2) && !done1Adl[adl->index()])
2666                ||(!(i % 2) && !done2Adl[adl->index()])) {
2667           if (i % 2)
2668             done1Adl[adl->index()] = 1;
2669           else 
2670             done2Adl[adl->index()] = 1;
2671           if (!skip)
2672             for (size_t j = 0; j < commonAdl[i]->size(); j++) {
2673               unsigned index;
2674               if (!adl->attributeIndex(commonAdl[i]->def(j)->name(),
2675                                        index))
2676                 adl->append(commonAdl[i]->def(j)->copy());
2677               else if (i == 2) {
2678                 // Give an error if an #ALL data attribute was 
2679                 // specified and is later redeclared as #IMPLICIT
2680                 Boolean implicit;
2681                 if (adl->def(index)->isSpecified(implicit) && !implicit)
2682                   message(ParserMessages::specifiedAttributeRedeclared,
2683                           StringMessageArg(adl->def(index)->name()));
2684               } 
2685             }
2686         }
2687       }
2688     }
2689   }
2690   {
2691     ElementType *e = dtd.removeElementType(syntax()
2692                                            .rniReservedName(Syntax::rIMPLICIT));
2693     if (e)
2694       dtd.setImplicitElementAttributeDef(e->attributeDef());
2695     delete e;
2696   }
2697   {
2698     Ptr<Notation> n
2699       = dtd.removeNotation(syntax().rniReservedName(Syntax::rIMPLICIT));
2700     if (!n.isNull())
2701       dtd.setImplicitNotationAttributeDef(n->attributeDef());
2702   }
2703 }
2704
2705 #endif
2706
2707 Boolean Parser::maybeStatusKeyword(const Entity &entity)
2708 {
2709   const InternalEntity *internal = entity.asInternalEntity();
2710   if (!internal)
2711     return 0;
2712   const StringC &text = internal->string();
2713   static const Syntax::ReservedName statusKeywords[] = {
2714     Syntax::rINCLUDE, Syntax::rIGNORE
2715     };
2716   for (size_t i = 0; i < SIZEOF(statusKeywords); i++) {
2717     const StringC &keyword = instanceSyntax().reservedName(statusKeywords[i]);
2718     size_t j = 0;
2719     while (j < text.size() && instanceSyntax().isS(text[j]))
2720       j++;
2721     size_t k = 0;
2722     while (j < text.size()
2723            && k < keyword.size()
2724            && ((*instanceSyntax().generalSubstTable())[text[j]]
2725                == keyword[k]))
2726       j++, k++;
2727     if (k == keyword.size()) {
2728       while (j < text.size() && instanceSyntax().isS(text[j]))
2729         j++;
2730       if (j == text.size())
2731         return 1;
2732     }
2733   }
2734   return 0;
2735 }
2736
2737 Boolean Parser::parseLinktypeDeclStart()
2738 {
2739   if (baseDtd().isNull())
2740     message(ParserMessages::lpdBeforeBaseDtd);
2741   unsigned declInputLevel = inputLevel();
2742   Param parm;
2743   
2744   if (!parseParam(allowName, declInputLevel, parm))
2745     return 0;
2746   StringC name;
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,
2754                     Param::name);
2755   if (!parseParam(allowSimpleName, declInputLevel, parm))
2756     return 0;
2757   Boolean simple;
2758   Ptr<Dtd> sourceDtd;
2759   if (parm.type == Param::indicatedReservedName + Syntax::rSIMPLE) {
2760     simple = 1;
2761     sourceDtd = baseDtd();
2762     if (sourceDtd.isNull())
2763       sourceDtd = new Dtd(StringC(), 1);
2764   }
2765   else {
2766     simple = 0;
2767     sourceDtd = lookupDtd(parm.token);
2768     if (sourceDtd.isNull()) {
2769       message(ParserMessages::noSuchDtd, StringMessageArg(parm.token));
2770       sourceDtd = new Dtd(parm.token, 0);
2771     }
2772   }
2773   static AllowedParams
2774     allowImpliedName(Param::indicatedReservedName + Syntax::rIMPLIED,
2775                      Param::name);
2776   if (!parseParam(allowImpliedName, declInputLevel, parm))
2777     return 0;
2778   Ptr<Dtd> resultDtd;
2779   Boolean implied = 0;
2780   if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2781     if (simple) {
2782       if (!sd().simpleLink())
2783         message(ParserMessages::simpleLinkFeature);
2784     }
2785     else {
2786       implied = 1;
2787       if (!sd().implicitLink())
2788         message(ParserMessages::implicitLinkFeature);
2789     }
2790   }
2791   else {
2792     if (simple)
2793       message(ParserMessages::simpleLinkResultNotImplied);
2794     else {
2795       if (!sd().explicitLink())
2796         message(ParserMessages::explicitLinkFeature);
2797       resultDtd = lookupDtd(parm.token);
2798       if (resultDtd.isNull())
2799         message(ParserMessages::noSuchDtd, StringMessageArg(parm.token));
2800     }
2801   }
2802   static AllowedParams
2803     allowPublicSystemDsoMdc(Param::reservedName + Syntax::rPUBLIC,
2804                             Param::reservedName + Syntax::rSYSTEM,
2805                             Param::dso,
2806                             Param::mdc);
2807   if (!parseParam(allowPublicSystemDsoMdc, declInputLevel, parm))
2808     return 0;
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);
2814     ExternalId id;
2815     if (!parseExternalId(allowSystemIdentifierDsoMdc, allowDsoMdc,
2816                          1, declInputLevel, parm, id))
2817       return 0;
2818     Ptr<Entity> tem
2819       = new ExternalTextEntity(name, Entity::linktype, markupLocation(), id);
2820     tem->generateSystemId(*this);
2821     entity = tem;
2822 #if 0
2823     eventHandler()
2824       .externalEntityDecl(new (eventAllocator())
2825                           ExternalEntityDeclEvent(entity, 0));
2826 #endif
2827   }
2828   Ptr<Lpd> lpd;
2829   if (simple)
2830     lpd = new SimpleLpd(name, markupLocation(), sourceDtd);
2831   else
2832     lpd = new ComplexLpd(name,
2833                          implied ? Lpd::implicitLink : Lpd::explicitLink,
2834                          markupLocation(),
2835                          syntax(),
2836                          sourceDtd,
2837                          resultDtd);
2838   if (!baseDtd().isNull() && shouldActivateLink(name)) {
2839     size_t nActive = nActiveLink();
2840     if (simple) {
2841       size_t nSimple = 0;
2842       for (size_t i = 0; i < nActive; i++)
2843         if (activeLpd(i).type() == Lpd::simpleLink)
2844           nSimple++;
2845       if (nSimple == sd().simpleLink())
2846         message(ParserMessages::simpleLinkCount,
2847                 NumberMessageArg(sd().simpleLink()));
2848       lpd->activate();
2849     }
2850     else {
2851       Boolean haveImplicit = 0;
2852       Boolean haveExplicit = 0;
2853       size_t i;
2854       for (i = 0; i < nActive; i++) {
2855         if (activeLpd(i).type() == Lpd::implicitLink)
2856           haveImplicit = 1;
2857         else if (activeLpd(i).type() == Lpd::explicitLink)
2858           haveExplicit = 1;
2859       }
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()));
2873       else
2874         lpd->activate();
2875     }
2876   }
2877   // Discard mdc or dso
2878   if (currentMarkup())
2879     currentMarkup()->resize(currentMarkup()->size() - 1);
2880   eventHandler().startLpd(new (eventAllocator())
2881                           StartLpdEvent(lpd->active(),
2882                                         name,
2883                                         entity,
2884                                         parm.type == Param::dso,
2885                                         markupLocation(),
2886                                         currentMarkup()));
2887   startLpd(lpd);
2888   if (parm.type == Param::mdc) {
2889     // unget the mdc
2890     currentInput()->ungetToken();
2891     if (entity.isNull()) {
2892       message(ParserMessages::noLpdSubset, StringMessageArg(name));
2893       (void)parseLinktypeDeclEnd();
2894       return 1;
2895     }
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();
2902       return 1;
2903     }
2904   }
2905   else if (!entity.isNull())
2906     setDsEntity(entity);
2907   setPhase(declSubsetPhase);
2908   return 1;
2909 }
2910
2911 Boolean Parser::parseLinktypeDeclEnd()
2912 {
2913
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()));
2923   }
2924   ConstPtr<Lpd> tem(defLpdPointer());
2925   endLpd();
2926   startMarkup(eventsWanted().wantPrologMarkup(), currentLocation());
2927   Param parm;
2928   Boolean result = parseParam(allowMdc, inputLevel(), parm);
2929   eventHandler().endLpd(new (eventAllocator()) EndLpdEvent(tem,
2930                                                            markupLocation(),
2931                                                            currentMarkup()));
2932   return result;
2933 }
2934
2935 Boolean Parser::parseLinkDecl()
2936 {
2937   return parseLinkSet(0);
2938 }
2939
2940 Boolean Parser::parseIdlinkDecl()
2941 {
2942   return parseLinkSet(1);
2943 }
2944
2945 // This will only get called if we're defining a complex lpd.
2946
2947 Boolean Parser::parseLinkSet(Boolean idlink)
2948 {
2949   if (defLpd().type() == Lpd::simpleLink) {
2950     message(idlink ? ParserMessages::idlinkDeclSimple : ParserMessages::linkDeclSimple);
2951     return 0;
2952   }
2953   if (idlink) {
2954     if (defComplexLpd().hadIdLinkSet())
2955       message(ParserMessages::duplicateIdLinkSet);
2956     else
2957       defComplexLpd().setHadIdLinkSet();
2958   }
2959   unsigned declInputLevel = inputLevel();
2960   Param parm;
2961   
2962   Boolean isExplicit = (defLpd().type() == Lpd::explicitLink);
2963   LinkSet *linkSet;
2964   if (idlink) {
2965     if (!parseParam(allowName, declInputLevel, parm))
2966       return 0;
2967     linkSet = 0;
2968   }
2969   else {
2970     static AllowedParams
2971       allowNameInitial(Param::name,
2972                        Param::indicatedReservedName + Syntax::rINITIAL);
2973     if (!parseParam(allowNameInitial, declInputLevel, parm))
2974       return 0;
2975     if (parm.type == Param::name)
2976       linkSet = lookupCreateLinkSet(parm.token);
2977     else
2978       linkSet = defComplexLpd().initialLinkSet();
2979     if (linkSet->defined())
2980       message(ParserMessages::duplicateLinkSet, StringMessageArg(linkSet->name()));
2981     static AllowedParams
2982       allowExplicitLinkRule(Param::name,
2983                             Param::nameGroup,
2984                             Param::indicatedReservedName + Syntax::rIMPLIED);
2985     if (!parseParam(isExplicit ? allowExplicitLinkRule : allowNameNameGroup,
2986                     declInputLevel, parm))
2987       return 0;
2988   }
2989
2990   do {
2991     StringC id;
2992     if (idlink) {
2993       parm.token.swap(id);
2994       if (!parseParam(isExplicit ? allowExplicitLinkRuleMdc : allowNameNameGroupMdc,
2995                       declInputLevel, parm))
2996         return 0;
2997     }
2998     if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
2999       if (!parseParam(allowName, declInputLevel, parm))
3000         return 0;
3001       Boolean resultImplied;
3002       const ElementType *resultType;
3003       AttributeList resultAttributes;
3004       if (!parseResultElementSpec(declInputLevel,
3005                                   parm,
3006                                   idlink,
3007                                   resultImplied,
3008                                   resultType,
3009                                   resultAttributes))
3010         return 0;
3011       if (resultType) {
3012         const AttributeList *dummy;
3013         if (linkSet->impliedResultAttributes(resultType, dummy))
3014           message(ParserMessages::duplicateImpliedResult,
3015                   StringMessageArg(resultType->name()));
3016         else
3017           linkSet->addImplied(resultType, resultAttributes);
3018       }
3019     }
3020     else {
3021       SourceLinkRule *linkRule = 0;
3022       IdLinkRule idLinkRule;
3023       Ptr<SourceLinkRuleResource> linkRuleResource;
3024       if (idlink)
3025         linkRule = &idLinkRule;
3026       else {
3027         linkRuleResource = new SourceLinkRuleResource;
3028         linkRule = linkRuleResource.pointer();
3029       }
3030       Vector<const ElementType *> assocElementTypes;
3031       if (parm.type == Param::name) {
3032         assocElementTypes.resize(1);
3033         assocElementTypes[0] = lookupCreateElement(parm.token);
3034       }
3035       else {
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);
3040       }
3041       static AllowedParams
3042         allow2i(Param::indicatedReservedName + Syntax::rUSELINK,
3043                 Param::indicatedReservedName + Syntax::rPOSTLINK,
3044                 Param::dso,
3045                 Param::mdc,
3046                 Param::name,
3047                 Param::nameGroup);
3048       static AllowedParams
3049         allow2id(Param::indicatedReservedName + Syntax::rUSELINK,
3050                  Param::indicatedReservedName + Syntax::rPOSTLINK,
3051                  Param::dso,
3052                  Param::mdc,
3053                  Param::name);
3054       static AllowedParams
3055         allow2e(Param::indicatedReservedName + Syntax::rUSELINK,
3056                 Param::indicatedReservedName + Syntax::rPOSTLINK,
3057                 Param::dso,
3058                 Param::name,
3059                 Param::indicatedReservedName + Syntax::rIMPLIED);
3060
3061       if (!parseParam(isExplicit
3062                       ? allow2e
3063                       : (idlink ? allow2id : allow2i), declInputLevel, parm))
3064         return 0;
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))
3071           return 0;
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();
3077         else
3078           uselink = defComplexLpd().emptyLinkSet();
3079         linkRule->setUselink(uselink);
3080         static AllowedParams
3081           allow3i(Param::indicatedReservedName + Syntax::rPOSTLINK,
3082                   Param::dso,
3083                   Param::mdc,
3084                   Param::name,
3085                   Param::nameGroup);
3086         static AllowedParams
3087           allow3id(Param::indicatedReservedName + Syntax::rPOSTLINK,
3088                    Param::dso,
3089                    Param::mdc,
3090                    Param::name);
3091         static AllowedParams
3092           allow3e(Param::indicatedReservedName + Syntax::rPOSTLINK,
3093                   Param::dso,
3094                   Param::name,
3095                   Param::indicatedReservedName + Syntax::rIMPLIED);
3096         
3097         if (!parseParam(isExplicit
3098                         ? allow3e
3099                         : (idlink ? allow3id : allow3i),
3100                         declInputLevel, parm))
3101           return 0;
3102       }
3103       if (parm.type == Param::indicatedReservedName + Syntax::rPOSTLINK) {
3104         if (!parseParam(allowLinkSetSpec, declInputLevel, parm))
3105           return 0;
3106         const LinkSet *postlink;
3107         if (parm.type == Param::indicatedReservedName + Syntax::rRESTORE)
3108           linkRule->setPostlinkRestore();
3109         else {
3110           if (parm.type == Param::name)
3111             postlink = lookupCreateLinkSet(parm.token);
3112           else if (parm.type
3113                    == Param::indicatedReservedName + Syntax::rINITIAL)
3114             postlink = defComplexLpd().initialLinkSet();
3115           else
3116             postlink = defComplexLpd().emptyLinkSet();
3117           linkRule->setPostlink(postlink);
3118         }
3119         static AllowedParams
3120           allow4i(Param::dso,
3121                   Param::mdc,
3122                   Param::name,
3123                   Param::nameGroup);
3124         static AllowedParams
3125           allow4id(Param::dso,
3126                    Param::mdc,
3127                    Param::name);
3128         static AllowedParams
3129           allow4e(Param::dso,
3130                   Param::name,
3131                   Param::indicatedReservedName + Syntax::rIMPLIED);
3132         if (!parseParam(isExplicit
3133                         ? allow4e
3134                         : (idlink ? allow4id : allow4i),
3135                         declInputLevel, parm))
3136           return 0;
3137       }
3138       AttributeList attributes;
3139       ConstPtr<AttributeDefinitionList> attDef;
3140       for (size_t i = 0; i < assocElementTypes.size(); i++) {
3141         const ElementType *e = assocElementTypes[i];
3142         if (e) {
3143           if (i == 0)
3144             attDef = defComplexLpd().attributeDef(e);
3145           else if (attDef != defComplexLpd().attributeDef(e))
3146             message(ParserMessages::assocElementDifferentAtts);
3147           // FIXME recover from this
3148         }
3149       }
3150       attributes.init(attDef);
3151       
3152       if (parm.type == Param::dso) {
3153         Boolean netEnabling;
3154         Ptr<AttributeDefinitionList> newAttDef;
3155         if (!parseAttributeSpec(asMode, attributes, netEnabling, newAttDef))
3156           return 0;
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);
3163           }
3164         }
3165         static AllowedParams
3166           allow5e(Param::name,
3167                   Param::indicatedReservedName + Syntax::rIMPLIED);
3168         if (!parseParam(isExplicit
3169                         ? allow5e
3170                         : (idlink ? allowNameMdc : allowNameNameGroupMdc),
3171                         declInputLevel, parm))
3172           return 0;
3173       }
3174       else
3175         attributes.finish(*this);
3176       linkRule->setLinkAttributes(attributes);
3177       if (isExplicit) {
3178         Boolean resultImplied;
3179         const ElementType *resultType;
3180         AttributeList resultAttributes;
3181         if (!parseResultElementSpec(declInputLevel,
3182                                     parm,
3183                                     idlink,
3184                                     resultImplied,
3185                                     resultType,
3186                                     resultAttributes))
3187           return 0;
3188         if (!resultImplied)
3189           linkRule->setResult(resultType, resultAttributes);
3190       }
3191       // Install the link rule.
3192       if (idlink) {
3193         idLinkRule.setAssocElementTypes(assocElementTypes);
3194         addIdLinkRule(id, idLinkRule);
3195       }
3196       else {
3197         if (!linkSet->defined()) {
3198           for (size_t i = 0; i < assocElementTypes.size(); i++)
3199             if (assocElementTypes[i])
3200               addLinkRule(linkSet, assocElementTypes[i], linkRuleResource);
3201         }
3202       }
3203     }
3204   } while (parm.type != Param::mdc);
3205   if (linkSet)
3206     linkSet->setDefined();
3207   if (currentMarkup()) {
3208     if (idlink)
3209       eventHandler().idLinkDecl(new (eventAllocator())
3210                                 IdLinkDeclEvent(defComplexLpdPointer(),
3211                                                 markupLocation(),
3212                                                 currentMarkup()));
3213     else
3214       eventHandler().linkDecl(new (eventAllocator())
3215                               LinkDeclEvent(linkSet,
3216                                             defComplexLpdPointer(),
3217                                             markupLocation(),
3218                                             currentMarkup()));
3219   }
3220   return 1;
3221 }
3222
3223 void Parser::addIdLinkRule(const StringC &id,
3224                            IdLinkRule &rule)
3225 {
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);
3233 }
3234
3235 void Parser::addLinkRule(LinkSet *linkSet,
3236                          const ElementType *sourceElement,
3237                          const ConstPtr<SourceLinkRuleResource> &linkRule)
3238 {
3239   size_t nRules = linkSet->nLinkRules(sourceElement);
3240   if ((nRules == 1
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);
3246 }
3247
3248 class ResultAttributeSpecModeSetter {
3249 public:
3250   ResultAttributeSpecModeSetter(ParserState *state) : state_(state) {
3251     state_->setResultAttributeSpecMode();
3252   }
3253   ~ResultAttributeSpecModeSetter() { clear(); }
3254   void clear() {
3255     if (state_) {
3256       state_->clearResultAttributeSpecMode();
3257       state_ = 0;
3258     }
3259   }
3260 private:
3261   ParserState *state_;
3262 };
3263
3264 Boolean Parser::parseResultElementSpec(unsigned declInputLevel,
3265                                        Param &parm,
3266                                        Boolean idlink,
3267                                        Boolean &implied,
3268                                        const ElementType *&resultType,
3269                                        AttributeList &attributes)
3270 {
3271   if (parm.type == Param::indicatedReservedName + Syntax::rIMPLIED) {
3272     if (!parseParam(idlink ? allowNameMdc : allowExplicitLinkRuleMdc,
3273                     declInputLevel, parm))
3274       return 0;
3275     implied = 1;
3276   }
3277   else {
3278     implied = 0;
3279     ElementType *e = lookupResultElementType(parm.token);
3280     resultType = e;
3281     static AllowedParams
3282       allow(Param::dso,
3283             Param::mdc,
3284             Param::name,
3285             Param::nameGroup,
3286             Param::indicatedReservedName + Syntax::rIMPLIED);
3287     static AllowedParams
3288       allowNameDsoMdc(Param::dso,
3289                       Param::mdc,
3290                       Param::name);
3291     if (!parseParam(idlink ? allowNameDsoMdc : allow,
3292                     declInputLevel, parm))
3293       return 0;
3294     ConstPtr<AttributeDefinitionList> attDef;
3295     if (e)
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))
3303         return 0;
3304       if (!newAttDef.isNull()) {
3305         Ptr<Dtd> r(defComplexLpd().resultDtd());
3306         if (!r.isNull()) {
3307           newAttDef->setIndex(r->allocAttributeDefinitionListIndex());
3308           if (e)
3309             e->setAttributeDef(newAttDef);
3310         }
3311       }
3312       modeSetter.clear();
3313       if (attributes.nSpec() == 0)
3314         message(ParserMessages::emptyResultAttributeSpec);
3315       if (!parseParam(idlink ? allowNameMdc : allowExplicitLinkRuleMdc,
3316                       declInputLevel, parm))
3317         return 0;
3318     }
3319     else {
3320       // For entity and notation attributes.
3321       ResultAttributeSpecModeSetter modeSetter(this);
3322       attributes.finish(*this);
3323       modeSetter.clear();
3324     }
3325   }
3326   return 1;
3327 }
3328
3329 ElementType *Parser::lookupResultElementType(const StringC &name)
3330 {
3331   Dtd *dtd = defComplexLpd().resultDtd().pointer();
3332   if (!dtd)
3333     return 0;
3334   ElementType *e = dtd->lookupElementType(name);
3335   if (!e)
3336     message(ParserMessages::noSuchResultElement, StringMessageArg(name));
3337   return e;
3338 }
3339
3340 Boolean Parser::parseUselinkDecl()
3341 {
3342   unsigned declInputLevel = inputLevel();
3343   Param parm;
3344   if (!parseParam(allowLinkSetSpec, declInputLevel, parm))
3345     return 0;
3346   Param parm2;
3347   if (!parseParam(allowName, declInputLevel, parm2))
3348     return 0;
3349   StringC linkType;
3350   parm2.token.swap(linkType);
3351   if (!parseParam(allowMdc, declInputLevel, parm2))
3352     return 0;
3353   ConstPtr<Lpd> lpd = lookupLpd(linkType);
3354   if (lpd.isNull()) 
3355     message(ParserMessages::uselinkBadLinkType, StringMessageArg(linkType));
3356   else if (lpd->type() == Lpd::simpleLink)
3357     message(ParserMessages::uselinkSimpleLpd, StringMessageArg(linkType));
3358   else {
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);
3364       if (!linkSet) {
3365         message(ParserMessages::uselinkBadLinkSet,
3366                 StringMessageArg(complexLpd->name()),
3367                 StringMessageArg(parm.token));
3368         return 1;
3369       }
3370     }
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();
3375     else {
3376       linkSet = 0;
3377       restore = 1;
3378     }
3379     if (lpd->active())
3380       eventHandler().uselink(new (eventAllocator())
3381                              UselinkEvent(lpd, linkSet,
3382                                           restore, markupLocation(),
3383                                           currentMarkup()));
3384     else
3385       eventHandler().ignoredMarkup(new (eventAllocator())
3386                                    IgnoredMarkupEvent(markupLocation(),
3387                                                       currentMarkup()));
3388   }
3389   return 1;
3390 }
3391
3392 LinkSet *Parser::lookupCreateLinkSet(const StringC &name)
3393 {
3394   LinkSet *linkSet = defComplexLpd().lookupLinkSet(name);
3395   if (!linkSet) {
3396     linkSet = new LinkSet(name, defComplexLpd().sourceDtd().pointer());
3397     defComplexLpd().insertLinkSet(linkSet);
3398   }
3399   return linkSet;
3400 }
3401
3402 Boolean Parser::parseMarkedSectionDeclStart()
3403 {
3404   if (markedSectionLevel() == syntax().taglvl())
3405     message(ParserMessages::markedSectionLevel,
3406             NumberMessageArg(syntax().taglvl()));
3407   if (!inInstance()
3408       && options().warnInternalSubsetMarkedSection
3409       && inputLevel() == 1)
3410     message(ParserMessages::internalSubsetMarkedSection);
3411   if (markedSectionSpecialLevel() > 0) {
3412     startMarkedSection(markupLocation());
3413     if (inInstance()
3414         ? eventsWanted().wantMarkedSections()
3415         : eventsWanted().wantPrologMarkup())
3416       eventHandler().ignoredChars(new (eventAllocator())
3417                                   IgnoredCharsEvent(currentInput()->currentTokenStart(),
3418                                                     currentInput()->currentTokenLength(),
3419                                                     currentLocation(),
3420                                                     0));
3421                                   
3422     return 1;
3423   }
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);
3431     discardMarkup = 0;
3432   }
3433   else if (options().warnInstanceStatusKeywordSpecS && inInstance()) {
3434     startMarkup(1, currentLocation());
3435     discardMarkup = 1;
3436   }
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);
3444   Param parm;
3445   MarkedSectionEvent::Status status = MarkedSectionEvent::include;
3446   if (!parseParam(allowStatusDso, declInputLevel, parm))
3447     return 0;
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;
3455       break;
3456     case Param::reservedName + Syntax::rRCDATA:
3457       if (status < MarkedSectionEvent::rcdata)
3458         status = MarkedSectionEvent::rcdata;
3459       if (options().warnRcdataMarkedSection)
3460         message(ParserMessages::rcdataMarkedSection);
3461       break;
3462     case Param::reservedName + Syntax::rIGNORE:
3463       if (status < MarkedSectionEvent::ignore)
3464         status = MarkedSectionEvent::ignore;
3465       if (inInstance() && options().warnInstanceIgnoreMarkedSection)
3466         message(ParserMessages::instanceIgnoreMarkedSection);
3467       break;
3468     case Param::reservedName + Syntax::rINCLUDE:
3469       if (inInstance() && options().warnInstanceIncludeMarkedSection)
3470         message(ParserMessages::instanceIncludeMarkedSection);
3471       break;
3472     case Param::reservedName + Syntax::rTEMP:
3473       if (options().warnTempMarkedSection)
3474         message(ParserMessages::tempMarkedSection);
3475       break;
3476     }
3477     if (!parseParam(allowStatusDso, declInputLevel, parm))
3478       return 0;
3479     if (options().warnMultipleStatusKeyword
3480         && parm.type != Param::dso)
3481       message(ParserMessages::multipleStatusKeyword);
3482   }
3483   // FIXME this disallows
3484   // <!entity % e "include [ stuff ">
3485   // ...
3486   // <![ %e; ]]>
3487   // which I think is legal.
3488
3489   if (inputLevel() > declInputLevel)
3490     message(ParserMessages::parameterEntityNotEnded);
3491   switch (status) {
3492   case MarkedSectionEvent::include:
3493     startMarkedSection(markupLocation());
3494     break;
3495   case MarkedSectionEvent::cdata:
3496     startSpecialMarkedSection(cmsMode, markupLocation());
3497     break;
3498   case MarkedSectionEvent::rcdata:
3499     startSpecialMarkedSection(rcmsMode, markupLocation());
3500     break;
3501   case MarkedSectionEvent::ignore:
3502     startSpecialMarkedSection(imsMode, markupLocation());
3503     break;
3504   }
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);
3512         }
3513       }
3514       if (discardMarkup)
3515         startMarkup(0, markupLocation());
3516     }
3517     eventHandler().markedSectionStart(new (eventAllocator())
3518                                       MarkedSectionStartEvent(status,
3519                                                               markupLocation(),
3520                                                               currentMarkup()));
3521   }
3522   return 1;
3523 }
3524
3525 void Parser::handleMarkedSectionEnd()
3526 {
3527   if (markedSectionLevel() == 0)
3528     message(ParserMessages::markedSectionEnd);
3529   else {
3530     if (inInstance()
3531         ? eventsWanted().wantMarkedSections()
3532         : eventsWanted().wantPrologMarkup()) {
3533       if (markedSectionSpecialLevel() > 1)
3534         eventHandler().ignoredChars(new (eventAllocator())
3535                                     IgnoredCharsEvent(currentInput()->currentTokenStart(),
3536                                                       currentInput()->currentTokenLength(),
3537                                                       currentLocation(),
3538                                                       0));
3539       else {
3540         MarkedSectionEvent::Status status;
3541         switch (currentMode()) {
3542         case cmsMode:
3543           status = MarkedSectionEvent::cdata;
3544           break;
3545         case rcmsMode:
3546           status = MarkedSectionEvent::rcdata;
3547           break;
3548         case imsMode:
3549           status = MarkedSectionEvent::ignore;
3550           break;
3551         default:
3552           status = MarkedSectionEvent::include;
3553           break;
3554         }
3555         startMarkup(1, currentLocation());
3556         currentMarkup()->addDelim(Syntax::dMSC);
3557         currentMarkup()->addDelim(Syntax::dMDC);
3558         eventHandler().markedSectionEnd(new (eventAllocator())
3559                                         MarkedSectionEndEvent(status,
3560                                                               markupLocation(),
3561                                                               currentMarkup()));
3562       }
3563     }
3564     endMarkedSection();
3565   }
3566 }
3567
3568 void Parser::emptyCommentDecl()
3569 {
3570   if (startMarkup(eventsWanted().wantCommentDecls(), currentLocation())) {
3571     currentMarkup()->addDelim(Syntax::dMDO);
3572     currentMarkup()->addDelim(Syntax::dMDC);
3573     eventHandler().commentDecl(new (eventAllocator())
3574                                CommentDeclEvent(markupLocation(),
3575                                                 currentMarkup()));
3576   }
3577   if (options().warnEmptyCommentDecl)
3578     message(ParserMessages::emptyCommentDecl);
3579 }
3580
3581 Boolean Parser::parseCommentDecl()
3582 {
3583   if (startMarkup(inInstance()
3584                   ? eventsWanted().wantCommentDecls()
3585                   : eventsWanted().wantPrologMarkup(),
3586                   currentLocation()))
3587     currentMarkup()->addDelim(Syntax::dMDO);
3588   if (!parseComment(comMode))
3589     return 0;
3590   for (;;) {
3591     Token token = getToken(mdMode);
3592     switch (token) {
3593     case tokenS:
3594       if (currentMarkup())
3595         currentMarkup()->addS(currentChar());
3596       if (options().warnCommentDeclS)
3597         message(ParserMessages::commentDeclS);
3598       break;
3599     case tokenCom:
3600       if (!parseComment(comMode))
3601         return 0;
3602       if (options().warnCommentDeclMultiple)
3603         message(ParserMessages::commentDeclMultiple);
3604       break;
3605     case tokenMdc:
3606       if (currentMarkup())
3607         currentMarkup()->addDelim(Syntax::dMDC);
3608       goto done;
3609     case tokenEe:
3610       message(ParserMessages::declarationLevel);
3611       return 0;
3612     case tokenUnrecognized:
3613       if (reportNonSgmlCharacter())
3614         break;
3615       // braces to work round Sun C++ 4.0 bug
3616       {
3617         message(ParserMessages::commentDeclarationCharacter,
3618                 StringMessageArg(currentToken()),
3619                 markupLocation());
3620       }
3621       return 0;
3622     default:
3623       // braces to work round Sun C++ 4.0 bug
3624       {
3625         message(ParserMessages::commentDeclInvalidToken,
3626                 TokenMessageArg(token, mdMode, syntaxPointer(), sdPointer()),
3627                 markupLocation());
3628       }
3629       return 0;
3630     }
3631   }
3632  done:
3633   if (currentMarkup())
3634     eventHandler().commentDecl(new (eventAllocator())
3635                                CommentDeclEvent(markupLocation(),
3636                                                 currentMarkup()));
3637   return 1;
3638 }
3639
3640 Boolean Parser::parseAfdrDecl()
3641 {
3642   unsigned declInputLevel = inputLevel();
3643   static AllowedParams allowMinimumLiteral(Param::minimumLiteral);
3644   Param parm;
3645   setHadAfdrDecl();
3646   if (!parseParam(allowMinimumLiteral, declInputLevel, parm))
3647     return 0;
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))
3652     return 0;
3653   eventHandler().ignoredMarkup(new (eventAllocator())
3654                                IgnoredMarkupEvent(markupLocation(),
3655                                                   currentMarkup()));
3656   return 1;
3657 }
3658
3659 #ifdef SP_NAMESPACE
3660 }
3661 #endif