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