1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3 #pragma ident "%Z%%M% %I% %E% SMI"
4
5 #ifdef __GNUG__
6 #pragma implementation
7 #endif
8 #include "splib.h"
9 #include "Entity.h"
10 #include "ParserState.h"
11 #include "macros.h"
12 #include "InternalInputSource.h"
13 #include "MessageArg.h"
14 #include "ParserMessages.h"
15
16 #ifdef SP_NAMESPACE
17 namespace SP_NAMESPACE {
18 #endif
19
Entity(const StringC & name,DeclType declType,DataType dataType,const Location & defLocation)20 Entity::Entity(const StringC &name, DeclType declType, DataType dataType,
21 const Location &defLocation)
22 : EntityDecl(name, declType, dataType, defLocation),
23 used_(0), defaulted_(0)
24 {
25 }
26
generateSystemId(ParserState &)27 void Entity::generateSystemId(ParserState &)
28 {
29 }
30
InternalEntity(const StringC & name,DeclType declType,DataType dataType,const Location & defLocation,Text & text)31 InternalEntity::InternalEntity(const StringC &name,
32 DeclType declType,
33 DataType dataType,
34 const Location &defLocation,
35 Text &text)
36 : Entity(name, declType, dataType, defLocation)
37 {
38 text.swap(text_);
39 }
40
PiEntity(const StringC & name,DeclType declType,const Location & defLocation,Text & text)41 PiEntity::PiEntity(const StringC &name, DeclType declType,
42 const Location &defLocation, Text &text)
43 : InternalEntity(name, declType, pi, defLocation, text)
44 {
45 }
46
copy() const47 Entity *PiEntity::copy() const
48 {
49 return new PiEntity(*this);
50 }
51
InternalDataEntity(const StringC & name,DataType dataType,const Location & defLocation,Text & text)52 InternalDataEntity::InternalDataEntity(const StringC &name, DataType dataType,
53 const Location &defLocation, Text &text)
54 : InternalEntity(name, generalEntity, dataType, defLocation, text)
55 {
56 }
57
58
InternalCdataEntity(const StringC & name,const Location & defLocation,Text & text)59 InternalCdataEntity::InternalCdataEntity(const StringC &name,
60 const Location &defLocation,
61 Text &text)
62 : InternalDataEntity(name, cdata, defLocation, text)
63 {
64 }
65
copy() const66 Entity *InternalCdataEntity::copy() const
67 {
68 return new InternalCdataEntity(*this);
69 }
70
InternalSdataEntity(const StringC & name,const Location & defLocation,Text & text)71 InternalSdataEntity::InternalSdataEntity(const StringC &name,
72 const Location &defLocation,
73 Text &text)
74 : InternalDataEntity(name, sdata, defLocation, text)
75 {
76 }
77
copy() const78 Entity *InternalSdataEntity::copy() const
79 {
80 return new InternalSdataEntity(*this);
81 }
82
InternalTextEntity(const StringC & name,DeclType declType,const Location & defLocation,Text & text,Bracketed bracketed)83 InternalTextEntity::InternalTextEntity(const StringC &name, DeclType declType,
84 const Location &defLocation, Text &text,
85 Bracketed bracketed)
86 : InternalEntity(name, declType, sgmlText, defLocation, text),
87 bracketed_(bracketed)
88 {
89 }
90
copy() const91 Entity *InternalTextEntity::copy() const
92 {
93 return new InternalTextEntity(*this);
94 }
95
96
ExternalEntity(const StringC & name,DeclType declType,DataType dataType,const Location & defLocation,const ExternalId & id)97 ExternalEntity::ExternalEntity(const StringC &name,
98 DeclType declType,
99 DataType dataType,
100 const Location &defLocation,
101 const ExternalId &id)
102 : Entity(name, declType, dataType, defLocation), externalId_(id)
103 {
104 }
105
asExternalEntity() const106 const ExternalEntity *ExternalEntity::asExternalEntity() const
107 {
108 return this;
109 }
110
systemIdPointer() const111 const StringC *ExternalEntity::systemIdPointer() const
112 {
113 return externalId_.systemIdString();
114 }
115
effectiveSystemIdPointer() const116 const StringC *ExternalEntity::effectiveSystemIdPointer() const
117 {
118 if (externalId_.effectiveSystemId().size() > 0)
119 return &externalId_.effectiveSystemId();
120 return 0;
121 }
122
publicIdPointer() const123 const StringC *ExternalEntity::publicIdPointer() const
124 {
125 return externalId_.publicIdString();
126 }
127
generateSystemId(ParserState & parser)128 void ExternalEntity::generateSystemId(ParserState &parser)
129 {
130 StringC str;
131 if (parser.entityCatalog().lookup(*this,
132 parser.syntax(),
133 parser.sd().docCharset(),
134 parser.messenger(),
135 str))
136 externalId_.setEffectiveSystem(str);
137 // Don't generate warning when declType == sgml.
138 else if (externalId_.publicIdString()) {
139 if (declType() != sgml)
140 parser.message(ParserMessages::cannotGenerateSystemIdPublic,
141 StringMessageArg(*externalId_.publicIdString()));
142 }
143 else {
144 switch (declType()) {
145 case generalEntity:
146 parser.message(ParserMessages::cannotGenerateSystemIdGeneral,
147 StringMessageArg(name()));
148 break;
149 case parameterEntity:
150 parser.message(ParserMessages::cannotGenerateSystemIdParameter,
151 StringMessageArg(name()));
152 break;
153 case doctype:
154 parser.message(ParserMessages::cannotGenerateSystemIdDoctype,
155 StringMessageArg(name()));
156 break;
157 case linktype:
158 parser.message(ParserMessages::cannotGenerateSystemIdLinktype,
159 StringMessageArg(name()));
160 break;
161 case sgml:
162 break;
163 default:
164 CANNOT_HAPPEN();
165 }
166 }
167 }
168
ExternalTextEntity(const StringC & name,DeclType declType,const Location & defLocation,const ExternalId & id)169 ExternalTextEntity::ExternalTextEntity(const StringC &name,
170 DeclType declType,
171 const Location &defLocation,
172 const ExternalId &id)
173 : ExternalEntity(name, declType, sgmlText, defLocation, id)
174 {
175 }
176
copy() const177 Entity *ExternalTextEntity::copy() const
178 {
179 return new ExternalTextEntity(*this);
180 }
181
ExternalNonTextEntity(const StringC & name,DataType dataType,const Location & defLocation,const ExternalId & id)182 ExternalNonTextEntity::ExternalNonTextEntity(const StringC &name,
183 DataType dataType,
184 const Location &defLocation,
185 const ExternalId &id)
186 : ExternalEntity(name, generalEntity, dataType, defLocation, id)
187 {
188 }
189
ExternalDataEntity(const StringC & name,DataType dataType,const Location & defLocation,const ExternalId & id,const ConstPtr<Notation> & nt,AttributeList & attributes)190 ExternalDataEntity::ExternalDataEntity(const StringC &name,
191 DataType dataType,
192 const Location &defLocation,
193 const ExternalId &id,
194 const ConstPtr<Notation> &nt,
195
196 AttributeList &attributes)
197 : ExternalNonTextEntity(name, dataType, defLocation, id),
198 notation_(nt)
199 {
200 attributes.swap(attributes_);
201 }
202
setNotation(const ConstPtr<Notation> & notation,AttributeList & attributes)203 void ExternalDataEntity::setNotation(const ConstPtr<Notation> ¬ation,
204 AttributeList &attributes)
205 {
206 notation_ = notation;
207 attributes.swap(attributes_);
208 }
209
copy() const210 Entity *ExternalDataEntity::copy() const
211 {
212 return new ExternalDataEntity(*this);
213 }
214
SubdocEntity(const StringC & name,const Location & defLocation,const ExternalId & id)215 SubdocEntity::SubdocEntity(const StringC &name,
216 const Location &defLocation,
217 const ExternalId &id)
218 : ExternalNonTextEntity(name, subdoc, defLocation, id)
219 {
220 }
221
copy() const222 Entity *SubdocEntity::copy() const
223 {
224 return new SubdocEntity(*this);
225 }
226
isDataOrSubdoc() const227 Boolean Entity::isDataOrSubdoc() const
228 {
229 return 0;
230 }
231
isCharacterData() const232 Boolean Entity::isCharacterData() const
233 {
234 return 0;
235 }
236
asExternalEntity() const237 const ExternalEntity *Entity::asExternalEntity() const
238 {
239 return 0;
240 }
241
asExternalDataEntity() const242 const ExternalDataEntity *Entity::asExternalDataEntity() const
243 {
244 return 0;
245 }
246
asSubdocEntity() const247 const SubdocEntity *Entity::asSubdocEntity() const
248 {
249 return 0;
250 }
251
asInternalEntity() const252 const InternalEntity *Entity::asInternalEntity() const
253 {
254 return 0;
255 }
256
dsReference(ParserState & parser,const Ptr<EntityOrigin> & origin) const257 void Entity::dsReference(ParserState &parser,
258 const Ptr<EntityOrigin> &origin)
259 const
260 {
261 normalReference(parser, origin, 1);
262 }
263
declReference(ParserState & parser,const Ptr<EntityOrigin> & origin) const264 void Entity::declReference(ParserState &parser,
265 const Ptr<EntityOrigin> &origin)
266 const
267 {
268 normalReference(parser, origin, 0);
269 if (parser.currentMarkup())
270 parser.currentMarkup()->addEntityStart(origin);
271 }
272
contentReference(ParserState & parser,const Ptr<EntityOrigin> & origin) const273 void Entity::contentReference(ParserState &parser,
274 const Ptr<EntityOrigin> &origin)
275 const
276 {
277 normalReference(parser, origin, 1);
278 }
279
rcdataReference(ParserState & parser,const Ptr<EntityOrigin> & origin) const280 void Entity::rcdataReference(ParserState &parser,
281 const Ptr<EntityOrigin> &origin)
282 const
283 {
284 normalReference(parser, origin, 1);
285 }
286
litReference(Text &,ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean) const287 void Entity::litReference(Text &, ParserState &parser,
288 const Ptr<EntityOrigin> &origin,
289 Boolean)
290 const
291 {
292 normalReference(parser, origin, 0);
293 }
294
asInternalEntity() const295 const InternalEntity *InternalEntity::asInternalEntity() const
296 {
297 return this;
298 }
299
litReference(Text &,ParserState & parser,const Ptr<EntityOrigin> &,Boolean) const300 void PiEntity::litReference(Text &, ParserState &parser,
301 const Ptr<EntityOrigin> &,
302 Boolean) const
303 {
304 parser.message(ParserMessages::piEntityReference);
305 }
306
normalReference(ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean) const307 void PiEntity::normalReference(ParserState &parser,
308 const Ptr<EntityOrigin> &origin,
309 Boolean) const
310 {
311 parser.noteMarkup();
312 parser.eventHandler().pi(new (parser.eventAllocator())
313 PiEntityEvent(this, origin.pointer()));
314 }
315
declReference(ParserState & parser,const Ptr<EntityOrigin> &) const316 void PiEntity::declReference(ParserState &parser,
317 const Ptr<EntityOrigin> &) const
318 {
319 parser.message(ParserMessages::piEntityReference);
320 }
321
rcdataReference(ParserState & parser,const Ptr<EntityOrigin> &) const322 void PiEntity::rcdataReference(ParserState &parser,
323 const Ptr<EntityOrigin> &) const
324 {
325 parser.message(ParserMessages::piEntityRcdata);
326 }
327
declReference(ParserState & parser,const Ptr<EntityOrigin> &) const328 void InternalDataEntity::declReference(ParserState &parser,
329 const Ptr<EntityOrigin> &) const
330 {
331 parser.message(ParserMessages::internalDataEntityReference);
332 }
333
isDataOrSubdoc() const334 Boolean InternalDataEntity::isDataOrSubdoc() const
335 {
336 return 1;
337 }
338
normalReference(ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean) const339 void InternalCdataEntity::normalReference(ParserState &parser,
340 const Ptr<EntityOrigin> &origin,
341 Boolean) const
342 {
343 checkEntlvl(parser);
344 if (string().size() > 0) {
345 parser.noteData();
346 parser.eventHandler().data(new (parser.eventAllocator())
347 CdataEntityEvent(this, origin.pointer()));
348 }
349 }
350
isCharacterData() const351 Boolean InternalCdataEntity::isCharacterData() const
352 {
353 return string().size() > 0;
354 }
355
litReference(Text & text,ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean squeeze) const356 void InternalCdataEntity::litReference(Text &text,
357 ParserState &parser,
358 const Ptr<EntityOrigin> &origin,
359 Boolean squeeze) const
360 {
361 checkEntlvl(parser);
362 if (squeeze) {
363 Location loc(origin.pointer(), 0);
364 text.addEntityStart(loc);
365 text.addCharsTokenize(text_.string(), loc, parser.syntax().space());
366 loc += text_.size();
367 text.addEntityEnd(loc);
368 }
369 else
370 text.addCdata(this, origin.pointer());
371 }
372
373
normalReference(ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean) const374 void InternalSdataEntity::normalReference(ParserState &parser,
375 const Ptr<EntityOrigin> &origin,
376 Boolean) const
377 {
378 checkEntlvl(parser);
379 parser.noteData();
380 parser.eventHandler().sdataEntity(new (parser.eventAllocator())
381 SdataEntityEvent(this,
382 origin.pointer()));
383 }
384
isCharacterData() const385 Boolean InternalSdataEntity::isCharacterData() const
386 {
387 return 1;
388 }
389
litReference(Text & text,ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean squeeze) const390 void InternalSdataEntity::litReference(Text &text,
391 ParserState &parser,
392 const Ptr<EntityOrigin> &origin,
393 Boolean squeeze) const
394 {
395 checkEntlvl(parser);
396 if (squeeze) {
397 Location loc(origin.pointer(), 0);
398 text.addEntityStart(loc);
399 text.addCharsTokenize(text_.string(), loc, parser.syntax().space());
400 loc += text_.size();
401 text.addEntityEnd(loc);
402 }
403 else
404 text.addSdata(this, origin.pointer());
405 }
406
normalReference(ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean generateEvent) const407 void InternalTextEntity::normalReference(ParserState &parser,
408 const Ptr<EntityOrigin> &origin,
409 Boolean generateEvent) const
410 {
411 checkEntlvl(parser);
412 if (checkNotOpen(parser)) {
413 if (generateEvent && parser.wantMarkup())
414 parser.eventHandler().entityStart(new (parser.eventAllocator())
415 EntityStartEvent(origin));
416 parser.pushInput(new (parser.internalAllocator())
417 InternalInputSource(text_.string(), origin.pointer()));
418 }
419 }
420
litReference(Text & text,ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean) const421 void InternalTextEntity::litReference(Text &text,
422 ParserState &parser,
423 const Ptr<EntityOrigin> &origin,
424 Boolean) const
425 {
426 text.addEntityStart(Location(origin.pointer(), 0));
427 normalReference(parser, origin, 0);
428 }
429
normalReference(ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean generateEvent) const430 void ExternalTextEntity::normalReference(ParserState &parser,
431 const Ptr<EntityOrigin> &origin,
432 Boolean generateEvent) const
433 {
434 checkEntlvl(parser);
435 if (checkNotOpen(parser)) {
436 if (generateEvent && parser.wantMarkup())
437 parser.eventHandler().entityStart(new (parser.eventAllocator())
438 EntityStartEvent(origin));
439 if (externalId().effectiveSystemId().size())
440 parser.pushInput(parser.entityManager()
441 .open(externalId().effectiveSystemId(),
442 parser.sd().docCharset(),
443 origin.pointer(),
444 0,
445 parser.messenger()));
446 else
447 parser.message(ParserMessages::nonExistentEntityRef,
448 StringMessageArg(name()),
449 defLocation());
450 }
451 }
452
litReference(Text & text,ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean) const453 void ExternalTextEntity::litReference(Text &text,
454 ParserState &parser,
455 const Ptr<EntityOrigin> &origin,
456 Boolean) const
457 {
458 if (parser.options().warnAttributeValueExternalEntityRef
459 && declType() == generalEntity)
460 parser.message(ParserMessages::attributeValueExternalEntityRef);
461 text.addEntityStart(Location(origin.pointer(), 0));
462 normalReference(parser, origin, 0);
463 }
464
asExternalDataEntity() const465 const ExternalDataEntity *ExternalDataEntity::asExternalDataEntity() const
466 {
467 return this;
468 }
469
contentReference(ParserState & parser,const Ptr<EntityOrigin> & origin) const470 void ExternalDataEntity::contentReference(ParserState &parser,
471 const Ptr<EntityOrigin> &origin) const
472 {
473 if (parser.options().warnExternalDataEntityRef)
474 parser.message(ParserMessages::externalDataEntityRef);
475 checkEntlvl(parser);
476 parser.noteData();
477 parser.eventHandler().externalDataEntity(new (parser.eventAllocator())
478 ExternalDataEntityEvent(this, origin.pointer()));
479 }
480
isDataOrSubdoc() const481 Boolean ExternalNonTextEntity::isDataOrSubdoc() const
482 {
483 return 1;
484 }
485
isCharacterData() const486 Boolean ExternalNonTextEntity::isCharacterData() const
487 {
488 return 1;
489 }
490
491
normalReference(ParserState & parser,const Ptr<EntityOrigin> &,Boolean) const492 void ExternalNonTextEntity::normalReference(ParserState &parser,
493 const Ptr<EntityOrigin> &,
494 Boolean) const
495 {
496 parser.message(ParserMessages::externalNonTextEntityReference);
497 }
498
litReference(Text &,ParserState & parser,const Ptr<EntityOrigin> &,Boolean) const499 void ExternalNonTextEntity::litReference(Text &,
500 ParserState &parser,
501 const Ptr<EntityOrigin> &,
502 Boolean) const
503 {
504 parser.message(ParserMessages::externalNonTextEntityRcdata);
505 }
506
rcdataReference(ParserState & parser,const Ptr<EntityOrigin> &) const507 void ExternalNonTextEntity::rcdataReference(ParserState &parser,
508 const Ptr<EntityOrigin> &) const
509 {
510 parser.message(ParserMessages::externalNonTextEntityRcdata);
511 }
512
contentReference(ParserState & parser,const Ptr<EntityOrigin> & origin) const513 void SubdocEntity::contentReference(ParserState &parser,
514 const Ptr<EntityOrigin> &origin) const
515 {
516 checkEntlvl(parser);
517 parser.noteData();
518 parser.eventHandler().subdocEntity(new (parser.eventAllocator())
519 SubdocEntityEvent(this, origin.pointer()));
520 }
521
asSubdocEntity() const522 const SubdocEntity *SubdocEntity::asSubdocEntity() const
523 {
524 return this;
525 }
526
IgnoredEntity(const StringC & name,DeclType declType)527 IgnoredEntity::IgnoredEntity(const StringC &name, DeclType declType)
528 : Entity(name, declType, sgmlText, Location())
529 {
530 }
531
copy() const532 Entity *IgnoredEntity::copy() const
533 {
534 return new IgnoredEntity(*this);
535 }
536
declReference(ParserState & parser,const Ptr<EntityOrigin> & origin) const537 void IgnoredEntity::declReference(ParserState &parser,
538 const Ptr<EntityOrigin> &origin)
539 const
540 {
541 if (parser.currentMarkup()) {
542 parser.currentMarkup()->addEntityStart(origin);
543 parser.currentMarkup()->addEntityEnd();
544 }
545 }
546
litReference(Text & text,ParserState &,const Ptr<EntityOrigin> & origin,Boolean) const547 void IgnoredEntity::litReference(Text &text,
548 ParserState &,
549 const Ptr<EntityOrigin> &origin,
550 Boolean) const
551 {
552 text.addEntityStart(Location(origin.pointer(), 0));
553 text.addEntityEnd(Location(origin.pointer(), 0));
554 }
555
normalReference(ParserState & parser,const Ptr<EntityOrigin> & origin,Boolean generateEvent) const556 void IgnoredEntity::normalReference(ParserState &parser,
557 const Ptr<EntityOrigin> &origin,
558 Boolean generateEvent) const
559 {
560 if (generateEvent && parser.wantMarkup()) {
561 parser.eventHandler().entityStart(new (parser.eventAllocator())
562 EntityStartEvent(origin));
563 Location loc(origin.pointer(), 0);
564 parser.eventHandler().entityEnd(new (parser.eventAllocator())
565 EntityEndEvent(loc));
566 }
567 }
568
checkEntlvl(ParserState & parser)569 void Entity::checkEntlvl(ParserState &parser)
570 {
571 // -1 because document entity isn't counted
572 if (parser.inputLevel() - 1 == parser.syntax().entlvl())
573 parser.message(ParserMessages::entlvl);
574 }
575
checkNotOpen(ParserState & parser) const576 Boolean Entity::checkNotOpen(ParserState &parser) const
577 {
578 if (parser.entityIsOpen(this)) {
579 parser.message(ParserMessages::recursiveEntityReference,
580 StringMessageArg(name()));
581 return 0;
582 }
583 return 1;
584 }
585
586
587 #ifdef SP_NAMESPACE
588 }
589 #endif
590