xref: /onnv-gate/usr/src/cmd/man/src/util/nsgmls.src/lib/ParserState.cxx (revision 0:68f95e015346)
1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3 #pragma ident	"%Z%%M%	%I%	%E% SMI"
4 
5 #ifdef __GNUG__
6 #pragma implementation
7 #endif
8 #include "splib.h"
9 #include "ParserState.h"
10 #include "InternalInputSource.h"
11 #include "MessageArg.h"
12 #include "macros.h"
13 #include "SgmlParser.h"
14 #include "IListIter.h"
15 #include "ParserMessages.h"
16 #include "Undo.h"
17 #include "Trie.h"
18 
19 #ifdef SP_NAMESPACE
20 namespace SP_NAMESPACE {
21 #endif
22 
23 const Location ParserState::nullLocation_;
24 sig_atomic_t ParserState::dummyCancel_ = 0;
25 
26 static const size_t eventSizes[] = {
27 #define EVENT(c, f) sizeof(c),
28 #include "events.h"
29 #undef EVENT
30 };
31 
32 static const size_t internalSizes[] = {
33   sizeof(InternalInputSource),
34   sizeof(OpenElement),
35   sizeof(UndoStartTag),
36   sizeof(UndoEndTag),
37   sizeof(UndoTransition)
38 };
39 
40 static
maxSize(const size_t * v,size_t n,size_t max=0)41 size_t maxSize(const size_t *v, size_t n, size_t max = 0)
42 {
43   for (size_t i = 0; i < n; i++) {
44     if (v[i] > max)
45       max = v[i];
46   }
47   return max;
48 }
49 
ParserState(const Ptr<EntityManager> & em,const ParserOptions & opt,unsigned subdocLevel,Phase finalPhase)50 ParserState::ParserState(const Ptr<EntityManager> &em,
51 			 const ParserOptions &opt,
52 			 unsigned subdocLevel,
53 			 Phase finalPhase)
54 : entityManager_(em),
55   options_(opt),
56   inInstance_(0),
57   keepingMessages_(0),
58   eventAllocator_(maxSize(eventSizes, SIZEOF(eventSizes)), 50),
59   internalAllocator_(maxSize(internalSizes, SIZEOF(internalSizes), EntityOrigin::allocSize), 50),
60   handler_(&eventQueue_),
61   subdocLevel_(subdocLevel),
62   inputLevel_(0),
63   specialParseInputLevel_(0),
64   markedSectionLevel_(0),
65   markedSectionSpecialLevel_(0),
66   currentMode_(proMode),
67   hadLpd_(0),
68   resultAttributeSpecMode_(0),
69   pass2_(0),
70   activeLinkTypesSubsted_(0),
71   allowPass2_(0),
72   hadPass2Start_(0),
73   pcdataRecovering_(0),
74   currentMarkup_(0),
75   cancelPtr_(&dummyCancel_),
76   finalPhase_(finalPhase),
77   hadAfdrDecl_(0)
78 {
79 }
80 
inheritActiveLinkTypes(const ParserState & parent)81 void ParserState::inheritActiveLinkTypes(const ParserState &parent)
82 {
83   activeLinkTypes_ = parent.activeLinkTypes_;
84   activeLinkTypesSubsted_ = parent.activeLinkTypesSubsted_;
85 }
86 
allDone()87 void ParserState::allDone()
88 {
89   phase_ = noPhase;
90 }
91 
setPass2Start()92 void ParserState::setPass2Start()
93 {
94   ASSERT(inputLevel_ == 1);
95   if (hadPass2Start_)
96     return;
97   hadPass2Start_ = 1;
98   if (!pass2() && sd().link() && activeLinkTypes_.size() > 0) {
99     allowPass2_ = 1;
100     pass1Handler_.init(handler_);
101     handler_ = &pass1Handler_;
102     const InputSourceOrigin *p
103       = currentLocation().origin()->asInputSourceOrigin();
104     pass2StartOffset_= p->startOffset(currentLocation().index());
105   }
106   else {
107     allowPass2_ = 0;
108     currentInput()->willNotRewind();
109   }
110 }
111 
allLinkTypesActivated()112 void ParserState::allLinkTypesActivated()
113 {
114   if (activeLinkTypes_.size() == 0 && inputLevel_ == 1)
115     currentInput()->willNotRewind();
116 }
117 
maybeStartPass2()118 Boolean ParserState::maybeStartPass2()
119 {
120   if (pass2_ || !allowPass2_)
121     return 0;
122   handler_ = pass1Handler_.origHandler();
123   if (!nActiveLink() || pass1Handler_.hadError()) {
124     while (!pass1Handler_.empty()) {
125       if (cancelled())
126 	return 0;
127       pass1Handler_.get()->handle(*handler_);
128     }
129     InputSource *top = 0;
130     for (IListIter<InputSource> iter(inputStack_);
131 	 !iter.done();
132 	 iter.next())
133       top = iter.cur();
134     if (top)
135       top->willNotRewind();
136     return 0;
137   }
138   pass1Handler_.clear();
139   while (inputLevel_ > 1) {
140     InputSource *p = inputStack_.get();
141     inputLevel_--;
142     delete p;
143   }
144   // Caller will call allDone() if inputLevel_ is 0.
145   if (inputLevel_ == 0)
146     return 0;
147   if (!inputStack_.head()->rewind(*this)) {
148     inputLevel_ = 0;
149     delete inputStack_.get();
150     return 0;
151   }
152   inputStack_.head()->willNotRewind();
153   for (; pass2StartOffset_ > 0; pass2StartOffset_--)
154     if (inputStack_.head()->get(messenger()) == InputSource::eE) {
155       message(ParserMessages::pass2Ee);
156       inputLevel_ = 0;
157       delete inputStack_.get();
158       return 0;
159     }
160   specialParseInputLevel_ = 0;
161   markedSectionLevel_ = 0;
162   markedSectionSpecialLevel_ = 0;
163   currentMode_ = proMode;
164   hadLpd_ = 0;
165   allowPass2_ = 0;
166   hadPass2Start_ = 0;
167   currentMarkup_ = 0;
168   inputLevel_ = 1;
169   inInstance_ = 0;
170   defDtd_.clear();
171   defLpd_.clear();
172   dtd_[0].swap(pass1Dtd_);
173   dtd_.clear();
174   dsEntity_.clear();
175   currentDtd_.clear();
176   currentDtdConst_.clear();
177   phase_ = noPhase;
178   pass2_ = 1;
179   lpd_.clear();
180   allLpd_.clear();
181   return 1;
182 }
183 
referenceDsEntity(const Location & loc)184 Boolean ParserState::referenceDsEntity(const Location &loc)
185 {
186   if (dsEntity_.isNull())
187     return 0;
188   Ptr<EntityOrigin> origin
189     = EntityOrigin::make(internalAllocator(), dsEntity_, loc);
190   dsEntity_->dsReference(*this, origin);
191   dsEntity_.clear();
192   return inputLevel() > 1;
193 }
194 
startDtd(const StringC & name)195 void ParserState::startDtd(const StringC &name)
196 {
197   defDtd_ = new Dtd(name, dtd_.size() == 0);
198   defLpd_.clear();
199   for (size_t i = 0; i < options().includes.size(); i++) {
200     StringC name = options().includes[i];
201     const SubstTable<Char> *subst = syntax().entitySubstTable();
202     for (size_t j = 0; j < name.size(); j++)
203       subst->subst(name[j]);
204     Text text;
205     text.addChars(syntax().reservedName(Syntax::rINCLUDE), Location());
206     Entity *entity
207       = new InternalTextEntity(name,
208 			       Entity::parameterEntity,
209 			       Location(),
210 			       text,
211 			       InternalTextEntity::none);
212     entity->setUsed();
213     defDtd_->insertEntity(entity);
214   }
215   size_t nEntities = instanceSyntax_->nEntities();
216   for (size_t i = 0; i < nEntities; i++) {
217     Text text;
218     text.addChar(instanceSyntax_->entityChar(i), Location());
219     Entity *entity
220       = new InternalCdataEntity(instanceSyntax_->entityName(i),
221 				Location(),
222 				text);
223     defDtd_->insertEntity(entity);
224   }
225   currentDtd_ = defDtd_;
226   currentDtdConst_ = defDtd_;
227   currentMode_ = dsMode;
228 }
229 
endDtd()230 void ParserState::endDtd()
231 {
232   dtd_.push_back(defDtd_);
233   defDtd_.clear();
234   currentDtd_.clear();
235   currentDtdConst_.clear();
236   currentMode_ = proMode;
237 }
238 
startLpd(Ptr<Lpd> & lpd)239 void ParserState::startLpd(Ptr<Lpd> &lpd)
240 {
241   defLpd_ = lpd;
242   defDtd_ = defLpd_->sourceDtd();
243   currentDtd_ = defLpd_->sourceDtd();
244   currentDtdConst_ = defLpd_->sourceDtd();
245   currentMode_ = dsMode;
246 }
247 
endLpd()248 void ParserState::endLpd()
249 {
250   hadLpd_ = 1;
251   if (defLpd_->active())
252     lpd_.push_back(defLpd_);
253   allLpd_.push_back(defLpd_);
254   defLpd_.clear();
255   currentDtd_.clear();
256   currentDtdConst_.clear();
257   currentMode_ = proMode;
258 }
259 
popInputStack()260 void ParserState::popInputStack()
261 {
262   ASSERT(inputLevel_ > 0);
263   InputSource *p = inputStack_.get();
264   inputLevel_--;
265   delete p;
266   if (specialParseInputLevel_ > 0 && inputLevel_ == specialParseInputLevel_)
267     currentMode_ = specialParseMode_;
268   if (currentMode_ == dsiMode
269       && inputLevel_ == 1
270       && markedSectionLevel_ == 0)
271     currentMode_ = dsMode;
272   if (inputLevelElementIndex_.size())
273     inputLevelElementIndex_.resize(inputLevelElementIndex_.size() - 1);
274 }
275 
setSd(ConstPtr<Sd> sd)276 void ParserState::setSd(ConstPtr<Sd> sd)
277 {
278   sd_ = sd;
279   mayDefaultAttribute_ = (sd_->omittag() || sd_->attributeDefault());
280   validate_ = sd_->typeValid();
281   implydefElement_ = sd_->implydefElement();
282   implydefAttlist_ = sd_->implydefAttlist();
283 }
284 
setSyntax(ConstPtr<Syntax> syntax)285 void ParserState::setSyntax(ConstPtr<Syntax> syntax)
286 {
287   syntax_ = syntax;
288   prologSyntax_ = syntax;
289   instanceSyntax_ = syntax;
290 }
291 
setSyntaxes(ConstPtr<Syntax> prologSyntax,ConstPtr<Syntax> instanceSyntax)292 void ParserState::setSyntaxes(ConstPtr<Syntax> prologSyntax,
293 			      ConstPtr<Syntax> instanceSyntax)
294 {
295   syntax_ = prologSyntax;
296   prologSyntax_ = prologSyntax;
297   instanceSyntax_ = instanceSyntax;
298 }
299 
pushInput(InputSource * in)300 void ParserState::pushInput(InputSource *in)
301 {
302   if (!in)
303     return;
304   if (!syntax_.isNull() && syntax_->multicode())
305     in->setMarkupScanTable(syntax_->markupScanTable());
306   inputStack_.insert(in);
307   inputLevel_++;
308   if (specialParseInputLevel_ > 0 && inputLevel_ > specialParseInputLevel_)
309     currentMode_ = rcconeMode;	// mode for rcdata in an entity
310   else if (currentMode_ == dsMode)
311     currentMode_ = dsiMode;
312   if (inInstance_ && sd().integrallyStored())
313     inputLevelElementIndex_.push_back(tagLevel() ? currentElement().index() : 0);
314 }
315 
startMarkedSection(const Location & loc)316 void ParserState::startMarkedSection(const Location &loc)
317 {
318   markedSectionLevel_++;
319   markedSectionStartLocation_.push_back(loc);
320   if (currentMode_ == dsMode)
321     currentMode_ = dsiMode;
322   if (markedSectionSpecialLevel_)
323     markedSectionSpecialLevel_++;
324 }
325 
startSpecialMarkedSection(Mode mode,const Location & loc)326 void ParserState::startSpecialMarkedSection(Mode mode, const Location &loc)
327 {
328   markedSectionLevel_++;
329   markedSectionStartLocation_.push_back(loc);
330   specialParseInputLevel_ = inputLevel_;
331   markedSectionSpecialLevel_ = 1;
332   specialParseMode_ = currentMode_ = mode;
333 }
334 
endMarkedSection()335 void ParserState::endMarkedSection()
336 {
337   ASSERT(markedSectionLevel_ > 0);
338   markedSectionLevel_--;
339   markedSectionStartLocation_.resize(markedSectionStartLocation_.size()
340 					- 1);
341   if (markedSectionSpecialLevel_ > 0) {
342     markedSectionSpecialLevel_--;
343     if (markedSectionSpecialLevel_ > 0)
344       return;			// remain in imsMode
345     specialParseInputLevel_ = 0;
346     if (inInstance_)
347       currentMode_ = contentMode();
348     else
349       currentMode_ = dsiMode;
350   }
351   if (currentMode_ == dsiMode
352       && inputLevel_ == 1
353       && markedSectionLevel_ == 0)
354     currentMode_ = dsMode;
355 }
356 
pushElement(OpenElement * e)357 void ParserState::pushElement(OpenElement *e)
358 {
359   ContentState::pushElement(e);
360   pcdataRecovering_ = 0;
361   // the start tag of this element may have been implied by data
362   // inside a cdata or rcdata marked section
363   if (markedSectionSpecialLevel_ == 0) {
364     currentMode_ = contentMode();
365     if (e->requiresSpecialParse()) {
366       specialParseMode_ = currentMode_;
367       specialParseInputLevel_ = inputLevel_;
368     }
369   }
370 }
371 
372 // PCDATA was encountered somewhere where it was not allowed.
373 // Change the current mode to improve recovery.
374 
pcdataRecover()375 void ParserState::pcdataRecover()
376 {
377   switch (currentMode_) {
378   case econMode:
379     currentMode_ = mconMode;
380     break;
381   case econnetMode:
382     currentMode_ = mconnetMode;
383     break;
384   default:
385     break;
386   }
387   pcdataRecovering_ = 1;
388 }
389 
popSaveElement()390 OpenElement *ParserState::popSaveElement()
391 {
392   OpenElement *e = ContentState::popSaveElement();
393   // the end tag of this element may have been implied by data
394   // inside a cdata or rcdata marked section
395   if (markedSectionSpecialLevel_ == 0) {
396     currentMode_ = contentMode();
397     specialParseInputLevel_ = 0;
398   }
399   pcdataRecovering_ = 0;
400   return e;
401 }
402 
popElement()403 void ParserState::popElement()
404 {
405   delete popSaveElement();
406 }
407 
entityIsOpen(const Entity * entity) const408 Boolean ParserState::entityIsOpen(const Entity *entity) const
409 {
410   for (IListIter<InputSource> iter(inputStack_); !iter.done(); iter.next()) {
411     const EntityOrigin *eo
412       = iter.cur()->currentLocation().origin()->asEntityOrigin();
413     if (eo && eo->entity() == entity)
414       return 1;
415   }
416   return 0;
417 }
418 
startInstance()419 void ParserState::startInstance()
420 {
421   if (!instanceSyntax_.isNull())
422     syntax_ = instanceSyntax_;
423   currentMode_ = econMode;
424   currentDtd_ = dtd_[0];
425   currentDtdConst_ = dtd_[0];
426   startContent(currentDtd());
427   inInstance_ = 1;
428   if (sd().rank())
429     currentRank_.assign(currentDtd().nRankStem(), StringC());
430   currentAttributes_.clear();
431   currentAttributes_.resize(currentDtd().nCurrentAttribute());
432   idTable_.clear();
433 }
434 
lookupCreateId(const StringC & name)435 Id *ParserState::lookupCreateId(const StringC &name)
436 {
437   Id *id = idTable_.lookup(name);
438   if (!id) {
439     id = new Id(name);
440     idTable_.insert(id);
441   }
442   return id;
443 }
444 
445 ConstPtr<Entity>
lookupEntity(Boolean isParameter,const StringC & name,const Location & useLocation,Boolean referenced)446 ParserState::lookupEntity(Boolean isParameter,
447 			  const StringC &name,
448 			  const Location &useLocation,
449 			  Boolean referenced)
450 {
451   Dtd *dtd;
452   if (resultAttributeSpecMode_)
453     dtd = defComplexLpd().resultDtd().pointer();
454   else
455     dtd = currentDtd_.pointer();
456   if (dtd) {
457     Ptr<Entity> entity(dtd->lookupEntity(isParameter, name));
458     // Did we find it in pass1Dtd?
459     // Did we look at the defaultEntity?
460     if (!inInstance_ && pass2() && dtd->isBase()
461 	&& !resultAttributeSpecMode_
462 	&& (entity.isNull() || !entity->declInActiveLpd())) {
463       ConstPtr<Entity> entity1
464 	= pass1Dtd_->lookupEntity(isParameter, name);
465       if (!entity1.isNull() && entity1->declInActiveLpd()
466 	  && !entity1->defaulted()) {
467 	if (referenced)
468 	  noteReferencedEntity(entity1, 1, 0);
469 	return entity1;
470       }
471       else if (!entity.isNull()) {
472 	if (referenced)
473 	  noteReferencedEntity(entity, 0, 0);
474 	entity->setUsed();
475 	return entity;
476       }
477     }
478     else if (!entity.isNull()) {
479       entity->setUsed();
480       return entity;
481     }
482     if (!isParameter) {
483       ConstPtr<Entity> entity(dtd->defaultEntity());
484       Boolean note = 0;
485       Boolean usedPass1 = 0;
486       if (!inInstance_ && pass2() && dtd->isBase()
487 	  && !resultAttributeSpecMode_
488 	  && (entity.isNull() || !entity->declInActiveLpd())) {
489 	if (referenced)
490 	  note = 1;
491 	ConstPtr<Entity> entity1 = pass1Dtd_->defaultEntity();
492 	if (!entity1.isNull() && entity1->declInActiveLpd()) {
493 	  usedPass1 = 1;
494 	  entity = entity1;
495 	}
496       }
497       if (!entity.isNull()) {
498 	Boolean mustCopy = 1;
499 	if (inInstance_) {
500 	  ConstPtr<Entity> tem
501 	    = instanceDefaultedEntityTable_.lookupConst(name);
502 	  if (!tem.isNull()) {
503 	    entity = tem;
504 	    mustCopy = 0;
505 	  }
506 	}
507 	if (mustCopy) {
508 	  Ptr<Entity> p(entity->copy());
509 	  p->setName(name);
510 	  p->generateSystemId(*this);
511 	  p->setDefaulted();
512 	  entity = p;
513 	  if (inInstance_) {
514 	    instanceDefaultedEntityTable_.insert(p);
515 	    eventHandler().entityDefaulted(new (eventAllocator())
516 					   EntityDefaultedEvent(entity,
517 								useLocation));
518 	  }
519 	  else
520 	    dtd->insertEntity(p);
521 	}
522 	if (note)
523 	  noteReferencedEntity(entity, usedPass1, 1);
524       }
525       else
526 	entity = undefinedEntityTable_.lookupConst(name);
527       return entity;
528     }
529   }
530   return (Entity *)0;
531 }
532 
createUndefinedEntity(const StringC & name,const Location & loc)533 ConstPtr<Entity> ParserState::createUndefinedEntity(const StringC &name, const Location &loc)
534 {
535   Text text;
536   Ptr<Entity> entity(new InternalCdataEntity(name, loc, text));
537   undefinedEntityTable_.insert(entity);
538   return entity;
539 }
540 
noteReferencedEntity(const ConstPtr<Entity> & entity,Boolean foundInPass1Dtd,Boolean lookedAtDefault)541 void ParserState::noteReferencedEntity(const ConstPtr<Entity> &entity,
542 				       Boolean foundInPass1Dtd,
543 				       Boolean lookedAtDefault)
544 {
545   LpdEntityRef ref;
546   ref.entity = entity;
547   ref.lookedAtDefault = lookedAtDefault;
548   ref.foundInPass1Dtd = foundInPass1Dtd;
549   LpdEntityRef *old = lpdEntityRefs_.lookup(ref);
550   if (!old)
551     lpdEntityRefs_.insert(new LpdEntityRef(ref));
552 }
553 
554 // Compare entity definitions.
555 // e1 is the original (will not be an external non-text entity).
556 // FIXME should look at generated sysids as well.
557 static
sameEntityDef(const Entity * e1,const Entity * e2)558 Boolean sameEntityDef(const Entity *e1, const Entity *e2)
559 {
560   if (e1->dataType() != e2->dataType())
561     return 0;
562   const InternalEntity *i1 = e1->asInternalEntity();
563   const InternalEntity *i2 = e2->asInternalEntity();
564   if (i1) {
565     if (!i2)
566       return 0;
567     if (i1->string() != i2->string())
568       return 0;
569     return 1;
570   }
571   else if (i2)
572     return 0;
573   const ExternalEntity *x1 = e1->asExternalEntity();
574   const ExternalEntity *x2 = e2->asExternalEntity();
575   const StringC *s1 = x1->externalId().systemIdString();
576   const StringC *s2 = x2->externalId().systemIdString();
577   if (s1) {
578     if (!s2)
579       return 0;
580     if (*s1 != *s2)
581       return 0;
582   }
583   else if (s2)
584     return 0;
585   s1 = x1->externalId().publicIdString();
586   s2 = x2->externalId().publicIdString();
587   if (s1) {
588     if (!s2)
589       return 0;
590     if (*s1 != *s2)
591       return 0;
592   }
593   else if (s2)
594     return 0;
595   return 1;
596 }
597 
checkEntityStability()598 void ParserState::checkEntityStability()
599 {
600   LpdEntityRefSetIter iter(lpdEntityRefs_);
601   LpdEntityRef *ref;
602   while ((ref = iter.next()) != 0) {
603     ConstPtr<Entity> entity
604       = dtd_[0]->lookupEntity(ref->entity->declType()
605 			      == Entity::parameterEntity,
606 			      ref->entity->name());
607     if (entity.isNull() && ref->lookedAtDefault)
608       entity = dtd_[0]->defaultEntity();
609     if (entity.isNull()
610 	? ref->foundInPass1Dtd
611 	: !sameEntityDef(ref->entity.pointer(), entity.pointer()))
612       message(((ref->entity->declType()
613 		== Entity::parameterEntity)
614 	       ? ParserMessages::unstableLpdParameterEntity
615 	       : ParserMessages::unstableLpdGeneralEntity),
616 	      StringMessageArg(ref->entity->name()));
617   }
618   {
619     // Ensure that the memory is released.
620     LpdEntityRefSet tem;
621     lpdEntityRefs_.swap(tem);
622   }
623 }
624 
appendCurrentRank(StringC & str,const RankStem * stem) const625 Boolean ParserState::appendCurrentRank(StringC &str, const RankStem *stem)
626      const
627 {
628   const StringC &suffix = currentRank_[stem->index()];
629   if (suffix.size() > 0) {
630     str += suffix;
631     return 1;
632   }
633   return 0;
634 }
635 
setCurrentRank(const RankStem * stem,const StringC & suffix)636 void ParserState::setCurrentRank(const RankStem *stem, const StringC &suffix)
637 {
638   currentRank_[stem->index()] = suffix;
639 }
640 
getCurrentToken(const SubstTable<Char> * subst,StringC & str) const641 void ParserState::getCurrentToken(const SubstTable<Char> *subst,
642 				  StringC &str) const
643 {
644   InputSource *in = currentInput();
645   const Char *p = in->currentTokenStart();
646   size_t count = in->currentTokenLength();
647   str.resize(count);
648   StringC::iterator s = str.begin();
649   for (; count > 0; --count)
650     *s++ = (*subst)[*p++];
651 }
652 
queueMessage(MessageEvent * event)653 void ParserState::queueMessage(MessageEvent *event)
654 {
655   if (cancelled()) {
656     delete event;
657     return;
658   }
659   if (keepingMessages_)
660     keptMessages_.append(event);
661   else
662     handler_->message(event);
663 }
664 
releaseKeptMessages()665 void ParserState::releaseKeptMessages()
666 {
667   keepingMessages_ = 0;
668   while (!keptMessages_.empty()) {
669     if (cancelled()) {
670       allDone();
671       return;
672     }
673     handler_->message(keptMessages_.get());
674   }
675 }
676 
discardKeptMessages()677 void ParserState::discardKeptMessages()
678 {
679   keepingMessages_ = 0;
680   keptMessages_.clear();
681 }
682 
initMessage(Message & msg)683 void ParserState::initMessage(Message &msg)
684 {
685   if (inInstance()) {
686     StringC rniPcdata = syntax().delimGeneral(Syntax::dRNI);
687     rniPcdata += syntax().reservedName(Syntax::rPCDATA);
688     getOpenElementInfo(msg.openElementInfo, rniPcdata);
689   }
690   msg.loc = currentLocation();
691 }
692 
dispatchMessage(Message & msg)693 void ParserState::dispatchMessage(Message &msg)
694 {
695   queueMessage(new MessageEvent(msg));
696 }
697 
dispatchMessage(const Message & msg)698 void ParserState::dispatchMessage(const Message &msg)
699 {
700   queueMessage(new MessageEvent(msg));
701 }
702 
703 AttributeList *
allocAttributeList(const ConstPtr<AttributeDefinitionList> & def,unsigned i)704 ParserState::allocAttributeList(const ConstPtr<AttributeDefinitionList> &def,
705 				unsigned i)
706 {
707   if (i < attributeLists_.size())
708     attributeLists_[i]->init(def);
709   else {
710     attributeLists_.resize(i + 1);
711     attributeLists_[i] = new AttributeList(def);
712   }
713   return attributeLists_[i].pointer();
714 }
715 
activateLinkType(const StringC & name)716 void ParserState::activateLinkType(const StringC &name)
717 {
718   if (!hadPass2Start_ && !pass2_)
719     activeLinkTypes_.push_back(name);
720   else
721     message(ParserMessages::linkActivateTooLate);
722 }
723 
shouldActivateLink(const StringC & name) const724 Boolean ParserState::shouldActivateLink(const StringC &name) const
725 {
726   if (!activeLinkTypesSubsted_) {
727     // FIXME use mutable
728     ParserState *state = (ParserState *)this;
729     for (size_t i = 0; i < activeLinkTypes_.size(); i++)
730       for (size_t j = 0; j < activeLinkTypes_[i].size(); j++)
731 	syntax().generalSubstTable()->subst(state->activeLinkTypes_[i][j]);
732     state->activeLinkTypesSubsted_ = 1;
733   }
734   for (size_t i = 0; i < activeLinkTypes_.size(); i++)
735     if (name == activeLinkTypes_[i])
736       return 1;
737   return 0;
738 }
739 
lookupDtd(const StringC & name)740 Ptr<Dtd> ParserState::lookupDtd(const StringC &name)
741 {
742   for (size_t i = 0; i < dtd_.size(); i++)
743     if (dtd_[i]->name() == name)
744       return dtd_[i];
745   return Ptr<Dtd>();
746 }
747 
lookupLpd(const StringC & name) const748 ConstPtr<Lpd> ParserState::lookupLpd(const StringC &name) const
749 {
750   for (size_t i = 0; i < allLpd_.size(); i++)
751     if (allLpd_[i]->name() == name)
752       return allLpd_[i];
753   return ConstPtr<Lpd>();
754 }
755 
getAttributeNotation(const StringC & name,const Location &)756 ConstPtr<Notation> ParserState::getAttributeNotation(const StringC &name,
757 						     const Location &)
758 {
759   ConstPtr<Notation> notation;
760   if (haveCurrentDtd())
761     notation = currentDtd().lookupNotation(name);
762   else if (resultAttributeSpecMode_) {
763     const Dtd *resultDtd = defComplexLpd().resultDtd().pointer();
764     if (!resultDtd)
765       return 0;
766     notation = resultDtd->lookupNotation(name);
767   }
768   return notation;
769 }
770 
getAttributeEntity(const StringC & str,const Location & loc)771 ConstPtr<Entity> ParserState::getAttributeEntity(const StringC &str,
772 						 const Location &loc)
773 {
774   ConstPtr<Entity> entity = lookupEntity(0, str, loc, 0);
775   if (!entity.isNull()
776       && entity->defaulted()
777       && options().warnDefaultEntityReference) {
778     setNextLocation(loc);
779     message(ParserMessages::defaultEntityInAttribute,
780 	    StringMessageArg(str));
781   }
782   return entity;
783 }
784 
defineId(const StringC & str,const Location & loc,Location & prevLoc)785 Boolean ParserState::defineId(const StringC &str, const Location &loc,
786 			      Location &prevLoc)
787 {
788   if (!inInstance() || !validate())
789     return 1;
790   Id *id = lookupCreateId(str);
791   if (id->defined()) {
792     prevLoc = id->defLocation();
793     return 0;
794   }
795   id->define(loc);
796   return 1;
797 }
798 
noteIdref(const StringC & str,const Location & loc)799 void ParserState::noteIdref(const StringC &str, const Location &loc)
800 {
801   if (!inInstance() || !options().errorIdref || !validate())
802     return;
803   Id *id = lookupCreateId(str);
804   if (!id->defined())
805     id->addPendingRef(loc);
806 }
807 
noteCurrentAttribute(size_t i,AttributeValue * value)808 void ParserState::noteCurrentAttribute(size_t i, AttributeValue *value)
809 {
810   if (inInstance())
811     currentAttributes_[i] = value;
812 }
813 
getCurrentAttribute(size_t i) const814 ConstPtr<AttributeValue> ParserState::getCurrentAttribute(size_t i) const
815 {
816   if (!inInstance())
817     return ConstPtr<AttributeValue>();
818   return currentAttributes_[i];
819 }
820 
attributeSyntax() const821 const Syntax &ParserState::attributeSyntax() const
822 {
823   return syntax();
824 }
825 
826 #ifdef SP_NAMESPACE
827 }
828 #endif
829