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