2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: SgmlsEventHandler.C /main/1 1996/07/29 17:04:20 cde-hp $ */
24 // Copyright (c) 1994 James Clark
25 // See the file COPYING for copying permission.
28 #include "SgmlsEventHandler.h"
29 #include "SgmlParser.h"
30 #include "ParserOptions.h"
33 #include "Attribute.h"
34 #include "ExtendEntityManager.h"
35 #include "StorageManager.h"
39 namespace SP_NAMESPACE {
42 const char dataCode = '-';
43 const char piCode = '?';
44 const char conformingCode = 'C';
45 const char appinfoCode = '#';
46 const char startElementCode = '(';
47 const char endElementCode = ')';
48 const char referenceEntityCode = '&';
49 const char attributeCode = 'A';
50 const char dataAttributeCode = 'D';
51 const char linkAttributeCode = 'a';
52 const char defineNotationCode = 'N';
53 const char defineExternalEntityCode = 'E';
54 const char defineInternalEntityCode = 'I';
55 const char defineSubdocEntityCode = 'S';
56 const char defineExternalTextEntityCode = 'T';
57 const char pubidCode = 'p';
58 const char sysidCode = 's';
59 const char startSubdocCode = '{';
60 const char endSubdocCode = '}';
61 const char fileCode = 'f';
62 const char locationCode = 'L';
63 const char includedElementCode = 'i';
65 const OutputCharStream::Newline nl = OutputCharStream::newline;
67 const char space = ' ';
71 void SgmlsEventHandler::startData()
80 void SgmlsEventHandler::flushData()
89 void SgmlsEventHandler::outputLocation(const Location &loc)
95 SgmlsEventHandler::SgmlsEventHandler(const SgmlParser *parser,
99 : SgmlsSubdocState(parser), os_(os), messenger_(messenger),
100 outputLine_((outputFlags & outputLine) != 0),
101 outputEntity_((outputFlags & outputEntity) != 0),
102 outputId_((outputFlags & outputId) != 0),
103 outputNotationSysid_((outputFlags & outputNotationSysid) != 0),
104 outputIncluded_((outputFlags & outputIncluded) != 0),
105 haveData_(0), lastSos_(0), lastLineno_(0)
107 os_->setEscaper(escape);
110 SgmlsEventHandler::~SgmlsEventHandler()
113 if (errorCount() == 0)
114 os() << conformingCode << nl;
118 void SgmlsEventHandler::message(MessageEvent *event)
120 messenger_->dispatchMessage(event->message());
121 ErrorCountEventHandler::message(event);
124 void SgmlsEventHandler::appinfo(AppinfoEvent *event)
127 if (event->literal(str)) {
128 outputLocation(event->location());
137 void SgmlsEventHandler::endProlog(EndPrologEvent *event)
141 const Dtd &dtd = event->dtd();
142 Dtd::ConstEntityIter iter(dtd.generalEntityIter());
144 const Entity *entity = iter.next().pointer();
147 defineEntity(entity);
150 if (!event->lpdPointer().isNull()) {
151 linkProcess_.init(event->lpdPointer());
152 haveLinkProcess_ = 1;
155 for (size_t i = 0; i < event->simpleLinkNames().size(); i++) {
157 attributes(event->simpleLinkAttributes()[i],
159 &event->simpleLinkNames()[i]);
164 void SgmlsEventHandler::entityDefaulted(EntityDefaultedEvent *event)
168 defineEntity(event->entityPointer().pointer());
173 void SgmlsEventHandler::uselink(UselinkEvent *event)
175 linkProcess_.uselink(event->linkSet(),
177 event->lpd().pointer());
181 void SgmlsEventHandler::sgmlDecl(SgmlDeclEvent *event)
183 sd_ = event->sdPointer();
184 syntax_ = event->instanceSyntaxPointer(); // FIXME which syntax?
188 void SgmlsEventHandler::data(DataEvent *event)
190 outputLocation(event->location());
192 outputString(event->data(), event->dataLength());
196 void SgmlsEventHandler::sdataEntity(SdataEntityEvent *event)
198 outputLocation(event->location());
201 outputString(event->data(), event->dataLength());
206 void SgmlsEventHandler::pi(PiEvent *event)
208 outputLocation(event->location());
211 outputString(event->data(), event->dataLength());
216 void SgmlsEventHandler::startElement(StartElementEvent *event)
219 currentLocation_ = event->location();
220 if (haveLinkProcess_) {
221 const AttributeList *linkAttributes;
222 const ResultElementSpec *resultElementSpec;
223 linkProcess_.startElement(event->elementType(),
226 *this, // Messenger &
230 attributes(*linkAttributes, linkAttributeCode, &linkProcess_.name());
232 attributes(event->attributes(), attributeCode, 0);
233 currentLocation_.clear();
234 if (outputIncluded_ && event->included())
235 os() << includedElementCode << nl;
236 outputLocation(event->location());
237 os() << startElementCode << event->name() << nl;
241 void SgmlsEventHandler::attributes(const AttributeList &attributes,
243 const StringC *ownerName)
245 size_t nAttributes = attributes.size();
246 for (size_t i = 0; i < nAttributes; i++) {
248 const StringC *string;
249 const AttributeValue *value = attributes.value(i);
251 switch (value->info(text, string)) {
252 case AttributeValue::implied:
253 startAttribute(attributes.name(i), code, ownerName);
254 os() << "IMPLIED" << nl;
256 case AttributeValue::tokenized:
258 const char *typeString = "TOKEN";
259 const AttributeSemantics *semantics = attributes.semantics(i);
261 ConstPtr<Notation> notation
262 = semantics->notation();
263 if (!notation.isNull()) {
264 defineNotation(notation.pointer());
265 typeString = "NOTATION";
268 size_t nEntities = semantics->nEntities();
270 typeString = "ENTITY";
272 for (size_t i = 0; i < nEntities; i++) {
273 const Entity *entity = semantics->entity(i).pointer();
274 if (!markEntity(entity))
275 defineEntity(entity);
280 if (outputId_ && attributes.id(i))
282 startAttribute(attributes.name(i), code, ownerName);
283 os() << typeString << space << *string << nl;
286 case AttributeValue::cdata:
288 startAttribute(attributes.name(i), code, ownerName);
290 TextIter iter(*text);
295 while (iter.next(type, p, length, loc))
298 case TextItem::cdata:
299 outputString(p, length);
301 case TextItem::sdata:
303 outputString(p, length);
317 void SgmlsEventHandler::startAttribute(const StringC &name,
319 const StringC *ownerName)
323 os() << *ownerName << space;
324 os() << name << space;
327 void SgmlsEventHandler::endElement(EndElementEvent *event)
330 if (haveLinkProcess_)
331 linkProcess_.endElement();
332 outputLocation(event->location());
333 os() << endElementCode << event->name() << nl;
337 void SgmlsEventHandler::externalDataEntity(ExternalDataEntityEvent *event)
339 currentLocation_ = event->location();
340 outputLocation(event->location());
342 if (!outputEntity_ && !markEntity(event->entity()))
343 defineExternalDataEntity(event->entity());
344 currentLocation_.clear();
345 os() << referenceEntityCode << event->entity()->name() << nl;
349 void SgmlsEventHandler::subdocEntity(SubdocEntityEvent *event)
351 currentLocation_ = event->location();
352 outputLocation(event->location());
354 const SubdocEntity *entity = event->entity();
355 if (!outputEntity_ && !markEntity(entity))
356 defineSubdocEntity(entity);
357 currentLocation_.clear();
358 os() << startSubdocCode << entity->name() << nl;
359 SgmlParser::Params params;
360 params.subdocInheritActiveLinkTypes = 1;
361 params.subdocReferenced = 1;
362 params.origin = event->entityOrigin()->copy();
363 params.parent = parser_;
364 params.sysid = entity->externalId().effectiveSystemId();
365 params.entityType = SgmlParser::Params::subdoc;
366 SgmlParser parser(params);
367 SgmlsSubdocState oldState;
368 SgmlsSubdocState::swap(oldState);
369 SgmlsSubdocState::init(&parser);
370 parser.parseAll(*this);
371 oldState.swap(*this);
372 os() << endSubdocCode << entity->name() << nl;
376 void SgmlsEventHandler::defineEntity(const Entity *entity)
378 const InternalEntity *internalEntity = entity->asInternalEntity();
380 defineInternalEntity(internalEntity);
382 switch (entity->dataType()) {
386 defineExternalDataEntity(entity->asExternalDataEntity());
389 defineSubdocEntity(entity->asSubdocEntity());
391 case Entity::sgmlText:
392 defineExternalTextEntity(entity->asExternalEntity());
400 void SgmlsEventHandler::defineExternalDataEntity(const ExternalDataEntity *entity)
402 const Notation *notation = entity->notation();
403 defineNotation(notation);
404 externalId(entity->externalId());
405 const char *typeString;
406 switch (entity->dataType()) {
408 typeString = "CDATA";
411 typeString = "SDATA";
414 typeString = "NDATA";
419 os() << defineExternalEntityCode << entity->name()
420 << space << typeString
421 << space << notation->name()
423 attributes(entity->attributes(), dataAttributeCode, &entity->name());
426 void SgmlsEventHandler::defineSubdocEntity(const SubdocEntity *entity)
428 externalId(entity->externalId());
429 os() << defineSubdocEntityCode << entity->name() << nl;
432 void SgmlsEventHandler::defineExternalTextEntity(const ExternalEntity *entity)
434 externalId(entity->externalId());
435 os() << defineExternalTextEntityCode << entity->name() << nl;
438 void SgmlsEventHandler::defineInternalEntity(const InternalEntity *entity)
440 os() << defineInternalEntityCode << entity->name() << space;
442 switch (entity->dataType()) {
449 case Entity::sgmlText:
459 outputString(entity->string());
463 void SgmlsEventHandler::defineNotation(const Notation *notation)
465 if (markNotation(notation))
467 externalId(notation->externalId(), outputNotationSysid_);
468 os() << defineNotationCode << notation->name() << nl;
471 void SgmlsEventHandler::externalId(const ExternalId &id, Boolean outputFile)
473 const StringC *str = id.publicIdString();
479 str = id.systemIdString();
485 if (outputFile && id.effectiveSystemId().size()) {
487 outputString(id.effectiveSystemId());
492 Boolean SgmlsEventHandler::markEntity(const Entity *entity)
494 return definedEntities_.add(entity->name());
497 Boolean SgmlsEventHandler::markNotation(const Notation *notation)
499 return definedNotations_.add(notation->name());
502 void SgmlsEventHandler::outputString(const Char *p, size_t n)
504 for (; n > 0; p++, n--) {
506 case '\\': // FIXME we're punning Chars and chars
511 if (outputLine_ && haveData_)
515 // FIXME not clear what to do here given possibility of wide characters
517 static const char digits[] = "0123456789";
518 os() << "\\0" << digits[*p / 8] << digits[*p % 8];
527 void SgmlsEventHandler::escape(OutputCharStream &s, Char c)
529 s << "\\#" << (unsigned long)c << ";";
532 void SgmlsEventHandler::outputLocation1(const Location &loc)
534 const Origin *origin = loc.origin().pointer();
535 const InputSourceOrigin *inputSourceOrigin;
536 const ExternalInfo *info;
537 Index index = loc.index();
541 inputSourceOrigin = origin->asInputSourceOrigin();
542 if (inputSourceOrigin) {
543 info = inputSourceOrigin->externalInfo();
547 const Location &loc = origin->parent();
549 origin = loc.origin().pointer();
551 Offset off = inputSourceOrigin->startOffset(index);
552 StorageObjectLocation soLoc;
553 if (!ExtendEntityManager::externalize(info, off, soLoc))
555 if (soLoc.lineNumber == (unsigned long)-1)
557 if (soLoc.storageObjectSpec == lastSos_) {
558 if (soLoc.lineNumber == lastLineno_)
561 os() << locationCode << soLoc.lineNumber << nl;
562 lastLineno_ = soLoc.lineNumber;
566 os() << locationCode << soLoc.lineNumber << space;
567 outputString(soLoc.storageObjectSpec->id);
569 lastLineno_ = soLoc.lineNumber;
570 lastSos_ = soLoc.storageObjectSpec;
571 lastLoc_ = loc; // make sure lastSos_ doesn't get freed
575 void SgmlsEventHandler::dispatchMessage(Message &msg)
577 dispatchMessage((const Message &) msg);
580 void SgmlsEventHandler::dispatchMessage(const Message &msg)
584 messenger_->dispatchMessage(msg);
588 void SgmlsEventHandler::initMessage(Message &msg)
590 msg.loc = currentLocation_;
593 SgmlsSubdocState::SgmlsSubdocState()
594 : haveLinkProcess_(0), parser_(0)
598 SgmlsSubdocState::SgmlsSubdocState(const SgmlParser *parser)
599 : haveLinkProcess_(0), parser_(parser)
603 void SgmlsSubdocState::init(const SgmlParser *parser)
606 definedNotations_.clear();
607 definedEntities_.clear();
608 haveLinkProcess_ = 0;
609 linkProcess_.clear();
612 void SgmlsSubdocState::swap(SgmlsSubdocState &to)
615 const SgmlParser *tem = to.parser_;
616 to.parser_ = parser_;
620 Boolean tem = to.haveLinkProcess_;
621 to.haveLinkProcess_ = haveLinkProcess_;
622 haveLinkProcess_ = tem;
624 linkProcess_.swap(to.linkProcess_);
625 definedNotations_.swap(to.definedNotations_);
626 definedEntities_.swap(to.definedEntities_);