nsgmls: fix up some gcc 4.8 warnings.
[oweals/cde.git] / cde / programs / nsgmls / ArcEngine.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: ArcEngine.C /main/1 1996/07/29 16:46:09 cde-hp $ */
24 // Copyright (c) 1996 James Clark
25 // See the file COPYING for copying permission.
26
27 #ifdef __GNUG__
28 #pragma implementation
29 #endif
30
31 #include "splib.h"
32 #include "ArcEngine.h"
33 #include "ArcProcessor.h"
34 #include "Vector.h"
35 #include "NCVector.h"
36 #include "IQueue.h"
37 #include "ArcEngineMessages.h"
38 #include "MessageArg.h"
39 #include "ParserOptions.h"
40 #include "SgmlParser.h"
41 #include "Allocator.h"
42 #include "LinkProcess.h"
43 #include "macros.h"
44
45 #ifdef SP_NAMESPACE
46 namespace SP_NAMESPACE {
47 #endif
48
49 static const char notationSetArchPublicId[]
50  = "ISO/IEC 10744//NOTATION AFDR ARCBASE \
51 Notation Set Architecture Definition Document//EN";
52
53 static const size_t sizes[] = {
54   sizeof(StartElementEvent),
55   sizeof(EndElementEvent),
56   sizeof(ImmediateDataEvent),
57   sizeof(SdataEntityEvent),
58   sizeof(EndPrologEvent),
59   sizeof(CdataEntityEvent),
60   sizeof(SdataEntityEvent),
61   sizeof(ExternalDataEntityEvent),
62   sizeof(OpenElement)
63 };
64
65 static
66 size_t maxSize(const size_t *v, size_t n)
67 {
68   size_t max = 0;
69   for (size_t i = 0; i < n; i++) {
70     if (v[i] > max)
71       max = v[i];
72   }
73   return max;
74 }
75
76 const unsigned invalidAtt = unsigned(-1);
77 const unsigned contentPseudoAtt = unsigned(-2);
78
79 class DelegateEventHandler : public EventHandler {
80 public:
81 #define EVENT(C, f) void f(C *ev) { delegateTo_->f(ev); }
82 #include "events.h"
83 #undef EVENT
84 protected:
85   EventHandler *delegateTo_;
86 };
87
88 class QueueEventHandler : public EventHandler, public IQueue<Event> {
89 public:
90 #define EVENT(C, f) void f(C *ev) { ev->copyData(); append(ev); }
91 #include "events.h"
92 #undef EVENT
93 };
94
95 // This just passes through messages.
96
97 class NullEventHandler : public EventHandler {
98 public:
99   NullEventHandler(Messenger &mgr) : mgr_(&mgr) { }
100   void message(MessageEvent *event) {
101     mgr_->dispatchMessage(event->message());
102   }
103 private:
104   Messenger *mgr_;
105 };
106
107 class ArcEngineImpl : public DelegateEventHandler, private Messenger {
108 public:
109   ArcEngineImpl(Messenger &mgr,
110                 const SgmlParser *parser,
111                 ArcDirector &director,
112                 SP_CONST SP_VOLATILE sig_atomic_t *cancelPtr,
113                 const Notation *,
114                 const Vector<StringC> &name,
115                 const SubstTable<Char> *table);
116   ~ArcEngineImpl();
117   void sgmlDecl(SgmlDeclEvent *);
118   void appinfo(AppinfoEvent *);
119   void startElement(StartElementEvent *);
120   void endElement(EndElementEvent *);
121   void data(DataEvent *);
122   void sdataEntity(SdataEntityEvent *);
123   void externalDataEntity(ExternalDataEntityEvent *);
124   void pi(PiEvent *);
125   void endProlog(EndPrologEvent *);
126   void startDtd(StartDtdEvent *);
127   void endDtd(EndDtdEvent *);
128   void startLpd(StartLpdEvent *);
129   void endLpd(EndLpdEvent *);
130   void uselink(UselinkEvent *);
131   size_t nBases() const { return arcProcessors_.size(); }
132   EventHandler *delegateHandler() { return eventHandler_; }
133 private:
134   void dispatchMessage(const Message &);
135   void dispatchMessage(Message &);
136   void initMessage(Message &);
137
138   EventHandler *eventHandler_;
139   NCVector<ArcProcessor> arcProcessors_;
140   ConstPtr<Sd> sd_;
141   ConstPtr<Syntax> syntax_;
142   StringC arcBase_;
143   int stage_;
144   QueueEventHandler eventQueue_;
145   NullEventHandler nullHandler_;
146   const SgmlParser *parser_;
147   Location currentLocation_;
148   unsigned gatheringContent_;
149   Text content_;
150   unsigned startAgain_;
151   Allocator allocator_;
152   StringC appinfo_;
153   const AttributeList *linkAttributes_;
154   LinkProcess linkProcess_;
155   Boolean haveLinkProcess_;
156   Vector<StringC> docName_;
157   ArcDirector *director_;
158   Messenger *mgr_;
159   SP_CONST SP_VOLATILE sig_atomic_t *cancelPtr_;
160 };
161
162
163 void ArcEngine::parseAll(SgmlParser &parser,
164                          Messenger &mgr,
165                          ArcDirector &director,
166                          SP_CONST SP_VOLATILE sig_atomic_t *cancelPtr)
167 {
168   ArcEngineImpl wrap(mgr, &parser, director, cancelPtr,
169                      0, Vector<StringC>(), 0);
170   parser.parseAll(wrap, cancelPtr);
171 }
172
173 EventHandler *
174 SelectOneArcDirector::arcEventHandler(const Notation *,
175                                       const Vector<StringC> &name,
176                                       const SubstTable<Char> *table)
177 {
178   if (name.size() != select_.size())
179     return 0;
180   for (size_t i = 0; i < name.size(); i++) {
181     StringC tem(select_[i]);
182     table->subst(tem);
183     if (name[i] != tem)
184       return 0;
185   }
186   return eh_;
187 }
188
189 void SelectOneArcDirector::dispatchMessage(const Message &msg)
190 {
191   eh_->message(new MessageEvent(msg));
192 }
193
194 void SelectOneArcDirector::dispatchMessage(Message &msg)
195 {
196   eh_->message(new MessageEvent(msg));
197 }
198
199 ArcEngineImpl::ArcEngineImpl(Messenger &mgr,
200                              const SgmlParser *parser,
201                              ArcDirector &director,
202                              SP_CONST SP_VOLATILE sig_atomic_t *cancelPtr,
203                              const Notation *notation,
204                              const Vector<StringC> &docName,
205                              const SubstTable<Char> *table)
206
207 : director_(&director), mgr_(&mgr), cancelPtr_(cancelPtr),
208   parser_(parser), stage_(0),
209   gatheringContent_(0), startAgain_(0), haveLinkProcess_(0),
210   allocator_(maxSize(sizes, SIZEOF(sizes)), 50),
211   nullHandler_(mgr), docName_(docName)
212 {
213   eventHandler_ = director.arcEventHandler(notation, docName, table);
214   if (!eventHandler_)
215     eventHandler_ = &nullHandler_;
216   delegateTo_ = eventHandler_;
217 }
218
219 ArcEngineImpl::~ArcEngineImpl()
220 {
221   for (size_t i = 0; i < arcProcessors_.size(); i++)
222     if (arcProcessors_[i].valid())
223       arcProcessors_[i].checkIdrefs();
224 }
225
226 void ArcEngineImpl::appinfo(AppinfoEvent *event)
227 {
228   const StringC *str;
229   if (event->literal(str))
230     appinfo_ = *str;
231   DelegateEventHandler::appinfo(event);
232 }
233
234 void ArcEngineImpl::pi(PiEvent *event)
235 {
236   currentLocation_ = event->location();
237   if (stage_ == 1
238       && arcBase_.size()
239       && event->dataLength() > arcBase_.size()) {
240     Boolean match = 1;
241     for (size_t i = 0; i < arcBase_.size() && match; i++)
242       if ((*syntax_->generalSubstTable())[event->data()[i]] != arcBase_[i])
243         match = 0;
244     if (!syntax_->isS(event->data()[arcBase_.size()]))
245       match = 0;
246     if (match) {
247       size_t i = arcBase_.size();
248       size_t dataLength = event->dataLength();
249       const Char *data = event->data();
250       for (;;) {
251         while (i < dataLength && syntax_->isS(data[i]))
252           i++;
253         if (i >= dataLength)
254           break;
255         size_t start = i++;
256         while (i < dataLength && !syntax_->isS(data[i]))
257           i++;
258         StringC name(data + start, i - start);
259         syntax_->generalSubstTable()->subst(name);
260         arcProcessors_.resize(arcProcessors_.size() + 1);
261         arcProcessors_.back().setName(name);
262       }
263     }
264   }
265   DelegateEventHandler::pi(event);
266 }
267
268 void ArcEngineImpl::endProlog(EndPrologEvent *event)
269 {
270   currentLocation_ = event->location();
271   for (size_t i = 0; i < arcProcessors_.size(); i++)
272     arcProcessors_[i].init(*event,
273                            sd_,
274                            syntax_,
275                            parser_,
276                            this,
277                            docName_,
278                            *director_,
279                            cancelPtr_);
280   if (!event->lpdPointer().isNull()) {
281     haveLinkProcess_ = 1;
282     linkProcess_.init(event->lpdPointer());
283   }
284   DelegateEventHandler::endProlog(event);
285 }
286
287 void ArcEngineImpl::startDtd(StartDtdEvent *event)
288 {
289   stage_++;
290   DelegateEventHandler::startDtd(event);
291 }
292
293 void ArcEngineImpl::endDtd(EndDtdEvent *event)
294 {
295   stage_++;
296   DelegateEventHandler::endDtd(event);
297 }
298
299 void ArcEngineImpl::startLpd(StartLpdEvent *event)
300 {
301   if (event->active())
302     stage_ = 1;
303   DelegateEventHandler::startLpd(event);
304 }
305
306 void ArcEngineImpl::endLpd(EndLpdEvent *event)
307 {
308   stage_++;
309   DelegateEventHandler::endLpd(event);
310 }
311
312 void ArcEngineImpl::sgmlDecl(SgmlDeclEvent *event)
313 {
314   currentLocation_ = event->location();
315   sd_ = event->sdPointer();
316   syntax_ = event->instanceSyntaxPointer();
317   arcBase_ = sd_->execToDoc("ArcBase");
318   syntax_->generalSubstTable()->subst(arcBase_);
319   Boolean atStart = 1;
320   for (size_t i = 0; i < appinfo_.size(); i++)
321     if (syntax_->isS(appinfo_[i]))
322       atStart = 1;
323     else if (atStart) {
324       if (i + 7 > appinfo_.size())
325         break;
326       StringC tem(appinfo_.data() + i, 7);
327       syntax_->generalSubstTable()->subst(tem);
328       if (tem == arcBase_) {
329         if (i + 7 == appinfo_.size() || syntax_->isS(appinfo_[i + 7]))
330           break;
331         if (appinfo_[i + 7] == sd_->execToDoc('=')) {
332           arcBase_.resize(0);
333           for (size_t j = i + 7; j < appinfo_.size(); j++) {
334             if (syntax_->isS(appinfo_[j]))
335               break;
336             arcBase_ += appinfo_[j];
337           }
338           syntax_->generalSubstTable()->subst(arcBase_);
339           break;
340         }
341       }
342       atStart = 0;
343     }
344   DelegateEventHandler::sgmlDecl(event);
345 }
346
347 void ArcEngineImpl::startElement(StartElementEvent *event)
348 {
349   if (gatheringContent_) {
350     gatheringContent_++;
351     DelegateEventHandler::startElement(event);
352     return;
353   }
354   currentLocation_ = event->location();
355   const Text *contentP;
356   size_t start;
357   if (startAgain_) {
358     start = startAgain_ - 1;
359     contentP = &content_;
360     startAgain_ = 0;
361   }
362   else {
363     contentP = 0;
364     start = 0;
365     if (haveLinkProcess_) {
366       const ResultElementSpec *resultElementSpec;
367       linkProcess_.startElement(event->elementType(),
368                                 event->attributes(),
369                                 event->location(),
370                                 *this, // Messenger &
371                                 linkAttributes_,
372                                 resultElementSpec);
373     }
374     else
375       linkAttributes_ = 0;
376   }
377   for (size_t i = start; i < arcProcessors_.size(); i++) {
378     if (arcProcessors_[i].valid()) {
379       if (!arcProcessors_[i].processStartElement(*event,
380                                                  linkAttributes_,
381                                                  contentP,
382                                                  allocator_)) {
383         ASSERT(contentP == 0);
384         startAgain_ = i + 1;
385         gatheringContent_ = 1;
386         delegateTo_ = &eventQueue_;
387         DelegateEventHandler::startElement(event);
388         return;
389       }
390     }
391   }
392   
393   content_.clear();
394   DelegateEventHandler::startElement(event);
395 }
396
397 void ArcEngineImpl::data(DataEvent *event)
398 {
399   const Entity *entity = event->entity();
400   if (gatheringContent_) {
401     if (entity)
402       content_.addCdata(entity->asInternalEntity(),
403                         event->location().origin());
404     else {
405       // Do attribute value literal interpretation.
406       Location loc(event->location());
407       for (size_t i = 0; i < event->dataLength(); i++, loc += 1) {
408         Char ch = event->data()[i];
409         if (syntax_->isS(ch) && ch != syntax_->space()) {
410           if (ch == syntax_->standardFunction(Syntax::fRS))
411             content_.ignoreChar(ch, loc);
412           else
413             content_.addChar(syntax_->space(),
414                              Location(new ReplacementOrigin(loc, ch), 0));
415         }                
416         else
417           content_.addChar(ch, loc);
418       }
419     }
420   }
421   else {
422     currentLocation_ = event->location();
423     for (size_t i = 0; i < arcProcessors_.size(); i++) {
424       if (arcProcessors_[i].valid() && arcProcessors_[i].processData()) {
425         if (entity)
426           arcProcessors_[i].docHandler()
427             .data(new (allocator_) CdataEntityEvent(entity->asInternalEntity(),
428                                                     event->location().origin()));
429         else
430           arcProcessors_[i].docHandler()
431             .data(new (allocator_) ImmediateDataEvent(event->type(),
432                                                       event->data(),
433                                                       event->dataLength(),
434                                                       event->location(),
435                                                       0));
436       }
437     }
438   }
439   DelegateEventHandler::data(event);
440 }
441
442 void ArcEngineImpl::sdataEntity(SdataEntityEvent *event)
443 {
444   if (gatheringContent_) {
445     content_.addSdata(event->entity()->asInternalEntity(),
446                       event->location().origin());
447     return;
448   }
449   else {
450     currentLocation_ = event->location();
451     for (size_t i = 0; i < arcProcessors_.size(); i++) {
452       if (arcProcessors_[i].valid() && arcProcessors_[i].processData()) {
453         const Entity *entity = event->entity();
454         arcProcessors_[i].docHandler()
455           .sdataEntity(new (allocator_)
456                        SdataEntityEvent(entity->asInternalEntity(),
457                                         event->location().origin()));
458       }
459     }
460   }
461   DelegateEventHandler::sdataEntity(event);
462 }
463
464 void ArcEngineImpl::externalDataEntity(ExternalDataEntityEvent *event)
465 {
466   if (!gatheringContent_) {
467     currentLocation_ = event->location();
468     for (size_t i = 0; i < arcProcessors_.size(); i++) {
469       if (arcProcessors_[i].valid()
470           && arcProcessors_[i].processData()) {
471         ConstPtr<Entity> entity
472           = arcProcessors_[i].dtdPointer()
473             ->lookupEntity(0, event->entity()->name());
474         if (!entity.isNull()) {
475           ConstPtr<EntityOrigin> oldOrigin = event->entityOrigin();
476           Owner<Markup> markup;
477           if (oldOrigin->markup())
478             markup = new Markup(*oldOrigin->markup());
479           ConstPtr<EntityOrigin> newOrigin
480             = new EntityOrigin(entity,
481                                oldOrigin->parent(),
482                                oldOrigin->refLength(),
483                                markup);
484           arcProcessors_[i].docHandler()
485             .externalDataEntity(new (allocator_)
486                                 ExternalDataEntityEvent(entity->asExternalDataEntity(),
487                                                         newOrigin));
488         }
489         // otherwise entity is not architectural
490       }
491     }
492   }
493   DelegateEventHandler::externalDataEntity(event);
494 }
495
496 void ArcEngineImpl::endElement(EndElementEvent *event)
497 {
498   while (gatheringContent_) {
499     if (--gatheringContent_ > 0) {
500       DelegateEventHandler::endElement(event);
501       return;
502     }
503     delegateTo_ = delegateHandler();
504     // Clear out eventQueue_ in case handling the events
505     // causes events to be queued again.
506     IQueue<Event> tem;
507     tem.swap(eventQueue_);
508     while (!tem.empty())
509       tem.get()->handle(*this);
510   }
511   currentLocation_ = event->location();
512   for (size_t i = 0; i < arcProcessors_.size(); i++)
513     if (arcProcessors_[i].valid())
514       arcProcessors_[i].processEndElement(*event, allocator_);
515   DelegateEventHandler::endElement(event);
516   if (haveLinkProcess_)
517     linkProcess_.endElement();
518 }
519
520 void ArcEngineImpl::uselink(UselinkEvent *event)
521 {
522   if (!gatheringContent_)
523     linkProcess_.uselink(event->linkSet(),
524                          event->restore(),
525                          event->lpd().pointer());
526   DelegateEventHandler::uselink(event);
527 }
528
529 void ArcEngineImpl::dispatchMessage(const Message &msg)
530 {
531   mgr_->dispatchMessage(msg);
532 }
533
534 void ArcEngineImpl::dispatchMessage(Message &msg)
535 {
536   mgr_->dispatchMessage(msg);
537 }
538
539 void ArcEngineImpl::initMessage(Message &msg)
540 {
541   mgr_->initMessage(msg);
542   msg.loc = currentLocation_;
543 }
544
545 ArcProcessor::ArcProcessor()
546 : errorIdref_(1), notationSetArch_(0), docHandler_(0), arcAuto_(1),
547   arcDtdIsParam_(0)
548 {
549 }
550
551 void ArcProcessor::setName(const StringC &name)
552 {
553   name_ = name;
554 }
555
556 const Syntax &ArcProcessor::attributeSyntax() const
557 {
558   return *docSyntax_;
559 }
560
561 ConstPtr<Notation> ArcProcessor::getAttributeNotation(const StringC &name,
562                                                       const Location &)
563 {
564   if (!metaDtd_.isNull())
565     return metaDtd_->lookupNotation(name);
566   return 0;
567 }
568
569 ConstPtr<Entity> ArcProcessor::getAttributeEntity(const StringC &name,
570                                                   const Location &)
571 {
572   // FIXME What about default entity
573   if (!notationSetArch_ && !metaDtd_.isNull())
574     return metaDtd_->lookupEntity(0, name);
575   return 0;
576 }
577
578 void ArcProcessor::noteCurrentAttribute(size_t i, AttributeValue *value)
579 {
580   if (valid_ && !notationSetArch_)
581     currentAttributes_[i] = value;
582 }
583
584 ConstPtr<AttributeValue> ArcProcessor::getCurrentAttribute(size_t i) const
585 {
586   if (notationSetArch_)
587     return 0;
588   return currentAttributes_[i];
589 }
590
591 // This code is the same as in the main parser.
592 // Once handling of ID/IDREF in architectures has been clarified.
593 // Maybe factor out into AttributeContext.
594
595 Boolean ArcProcessor::defineId(const StringC &str, const Location &loc,
596                                Location &prevLoc)
597 {
598   if (!valid_)
599     return 1;
600   Id *id = lookupCreateId(str);
601   if (id->defined()) {
602     prevLoc = id->defLocation();
603     return 0;
604   }
605   id->define(loc);
606   return 1;
607 }
608
609 void ArcProcessor::noteIdref(const StringC &str, const Location &loc)
610 {
611   if (!valid_ || !errorIdref_)
612     return;
613   Id *id = lookupCreateId(str);
614   if (!id->defined())
615     id->addPendingRef(loc);
616 }
617
618 Id *ArcProcessor::lookupCreateId(const StringC &name)
619 {
620   Id *id = idTable_.lookup(name);
621   if (!id) {
622     id = new Id(name);
623     idTable_.insert(id);
624   }
625   return id;
626 }
627
628 void ArcProcessor::checkIdrefs()
629 {
630   NamedTableIter<Id> iter(idTable_);
631   Id *id;
632   while ((id = iter.next()) != 0) {
633     for (size_t i = 0; i < id->pendingRefs().size(); i++) {
634       Messenger::setNextLocation(id->pendingRefs()[i]);
635       message(ArcEngineMessages::missingId, StringMessageArg(id->name()));
636     }
637   }
638 }
639
640 void ArcProcessor::init(const EndPrologEvent &event,
641                         const ConstPtr<Sd> &sd,
642                         const ConstPtr<Syntax> &syntax,
643                         const SgmlParser *parentParser,
644                         Messenger *mgr,
645                         const Vector<StringC> &superName,
646                         ArcDirector &director,
647                         SP_CONST SP_VOLATILE sig_atomic_t *cancelPtr)
648 {
649   director_ = &director;
650   mgr_ = mgr;
651   docSyntax_ = syntax;
652   docSd_ = sd;
653   mgr_ = mgr;
654   valid_ = 0;
655   docDtd_ = event.dtdPointer();
656   metaSyntax_ = docSyntax_;
657   mayDefaultAttribute_ = 1;
658   docSyntax_->generalSubstTable()->subst(name_);
659   Vector<StringC> docName(superName);
660   docName.push_back(name_);
661   ConstPtr<Notation> notation;
662   if (name_ == docSyntax_->rniReservedName(Syntax::rNOTATION)) {
663     notationSetArch_ = 1;
664     supportAtts_[rArcNamrA] = docSd_->execToDoc("NOTNAMES");
665     supportAtts_[rArcSuprA] = docSd_->execToDoc("NOTSUPR");
666   }
667   else {
668     notation = docDtd_->lookupNotation(name_);
669     if (!notation.isNull()) {
670       ConstPtr<AttributeDefinitionList> notAttDef = notation->attributeDef();
671       attributeList_.init(notAttDef);
672       attributeList_.finish(*this);
673       supportAttributes(attributeList_);
674       // FIXME make sure locations in error messages are right
675       if (notation->externalId().publicIdString()
676           && (*notation->externalId().publicIdString()
677               == docSd_->execToDoc(notationSetArchPublicId))) {
678         notationSetArch_ = 1;
679       }
680     }
681     else
682       message(ArcEngineMessages::noArcNotation, StringMessageArg(name_));
683   }
684   ArcEngineImpl *engine
685     = new ArcEngineImpl(*mgr, parentParser, director, cancelPtr,
686                         notation.pointer(),
687                         docName,
688                         docSyntax_->generalSubstTable());
689   docHandler_ = engine;
690   ownEventHandler_ = engine;
691   if (notationSetArch_) {
692     initNotationSet(event.location());
693     return;
694   }
695   if (supportAtts_[rArcDocF].size() == 0)
696     supportAtts_[rArcDocF] = name_;
697   if (supportAtts_[rArcFormA].size() == 0)
698     supportAtts_[rArcFormA] = name_;
699   rniContent_ = docSyntax_->delimGeneral(Syntax::dRNI);
700   rniContent_ += sd->execToDoc("CONTENT");
701   rniDefault_ = docSyntax_->delimGeneral(Syntax::dRNI);
702   rniDefault_ += docSyntax_->reservedName(Syntax::rDEFAULT);
703   rniArcCont_ = metaSyntax_->delimGeneral(Syntax::dRNI);
704   rniArcCont_ += sd->execToDoc("ARCCONT");
705   ConstPtr<Entity> dtdent = makeDtdEntity(notation.pointer());
706   if (dtdent.isNull())
707     return;
708   StringC sysid = dtdent->asExternalEntity()->externalId().effectiveSystemId();
709   if (sysid.size() == 0
710       && !parentParser->entityCatalog().lookup(*dtdent,
711                                                *docSyntax_,
712                                                sd->docCharset(),
713                                                *mgr_,
714                                                sysid)) {
715     message(ArcEngineMessages::arcGenerateSystemId,
716             StringMessageArg(name_));
717     return;
718   }
719   docHandler_->sgmlDecl(new SgmlDeclEvent(sd, syntax));
720   docHandler_->startDtd(new StartDtdEvent(dtdent->name(),
721                                           dtdent,
722                                           0,
723                                           event.location(),
724                                           0));
725   SgmlParser::Params params;
726   params.entityType = SgmlParser::Params::dtd;
727   params.sysid = sysid;
728   params.parent = parentParser;
729   ParserOptions options = parentParser->options();
730   errorIdref_ = options.errorIdref;
731   options.errorAfdr = 0;
732   options.includes = arcOpts_;
733   params.options = &options;
734   params.sd = docSd_;
735   params.prologSyntax = metaSyntax_;
736   params.instanceSyntax = metaSyntax_;
737   params.doctypeName = dtdent->name();
738   SgmlParser parser(params);
739   parser.parseAll(*docHandler_, cancelPtr);
740   Ptr<Dtd> baseDtd = parser.baseDtd();
741   if (baseDtd.isNull()
742       || baseDtd->documentElementType()->definition()->undefined())
743     return;
744   metaDtd_ = baseDtd;
745   metaMapCache_.resize(docDtd_->nElementTypeIndex());
746   mungeMetaDtd(*baseDtd, *docDtd_);
747   docHandler_->endDtd(new EndDtdEvent(metaDtd_, event.location(), 0));
748   startContent(*metaDtd_);
749   currentAttributes_.resize(metaDtd_->nCurrentAttribute());
750   valid_ = 1;
751   docHandler_->endProlog(new EndPrologEvent(metaDtd_, event.location()));
752   if (engine->nBases() == 0)
753     docHandler_ = engine->delegateHandler();
754 }
755
756 void ArcProcessor::initNotationSet(const Location &loc)
757 {
758   StringC name(docSyntax_->rniReservedName(Syntax::rNOTATION));
759   Ptr<Dtd> notDtd(new Dtd(name, 1));
760   metaDtd_ = notDtd;
761   ConstPtr<ElementDefinition> def
762     = new ElementDefinition(loc,
763                             notDtd->allocElementDefinitionIndex(),
764                             0,
765                             ElementDefinition::any);
766   notDtd->lookupElementType(name)->setElementDefinition(def, 0);
767   Dtd::ConstNotationIter iter(docDtd_->notationIter());
768   for (size_t i = 1;; i++) {
769     const Notation *notation = iter.next().pointer();
770     if (!notation)
771       break;
772     ElementType *e = new ElementType(notation->name(),
773                                      notDtd->nElementTypeIndex());
774     notDtd->insertElementType(e);
775     e->setElementDefinition(def, i);
776     if (!notation->attributeDef().isNull()) {
777       Vector<CopyOwner<AttributeDefinition> >
778         attdefs(notation->attributeDef()->size());
779       for (size_t i = 0; i < attdefs.size(); i++)
780         attdefs[i] = notation->attributeDef()->def(i)->copy();
781       e->setAttributeDef(new AttributeDefinitionList(attdefs,
782                                                      notDtd->allocAttributeDefinitionListIndex()));
783     }
784   }
785   docHandler_->endProlog(new EndPrologEvent(metaDtd_, loc));
786   metaMapCache_.resize(docDtd_->nElementTypeIndex());
787   startContent(*notDtd);
788   valid_ = 1;
789 }
790
791 void ArcProcessor::mungeMetaDtd(Dtd &metaDtd, const Dtd &docDtd)
792 {
793   if (supportAtts_[rArcDataF].size() > 0
794       && metaDtd.lookupNotation(supportAtts_[rArcDataF]).isNull()) {
795     Messenger::message(ArcEngineMessages::noArcDataF,
796                        StringMessageArg(supportAtts_[rArcDataF]));
797     metaDtd.insertNotation(new Notation(supportAtts_[rArcDataF],
798                                         metaDtd.namePointer(),
799                                         metaDtd.isBase()));
800   }
801   // FIXME check for ArcAutoF
802   Dtd::ConstEntityIter iter(docDtd.generalEntityIter());
803   for (;;) {
804     ConstPtr<Entity> ent = iter.next();
805     if (ent.isNull())
806       break;
807     Ptr<Entity> copy(ent->copy());
808     if (!copy->asExternalDataEntity()
809         || mungeDataEntity(*(ExternalDataEntity *)copy.pointer()))
810       metaDtd.insertEntity(copy, 1);
811   }
812 }
813
814 Boolean ArcProcessor::mungeDataEntity(ExternalDataEntity &entity)
815 {
816   const MetaMap &map = buildMetaMap(0,
817                                     entity.notation(),
818                                     entity.attributes(),
819                                     0,
820                                     0);
821   if (!map.attributed)
822     return 0;
823   AttributeList atts;
824   const Notation *notation = (const Notation *)map.attributed;
825   ConstPtr<AttributeValue> arcContent;
826   if (mapAttributes(entity.attributes(), 0, 0, atts, arcContent, map)) {
827     // FIXME check arcContent
828     entity.setNotation((Notation *)notation, atts);
829     return 1;
830   }
831   // FIXME error tried to use #CONTENT
832   return 0;
833 }
834
835 ConstPtr<Entity> ArcProcessor::makeDtdEntity(const Notation *)
836 {
837   if (!supportAtts_[rArcDTD].size()) {
838     mgr_->message(ArcEngineMessages::noArcDTDAtt);
839     return 0;
840   }
841   ConstPtr<Entity> entity = docDtd_->lookupEntity(arcDtdIsParam_,
842                                                   supportAtts_[rArcDTD]);
843   if (entity.isNull()) {
844     mgr_->message(ArcEngineMessages::arcDtdNotDeclared,
845                   StringMessageArg(supportAtts_[rArcDTD]));
846     return 0;
847   }
848   if (!entity->asExternalEntity()) {
849     mgr_->message(ArcEngineMessages::arcDtdNotExternal,
850                   StringMessageArg(supportAtts_[rArcDTD]));
851     return 0;
852   }
853   ExternalId externalId(entity->asExternalEntity()->externalId());
854 #if 0
855   // Use the public identifier of the notation to find the meta-DTD.
856   if (externalId.effectiveSystemId().size() == 0 && notation) {
857     if (notation->externalId().effectiveSystemId().size()) {
858       StringC tem(notation->externalId().effectiveSystemId());
859       externalId.setEffectiveSystem(tem);
860     }
861     else  if (!externalId.publicId()) {
862       const PublicId *pubid = notation->externalId().publicId();
863       PublicId::OwnerType ownerType;
864       if (pubid && pubid->getOwnerType(ownerType)) {
865         Text pubidText;
866         unsigned textClassPos = 2;
867         if (ownerType != PublicId::ISO)
868           textClassPos += 3;
869         StringC owner;
870         pubid->getOwner(owner);
871         textClassPos += owner.size();
872         pubidText.addChars(pubid->string().data(),
873                            textClassPos,
874                            pubid->text().charLocation(0));
875         pubidText.addChars(docSd_->execToDoc("DTD"),
876                            pubid->text().charLocation(textClassPos));
877         for (; textClassPos < pubid->string().size(); textClassPos++)
878           if (pubid->string()[textClassPos] == docSyntax_->space())
879             break;
880         pubidText.addChars(pubid->string().data() + textClassPos,
881                            pubid->string().size() - textClassPos,
882                            pubid->text().charLocation(textClassPos));
883         const MessageType1 *msg;
884         externalId.setPublic(pubidText, docSd_->docCharset(),
885                              docSyntax_->space(), msg);
886       }
887     }
888   }
889 #endif
890   return new ExternalTextEntity(supportAtts_[rArcDocF],
891                                 Entity::doctype,
892                                 entity->defLocation(),
893                                 externalId);
894 }
895
896 void ArcProcessor::supportAttributes(const AttributeList &atts)
897 {
898   static const char *const s[] = {
899     "ArcFormA",
900     "ArcNamrA",
901     "ArcSuprA",
902     "ArcIgnDA",
903     "ArcDocF",
904     "ArcSuprF",
905     "ArcBridF",
906     "ArcDataF",
907     "ArcAuto",
908     "ArcIndr",
909     "ArcDTD",
910     "ArcQuant",
911     };
912   for (size_t i = 0; i < SIZEOF(s); i++) {
913     StringC attName(docSd_->execToDoc(s[i]));
914     docSyntax_->generalSubstTable()->subst(attName);
915     unsigned ind;
916     if (atts.attributeIndex(attName, ind)) {
917       const AttributeValue *value = atts.value(ind);
918       if (value) {
919         const Text *textP = value->text();
920         // FIXME check for empty value
921         if (textP) {
922           supportAtts_[i] = textP->string();
923           switch (i) {
924           case rArcQuant:
925             processArcQuant(*textP);
926             break;
927           case rArcAuto:
928             docSyntax_->generalSubstTable()->subst(supportAtts_[i]);
929             if (supportAtts_[i] == docSd_->execToDoc("ARCAUTO"))
930               arcAuto_ = 1;
931             else if (supportAtts_[i] == docSd_->execToDoc("NARCAUTO"))
932               arcAuto_ = 0;
933             else
934               Messenger::message(ArcEngineMessages::invalidArcAuto,
935                                  StringMessageArg(supportAtts_[i]));
936             break;
937           case rArcIndr:
938             docSyntax_->generalSubstTable()->subst(supportAtts_[i]);
939             if (supportAtts_[i] == docSd_->execToDoc("ARCINDR")) {
940               Messenger::setNextLocation(textP->charLocation(0));
941               Messenger::message(ArcEngineMessages::arcIndrNotSupported);
942             }
943             else if (supportAtts_[i] != docSd_->execToDoc("NARCINDR")) {
944               Messenger::setNextLocation(textP->charLocation(0));
945               Messenger::message(ArcEngineMessages::invalidArcIndr,
946                                  StringMessageArg(supportAtts_[i]));
947             }
948             break;
949           case rArcFormA:
950           case rArcNamrA:
951           case rArcSuprA:
952           case rArcIgnDA:
953             docSyntax_->generalSubstTable()->subst(supportAtts_[i]);
954             break;
955           case rArcDocF:
956           case rArcSuprF:
957           case rArcBridF:
958           case rArcDataF:
959             metaSyntax_->generalSubstTable()->subst(supportAtts_[i]);
960             break;
961           case rArcDTD:
962             {
963               const StringC &pero = docSyntax_->delimGeneral(Syntax::dPERO);
964               if (supportAtts_[i].size() >= pero.size()) {
965                 StringC tem(supportAtts_[i].data(), pero.size());
966                 docSyntax_->generalSubstTable()->subst(tem);
967                 if (tem == pero) {
968                   arcDtdIsParam_ = 1;
969                   tem.assign(supportAtts_[i].data() + pero.size(),
970                              supportAtts_[i].size() - pero.size());
971                   tem.swap(supportAtts_[i]);
972                 }
973               }
974               docSyntax_->entitySubstTable()->subst(supportAtts_[i]);
975             }
976             break;
977           }
978         }
979       }
980     }
981   }
982   processArcOpts(atts);
983 }
984
985 void ArcProcessor::processArcOpts(const AttributeList &atts)
986 {
987   StringC attName(docSd_->execToDoc("ArcOptSA"));
988   docSyntax_->generalSubstTable()->subst(attName);
989   unsigned ind;
990   Vector<StringC> arcOptA;
991   Vector<size_t> arcOptAPos;
992   const Text *arcOptAText = 0;
993   if (atts.attributeIndex(attName, ind)) {
994     const AttributeValue *value = atts.value(ind);
995     if (value) {
996       arcOptAText = value->text();
997       if (arcOptAText)
998         split(*arcOptAText, docSyntax_->space(), arcOptA, arcOptAPos);
999     }
1000   }
1001   if (!arcOptAText)
1002     arcOptA.push_back(docSd_->execToDoc("ArcOpt"));
1003   for (size_t i = 0; i < arcOptA.size(); i++) {
1004     docSyntax_->generalSubstTable()->subst(arcOptA[i]);
1005     if (atts.attributeIndex(arcOptA[i], ind)) {
1006       const AttributeValue *value = atts.value(ind);
1007       if (value) {
1008         const Text *textP = value->text();
1009         if (textP) {
1010           Vector<StringC> opts;
1011           Vector<size_t> optsPos;
1012           split(*textP, docSyntax_->space(), opts, optsPos);
1013           arcOpts_.insert(arcOpts_.begin(),
1014                           opts.begin(), opts.begin() + opts.size());
1015         }
1016       }
1017     }
1018   }
1019 }
1020
1021 void ArcProcessor::processArcQuant(const Text &text)
1022 {
1023   Ptr<Syntax> newMetaSyntax;
1024   Vector<StringC> tokens;
1025   Vector<size_t> tokensPos;
1026   split(text, docSyntax_->space(), tokens, tokensPos);
1027   for (size_t i = 0; i < tokens.size(); i++) {
1028     docSyntax_->generalSubstTable()->subst(tokens[i]);
1029     Syntax::Quantity quantityName;
1030     if (!docSd_->lookupQuantityName(tokens[i], quantityName)) {
1031       setNextLocation(text.charLocation(tokensPos[i]));
1032       Messenger::message(ArcEngineMessages::invalidQuantity,
1033                          StringMessageArg(tokens[i]));
1034     }
1035     else if (i + 1 >= tokens.size()) {
1036       setNextLocation(text.charLocation(tokensPos[i]));
1037       Messenger::message(ArcEngineMessages::missingQuantityValue,
1038                          StringMessageArg(tokens[i]));
1039     }
1040     else {
1041       i++;
1042       unsigned long val = 0;
1043       if (tokens[i].size() > 8) {
1044         setNextLocation(text.charLocation(tokensPos[i] + 8));
1045         Messenger::message(ArcEngineMessages::quantityValueTooLong,
1046                            StringMessageArg(tokens[i]));
1047         tokens[i].resize(8);
1048       }
1049       for (size_t j = 0; j < tokens[i].size(); j++) {
1050         int weight = docSd_->digitWeight(tokens[i][j]);
1051         if (weight < 0) {
1052           setNextLocation(text.charLocation(tokensPos[i] + j));
1053           Char c = tokens[i][j];
1054           Messenger::message(ArcEngineMessages::invalidDigit,
1055                              StringMessageArg(StringC(&c, 1)));
1056           val = 0;
1057           break;
1058         }
1059         else {
1060           val *= 10;
1061           val += weight;
1062         }
1063       }
1064       if (val > docSyntax_->quantity(quantityName)) {
1065         if (newMetaSyntax.isNull())
1066           newMetaSyntax = new Syntax(*docSyntax_);
1067         newMetaSyntax->setQuantity(quantityName, val);
1068       }
1069     }
1070   }
1071   if (!newMetaSyntax.isNull())
1072     metaSyntax_ = newMetaSyntax;
1073 }
1074
1075 Boolean ArcProcessor::processStartElement(const StartElementEvent &event,
1076                                           const AttributeList *linkAttributes,
1077                                           const Text *content,
1078                                           Allocator &allocator)
1079 {
1080   unsigned suppressFlags = (openElementFlags_.size() > 0
1081                             ? (openElementFlags_.back() & ~isArc)
1082                             : (unsigned)condIgnoreData);
1083   if ((suppressFlags & suppressForm)
1084       && (suppressFlags & suppressSupr)) {
1085     // Make this case efficient.
1086     openElementFlags_.push_back(suppressFlags);
1087     return 1;
1088   }
1089   const AttributeList &atts = event.attributes();
1090   const MetaMap &map = buildMetaMap(event.elementType(),
1091                                     0,
1092                                     atts,
1093                                     linkAttributes,
1094                                     suppressFlags);
1095   const ElementType *metaType;
1096   ConstPtr<AttributeValue> arcContent;
1097   if (map.attributed == 0) {
1098     if (!(tagLevel() == 0
1099           && !currentElement().isFinished())) {
1100       if (!arcContent.isNull()
1101           && (currentElement().declaredEmpty()
1102               || !currentElement().tryTransitionPcdata()))
1103         Messenger::message(ArcEngineMessages::invalidArcContent);
1104       openElementFlags_.push_back(map.suppressFlags);
1105       return 1;
1106     }
1107     metaType = metaDtd_->documentElementType();
1108     if (!notationSetArch_)
1109       mgr_->message(ArcEngineMessages::documentElementNotArc,
1110                     StringMessageArg(metaType->name()));
1111     attributeList_.init(metaType->attributeDef());
1112     attributeList_.finish(*this);
1113   }
1114   else {
1115     if (!mapAttributes(atts, linkAttributes, content, attributeList_,
1116                        arcContent, map))
1117       return 0;
1118     metaType = (const ElementType *)map.attributed;
1119     suppressFlags = map.suppressFlags;
1120   }
1121   StartElementEvent *genEvent
1122     = new (allocator) StartElementEvent(metaType,
1123                                         metaDtd_,
1124                                         &attributeList_,
1125                                         event.location(),
1126                                         0);
1127   if (notationSetArch_) {
1128     if (tagLevel() == 0
1129         && !currentElement().isFinished())
1130       currentElement().tryTransition(metaDtd_->documentElementType());
1131   }
1132   else if (metaType->definition()->undefined())
1133     Messenger::message(ArcEngineMessages::undefinedElement,
1134                        StringMessageArg(metaType->name()));
1135   else if (elementIsExcluded(metaType))
1136     Messenger::message(ArcEngineMessages::elementExcluded,
1137                        StringMessageArg(metaType->name()));
1138   else if (elementIsIncluded(metaType))
1139     genEvent->setIncluded();
1140   else if (!currentElement().tryTransition(metaType))
1141     Messenger::message(ArcEngineMessages::invalidElement,
1142                        StringMessageArg(metaType->name()));
1143                        
1144   pushElement(new (allocator) OpenElement(metaType,
1145                                           0,
1146                                           genEvent->included(),
1147                                           0,
1148                                           event.location()));
1149   docHandler_->startElement(genEvent);
1150   if (attributeList_.conref())
1151     currentElement().setConref();
1152   if (!arcContent.isNull() && arcContent->text() != 0) {
1153     if (currentElement().declaredEmpty()
1154         || !currentElement().tryTransitionPcdata())
1155       Messenger::message(ArcEngineMessages::invalidArcContent);
1156     else
1157       emitArcContent(*arcContent->text(), docHandler(), allocator);
1158     suppressFlags |= (suppressForm|suppressSupr|ignoreData);
1159   }
1160   suppressFlags &= ~recoverData;
1161   openElementFlags_.push_back(suppressFlags | isArc);
1162   return 1;
1163 }
1164
1165 void ArcProcessor::emitArcContent(const Text &text,
1166                                   EventHandler &handler,
1167                                   Allocator &allocator)
1168 {
1169   TextIter iter(text);
1170   TextItem::Type type;
1171   const Char *s;
1172   size_t n;
1173   const Location *loc;
1174   while (iter.next(type, s, n, loc))
1175     switch (type) {
1176     case TextItem::data:
1177     case TextItem::cdata:
1178       // +1 because first dataEvent is the non-architectural data.
1179       if (type == TextItem::data)
1180         handler.data(new (allocator) ImmediateDataEvent(Event::characterData,
1181                                                         s,
1182                                                         n,
1183                                                         *loc,
1184                                                         0));
1185       else
1186                           
1187         handler.data(new (allocator)
1188                      CdataEntityEvent(loc->origin()->asEntityOrigin()
1189                                       ->entity()->asInternalEntity(),
1190                                       loc->origin()));
1191       break;
1192     case TextItem::sdata:
1193                      
1194       handler.sdataEntity(new (allocator)
1195                           SdataEntityEvent(loc->origin()->asEntityOrigin()
1196                                            ->entity()->asInternalEntity(),
1197                                            loc->origin()));
1198       break;
1199     default:
1200       break;
1201     }
1202 }
1203
1204 Boolean ArcProcessor::processData()
1205 {
1206   if (openElementFlags_.size() > 0
1207       && (openElementFlags_.back() & ignoreData))
1208     return 0;
1209   if (notationSetArch_)
1210     return currentElement().type() != metaDtd_->documentElementType();
1211   else if (!currentElement().declaredEmpty()
1212            && currentElement().tryTransitionPcdata())
1213     return 1;
1214   else if (openElementFlags_.size() > 0
1215            && (openElementFlags_.back() & condIgnoreData))
1216     return 0;
1217   else {
1218     // Only give this error once per element
1219     if (openElementFlags_.size() > 0) {
1220       if (openElementFlags_.back() & recoverData)
1221         return 1;
1222       openElementFlags_.back() |= recoverData;
1223     }
1224     Messenger::message(ArcEngineMessages::invalidData);
1225     return 1;
1226   }
1227 }
1228
1229 Boolean ArcProcessor::mapAttributes(const AttributeList &from,
1230                                     const AttributeList *fromLink,
1231                                     const Text *content,
1232                                     AttributeList &to,
1233                                     ConstPtr<AttributeValue> &arcContent,
1234                                     const MetaMap &map)
1235 {
1236   if (map.attributed)
1237     to.init(map.attributed->attributeDef());
1238   for (size_t i = 0; i < map.attMapFrom.size(); i++) {
1239     unsigned fromIndex = map.attMapFrom[i];
1240     const AttributeList *fromList = &from;
1241     if (fromIndex != contentPseudoAtt && fromIndex >= fromList->size()) {
1242       fromList = fromLink;
1243       fromIndex -= from.size();
1244     }
1245     if (map.attMapTo[i] == contentPseudoAtt) {
1246       if (fromIndex != contentPseudoAtt)
1247         arcContent = fromList->valuePointer(fromIndex);
1248     }
1249     else {
1250       const Text *fromText = 0;
1251       Boolean fromTextTokenized = 0;
1252       if (map.attMapFrom[i] == contentPseudoAtt) {
1253         if (!content)
1254           return 0;
1255         fromText = content;
1256       }
1257       else {
1258         const AttributeValue *value = fromList->value(fromIndex);
1259         if (value) {
1260           fromText = value->text();
1261           fromTextTokenized = fromList->tokenized(fromIndex);
1262           if (fromText
1263               && fromList == &from
1264               && !from.specified(fromIndex)
1265               && (map.attributed->attributeDef()->def(map.attMapTo[i])
1266                   ->missingValueWouldMatch(*fromText, *this)))
1267             fromText = 0;
1268         }
1269       }
1270       if (fromText) {
1271         unsigned specLength = 0;
1272         Text tem;
1273         if (!fromTextTokenized && to.tokenized(map.attMapTo[i]))
1274           fromText->tokenize(docSyntax_->space(), tem);
1275         else
1276           tem = *fromText;
1277         to.setSpec(map.attMapTo[i], *this);
1278         to.setValue(map.attMapTo[i], tem, *this, specLength);
1279       }
1280     }
1281   }
1282   if (map.attributed)
1283     to.finish(*this);
1284   return 1;
1285 }
1286
1287 const ArcProcessor::MetaMap &
1288 ArcProcessor::buildMetaMap(const ElementType *docElementType,
1289                            const Notation *notation,
1290                            const AttributeList &atts,
1291                            const AttributeList *linkAtts,
1292                            unsigned suppressFlags)
1293 {
1294   Boolean isNotation;
1295   const Attributed *attributed = docElementType;
1296   const StringC *nameP;
1297   if (!attributed) {
1298     attributed = notation;
1299     isNotation = 1;
1300     nameP = &notation->name();
1301   }
1302   else {
1303     isNotation = 0;
1304     nameP = &docElementType->name();
1305   }
1306   // Try to use cached entry.
1307   Boolean inhibitCache = 0;
1308   size_t cacheIndex;
1309   if (isNotation || docElementType->definition()->undefined()) {
1310     inhibitCache = 1;
1311     cacheIndex = (unsigned)-1;
1312   }
1313   else {
1314     cacheIndex = docElementType->index();
1315     const MetaMapCache *cache = metaMapCache_[cacheIndex].pointer();
1316     if (cache
1317         && cache->suppressFlags == suppressFlags
1318         && cache->linkAtts == linkAtts) {
1319       for (int i = 0;; i++) {
1320         if (i == MetaMapCache::nNoSpec)
1321           return cache->map;
1322         unsigned attIndex = cache->noSpec[i];
1323         if (attIndex != invalidAtt && atts.specified(attIndex))
1324           break;
1325       }
1326     }
1327   }
1328   // no valid cached MetaMap
1329   // Handle suppression.
1330   unsigned oldSuppressFlags = suppressFlags;
1331   unsigned newSuppressFlags = suppressFlags;
1332   unsigned arcSuprIndex;
1333   if (!isNotation)
1334     considerSupr(atts, linkAtts, suppressFlags, newSuppressFlags, inhibitCache,
1335                  arcSuprIndex);
1336   else
1337     arcSuprIndex = invalidAtt;
1338   // Handle ArcIgnD
1339   unsigned arcIgnDIndex;
1340   if (!isNotation)
1341     considerIgnD(atts, linkAtts, suppressFlags, newSuppressFlags, inhibitCache,
1342                  arcIgnDIndex);
1343   else
1344     arcIgnDIndex = invalidAtt;
1345   // Handle ArcForm.
1346   unsigned arcFormIndex;
1347   const Attributed *metaAttributed
1348     = (notationSetArch_
1349        ? considerNotation(atts, suppressFlags, inhibitCache, arcFormIndex)
1350        : considerForm(atts, linkAtts, *nameP, isNotation,
1351                       suppressFlags, newSuppressFlags,
1352                       inhibitCache, arcFormIndex));
1353   // See if there's a renamer that will inhibit cacheing.
1354   unsigned arcNamerIndex;
1355   const Text *namerText;
1356   if (metaAttributed)
1357     namerText = considerNamer(atts, inhibitCache, arcNamerIndex);
1358   else {
1359     arcNamerIndex = invalidAtt;
1360     namerText = 0;
1361   }
1362   MetaMap *mapP;
1363   if (inhibitCache) {
1364     noCacheMetaMap_.clear();
1365     mapP = &noCacheMetaMap_;
1366   }
1367   else {
1368     MetaMapCache *cache = metaMapCache_[cacheIndex].pointer();
1369     if (cache)
1370       cache->clear();
1371     else {
1372       cache = new MetaMapCache;
1373       metaMapCache_[cacheIndex] = cache;
1374     }
1375     cache->noSpec[0] = arcFormIndex;
1376     cache->noSpec[1] = arcNamerIndex;
1377     cache->noSpec[2] = arcSuprIndex;
1378     cache->noSpec[3] = arcIgnDIndex;
1379     cache->suppressFlags = oldSuppressFlags;
1380     cache->linkAtts = linkAtts;
1381     mapP = &cache->map;
1382   }
1383   mapP->attributed = metaAttributed;
1384   mapP->suppressFlags = newSuppressFlags;
1385   // Build the attribute map.
1386   if (metaAttributed) {
1387     Vector<PackedBoolean> renamed;
1388     ConstPtr<AttributeDefinitionList> metaAttDef
1389       = metaAttributed->attributeDef();
1390     if (!metaAttDef.isNull())
1391       renamed.assign(metaAttDef->size(), PackedBoolean(0));
1392     if (linkAtts) {
1393       Boolean specified;
1394       unsigned index;
1395       const Text *linkNamerText = considerNamer(*linkAtts, specified, index);
1396       if (linkNamerText)
1397         buildAttributeMapRename(*mapP, *linkNamerText, atts, linkAtts, renamed);
1398     }
1399     if (namerText)
1400       buildAttributeMapRename(*mapP, *namerText, atts, 0, renamed);
1401     buildAttributeMapRest(*mapP, atts, linkAtts, renamed);
1402   }
1403   return *mapP;
1404 }
1405
1406 void ArcProcessor::considerSupr(const AttributeList &atts,
1407                                 const AttributeList *linkAtts,
1408                                 unsigned &thisSuppressFlags,
1409                                 unsigned &newSuppressFlags,
1410                                 Boolean &inhibitCache,
1411                                 unsigned &arcSuprIndex)
1412 {
1413   arcSuprIndex = invalidAtt;
1414   if (thisSuppressFlags & suppressSupr)
1415     return;
1416   if (!supportAtts_[rArcSuprA].size())
1417     return;
1418   const AttributeValue *val;
1419   unsigned tem;
1420   if (linkAtts && linkAtts->attributeIndex(supportAtts_[rArcSuprA], tem))
1421     val = linkAtts->value(tem);
1422   else if (atts.attributeIndex(supportAtts_[rArcSuprA], arcSuprIndex)) {
1423     if (atts.current(arcSuprIndex) || atts.specified(arcSuprIndex))
1424       inhibitCache = 1;
1425     val = atts.value(arcSuprIndex);
1426   }
1427   else
1428     return;
1429   if (!val)
1430     return;
1431   const Text *textP = val->text();
1432   if (!textP)
1433     return;
1434   StringC token = textP->string();
1435   // FIXME trim spaces
1436   docSyntax_->generalSubstTable()->subst(token);
1437   // sArcForm suppress processing for all elements except
1438   // those that have a non-implied ArcSupr attribute.
1439   thisSuppressFlags &= ~suppressForm;
1440   newSuppressFlags &= ~(suppressForm|suppressSupr);
1441   if (matchName(token, "sArcForm"))
1442     newSuppressFlags |= suppressForm;
1443 #if 0
1444   // I don't think this is useful
1445   else if (matchName(token, "sArcSupr"))
1446     newSuppressFlags |= suppressSupr;
1447 #endif
1448   else if (matchName(token, "sArcAll"))
1449     newSuppressFlags |= (suppressSupr|suppressForm);
1450   else if (!matchName(token, "sArcNone")) {
1451     Messenger::setNextLocation(textP->charLocation(0));
1452     Messenger::message(ArcEngineMessages::invalidSuppress,
1453                        StringMessageArg(token));
1454   }
1455 }
1456
1457 void ArcProcessor::considerIgnD(const AttributeList &atts,
1458                                 const AttributeList *linkAtts,
1459                                 unsigned thisSuppressFlags,
1460                                 unsigned &newSuppressFlags,
1461                                 Boolean &inhibitCache,
1462                                 unsigned &arcIgnDIndex)
1463 {
1464   arcIgnDIndex = invalidAtt;
1465   if (thisSuppressFlags & suppressSupr)
1466     return;
1467   if (!supportAtts_[rArcIgnDA].size())
1468     return;
1469   const AttributeValue *val;
1470   unsigned tem;
1471   if (linkAtts && linkAtts->attributeIndex(supportAtts_[rArcIgnDA], tem))
1472     val = linkAtts->value(tem);
1473   else if (atts.attributeIndex(supportAtts_[rArcIgnDA], arcIgnDIndex)) {
1474     if (atts.current(arcIgnDIndex) || atts.specified(arcIgnDIndex))
1475       inhibitCache = 1;
1476     val = atts.value(arcIgnDIndex);
1477   }
1478   else
1479     return;
1480   if (!val)
1481     return;
1482   const Text *textP = val->text();
1483   if (!textP)
1484     return;
1485   StringC token = textP->string();
1486   // FIXME trim spaces
1487   docSyntax_->generalSubstTable()->subst(token);
1488   newSuppressFlags &= ~(ignoreData|condIgnoreData);
1489   if (matchName(token, "ArcIgnD"))
1490     newSuppressFlags |= ignoreData;
1491   else if (matchName(token, "cArcIgnD"))
1492     newSuppressFlags |= condIgnoreData;
1493   else if (!matchName(token, "nArcIgnD")) {
1494     Messenger::setNextLocation(textP->charLocation(0));
1495     Messenger::message(ArcEngineMessages::invalidIgnD,
1496                        StringMessageArg(token));
1497   }
1498 }
1499
1500 const Attributed *
1501 ArcProcessor::considerNotation(const AttributeList &atts,
1502                                unsigned thisSuppressFlags,
1503                                Boolean &inhibitCache,
1504                                unsigned &notAttIndex)
1505 {
1506   if (thisSuppressFlags & suppressForm)
1507     return 0;
1508   for (unsigned i = 0; i < atts.size(); i++) {
1509     const AttributeSemantics *sem = atts.semantics(i);
1510     if (sem) {
1511       ConstPtr<Notation> notation = sem->notation();
1512       if (!notation.isNull()) {
1513         notAttIndex = i;
1514         if (atts.current(notAttIndex) || atts.specified(notAttIndex))
1515           inhibitCache = 1;
1516         return metaDtd_->lookupElementType(notation->name());
1517       }
1518     }
1519   }
1520   notAttIndex = invalidAtt;
1521   return 0;
1522 }
1523
1524 const Attributed *
1525 ArcProcessor::considerForm(const AttributeList &atts,
1526                            const AttributeList *linkAtts,
1527                            const StringC &name,
1528                            Boolean isNotation,
1529                            unsigned thisSuppressFlags,
1530                            unsigned &newSuppressFlags,
1531                            Boolean &inhibitCache,
1532                            unsigned &arcFormIndex)
1533 {
1534   arcFormIndex = invalidAtt;
1535   if ((thisSuppressFlags & suppressForm)
1536       && (supportAtts_[rArcSuprF].size() == 0
1537           || (thisSuppressFlags & suppressSupr)
1538           || isNotation))
1539     return 0;
1540   unsigned tem;
1541   const AttributeValue *val;
1542   if (linkAtts && linkAtts->attributeIndex(supportAtts_[rArcFormA], tem))
1543     val = linkAtts->value(tem);
1544   else if (atts.attributeIndex(supportAtts_[rArcFormA], arcFormIndex)) {
1545     if (atts.current(arcFormIndex) || atts.specified(arcFormIndex))
1546       inhibitCache = 1;
1547     val = atts.value(arcFormIndex);
1548   }
1549   else
1550     return autoForm(atts, name, isNotation,
1551                     thisSuppressFlags, newSuppressFlags,
1552                     inhibitCache, arcFormIndex);
1553     
1554   if (!val)
1555     return 0;
1556   const Text *textP = val->text();
1557   if (!textP)
1558     return 0;
1559   StringC metaName;
1560   metaName = textP->string();
1561   // FIXME should trim leading and trailing spaces
1562   metaSyntax_->generalSubstTable()->subst(metaName);
1563   if (!isNotation) {
1564     const Attributed *metaAttributed = metaDtd_->lookupElementType(metaName);
1565     if (!metaAttributed)
1566       metaAttributed = lookupCreateUndefinedElement(metaName, Location());
1567     if (metaName == supportAtts_[rArcSuprF]) {
1568       newSuppressFlags |= suppressForm;
1569       return metaAttributed;
1570     }
1571     if (thisSuppressFlags & suppressForm)
1572       return 0;
1573     return metaAttributed;
1574   }
1575   else
1576     return metaDtd_->lookupNotation(metaName).pointer();
1577 }
1578
1579 const Attributed *
1580 ArcProcessor::autoForm(const AttributeList &atts,
1581                        const StringC &name,
1582                        Boolean isNotation,
1583                        unsigned thisSuppressFlags,
1584                        unsigned &newSuppressFlags,
1585                        Boolean &inhibitCache,
1586                        unsigned &idIndex)
1587 {
1588   if (!isNotation) {
1589     const Attributed *metaAttributed;
1590     if (openElementFlags_.size() == 0) {
1591       metaAttributed = metaDtd_->documentElementType();
1592       inhibitCache = 1;
1593     }
1594     else {
1595       metaAttributed = 0;
1596       if (arcAuto_)
1597         metaAttributed = metaDtd_->lookupElementType(name);
1598       if (!metaAttributed
1599           && supportAtts_[rArcBridF].size() > 0
1600           && atts.idIndex(idIndex)
1601           && atts.specified(idIndex)) {
1602         inhibitCache = 1;
1603         metaAttributed
1604           = metaDtd_->lookupElementType(supportAtts_[rArcBridF]);
1605       }
1606     }
1607     if (metaAttributed
1608         && name == supportAtts_[rArcSuprF]) {
1609       newSuppressFlags = suppressForm|ignoreData;
1610     }
1611     else if (thisSuppressFlags & suppressForm)
1612       return 0;
1613     return metaAttributed;
1614   }
1615   else if (thisSuppressFlags & suppressForm)
1616     return 0;
1617   else {
1618     const Attributed *metaAttributed = 0;
1619     if (arcAuto_)
1620       metaAttributed = metaDtd_->lookupNotation(name).pointer();
1621     if (!metaAttributed && supportAtts_[rArcDataF].size() > 0)
1622       metaAttributed
1623         = metaDtd_->lookupNotation(supportAtts_[rArcDataF]).pointer();
1624     return metaAttributed;
1625   }
1626 }
1627
1628
1629 const Text *
1630 ArcProcessor::considerNamer(const AttributeList &atts,
1631                             Boolean &inhibitCache,
1632                             unsigned &arcNamerIndex)
1633 {
1634   arcNamerIndex = invalidAtt;
1635   if (supportAtts_[rArcNamrA].size() == 0
1636       || !atts.attributeIndex(supportAtts_[rArcNamrA], arcNamerIndex))
1637     return 0;
1638   if (atts.current(arcNamerIndex) || atts.specified(arcNamerIndex))
1639     inhibitCache = 1;
1640   const AttributeValue *val = atts.value(arcNamerIndex);
1641   if (!val)
1642     return 0;
1643   return val->text();
1644 }
1645
1646 void ArcProcessor::buildAttributeMapRename(MetaMap &map,
1647                                            const Text &rename,
1648                                            const AttributeList &atts,
1649                                            const AttributeList *linkAtts,
1650                                            Vector<PackedBoolean> &attRenamed)
1651 {
1652   Vector<StringC> tokens;
1653   Vector<size_t> tokensPos;
1654   split(rename, docSyntax_->space(), tokens, tokensPos);
1655   ConstPtr<AttributeDefinitionList> metaAttDef;
1656   if (map.attributed)
1657     metaAttDef = map.attributed->attributeDef();
1658   // FIXME Should check that ARCCONT doesn't appear more than once.
1659   for (size_t i = 0; i < tokens.size(); i += 2) {
1660     unsigned fromIndex = invalidAtt;
1661     unsigned toIndex = invalidAtt;
1662     metaSyntax_->generalSubstTable()->subst(tokens[i]);
1663     if (tokens[i] == rniArcCont_)
1664       toIndex = contentPseudoAtt;
1665     else if (metaAttDef.isNull()
1666              || !metaAttDef->attributeIndex(tokens[i], toIndex)) {
1667       setNextLocation(rename.charLocation(tokensPos[i]));
1668       Messenger::message(ArcEngineMessages::renameToInvalid,
1669                          StringMessageArg(tokens[i]));
1670     }
1671     else if (attRenamed[toIndex]) {
1672       toIndex = invalidAtt;
1673       setNextLocation(rename.charLocation(tokensPos[i]));
1674       Messenger::message(ArcEngineMessages::renameToDuplicate,
1675                          StringMessageArg(tokens[i]));
1676     }
1677     if (i + 1 >= tokens.size()) {
1678       setNextLocation(rename.charLocation(tokensPos[i]));
1679       Messenger::message(ArcEngineMessages::renameMissingAttName);
1680     }
1681     else {
1682       docSyntax_->generalSubstTable()->subst(tokens[i + 1]);
1683       if (tokens[i + 1] == rniContent_) {
1684         fromIndex = contentPseudoAtt;
1685       }
1686       else if (tokens[i + 1] == rniDefault_) {
1687         if (toIndex != contentPseudoAtt)
1688           attRenamed[toIndex] = 1;
1689       }
1690       else if (linkAtts
1691                && linkAtts->attributeIndex(tokens[i + 1], fromIndex))
1692         fromIndex += atts.size();
1693       else if (!atts.attributeIndex(tokens[i + 1], fromIndex)) {
1694         setNextLocation(rename.charLocation(tokensPos[i + 1]));
1695         Messenger::message(ArcEngineMessages::renameFromInvalid,
1696                            StringMessageArg(tokens[i + 1]));
1697       }
1698     }
1699     if (fromIndex != invalidAtt && toIndex != invalidAtt) {
1700       map.attMapFrom.push_back(fromIndex);
1701       map.attMapTo.push_back(toIndex);
1702       if (toIndex != contentPseudoAtt) {
1703         attRenamed[toIndex] = 1;
1704         if (metaAttDef->def(toIndex)->isId()
1705             && (fromIndex >= atts.size() || !atts.id(fromIndex)))
1706           Messenger::message(ArcEngineMessages::idMismatch,
1707                              StringMessageArg(metaAttDef->def(toIndex)
1708                                               ->name()));
1709       }
1710     }
1711   }
1712 }
1713
1714 void ArcProcessor::buildAttributeMapRest(MetaMap &map,
1715                                          const AttributeList &atts,
1716                                          const AttributeList *linkAtts,
1717                                          const Vector<PackedBoolean> &attRenamed)
1718 {
1719   ConstPtr<AttributeDefinitionList> metaAttDef
1720     = map.attributed->attributeDef();
1721   if (metaAttDef.isNull())
1722     return;
1723   for (unsigned i = 0; i < metaAttDef->size(); i++)
1724     if (!attRenamed[i]) {
1725       unsigned fromIndex;
1726       if (metaAttDef->def(i)->isId()) {
1727         for (unsigned j = 0; j < atts.size(); j++)
1728           if (atts.id(j)) {
1729             map.attMapFrom.push_back(j);
1730             map.attMapTo.push_back(i);
1731             break;
1732           }
1733       }
1734       else if (linkAtts && linkAtts->attributeIndex(metaAttDef->def(i)->name(),
1735                                                     fromIndex)) {
1736         map.attMapFrom.push_back(fromIndex + atts.size());
1737         map.attMapTo.push_back(i);
1738       }
1739       else if (atts.attributeIndex(metaAttDef->def(i)->name(), fromIndex)) {
1740         map.attMapFrom.push_back(fromIndex);
1741         map.attMapTo.push_back(i);
1742       }
1743     }
1744 }
1745
1746 Boolean ArcProcessor::matchName(const StringC &name, const char *key)
1747 {
1748   if (name.size() != strlen(key))
1749     return 0;
1750   StringC tem(docSd_->execToDoc(key));
1751   docSyntax_->generalSubstTable()->subst(tem);
1752   return name == tem;
1753 }
1754
1755 void ArcProcessor::split(const Text &text,
1756                          Char space,
1757                          Vector<StringC> &tokens,
1758                          Vector<size_t> &tokensPos)
1759 {
1760   const StringC &str = text.string();
1761   for (size_t i = 0;;) {
1762     for (; i < str.size() && str[i] == space; i++)
1763       ;
1764     if (i >= str.size())
1765       break;
1766     size_t start = i;
1767     for (; i < str.size() && str[i] != space; i++)
1768       ;
1769     tokens.push_back(StringC(str.data() + start, i - start));
1770     tokensPos.push_back(start);
1771   }
1772 }
1773
1774 void ArcProcessor::processEndElement(const EndElementEvent &event,
1775                                      Allocator &allocator)
1776 {
1777   Boolean wasArc = (openElementFlags_.back() & isArc);
1778   openElementFlags_.resize(openElementFlags_.size() - 1);
1779   if (wasArc) {
1780     EndElementEvent *genEvent
1781       = new (allocator) EndElementEvent(currentElement().type(),
1782                                         metaDtd_,
1783                                         event.location(),
1784                                         0);
1785     if (currentElement().included())
1786       genEvent->setIncluded();
1787     docHandler_->endElement(genEvent);
1788     if (!currentElement().isFinished())
1789       Messenger::message(ArcEngineMessages::unfinishedElement,
1790                          StringMessageArg(currentElement().type()->name()));
1791     popElement();
1792   }
1793 }
1794
1795 void ArcProcessor::dispatchMessage(Message &msg)
1796 {
1797   mgr_->dispatchMessage(msg);
1798 }
1799
1800 void ArcProcessor::dispatchMessage(const Message &msg)
1801 {
1802   mgr_->dispatchMessage(msg);
1803 }
1804
1805 void ArcProcessor::initMessage(Message &msg)
1806 {
1807   mgr_->initMessage(msg);
1808   if (valid_) {
1809     StringC rniPcdata = metaSyntax_->delimGeneral(Syntax::dRNI);
1810     rniPcdata += metaSyntax_->reservedName(Syntax::rPCDATA);
1811     getOpenElementInfo(msg.openElementInfo, rniPcdata);
1812   }
1813 }
1814
1815 ArcProcessor::MetaMapCache::MetaMapCache()
1816 {
1817   for (int i = 0; i < nNoSpec; i++)
1818     noSpec[i] = invalidAtt;
1819   linkAtts = 0;
1820 }
1821
1822 void ArcProcessor::MetaMapCache::clear()
1823 {
1824   for (int i = 0; i < nNoSpec; i++)
1825     noSpec[i] = invalidAtt;
1826   linkAtts = 0;
1827   map.clear();
1828 }
1829
1830 ArcProcessor::MetaMap::MetaMap()
1831 : attributed(0)
1832 {
1833 }
1834
1835 void ArcProcessor::MetaMap::clear()
1836 {
1837   attMapFrom.clear();
1838   attMapTo.clear();
1839   attributed = 0;
1840 }
1841
1842 #ifdef SP_NAMESPACE
1843 }
1844 #endif