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