cdesktopenv/cde/programs/nsgmls/Entity.C

671 lines
16 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: Entity.C /main/1 1996/07/29 16:49:46 cde-hp $ */
// Copyright (c) 1994 James Clark
// See the file COPYING for copying permission.
#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);
else if (externalId_.publicIdString())
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;
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
{
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
{
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;
}
EntityOrigin::EntityOrigin()
: refLength_(0)
{
}
EntityOrigin::EntityOrigin(const Location &refLocation)
: InputSourceOrigin(refLocation), refLength_(0)
{
}
EntityOrigin::EntityOrigin(const ConstPtr<Entity> &entity,
const Location &refLocation)
: InputSourceOrigin(refLocation), refLength_(0), entity_(entity)
{
}
EntityOrigin::EntityOrigin(const ConstPtr<Entity> &entity,
const Location &refLocation,
Index refLength,
Owner<Markup> &markup)
: InputSourceOrigin(refLocation), refLength_(refLength), entity_(entity)
{
markup.swap(markup_);
}
EntityOrigin::~EntityOrigin()
{
}
InputSourceOrigin *EntityOrigin::copy() const
{
Owner<Markup> m;
if (markup_)
m = new Markup(*markup_);
return new EntityOrigin(entity_, parent(), refLength_, m);
}
const StringC *EntityOrigin::entityName() const
{
if (entity_.isNull())
return 0;
return entity_->namePointer();
}
Index EntityOrigin::refLength() const
{
return refLength_;
}
const EntityOrigin *EntityOrigin::asEntityOrigin() const
{
return this;
}
Boolean EntityOrigin::defLocation(Offset off, Location &loc) const
{
if (entity_.isNull())
return 0;
const InternalEntity *internal = entity_->asInternalEntity();
if (!internal)
return 0;
loc = internal->text().charLocation(off);
return 1;
}
const EntityDecl *EntityOrigin::entityDecl() const
{
return entity_.pointer();
}
#ifdef SP_NAMESPACE
}
#endif