1 // Copyright (c) 1996 James Clark
2 // See the file copying.txt for copying permission.
3 
4 #include "stylelib.h"
5 #include "DssslSpecEventHandler.h"
6 #include "InterpreterMessages.h"
7 #include "InternalInputSource.h"
8 #include "FOTBuilder.h"
9 #include "macros.h"
10 
11 #ifdef DSSSL_NAMESPACE
12 namespace DSSSL_NAMESPACE {
13 #endif
14 
15 // FIXME Stop parsing spec when we know we don't we have everything we ever need
16 
17 class TextInputSourceOrigin : public InputSourceOrigin {
18 public:
19   TextInputSourceOrigin(Text &text);
20   Boolean defLocation(Offset off, const Origin *&, Index &) const;
text() const21   const Text &text() const { return text_; }
noteCharRef(Index,const NamedCharRef &)22   void noteCharRef(Index, const NamedCharRef &) {
23     CANNOT_HAPPEN();
24   }
setExternalInfo(ExternalInfo *)25   void setExternalInfo(ExternalInfo *) {
26     CANNOT_HAPPEN();
27   }
copy() const28   InputSourceOrigin *copy() const { return new TextInputSourceOrigin(*this); }
parent() const29   const Location &parent() const { return refLocation_; }
30 private:
31   Text text_;
32   Location refLocation_;
33 };
34 
DssslSpecEventHandler(Messenger & mgr)35 DssslSpecEventHandler::DssslSpecEventHandler(Messenger &mgr)
36 : mgr_(&mgr), gatheringBody_(0)
37 {
38 }
39 
load(SgmlParser & specParser,const CharsetInfo & charset,const StringC & id,Vector<Part * > & parts)40 void DssslSpecEventHandler::load(SgmlParser &specParser,
41 				 const CharsetInfo &charset,
42 				 const StringC &id,
43 				 Vector<Part *> &parts)
44 {
45   parser_ = &specParser;
46   charset_ = &charset;
47   Doc *doc = findDoc(StringC());
48   // Load it now so that we can get the concrete syntax.
49   doc->load(*this);
50   Part *tem;
51   if (id.size() == 0)
52     tem = doc->resolveFirstPart(*this);
53   else {
54     StringC normId(id);
55     ConstPtr<Syntax> syn = parser_->instanceSyntax();
56     if (!syn.isNull())
57       syn->generalSubstTable()->subst(normId);
58     tem = doc->refPart(normId)->resolve(*this);
59   }
60   resolveParts(tem, parts);
61 }
62 
findDoc(const StringC & sysid)63 DssslSpecEventHandler::Doc *DssslSpecEventHandler::findDoc(const StringC &sysid)
64 {
65   for (IListIter<Doc> iter(docs_); !iter.done(); iter.next())
66     if (sysid == iter.cur()->sysid())
67       return iter.cur();
68   Doc *doc = new Doc(sysid);
69   docs_.insert(doc);
70   return doc;
71 }
72 
resolveParts(Part * part,Vector<Part * > & parts)73 void DssslSpecEventHandler::resolveParts(Part *part,
74 					 Vector<Part *> &parts)
75 {
76   if (!part)
77     return;
78   parts.push_back(part);
79   if (part->setMark()) {
80     mgr_->message(InterpreterMessages::useLoop);
81     return;
82   }
83   const Vector<PartHeader *> &use = part->use();
84   for (size_t i = 0; i < use.size(); i++) {
85     Part *tem = use[i]->resolve(*this);
86     resolveParts(tem, parts);
87   }
88   part->setMark(0);
89 }
90 
loadDoc(SgmlParser & parser,Doc & doc)91 void DssslSpecEventHandler::loadDoc(SgmlParser &parser, Doc &doc)
92 {
93   currentDoc_ = &doc;
94   gotArc_ = 0;
95   ArcEngine::parseAll(parser, *mgr_, *this, cancelPtr());
96   if (!gotArc_) {
97     mgr_->message(InterpreterMessages::specNotArc);
98     return;
99   }
100 }
101 
102 
103 EventHandler *
arcEventHandler(const Notation * notation,const Vector<StringC> &,const SubstTable<Char> *)104 DssslSpecEventHandler::arcEventHandler(const Notation *notation,
105 				       const Vector<StringC> &,
106 				       const SubstTable<Char> *)
107 {
108   if (!notation)
109     return 0;
110   const StringC *pubid = notation->externalId().publicIdString();
111   static const char dssslArc[]
112     = "ISO/IEC 10179:1996//NOTATION DSSSL Architecture Definition Document//EN";
113   if (pubid == 0 || pubid->size() != sizeof(dssslArc) - 1)
114     return 0;
115   for (int i = 0; dssslArc[i] != '\0'; i++) {
116     if (dssslArc[i] != (*pubid)[i])
117       return 0;
118   }
119   gotArc_ = 1;
120   return this;
121 }
122 
message(MessageEvent * event)123 void DssslSpecEventHandler::message(MessageEvent *event)
124 {
125   mgr_->dispatchMessage(event->message());
126   delete event;
127 }
128 
129 static struct {
130   const char *gi;
131   void (DssslSpecEventHandler::*start)(const StartElementEvent &);
132   void (DssslSpecEventHandler::*end)(const EndElementEvent &);
133 } mappingTable[] = {
134   { "STYLE-SPECIFICATION",
135     &DssslSpecEventHandler::styleSpecificationStart,
136     &DssslSpecEventHandler::styleSpecificationEnd },
137   { "STYLE-SPECIFICATION-BODY",
138     &DssslSpecEventHandler::styleSpecificationBodyStart,
139     &DssslSpecEventHandler::styleSpecificationBodyEnd },
140   { "EXTERNAL-SPECIFICATION",
141     &DssslSpecEventHandler::externalSpecificationStart,
142     &DssslSpecEventHandler::externalSpecificationEnd },
143 };
144 
endProlog(EndPrologEvent * event)145 void DssslSpecEventHandler::endProlog(EndPrologEvent *event)
146 {
147   currentDoc_->setLocation(event->location());
148   delete event;
149 }
150 
startElement(StartElementEvent * event)151 void DssslSpecEventHandler::startElement(StartElementEvent *event)
152 {
153   for (size_t i = 0; i < SIZEOF(mappingTable); i++)
154     if (event->name() == mappingTable[i].gi) {
155       (this->*(mappingTable[i].start))(*event);
156       break;
157     }
158   delete event;
159 }
160 
endElement(EndElementEvent * event)161 void DssslSpecEventHandler::endElement(EndElementEvent *event)
162 {
163   for (size_t i = 0; i < SIZEOF(mappingTable); i++)
164     if (event->name() == mappingTable[i].gi) {
165       (this->*(mappingTable[i].end))(*event);
166       break;
167     }
168   delete event;
169 }
170 
data(DataEvent * event)171 void DssslSpecEventHandler::data(DataEvent *event)
172 {
173   if (gatheringBody_)
174     currentBody_.addChars(event->data(), event->dataLength(), event->location());
175   delete event;
176 }
177 
178 const Text *
attributeText(const StartElementEvent & event,const char * attName)179 DssslSpecEventHandler::attributeText(const StartElementEvent &event,
180 				     const char *attName)
181 {
182   const AttributeList &atts = event.attributes();
183   StringC attNameString;
184   for (const char *p = attName; *p; p++)
185     attNameString += Char(*p);
186   unsigned index;
187   if (atts.attributeIndex(attNameString, index)) {
188     const AttributeValue *val = atts.value(index);
189     if (val)
190       return val->text();
191   }
192   return 0;
193 }
194 
195 const StringC *
attributeString(const StartElementEvent & event,const char * attName)196 DssslSpecEventHandler::attributeString(const StartElementEvent &event,
197 				       const char *attName)
198 {
199   const Text *text = attributeText(event, attName);
200   if (text)
201     return &text->string();
202   else
203     return 0;
204 }
205 
206 ConstPtr<Entity>
attributeEntity(const StartElementEvent & event,const char * attName)207 DssslSpecEventHandler::attributeEntity(const StartElementEvent &event,
208 				       const char *attName)
209 {
210   const AttributeList &atts = event.attributes();
211   StringC attNameString;
212   for (const char *p = attName; *p; p++)
213     attNameString += Char(*p);
214   unsigned index;
215   if (!atts.attributeIndex(attNameString, index))
216     return 0;
217   const AttributeSemantics *sem = atts.semantics(index);
218   if (!sem || sem->nEntities() != 1)
219     return 0;
220   return sem->entity(0);
221 }
222 
externalSpecificationStart(const StartElementEvent & event)223 void DssslSpecEventHandler::externalSpecificationStart(const StartElementEvent &event)
224 {
225   StringC empty;
226   const StringC *idP = attributeString(event, "ID");
227   if (!idP)
228     idP = &empty;
229   PartHeader *header = currentDoc_->refPart(*idP);
230   const Entity *ent = attributeEntity(event, "DOCUMENT").pointer();
231   if (!ent)
232     return;
233   const ExternalEntity *ext = ent->asExternalEntity();
234   if (!ext)
235     return;
236   const StringC &sysid = ext->externalId().effectiveSystemId();
237   if (sysid.size()) {
238     Doc *doc = findDoc(sysid);
239     const StringC *specidP = attributeString(event, "SPECID");
240     if (!specidP)
241       header->setPart(new ExternalFirstPart(doc));
242     else
243       header->setPart(new ExternalPart(doc->refPart(*specidP, event.location())));
244   }
245 }
246 
externalSpecificationEnd(const EndElementEvent &)247 void DssslSpecEventHandler::externalSpecificationEnd(const EndElementEvent &)
248 {
249   // nothing to do
250 }
251 
styleSpecificationStart(const StartElementEvent & event)252 void DssslSpecEventHandler::styleSpecificationStart(const StartElementEvent &event)
253 {
254   StringC empty;
255   const StringC *idP = attributeString(event, "ID");
256   if (!idP)
257     idP = &empty;
258   PartHeader *header = currentDoc_->refPart(*idP);
259   // FIXME give an error (or ignore) if header has part already
260   const Text *useP = attributeText(event, "USE");
261   header->setPart(currentPart_ = new Part);
262   if (useP) {
263     const StringC &use = useP->string();
264     size_t i = 0;
265     for (;;) {
266       size_t j;
267       for (j = i; j < use.size() && use[j] != ' '; j++)
268 	;
269       if (j > i)
270 	currentPart_->addUse(currentDoc_->refPart(StringC(use.data() + i,
271 							  j - i),
272 						  useP->charLocation(i)));
273       if (j >= use.size())
274 	break;
275       i = j + 1;
276     }
277   }
278   // FIXME Give warning if selected part is incomplete
279 }
280 
styleSpecificationEnd(const EndElementEvent & event)281 void DssslSpecEventHandler::styleSpecificationEnd(const EndElementEvent &event)
282 {
283   currentPart_ = 0;
284 }
285 
styleSpecificationBodyStart(const StartElementEvent & event)286 void DssslSpecEventHandler::styleSpecificationBodyStart(const StartElementEvent &event)
287 {
288   if (currentPart_) {
289     currentBody_.clear();
290     ConstPtr<Entity> entity = attributeEntity(event, "CONTENT");
291     if (entity.isNull())
292       gatheringBody_ = 1;
293     else
294       currentPart_->append(new EntityBodyElement(entity));
295   }
296 }
297 
styleSpecificationBodyEnd(const EndElementEvent & event)298 void DssslSpecEventHandler::styleSpecificationBodyEnd(const EndElementEvent &event)
299 {
300   if (gatheringBody_) {
301     if (currentPart_)
302       currentPart_->append(new ImmediateBodyElement(currentBody_));
303     gatheringBody_ = 0;
304   }
305 }
306 
TextInputSourceOrigin(Text & text)307 TextInputSourceOrigin::TextInputSourceOrigin(Text &text)
308 {
309   text_.swap(text);
310 }
311 
defLocation(Offset off,const Origin * & origin,Index & index) const312 Boolean TextInputSourceOrigin::defLocation(Offset off, const Origin *&origin, Index &index) const
313 {
314   return text_.charLocation(off, origin, index);
315 }
316 
Doc()317 DssslSpecEventHandler::Doc::Doc()
318 : loaded_(0)
319 {
320 }
321 
Doc(const StringC & sysid)322 DssslSpecEventHandler::Doc::Doc(const StringC &sysid)
323 : sysid_(sysid), loaded_(0)
324 {
325 }
326 
setLocation(const Location & loc)327 void DssslSpecEventHandler::Doc::setLocation(const Location &loc)
328 {
329   loc_ = loc;
330 }
331 
332 DssslSpecEventHandler::Part *
resolveFirstPart(DssslSpecEventHandler & eh)333 DssslSpecEventHandler::Doc::resolveFirstPart(DssslSpecEventHandler &eh)
334 {
335   load(eh);
336   PartHeader *header = 0;
337   for (IListIter<PartHeader> iter(headers_); !iter.done(); iter.next())
338     header = iter.cur();
339   if (!header) {
340     if (!loc_.origin().isNull()) {
341       eh.mgr_->setNextLocation(loc_);
342       eh.mgr_->message(InterpreterMessages::noParts);
343     }
344     return 0;
345   }
346   return header->resolve(eh);
347 }
348 
load(DssslSpecEventHandler & eh)349 void DssslSpecEventHandler::Doc::load(DssslSpecEventHandler &eh)
350 {
351   if (loaded_)
352     return;
353   loaded_ = 1;
354   if (sysid_.size() > 0) {
355     SgmlParser::Params params;
356     params.parent = eh.parser_;
357     params.sysid = sysid_;
358     SgmlParser specParser(params);
359     eh.loadDoc(specParser, *this);
360   }
361   else
362     eh.loadDoc(*eh.parser_, *this);
363 }
364 
365 DssslSpecEventHandler::PartHeader *
refPart(const StringC & id)366 DssslSpecEventHandler::Doc::refPart(const StringC &id)
367 {
368   for (IListIter<PartHeader> iter(headers_); !iter.done(); iter.next())
369     if (iter.cur()->id() == id)
370       return iter.cur();
371   PartHeader *header = new PartHeader(this, id);
372   headers_.insert(header);
373   return header;
374 }
375 
376 DssslSpecEventHandler::PartHeader *
refPart(const StringC & id,const Location & refLoc)377 DssslSpecEventHandler::Doc::refPart(const StringC &id, const Location &refLoc)
378 {
379   PartHeader *header = refPart(id);
380   header->setRefLoc(refLoc);
381   return header;
382 }
383 
~BodyElement()384 DssslSpecEventHandler::BodyElement::~BodyElement()
385 {
386 }
387 
ImmediateBodyElement(Text & text)388 DssslSpecEventHandler::ImmediateBodyElement::ImmediateBodyElement(Text &text)
389 {
390   text_.swap(text);
391 }
392 
393 void DssslSpecEventHandler
makeInputSource(DssslSpecEventHandler &,Owner<InputSource> & in)394 ::ImmediateBodyElement::makeInputSource(DssslSpecEventHandler &, Owner<InputSource> &in)
395 {
396   TextInputSourceOrigin *origin = new TextInputSourceOrigin(text_);
397   in = new InternalInputSource(origin->text().string(), origin);
398 }
399 
400 DssslSpecEventHandler
EntityBodyElement(const ConstPtr<Entity> & entity)401 ::EntityBodyElement::EntityBodyElement(const ConstPtr<Entity> &entity)
402 : entity_(entity)
403 {
404 }
405 
406 void DssslSpecEventHandler
makeInputSource(DssslSpecEventHandler & eh,Owner<InputSource> & in)407 ::EntityBodyElement::makeInputSource(DssslSpecEventHandler &eh,
408 				     Owner<InputSource> &in)
409 {
410   const InternalEntity *internal = entity_->asInternalEntity();
411   if (internal) {
412     in = new InternalInputSource(internal->string(),
413 			         EntityOrigin::make(entity_, Location()));
414     return;
415   }
416   const StringC &sysid
417     = entity_->asExternalEntity()->externalId().effectiveSystemId();
418   if (sysid.size())
419     in = eh.parser_->entityManager().open(sysid, *eh.charset_, InputSourceOrigin::make(),
420 					  0, *eh.mgr_);
421 }
422 
PartHeader(Doc * doc,const StringC & id)423 DssslSpecEventHandler::PartHeader::PartHeader(Doc *doc, const StringC &id)
424 : doc_(doc), id_(id)
425 {
426 }
427 
setRefLoc(const Location & loc)428 void DssslSpecEventHandler::PartHeader::setRefLoc(const Location &loc)
429 {
430   if (refLoc_.origin().isNull())
431     refLoc_ = loc;
432 }
433 
434 DssslSpecEventHandler::Part *
resolve(DssslSpecEventHandler & eh)435 DssslSpecEventHandler::PartHeader::resolve(DssslSpecEventHandler &eh)
436 {
437   doc_->load(eh);
438   if (!specPart_) {
439     eh.mgr_->setNextLocation(refLoc_);
440     eh.mgr_->message(InterpreterMessages::missingPart, StringMessageArg(id_));
441     return 0;
442   }
443   return specPart_->resolve(eh);
444 }
445 
~SpecPart()446 DssslSpecEventHandler::SpecPart::~SpecPart()
447 {
448 }
449 
ExternalPart(PartHeader * header)450 DssslSpecEventHandler::ExternalPart::ExternalPart(PartHeader *header)
451 : header_(header)
452 {
453 }
454 
455 DssslSpecEventHandler::Part *
resolve(DssslSpecEventHandler & eh)456 DssslSpecEventHandler::ExternalPart::resolve(DssslSpecEventHandler &eh)
457 {
458   return header_->resolve(eh);
459 }
460 
ExternalFirstPart(Doc * doc)461 DssslSpecEventHandler::ExternalFirstPart::ExternalFirstPart(Doc *doc)
462 : doc_(doc)
463 {
464 }
465 
466 DssslSpecEventHandler::Part *
resolve(DssslSpecEventHandler & eh)467 DssslSpecEventHandler::ExternalFirstPart::resolve(DssslSpecEventHandler &eh)
468 {
469   return doc_->resolveFirstPart(eh);
470 }
471 
Part()472 DssslSpecEventHandler::Part::Part()
473 : mark_(0)
474 {
475 }
476 
477 DssslSpecEventHandler::Part *
resolve(DssslSpecEventHandler &)478 DssslSpecEventHandler::Part::resolve(DssslSpecEventHandler &)
479 {
480   return this;
481 }
482 
append(BodyElement * element)483 void DssslSpecEventHandler::Part::append(BodyElement *element)
484 {
485   bodyElements_.append(element);
486 }
487 
488 #ifdef DSSSL_NAMESPACE
489 }
490 #endif
491