Entity.cxx revision 7c478bd95313f5f23a4c958a745db2134aa03244
// Copyright (c) 1994 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 "Entity.h"
#include "ParserState.h"
#include "macros.h"
#include "InternalInputSource.h"
#include "MessageArg.h"
#include "ParserMessages.h"
#ifdef SP_NAMESPACE
namespace SP_NAMESPACE {
#endif
Entity::Entity(const StringC &name, DeclType declType, DataType dataType,
const Location &defLocation)
: EntityDecl(name, declType, dataType, defLocation),
used_(0), defaulted_(0)
{
}
void Entity::generateSystemId(ParserState &)
{
}
InternalEntity::InternalEntity(const StringC &name,
DeclType declType,
DataType dataType,
const Location &defLocation,
Text &text)
: Entity(name, declType, dataType, defLocation)
{
text.swap(text_);
}
PiEntity::PiEntity(const StringC &name, DeclType declType,
const Location &defLocation, Text &text)
: InternalEntity(name, declType, pi, defLocation, text)
{
}
Entity *PiEntity::copy() const
{
return new PiEntity(*this);
}
InternalDataEntity::InternalDataEntity(const StringC &name, DataType dataType,
const Location &defLocation, Text &text)
: InternalEntity(name, generalEntity, dataType, defLocation, text)
{
}
InternalCdataEntity::InternalCdataEntity(const StringC &name,
const Location &defLocation,
Text &text)
: InternalDataEntity(name, cdata, defLocation, text)
{
}
Entity *InternalCdataEntity::copy() const
{
return new InternalCdataEntity(*this);
}
InternalSdataEntity::InternalSdataEntity(const StringC &name,
const Location &defLocation,
Text &text)
: InternalDataEntity(name, sdata, defLocation, text)
{
}
Entity *InternalSdataEntity::copy() const
{
return new InternalSdataEntity(*this);
}
InternalTextEntity::InternalTextEntity(const StringC &name, DeclType declType,
const Location &defLocation, Text &text,
Bracketed bracketed)
: InternalEntity(name, declType, sgmlText, defLocation, text),
bracketed_(bracketed)
{
}
Entity *InternalTextEntity::copy() const
{
return new InternalTextEntity(*this);
}
ExternalEntity::ExternalEntity(const StringC &name,
DeclType declType,
DataType dataType,
const Location &defLocation,
const ExternalId &id)
: Entity(name, declType, dataType, defLocation), externalId_(id)
{
}
const ExternalEntity *ExternalEntity::asExternalEntity() const
{
return this;
}
const StringC *ExternalEntity::systemIdPointer() const
{
return externalId_.systemIdString();
}
const StringC *ExternalEntity::effectiveSystemIdPointer() const
{
if (externalId_.effectiveSystemId().size() > 0)
return &externalId_.effectiveSystemId();
return 0;
}
const StringC *ExternalEntity::publicIdPointer() const
{
return externalId_.publicIdString();
}
void ExternalEntity::generateSystemId(ParserState &parser)
{
StringC str;
if (parser.entityCatalog().lookup(*this,
parser.syntax(),
parser.sd().docCharset(),
parser.messenger(),
str))
externalId_.setEffectiveSystem(str);
// Don't generate warning when declType == sgml.
else if (externalId_.publicIdString()) {
if (declType() != sgml)
parser.message(ParserMessages::cannotGenerateSystemIdPublic,
StringMessageArg(*externalId_.publicIdString()));
}
else {
switch (declType()) {
case generalEntity:
parser.message(ParserMessages::cannotGenerateSystemIdGeneral,
StringMessageArg(name()));
break;
case parameterEntity:
parser.message(ParserMessages::cannotGenerateSystemIdParameter,
StringMessageArg(name()));
break;
case doctype:
parser.message(ParserMessages::cannotGenerateSystemIdDoctype,
StringMessageArg(name()));
break;
case linktype:
parser.message(ParserMessages::cannotGenerateSystemIdLinktype,
StringMessageArg(name()));
break;
case sgml:
break;
default:
CANNOT_HAPPEN();
}
}
}
ExternalTextEntity::ExternalTextEntity(const StringC &name,
DeclType declType,
const Location &defLocation,
const ExternalId &id)
: ExternalEntity(name, declType, sgmlText, defLocation, id)
{
}
Entity *ExternalTextEntity::copy() const
{
return new ExternalTextEntity(*this);
}
ExternalNonTextEntity::ExternalNonTextEntity(const StringC &name,
DataType dataType,
const Location &defLocation,
const ExternalId &id)
: ExternalEntity(name, generalEntity, dataType, defLocation, id)
{
}
ExternalDataEntity::ExternalDataEntity(const StringC &name,
DataType dataType,
const Location &defLocation,
const ExternalId &id,
const ConstPtr<Notation> &nt,
AttributeList &attributes)
: ExternalNonTextEntity(name, dataType, defLocation, id),
notation_(nt)
{
attributes.swap(attributes_);
}
void ExternalDataEntity::setNotation(const ConstPtr<Notation> &notation,
AttributeList &attributes)
{
notation_ = notation;
attributes.swap(attributes_);
}
Entity *ExternalDataEntity::copy() const
{
return new ExternalDataEntity(*this);
}
SubdocEntity::SubdocEntity(const StringC &name,
const Location &defLocation,
const ExternalId &id)
: ExternalNonTextEntity(name, subdoc, defLocation, id)
{
}
Entity *SubdocEntity::copy() const
{
return new SubdocEntity(*this);
}
Boolean Entity::isDataOrSubdoc() const
{
return 0;
}
Boolean Entity::isCharacterData() const
{
return 0;
}
const ExternalEntity *Entity::asExternalEntity() const
{
return 0;
}
const ExternalDataEntity *Entity::asExternalDataEntity() const
{
return 0;
}
const SubdocEntity *Entity::asSubdocEntity() const
{
return 0;
}
const InternalEntity *Entity::asInternalEntity() const
{
return 0;
}
void Entity::dsReference(ParserState &parser,
const Ptr<EntityOrigin> &origin)
const
{
normalReference(parser, origin, 1);
}
void Entity::declReference(ParserState &parser,
const Ptr<EntityOrigin> &origin)
const
{
normalReference(parser, origin, 0);
if (parser.currentMarkup())
parser.currentMarkup()->addEntityStart(origin);
}
void Entity::contentReference(ParserState &parser,
const Ptr<EntityOrigin> &origin)
const
{
normalReference(parser, origin, 1);
}
void Entity::rcdataReference(ParserState &parser,
const Ptr<EntityOrigin> &origin)
const
{
normalReference(parser, origin, 1);
}
void Entity::litReference(Text &, ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean)
const
{
normalReference(parser, origin, 0);
}
const InternalEntity *InternalEntity::asInternalEntity() const
{
return this;
}
void PiEntity::litReference(Text &, ParserState &parser,
const Ptr<EntityOrigin> &,
Boolean) const
{
parser.message(ParserMessages::piEntityReference);
}
void PiEntity::normalReference(ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean) const
{
parser.noteMarkup();
parser.eventHandler().pi(new (parser.eventAllocator())
PiEntityEvent(this, origin.pointer()));
}
void PiEntity::declReference(ParserState &parser,
const Ptr<EntityOrigin> &) const
{
parser.message(ParserMessages::piEntityReference);
}
void PiEntity::rcdataReference(ParserState &parser,
const Ptr<EntityOrigin> &) const
{
parser.message(ParserMessages::piEntityRcdata);
}
void InternalDataEntity::declReference(ParserState &parser,
const Ptr<EntityOrigin> &) const
{
parser.message(ParserMessages::internalDataEntityReference);
}
Boolean InternalDataEntity::isDataOrSubdoc() const
{
return 1;
}
void InternalCdataEntity::normalReference(ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean) const
{
checkEntlvl(parser);
if (string().size() > 0) {
parser.noteData();
parser.eventHandler().data(new (parser.eventAllocator())
CdataEntityEvent(this, origin.pointer()));
}
}
Boolean InternalCdataEntity::isCharacterData() const
{
return string().size() > 0;
}
void InternalCdataEntity::litReference(Text &text,
ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean squeeze) const
{
checkEntlvl(parser);
if (squeeze) {
Location loc(origin.pointer(), 0);
text.addEntityStart(loc);
text.addCharsTokenize(text_.string(), loc, parser.syntax().space());
loc += text_.size();
text.addEntityEnd(loc);
}
else
text.addCdata(this, origin.pointer());
}
void InternalSdataEntity::normalReference(ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean) const
{
checkEntlvl(parser);
parser.noteData();
parser.eventHandler().sdataEntity(new (parser.eventAllocator())
SdataEntityEvent(this,
origin.pointer()));
}
Boolean InternalSdataEntity::isCharacterData() const
{
return 1;
}
void InternalSdataEntity::litReference(Text &text,
ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean squeeze) const
{
checkEntlvl(parser);
if (squeeze) {
Location loc(origin.pointer(), 0);
text.addEntityStart(loc);
text.addCharsTokenize(text_.string(), loc, parser.syntax().space());
loc += text_.size();
text.addEntityEnd(loc);
}
else
text.addSdata(this, origin.pointer());
}
void InternalTextEntity::normalReference(ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean generateEvent) const
{
checkEntlvl(parser);
if (checkNotOpen(parser)) {
if (generateEvent && parser.wantMarkup())
parser.eventHandler().entityStart(new (parser.eventAllocator())
EntityStartEvent(origin));
parser.pushInput(new (parser.internalAllocator())
InternalInputSource(text_.string(), origin.pointer()));
}
}
void InternalTextEntity::litReference(Text &text,
ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean) const
{
text.addEntityStart(Location(origin.pointer(), 0));
normalReference(parser, origin, 0);
}
void ExternalTextEntity::normalReference(ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean generateEvent) const
{
checkEntlvl(parser);
if (checkNotOpen(parser)) {
if (generateEvent && parser.wantMarkup())
parser.eventHandler().entityStart(new (parser.eventAllocator())
EntityStartEvent(origin));
if (externalId().effectiveSystemId().size())
parser.pushInput(parser.entityManager()
.open(externalId().effectiveSystemId(),
parser.sd().docCharset(),
origin.pointer(),
0,
parser.messenger()));
else
parser.message(ParserMessages::nonExistentEntityRef,
StringMessageArg(name()),
defLocation());
}
}
void ExternalTextEntity::litReference(Text &text,
ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean) const
{
if (parser.options().warnAttributeValueExternalEntityRef
&& declType() == generalEntity)
parser.message(ParserMessages::attributeValueExternalEntityRef);
text.addEntityStart(Location(origin.pointer(), 0));
normalReference(parser, origin, 0);
}
const ExternalDataEntity *ExternalDataEntity::asExternalDataEntity() const
{
return this;
}
void ExternalDataEntity::contentReference(ParserState &parser,
const Ptr<EntityOrigin> &origin) const
{
if (parser.options().warnExternalDataEntityRef)
parser.message(ParserMessages::externalDataEntityRef);
checkEntlvl(parser);
parser.noteData();
parser.eventHandler().externalDataEntity(new (parser.eventAllocator())
ExternalDataEntityEvent(this, origin.pointer()));
}
Boolean ExternalNonTextEntity::isDataOrSubdoc() const
{
return 1;
}
Boolean ExternalNonTextEntity::isCharacterData() const
{
return 1;
}
void ExternalNonTextEntity::normalReference(ParserState &parser,
const Ptr<EntityOrigin> &,
Boolean) const
{
parser.message(ParserMessages::externalNonTextEntityReference);
}
void ExternalNonTextEntity::litReference(Text &,
ParserState &parser,
const Ptr<EntityOrigin> &,
Boolean) const
{
parser.message(ParserMessages::externalNonTextEntityRcdata);
}
void ExternalNonTextEntity::rcdataReference(ParserState &parser,
const Ptr<EntityOrigin> &) const
{
parser.message(ParserMessages::externalNonTextEntityRcdata);
}
void SubdocEntity::contentReference(ParserState &parser,
const Ptr<EntityOrigin> &origin) const
{
checkEntlvl(parser);
parser.noteData();
parser.eventHandler().subdocEntity(new (parser.eventAllocator())
SubdocEntityEvent(this, origin.pointer()));
}
const SubdocEntity *SubdocEntity::asSubdocEntity() const
{
return this;
}
IgnoredEntity::IgnoredEntity(const StringC &name, DeclType declType)
: Entity(name, declType, sgmlText, Location())
{
}
Entity *IgnoredEntity::copy() const
{
return new IgnoredEntity(*this);
}
void IgnoredEntity::declReference(ParserState &parser,
const Ptr<EntityOrigin> &origin)
const
{
if (parser.currentMarkup()) {
parser.currentMarkup()->addEntityStart(origin);
parser.currentMarkup()->addEntityEnd();
}
}
void IgnoredEntity::litReference(Text &text,
ParserState &,
const Ptr<EntityOrigin> &origin,
Boolean) const
{
text.addEntityStart(Location(origin.pointer(), 0));
text.addEntityEnd(Location(origin.pointer(), 0));
}
void IgnoredEntity::normalReference(ParserState &parser,
const Ptr<EntityOrigin> &origin,
Boolean generateEvent) const
{
if (generateEvent && parser.wantMarkup()) {
parser.eventHandler().entityStart(new (parser.eventAllocator())
EntityStartEvent(origin));
Location loc(origin.pointer(), 0);
parser.eventHandler().entityEnd(new (parser.eventAllocator())
EntityEndEvent(loc));
}
}
void Entity::checkEntlvl(ParserState &parser)
{
// -1 because document entity isn't counted
if (parser.inputLevel() - 1 == parser.syntax().entlvl())
parser.message(ParserMessages::entlvl);
}
Boolean Entity::checkNotOpen(ParserState &parser) const
{
if (parser.entityIsOpen(this)) {
parser.message(ParserMessages::recursiveEntityReference,
StringMessageArg(name()));
return 0;
}
return 1;
}
#ifdef SP_NAMESPACE
}
#endif