GenericEventHandler.cxx revision 7c478bd95313f5f23a4c958a745db2134aa03244
// Copyright (c) 1996 James Clark
// See the file COPYING for copying permission.
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __GNUG__
#pragma implementation
#endif
#include "splib.h"
#include "GenericEventHandler.h"
#include "macros.h"
#include "ExtendEntityManager.h"
#ifdef SP_NAMESPACE
namespace SP_NAMESPACE {
#endif
class SpOpenEntity : public SGMLApplication::OpenEntity {
public:
SpOpenEntity(const ConstPtr<Origin> &origin);
SGMLApplication::Location location(SGMLApplication::Position) const;
private:
ConstPtr<Origin> origin_;
StorageObjectLocation soLoc_;
};
inline
void GenericEventHandler::freeAll()
{
if (allocBlocks_)
freeAll1();
}
inline
void GenericEventHandler::clearNotation(SGMLApplication::Notation &to)
{
clearString(to.name);
}
inline
void GenericEventHandler::setLocation(SGMLApplication::Position &pos,
const Location &loc)
{
if (lastOrigin_ != loc.origin())
setLocation1(pos, loc);
else
pos = loc.index();
}
GenericEventHandler::GenericEventHandler(SGMLApplication &app,
bool generalEntities)
: app_(&app), generalEntities_(generalEntities),
freeBlocks_(0), allocBlocks_(0), firstBlockSpare_(0), firstBlockUsed_(0)
{
}
GenericEventHandler::~GenericEventHandler()
{
freeAll();
while (freeBlocks_) {
Block *tem = freeBlocks_;
freeBlocks_ = freeBlocks_->next;
delete [] tem->mem;
delete tem;
}
}
void GenericEventHandler::freeAll1()
{
Block **p;
for (p = &allocBlocks_; *p; p = &(*p)->next)
;
*p = freeBlocks_;
freeBlocks_ = allocBlocks_;
allocBlocks_ = 0;
if (freeBlocks_)
firstBlockSpare_ = freeBlocks_->size;
else
firstBlockSpare_ = 0;
firstBlockUsed_ = 0;
}
void *GenericEventHandler::allocate(size_t n)
{
if (n == 0)
return 0;
// round up to avoid alignment problems
n = (n + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
enum { BIG = 1024 };
if (n > firstBlockSpare_) {
if (freeBlocks_ && firstBlockUsed_) {
Block *tem = freeBlocks_;
freeBlocks_ = freeBlocks_->next;
tem->next = allocBlocks_;
allocBlocks_ = tem;
}
if (!freeBlocks_ || freeBlocks_->size < n) {
Block *tem = new Block;
tem->size = n < BIG ? int(BIG) : n;
tem->mem = new char[tem->size];
tem->next = freeBlocks_;
freeBlocks_ = tem;
}
firstBlockUsed_ = 0;
firstBlockSpare_ = freeBlocks_->size;
}
char *tem = freeBlocks_->mem + firstBlockUsed_;
firstBlockUsed_ += n;
firstBlockSpare_ -= n;
return tem;
}
void GenericEventHandler::startElement(StartElementEvent *event)
{
SGMLApplication::StartElementEvent appEvent;
setString(appEvent.gi, event->name());
const ElementDefinition *def = event->elementType()->definition();
switch (def->declaredContent()) {
case ElementDefinition::modelGroup:
appEvent.contentType
= (def->compiledModelGroup()->containsPcdata()
? SGMLApplication::StartElementEvent::mixed
: SGMLApplication::StartElementEvent::element);
break;
case ElementDefinition::any:
appEvent.contentType = SGMLApplication::StartElementEvent::mixed;
break;
case ElementDefinition::cdata:
appEvent.contentType = SGMLApplication::StartElementEvent::cdata;
break;
case ElementDefinition::rcdata:
appEvent.contentType = SGMLApplication::StartElementEvent::rcdata;
break;
case ElementDefinition::empty:
appEvent.contentType = SGMLApplication::StartElementEvent::empty;
break;
}
appEvent.included = event->included();
appEvent.nAttributes = event->attributes().size();
if (appEvent.nAttributes != 0) {
if (event->attributes().conref())
appEvent.contentType = SGMLApplication::StartElementEvent::empty;
setAttributes(appEvent.attributes, event->attributes());
}
setLocation(appEvent.pos, event->location());
app_->startElement(appEvent);
freeAll();
delete event;
}
void GenericEventHandler::endElement(EndElementEvent *event)
{
SGMLApplication::EndElementEvent appEvent;
setString(appEvent.gi, event->name());
setLocation(appEvent.pos, event->location());
app_->endElement(appEvent);
delete event;
}
void GenericEventHandler::data(DataEvent *event)
{
SGMLApplication::DataEvent appEvent;
appEvent.data.ptr = event->data();
appEvent.data.len = event->dataLength();
setLocation(appEvent.pos, event->location());
app_->data(appEvent);
delete event;
}
void GenericEventHandler::pi(PiEvent *event)
{
SGMLApplication::PiEvent appEvent;
appEvent.data.ptr = event->data();
appEvent.data.len = event->dataLength();
const Entity *entity = event->entity();
if (entity)
setString(appEvent.entityName, entity->name());
else
appEvent.entityName.len = 0;
setLocation(appEvent.pos, event->location());
app_->pi(appEvent);
delete event;
}
void GenericEventHandler::sdataEntity(SdataEntityEvent *event)
{
SGMLApplication::SdataEvent appEvent;
appEvent.text.ptr = event->data();
appEvent.text.len = event->dataLength();
setString(appEvent.entityName, event->entity()->name());
// Don't want location of chars in entity.
setLocation(appEvent.pos, event->location().origin()->parent());
app_->sdata(appEvent);
delete event;
}
void GenericEventHandler::externalDataEntity(ExternalDataEntityEvent *event)
{
SGMLApplication::ExternalDataEntityRefEvent appEvent;
setEntity(appEvent.entity, *event->entity());
setLocation(appEvent.pos, event->location());
app_->externalDataEntityRef(appEvent);
freeAll();
delete event;
}
void GenericEventHandler::subdocEntity(SubdocEntityEvent *event)
{
SGMLApplication::SubdocEntityRefEvent appEvent;
setEntity(appEvent.entity, *event->entity());
setLocation(appEvent.pos, event->location());
app_->subdocEntityRef(appEvent);
freeAll();
delete event;
}
void GenericEventHandler::nonSgmlChar(NonSgmlCharEvent *event)
{
SGMLApplication::NonSgmlCharEvent appEvent;
appEvent.c = event->character();
setLocation(appEvent.pos, event->location());
app_->nonSgmlChar(appEvent);
delete event;
}
void GenericEventHandler::startDtd(StartDtdEvent *event)
{
SGMLApplication::StartDtdEvent appEvent;
setString(appEvent.name, event->name());
const Entity *entity = event->entity().pointer();
if (entity) {
appEvent.haveExternalId = 1;
setExternalId(appEvent.externalId,
entity->asExternalEntity()->externalId());
}
else
appEvent.haveExternalId = 0;
setLocation(appEvent.pos, event->location());
app_->startDtd(appEvent);
freeAll();
delete event;
}
void GenericEventHandler::endDtd(EndDtdEvent *event)
{
SGMLApplication::EndDtdEvent appEvent;
setString(appEvent.name, event->dtd().name());
setLocation(appEvent.pos, event->location());
app_->endDtd(appEvent);
delete event;
}
void GenericEventHandler::endProlog(EndPrologEvent *event)
{
if (generalEntities_) {
SGMLApplication::GeneralEntityEvent entityEvent;
const Dtd &dtd = event->dtd();
Dtd::ConstEntityIter iter(dtd.generalEntityIter());
for (;;) {
const Entity *entity = iter.nextTemp();
if (!entity)
break;
setEntity(entityEvent.entity, *entity);
app_->generalEntity(entityEvent);
}
freeAll();
}
SGMLApplication::EndPrologEvent appEvent;
setLocation(appEvent.pos, event->location());
app_->endProlog(appEvent);
delete event;
}
void GenericEventHandler::entityDefaulted(EntityDefaultedEvent *event)
{
if (generalEntities_) {
SGMLApplication::GeneralEntityEvent appEvent;
setEntity(appEvent.entity, event->entity());
app_->generalEntity(appEvent);
}
delete event;
}
void GenericEventHandler::appinfo(AppinfoEvent *event)
{
SGMLApplication::AppinfoEvent appEvent;
const StringC *str;
if (event->literal(str)) {
setString(appEvent.string, *str);
appEvent.none = 0;
}
else
appEvent.none = 1;
setLocation(appEvent.pos, event->location());
app_->appinfo(appEvent);
delete event;
}
void GenericEventHandler::commentDecl(CommentDeclEvent *event)
{
SGMLApplication::CommentDeclEvent appEvent;
appEvent.nComments = 0;
{
for (MarkupIter iter(event->markup()); iter.valid(); iter.advance())
if (iter.type() == Markup::comment)
appEvent.nComments++;
}
SGMLApplication::CharString *comments
= (SGMLApplication::CharString *)allocate(appEvent.nComments * 2
* sizeof(SGMLApplication::CharString));
appEvent.comments = comments;
appEvent.seps = appEvent.comments + appEvent.nComments;
size_t i = 0;
for (MarkupIter iter(event->markup()); iter.valid(); iter.advance())
switch (iter.type()) {
case Markup::comment:
comments[i].ptr = iter.charsPointer();
comments[i].len = iter.charsLength();
clearString(comments[appEvent.nComments + i]);
i++;
break;
case Markup::s:
comments[appEvent.nComments + i - 1].ptr = iter.charsPointer();
comments[appEvent.nComments + i - 1].len = iter.charsLength();
break;
default:
break;
}
setLocation(appEvent.pos, event->location());
app_->commentDecl(appEvent);
freeAll();
delete event;
}
void GenericEventHandler::markedSectionStart(MarkedSectionStartEvent *event)
{
SGMLApplication::MarkedSectionStartEvent appEvent;
unsigned depth = 0;
appEvent.nParams = 0;
{
for (MarkupIter iter(event->markup()); iter.valid(); iter.advance())
switch (iter.type()) {
case Markup::reservedName:
if (!depth)
appEvent.nParams++;
break;
case Markup::entityStart:
if (!depth)
appEvent.nParams++;
depth++;
break;
case Markup::entityEnd:
depth--;
break;
default:
break;
}
}
SGMLApplication::MarkedSectionStartEvent::Param *params
= (SGMLApplication::MarkedSectionStartEvent::Param *)
allocate(appEvent.nParams * sizeof(appEvent.params[0]));
appEvent.params = params;
size_t i = 0;
for (MarkupIter iter(event->markup()); iter.valid(); iter.advance())
switch (iter.type()) {
case Markup::reservedName:
if (!depth) {
switch (iter.reservedName()) {
case Syntax::rTEMP:
params[i].type
= SGMLApplication::MarkedSectionStartEvent::Param::temp;
break;
case Syntax::rINCLUDE:
params[i].type
= SGMLApplication::MarkedSectionStartEvent::Param::include;
break;
case Syntax::rRCDATA:
params[i].type
= SGMLApplication::MarkedSectionStartEvent::Param::rcdata;
break;
case Syntax::rCDATA:
params[i].type
= SGMLApplication::MarkedSectionStartEvent::Param::cdata;
break;
case Syntax::rIGNORE:
params[i].type
= SGMLApplication::MarkedSectionStartEvent::Param::ignore;
break;
default:
CANNOT_HAPPEN();
}
clearString(params[i].entityName);
i++;
}
break;
case Markup::entityStart:
if (!depth) {
params[i].type
= SGMLApplication::MarkedSectionStartEvent::Param::entityRef;
setString(params[i].entityName,
iter.entityOrigin()->entity()->name());
i++;
}
depth++;
break;
case Markup::entityEnd:
depth--;
break;
default:
break;
}
switch (event->status()) {
case MarkedSectionEvent::include:
appEvent.status = SGMLApplication::MarkedSectionStartEvent::include;
break;
case MarkedSectionEvent::rcdata:
appEvent.status = SGMLApplication::MarkedSectionStartEvent::rcdata;
break;
case MarkedSectionEvent::cdata:
appEvent.status = SGMLApplication::MarkedSectionStartEvent::cdata;
break;
case MarkedSectionEvent::ignore:
appEvent.status = SGMLApplication::MarkedSectionStartEvent::ignore;
break;
}
setLocation(appEvent.pos, event->location());
app_->markedSectionStart(appEvent);
freeAll();
delete event;
}
void GenericEventHandler::ignoredChars(IgnoredCharsEvent *event)
{
SGMLApplication::IgnoredCharsEvent appEvent;
appEvent.data.ptr = event->data();
appEvent.data.len = event->dataLength();
setLocation(appEvent.pos, event->location());
app_->ignoredChars(appEvent);
delete event;
}
void GenericEventHandler::markedSectionEnd(MarkedSectionEndEvent *event)
{
SGMLApplication::MarkedSectionEndEvent appEvent;
switch (event->status()) {
case MarkedSectionEvent::include:
appEvent.status = SGMLApplication::MarkedSectionEndEvent::include;
break;
case MarkedSectionEvent::rcdata:
appEvent.status = SGMLApplication::MarkedSectionEndEvent::rcdata;
break;
case MarkedSectionEvent::cdata:
appEvent.status = SGMLApplication::MarkedSectionEndEvent::cdata;
break;
case MarkedSectionEvent::ignore:
appEvent.status = SGMLApplication::MarkedSectionEndEvent::ignore;
break;
}
setLocation(appEvent.pos, event->location());
app_->markedSectionEnd(appEvent);
delete event;
}
void GenericEventHandler::message(MessageEvent *event)
{
SGMLApplication::ErrorEvent appEvent;
switch (event->message().type->severity()) {
case MessageType::quantityError:
appEvent.type = SGMLApplication::ErrorEvent::quantity;
break;
case MessageType::idrefError:
appEvent.type = SGMLApplication::ErrorEvent::idref;
break;
case MessageType::error:
appEvent.type = SGMLApplication::ErrorEvent::otherError;
break;
case MessageType::info:
appEvent.type = SGMLApplication::ErrorEvent::info;
break;
case MessageType::warning:
appEvent.type = SGMLApplication::ErrorEvent::warning;
break;
}
setLocation(appEvent.pos, event->message().loc);
StringC str;
reportMessage(event->message(), str);
setString(appEvent.message, str);
app_->error(appEvent);
ErrorCountEventHandler::message(event);
}
void GenericEventHandler::setLocation1(SGMLApplication::Position &pos,
const Location &loc)
{
const Location *locp = &loc;
for (;;) {
if (locp->origin().isNull()) {
lastOrigin_.clear();
openEntityPtr_ = (SpOpenEntity *)0;
return;
}
const InputSourceOrigin *origin = locp->origin()->asInputSourceOrigin();
if (origin && origin->externalInfo())
break;
locp = &locp->origin()->parent();
}
lastOrigin_ = locp->origin();
pos = locp->index();
openEntityPtr_ = new SpOpenEntity(locp->origin());
app_->openEntityChange(openEntityPtr_);
}
void
GenericEventHandler::setAttributes(const SGMLApplication::Attribute *&attributes,
const AttributeList &attributeList)
{
size_t nAttributes = attributeList.size();
SGMLApplication::Attribute *to
= (SGMLApplication::Attribute *)allocate(nAttributes * sizeof(*to));
attributes = to;
for (size_t i = 0; i < nAttributes; i++) {
SGMLApplication::Attribute *p = to + i;
setString(p->name, attributeList.name(i));
const AttributeValue *value = attributeList.value(i);
if (!value)
p->type = SGMLApplication::Attribute::invalid;
else {
const Text *text;
const StringC *string;
switch (value->info(text, string)) {
case AttributeValue::implied:
p->type = SGMLApplication::Attribute::implied;
break;
case AttributeValue::tokenized:
{
if (attributeList.specified(i))
p->defaulted = SGMLApplication::Attribute::specified;
else if (attributeList.current(i))
p->defaulted = SGMLApplication::Attribute::current;
else
p->defaulted = SGMLApplication::Attribute::definition;
p->type = SGMLApplication::Attribute::tokenized;
p->nEntities = 0;
p->notation.name.len = 0;
p->isId = attributeList.id(i);
p->isGroup = (attributeList.getAllowedTokens(i) != 0);
setString(p->tokens, *string);
const AttributeSemantics *semantics = attributeList.semantics(i);
if (semantics) {
ConstPtr<Notation> notation = semantics->notation();
if (!notation.isNull())
setNotation(p->notation, *notation);
else {
size_t nEntities = semantics->nEntities();
if (nEntities) {
SGMLApplication::Entity *v
= (SGMLApplication::Entity *)allocate(nEntities * sizeof(*v));
p->entities = v;
p->nEntities = nEntities;
for (size_t i = 0; i < nEntities; i++)
setEntity(v[i], *semantics->entity(i));
}
}
}
}
break;
case AttributeValue::cdata:
{
p->type = SGMLApplication::Attribute::cdata;
if (attributeList.specified(i))
p->defaulted = SGMLApplication::Attribute::specified;
else if (attributeList.current(i))
p->defaulted = SGMLApplication::Attribute::current;
else
p->defaulted = SGMLApplication::Attribute::definition;
TextItem::Type type;
const Char *s;
size_t length;
const Location *loc;
size_t nChunks = 0;
{
TextIter iter(*text);
while (iter.next(type, s, length, loc))
switch (type) {
case TextItem::data:
case TextItem::sdata:
case TextItem::cdata:
case TextItem::nonSgml:
nChunks++;
break;
default:
break;
}
}
p->cdataChunks
= (SGMLApplication::Attribute::CdataChunk *)allocate(nChunks * sizeof(SGMLApplication::Attribute::CdataChunk));
p->nCdataChunks = nChunks;
{
size_t i = 0;
for (TextIter iter(*text); iter.next(type, s, length, loc);) {
switch (type) {
case TextItem::data:
case TextItem::sdata:
case TextItem::cdata:
{
SGMLApplication::Attribute::CdataChunk *chunk
= (SGMLApplication::Attribute::CdataChunk *)(p->cdataChunks + i++);
if (type != TextItem::sdata) {
chunk->isSdata = 0;
chunk->isNonSgml = 0;
}
else {
chunk->isSdata = 1;
setString(chunk->entityName,
*loc->origin()->asInputSourceOrigin()->entityName());
}
chunk->data.ptr = s;
chunk->data.len = length;
}
break;
case TextItem::nonSgml:
{
SGMLApplication::Attribute::CdataChunk *chunk
= (SGMLApplication::Attribute::CdataChunk *)(p->cdataChunks + i++);
chunk->isSdata = 0;
chunk->isNonSgml = 1;
chunk->nonSgmlChar = *s;
chunk->data.len = 0;
chunk->data.ptr = 0;
}
break;
default:
break;
}
}
}
}
break;
}
}
}
}
void GenericEventHandler::setEntity(SGMLApplication::Entity &to,
const Entity &from)
{
setString(to.name, from.name());
switch (from.declType()) {
case Entity::generalEntity:
to.declType = SGMLApplication::Entity::general;
break;
case Entity::parameterEntity:
to.declType = SGMLApplication::Entity::parameter;
break;
case Entity::doctype:
to.declType = SGMLApplication::Entity::doctype;
break;
case Entity::linktype:
to.declType = SGMLApplication::Entity::linktype;
break;
default:
CANNOT_HAPPEN();
}
switch (from.dataType()) {
case Entity::sgmlText:
to.dataType = SGMLApplication::Entity::sgml;
break;
case Entity::cdata:
to.dataType = SGMLApplication::Entity::cdata;
break;
case Entity::sdata:
to.dataType = SGMLApplication::Entity::sdata;
break;
case Entity::ndata:
to.dataType = SGMLApplication::Entity::ndata;
break;
case Entity::subdoc:
to.dataType = SGMLApplication::Entity::subdoc;
break;
case Entity::pi:
to.dataType = SGMLApplication::Entity::pi;
break;
}
const InternalEntity *internal = from.asInternalEntity();
if (internal) {
to.isInternal = 1;
setString(to.text, internal->string());
}
else {
const ExternalEntity *external = from.asExternalEntity();
to.isInternal = 0;
setExternalId(to.externalId, external->externalId());
const ExternalDataEntity *externalData = from.asExternalDataEntity();
if (externalData) {
setNotation(to.notation, *externalData->notation());
to.nAttributes = externalData->attributes().size();
if (to.nAttributes)
setAttributes(to.attributes, externalData->attributes());
}
else {
to.notation.name.len = 0;
to.nAttributes = 0;
}
}
}
void GenericEventHandler::setNotation(SGMLApplication::Notation &to,
const Notation &from)
{
setString(to.name, from.name());
setExternalId(to.externalId, from.externalId());
}
void GenericEventHandler::setExternalId(SGMLApplication::ExternalId &to,
const ExternalId &from)
{
const StringC *str;
str = from.systemIdString();
if (str) {
to.haveSystemId = 1;
setString(to.systemId, *str);
}
else
to.haveSystemId = 0;
str = from.publicIdString();
if (str) {
to.havePublicId = 1;
setString(to.publicId, *str);
}
else
to.havePublicId = 0;
str = &from.effectiveSystemId();
if (str->size()) {
to.haveGeneratedSystemId = 1;
setString(to.generatedSystemId, *str);
}
else
to.haveGeneratedSystemId = 0;
}
MsgGenericEventHandler::MsgGenericEventHandler(SGMLApplication &app,
bool generalEntities,
MessageReporter &reporter,
const bool *messagesInhibitedPtr)
: GenericEventHandler(app, generalEntities),
reporter_(&reporter),
messagesInhibitedPtr_(messagesInhibitedPtr)
{
}
void MsgGenericEventHandler::reportMessage(const Message &msg, StringC &str)
{
WrapReporter wrap(reporter_);
reporter_->dispatchMessage(msg);
wrap.strStream.extractString(str);
if (!*messagesInhibitedPtr_)
*wrap.origStream << str;
}
SpOpenEntity::SpOpenEntity(const ConstPtr<Origin> &origin)
: origin_(origin)
{
}
SGMLApplication::Location
SpOpenEntity::location(SGMLApplication::Position pos) const
{
SGMLApplication::Location loc;
const Origin *origin = origin_.pointer();
const InputSourceOrigin *inputSourceOrigin;
const ExternalInfo *externalInfo;
Index index = Index(pos);
for (;;) {
if (!origin)
return loc;
inputSourceOrigin = origin->asInputSourceOrigin();
if (inputSourceOrigin) {
externalInfo = inputSourceOrigin->externalInfo();
if (externalInfo)
break;
}
// Qualifier is for CodeWarrior
const ::SP_NAMESPACE_SCOPE Location &loc = origin->parent();
index = loc.index();
origin = loc.origin().pointer();
}
const StringC *entityName = inputSourceOrigin->entityName();
if (entityName)
GenericEventHandler::setString(loc.entityName, *entityName);
Offset off = inputSourceOrigin->startOffset(index);
loc.entityOffset = off;
if (!ExtendEntityManager::externalize(externalInfo, off, ((SpOpenEntity *)this)->soLoc_))
return loc;
loc.lineNumber = soLoc_.lineNumber;
GenericEventHandler::setString(loc.filename, soLoc_.actualStorageId);
loc.columnNumber = soLoc_.columnNumber;
loc.byteOffset = soLoc_.byteIndex;
loc.other = soLoc_.storageObjectSpec;
return loc;
}
#ifdef SP_NAMESPACE
}
#endif