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 = ∅
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 = ∅
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