1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3 
4 #include "config.h"
5 #include "SgmlsEventHandler.h"
6 #include "SgmlParser.h"
7 #include "ParserOptions.h"
8 #include "Entity.h"
9 #include "Notation.h"
10 #include "Attribute.h"
11 #include "ExtendEntityManager.h"
12 #include "StorageManager.h"
13 #include "macros.h"
14 #include "sptchar.h"
15 #include "nsgmls.h"
16 
17 #ifdef SP_NAMESPACE
18 namespace SP_NAMESPACE {
19 #endif
20 
21 const char dataCode = '-';
22 const char piCode = '?';
23 const char conformingCode = 'C';
24 const char appinfoCode = '#';
25 const char startElementCode = '(';
26 const char endElementCode = ')';
27 const char referenceEntityCode = '&';
28 const char attributeCode = 'A';
29 const char dataAttributeCode = 'D';
30 const char linkAttributeCode = 'a';
31 const char defineNotationCode = 'N';
32 const char defineExternalEntityCode = 'E';
33 const char defineInternalEntityCode = 'I';
34 const char defineSubdocEntityCode = 'S';
35 const char defineExternalTextEntityCode = 'T';
36 const char pubidCode = 'p';
37 const char sysidCode = 's';
38 const char startSubdocCode = '{';
39 const char endSubdocCode = '}';
40 const char fileCode = 'f';
41 const char locationCode = 'L';
42 const char includedElementCode = 'i';
43 const char emptyElementCode = 'e';
44 const char commentCode = '_';
45 const char omissionCode = 'o';
46 const char featuresCode = 'V';
47 const char featuresSubCodeOptions = 'o';
48 const char featuresSubCodeVersion = 'v';
49 const char featuresSubCodePackage = 'p';
50 const char featuresSubCodePossibleCodes = 'c';
51 
52 const OutputCharStream::Newline nl = OutputCharStream::newline;
53 
54 const char space = ' ';
55 const char re = '\r';
56 const Char reChar = re;
57 const char escapePrefix = '\\';
58 const Char escapePrefixChar = escapePrefix;
59 const char sdataDelim = '|';
60 const char nonSgmlEscape = '%';
61 const char newlineEscape = 'n';
62 const char numEscape = '#';
63 const char escapeEnd = ';';
64 
65 inline
startData()66 void SgmlsEventHandler::startData()
67 {
68   if (!haveData_) {
69     os() << dataCode;
70     haveData_ = 1;
71   }
72 }
73 
74 inline
flushData()75 void SgmlsEventHandler::flushData()
76 {
77   if (haveData_) {
78     os() << nl;
79     haveData_ = 0;
80   }
81 }
82 
83 inline
outputLocation(const Location & loc)84 void SgmlsEventHandler::outputLocation(const Location &loc)
85 {
86   if (outputLine_)
87     outputLocation1(loc);
88 }
89 
SgmlsEventHandler(const SgmlParser * parser,OutputCharStream * os,Messenger * messenger,unsigned outputFlags)90 SgmlsEventHandler::SgmlsEventHandler(const SgmlParser *parser,
91 				     OutputCharStream *os,
92 				     Messenger *messenger,
93 				     unsigned outputFlags)
94 : SgmlsSubdocState(parser), os_(os), messenger_(messenger),
95   outputLine_((outputFlags & outputLine) != 0),
96   outputEntity_((outputFlags & outputEntity) != 0),
97   outputId_((outputFlags & outputId) != 0),
98   outputNotationSysid_((outputFlags & outputNotationSysid) != 0),
99   outputIncluded_((outputFlags & outputIncluded) != 0),
100   outputNonSgml_((outputFlags & outputNonSgml) != 0),
101   outputEmpty_((outputFlags & outputEmpty) != 0),
102   outputDataAtt_((outputFlags & outputDataAtt) != 0),
103   outputComment_((outputFlags & outputComment) != 0),
104   outputTagOmission_((outputFlags & outputTagOmission) != 0),
105   outputAttributeOmission_((outputFlags & outputAttributeOmission) != 0),
106   outputParserInformation_((outputFlags & outputParserInformation) != 0),
107 
108   haveData_(0), lastSos_(0), inDocument_(0)
109 {
110   os_->setEscaper(escaper);
111   if (outputParserInformation_)
112     features(outputFlags);
113 }
114 
~SgmlsEventHandler()115 SgmlsEventHandler::~SgmlsEventHandler()
116 {
117   flushData();
118   if (errorCount() == 0)
119     os() << conformingCode << nl;
120   delete os_;
121 }
122 
message(MessageEvent * event)123 void SgmlsEventHandler::message(MessageEvent *event)
124 {
125   messenger_->dispatchMessage(event->message());
126   ErrorCountEventHandler::message(event);
127 }
128 
features(unsigned outputFlags)129 void SgmlsEventHandler::features(unsigned outputFlags)
130 {
131     os() << featuresCode << featuresSubCodePackage << space
132          << SP_PACKAGE
133          << nl;
134 
135     os() << featuresCode << featuresSubCodeVersion << space
136          << SP_VERSION
137          << nl;
138 
139     os() << featuresCode << featuresSubCodePossibleCodes << space;
140     os() << dataCode;
141     os() << piCode;
142     os() << conformingCode;
143     os() << appinfoCode;
144     os() << startElementCode;
145     os() << endElementCode;
146     os() << referenceEntityCode;
147     os() << attributeCode;
148     os() << dataAttributeCode;
149     os() << linkAttributeCode;
150     os() << defineNotationCode;
151     os() << defineExternalEntityCode;
152     os() << defineInternalEntityCode;
153     os() << defineSubdocEntityCode;
154     os() << defineExternalTextEntityCode;
155     os() << pubidCode;
156     os() << sysidCode;
157     os() << startSubdocCode;
158     os() << endSubdocCode;
159     os() << fileCode;
160     os() << locationCode;
161     os() << includedElementCode;
162     os() << emptyElementCode;
163     os() << commentCode;
164     os() << omissionCode;
165     os() << featuresCode;
166 
167     os() << nl;
168 
169     os() << featuresCode << featuresSubCodeOptions
170          << space << SP_T("esis");
171     for (size_t i = 1; NsgmlsApp::outputOptions[i].flag != 0; i++) {
172       if (NsgmlsApp::outputOptions[i].flag == 0)
173         break;
174       if (0 != (outputFlags & NsgmlsApp::outputOptions[i].flag)) {
175         os() << space << NsgmlsApp::outputOptions[i].name;
176       }
177     }
178     os() << nl;
179 }
180 
appinfo(AppinfoEvent * event)181 void SgmlsEventHandler::appinfo(AppinfoEvent *event)
182 {
183   const StringC *str;
184   if (event->literal(str)) {
185     outputLocation(event->location());
186     flushData();
187     os() << appinfoCode;
188     outputString(*str);
189     os() << nl;
190   }
191   delete event;
192 }
193 
endProlog(EndPrologEvent * event)194 void SgmlsEventHandler::endProlog(EndPrologEvent *event)
195 {
196   if (outputEntity_) {
197     flushData();
198     const Dtd &dtd = event->dtd();
199     Dtd::ConstEntityIter iter(dtd.generalEntityIter());
200     for (;;) {
201       const Entity *entity = iter.next().pointer();
202       if (!entity)
203 	break;
204       defineEntity(entity);
205     }
206   }
207   if (outputComment_)
208     inDocument_ = true;
209   if (!event->lpdPointer().isNull()) {
210     linkProcess_.init(event->lpdPointer());
211     haveLinkProcess_ = 1;
212     flushData();
213   }
214   for (size_t i = 0; i < event->simpleLinkNames().size(); i++) {
215     flushData();
216     attributes(event->simpleLinkAttributes()[i],
217 	       linkAttributeCode,
218 	       &event->simpleLinkNames()[i]);
219   }
220   delete event;
221 }
222 
entityDefaulted(EntityDefaultedEvent * event)223 void SgmlsEventHandler::entityDefaulted(EntityDefaultedEvent *event)
224 {
225   if (outputEntity_) {
226     flushData();
227     defineEntity(event->entityPointer().pointer());
228   }
229   delete event;
230 }
231 
uselink(UselinkEvent * event)232 void SgmlsEventHandler::uselink(UselinkEvent *event)
233 {
234   linkProcess_.uselink(event->linkSet(),
235 		       event->restore(),
236 		       event->lpd().pointer());
237   delete event;
238 }
239 
sgmlDecl(SgmlDeclEvent * event)240 void SgmlsEventHandler::sgmlDecl(SgmlDeclEvent *event)
241 {
242   sd_ = event->sdPointer();
243   syntax_ = event->instanceSyntaxPointer(); // FIXME which syntax?
244   delete event;
245 }
246 
data(DataEvent * event)247 void SgmlsEventHandler::data(DataEvent *event)
248 {
249   outputLocation(event->location());
250   startData();
251   outputString(event->data(), event->dataLength());
252   delete event;
253 }
254 
sdataEntity(SdataEntityEvent * event)255 void SgmlsEventHandler::sdataEntity(SdataEntityEvent *event)
256 {
257   outputLocation(event->location());
258   startData();
259   os() << escapePrefix << sdataDelim;
260   outputString(event->data(), event->dataLength());
261   os() << escapePrefix << sdataDelim;
262   delete event;
263 }
264 
pi(PiEvent * event)265 void SgmlsEventHandler::pi(PiEvent *event)
266 {
267   outputLocation(event->location());
268   flushData();
269   os() << piCode;
270   outputString(event->data(), event->dataLength());
271   os() << nl;
272   delete event;
273 }
274 
commentDecl(CommentDeclEvent * event)275 void SgmlsEventHandler::commentDecl(CommentDeclEvent *event)
276 {
277   if (inDocument_) {  //only receive this event if outputComment_ true
278     outputLocation(event->location());
279     flushData();
280     MarkupIter iter(event->markup());
281     for (; iter.valid(); iter.advance()) {
282       if (iter.type() == Markup::comment) {
283         os() << commentCode;
284         outputString(iter.charsPointer(), iter.charsLength());
285         os() << nl;
286       }
287     }
288   }
289   delete event;
290 }
291 
nonSgmlChar(NonSgmlCharEvent * event)292 void SgmlsEventHandler::nonSgmlChar(NonSgmlCharEvent *event)
293 {
294   if (outputNonSgml_) {
295     outputLocation(event->location());
296     startData();
297     os() << escapePrefix << nonSgmlEscape << (unsigned long)event->character() << escapeEnd;
298   }
299   delete event;
300 }
301 
startElement(StartElementEvent * event)302 void SgmlsEventHandler::startElement(StartElementEvent *event)
303 {
304   flushData();
305   currentLocation_ = event->location();
306   if (haveLinkProcess_) {
307     const AttributeList *linkAttributes;
308     const ResultElementSpec *resultElementSpec;
309     linkProcess_.startElement(event->elementType(),
310 			      event->attributes(),
311 			      event->location(),
312 			      *this, // Messenger &
313 			      linkAttributes,
314 			      resultElementSpec);
315     if (linkAttributes)
316       attributes(*linkAttributes, linkAttributeCode, &linkProcess_.name());
317   }
318   attributes(event->attributes(), attributeCode, 0);
319   currentLocation_.clear();
320   if (outputTagOmission_ && !event->markupPtr())
321     os() << omissionCode << nl;
322   if (outputIncluded_ && event->included())
323     os() << includedElementCode << nl;
324   if (outputEmpty_ && event->mustOmitEnd())
325     os() << emptyElementCode << nl;
326   outputLocation(event->location());
327   os() << startElementCode << event->name() << nl;
328   delete event;
329 }
330 
attributes(const AttributeList & attributes,char code,const StringC * ownerName)331 void SgmlsEventHandler::attributes(const AttributeList &attributes,
332 				   char code,
333 				   const StringC *ownerName)
334 {
335   size_t nAttributes = attributes.size();
336   for (size_t i = 0; i < nAttributes; i++) {
337     const Text *text;
338     const StringC *string;
339     const AttributeValue *value = attributes.value(i);
340     if (value) {
341       if (outputAttributeOmission_) {
342         if (! attributes.specified(i)) {
343           os() << omissionCode << nl;
344         }
345       }
346       switch (value->info(text, string)) {
347       case AttributeValue::implied:
348 	startAttribute(attributes.name(i), code, ownerName);
349 	os() << "IMPLIED" << nl;
350 	break;
351       case AttributeValue::tokenized:
352 	{
353 	  const char *typeString = "TOKEN";
354 	  const AttributeSemantics *semantics = attributes.semantics(i);
355 	  if (semantics) {
356 	    ConstPtr<Notation> notation
357 	      = semantics->notation();
358 	    if (!notation.isNull()) {
359 	      defineNotation(notation.pointer());
360 	      typeString = "NOTATION";
361 	    }
362 	    else {
363 	      size_t nEntities = semantics->nEntities();
364 	      if (nEntities) {
365 		typeString = "ENTITY";
366 		if (!outputEntity_)
367 		  for (size_t i = 0; i < nEntities; i++) {
368 		    const Entity *entity = semantics->entity(i).pointer();
369 		    if (!markEntity(entity))
370 		      defineEntity(entity);
371 		  }
372 	      }
373 	    }
374 	  }
375 	  if (outputId_ && attributes.id(i))
376 	    typeString = "ID";
377 	  startAttribute(attributes.name(i), code, ownerName);
378 	  os() << typeString << space << *string << nl;
379 	}
380 	break;
381       case AttributeValue::cdata:
382 	{
383 	  startAttribute(attributes.name(i), code, ownerName);
384 	  CdataAttributeValue *cdataValue = (CdataAttributeValue *)value;
385 	  if (outputDataAtt_ && cdataValue->notation())
386 	    os() << "DATA " << cdataValue->notation()->name() << " ";
387 	  else
388 	    os() << "CDATA ";
389 	  TextIter iter(*text);
390 	  TextItem::Type type;
391 	  const Char *p;
392 	  size_t length;
393 	  const Location *loc;
394 	  while (iter.next(type, p, length, loc))
395 	    switch (type) {
396 	    case TextItem::data:
397 	    case TextItem::cdata:
398 	      outputString(p, length);
399 	      break;
400 	    case TextItem::sdata:
401 	      os() << escapePrefix << sdataDelim;
402 	      outputString(p, length);
403 	      os() << escapePrefix << sdataDelim;
404 	      break;
405 	    case TextItem::nonSgml:
406 	      if (outputNonSgml_)
407 		os() << escapePrefix << nonSgmlEscape << (unsigned long)*p << escapeEnd;
408 	      break;
409 	    default:
410 	      break;
411 	    }
412 	  os() << nl;
413 	  if (outputDataAtt_ && cdataValue->notation()) {
414 	    defineNotation(cdataValue->notation());
415 	    DataAttributeValue *dataValue = (DataAttributeValue *)cdataValue;
416 	    SgmlsEventHandler::attributes(dataValue->attributes(),
417 					  dataAttributeCode,
418 					  &attributes.name(i));
419 	  }
420 	}
421 	break;
422       }
423     }
424   }
425 }
426 
startAttribute(const StringC & name,char code,const StringC * ownerName)427 void SgmlsEventHandler::startAttribute(const StringC &name,
428 				       char code,
429 				       const StringC *ownerName)
430 {
431   os() << code;
432   if (ownerName)
433     os() << *ownerName << space;
434   os() << name << space;
435 }
436 
endElement(EndElementEvent * event)437 void SgmlsEventHandler::endElement(EndElementEvent *event)
438 {
439   flushData();
440   if (haveLinkProcess_)
441     linkProcess_.endElement();
442   outputLocation(event->location());
443   if (outputTagOmission_ && !event->markupPtr())
444     os() << omissionCode << nl;
445   os() << endElementCode << event->name() << nl;
446   delete event;
447 }
448 
externalDataEntity(ExternalDataEntityEvent * event)449 void SgmlsEventHandler::externalDataEntity(ExternalDataEntityEvent *event)
450 {
451   currentLocation_ = event->location();
452   outputLocation(event->location());
453   flushData();
454   if (!outputEntity_ && !markEntity(event->entity()))
455     defineExternalDataEntity(event->entity());
456   currentLocation_.clear();
457   os() << referenceEntityCode << event->entity()->name() << nl;
458   delete event;
459 }
460 
subdocEntity(SubdocEntityEvent * event)461 void SgmlsEventHandler::subdocEntity(SubdocEntityEvent *event)
462 {
463   currentLocation_ = event->location();
464   outputLocation(event->location());
465   flushData();
466   const SubdocEntity *entity = event->entity();
467   if (!outputEntity_ && !markEntity(entity))
468     defineSubdocEntity(entity);
469   currentLocation_.clear();
470   os() << startSubdocCode << entity->name() << nl;
471   SgmlParser::Params params;
472   params.subdocInheritActiveLinkTypes = 1;
473   params.subdocReferenced = 1;
474   params.origin = event->entityOrigin()->copy();
475   params.parent = parser_;
476   params.sysid = entity->externalId().effectiveSystemId();
477   params.entityType = SgmlParser::Params::subdoc;
478   SgmlParser parser(params);
479   SgmlsSubdocState oldState;
480   SgmlsSubdocState::swap(oldState);
481   SgmlsSubdocState::init(&parser);
482   parser.parseAll(*this);
483   oldState.swap(*this);
484   os() << endSubdocCode << entity->name() << nl;
485   delete event;
486 }
487 
defineEntity(const Entity * entity)488 void SgmlsEventHandler::defineEntity(const Entity *entity)
489 {
490   const InternalEntity *internalEntity = entity->asInternalEntity();
491   if (internalEntity)
492     defineInternalEntity(internalEntity);
493   else {
494     switch (entity->dataType()) {
495     case Entity::cdata:
496     case Entity::sdata:
497     case Entity::ndata:
498       defineExternalDataEntity(entity->asExternalDataEntity());
499       break;
500     case Entity::subdoc:
501       defineSubdocEntity(entity->asSubdocEntity());
502       break;
503     case Entity::sgmlText:
504       defineExternalTextEntity(entity->asExternalEntity());
505       break;
506     default:
507       CANNOT_HAPPEN();
508     }
509   }
510 }
511 
defineExternalDataEntity(const ExternalDataEntity * entity)512 void SgmlsEventHandler::defineExternalDataEntity(const ExternalDataEntity *entity)
513 {
514   const Notation *notation = entity->notation();
515   defineNotation(notation);
516   externalId(entity->externalId());
517   const char *typeString;
518   switch (entity->dataType()) {
519   case Entity::cdata:
520     typeString = "CDATA";
521     break;
522   case Entity::sdata:
523     typeString = "SDATA";
524     break;
525   case Entity::ndata:
526     typeString = "NDATA";
527     break;
528   default:
529     CANNOT_HAPPEN();
530   }
531   os() << defineExternalEntityCode << entity->name()
532        << space << typeString
533        << space << notation->name()
534        << nl;
535   attributes(entity->attributes(), dataAttributeCode, &entity->name());
536 }
537 
defineSubdocEntity(const SubdocEntity * entity)538 void SgmlsEventHandler::defineSubdocEntity(const SubdocEntity *entity)
539 {
540   externalId(entity->externalId());
541   os() << defineSubdocEntityCode << entity->name() << nl;
542 }
543 
defineExternalTextEntity(const ExternalEntity * entity)544 void SgmlsEventHandler::defineExternalTextEntity(const ExternalEntity *entity)
545 {
546   externalId(entity->externalId());
547   os() << defineExternalTextEntityCode << entity->name() << nl;
548 }
549 
defineInternalEntity(const InternalEntity * entity)550 void SgmlsEventHandler::defineInternalEntity(const InternalEntity *entity)
551 {
552   os() << defineInternalEntityCode << entity->name() << space;
553   const char *s;
554   switch (entity->dataType()) {
555   case Entity::sdata:
556     s = "SDATA";
557     break;
558   case Entity::cdata:
559     s = "CDATA";
560     break;
561   case Entity::sgmlText:
562     s = "TEXT";
563     break;
564   case Entity::pi:
565     s = "PI";
566     break;
567   default:
568     CANNOT_HAPPEN();
569   }
570   os() << s << space;
571   outputString(entity->string());
572   os() << nl;
573 }
574 
defineNotation(const Notation * notation)575 void SgmlsEventHandler::defineNotation(const Notation *notation)
576 {
577   if (markNotation(notation))
578     return;
579   externalId(notation->externalId(), outputNotationSysid_);
580   os() << defineNotationCode << notation->name() << nl;
581 }
582 
externalId(const ExternalId & id,Boolean outputFile)583 void SgmlsEventHandler::externalId(const ExternalId &id, Boolean outputFile)
584 {
585   const StringC *str = id.publicIdString();
586   if (str) {
587     os() << pubidCode;
588     outputString(*str);
589     os() << nl;
590   }
591   str = id.systemIdString();
592   if (str) {
593     os() << sysidCode;
594     outputString(*str);
595     os() << nl;
596   }
597   if (outputFile && id.effectiveSystemId().size()) {
598     os() << fileCode;
599     outputString(id.effectiveSystemId());
600     os() << nl;
601   }
602 }
603 
markEntity(const Entity * entity)604 Boolean SgmlsEventHandler::markEntity(const Entity *entity)
605 {
606   return definedEntities_.add(entity->name());
607 }
608 
markNotation(const Notation * notation)609 Boolean SgmlsEventHandler::markNotation(const Notation *notation)
610 {
611   return definedNotations_.add(notation->name());
612 }
613 
outputString(const Char * p,size_t n)614 void SgmlsEventHandler::outputString(const Char *p, size_t n)
615 {
616   for (; n > 0; p++, n--) {
617     switch (*p) {
618     case escapePrefixChar:
619       os() << escapePrefix << escapePrefix;
620       break;
621     case reChar:
622       os() << escapePrefix << newlineEscape;
623       if (outputLine_ && haveData_)
624 	lastLineno_++;
625       break;
626     default:
627       // FIXME not clear what to do here given possibility of wide characters
628       unsigned long c = *p;
629       if (c < 040) {
630 	static const char digits[] = "0123456789";
631 	os() << escapePrefix << '0' << digits[(c / 8) % 8] << digits[c % 8];
632       }
633       else
634 	os().put(*p);
635       break;
636     }
637   }
638 }
639 
escaper(OutputCharStream & s,Char c)640 void SgmlsEventHandler::escaper(OutputCharStream &s, Char c)
641 {
642   s << escapePrefix << numEscape << (unsigned long)c << escapeEnd;
643 }
644 
outputLocation1(const Location & loc)645 void SgmlsEventHandler::outputLocation1(const Location &loc)
646 {
647   const Origin *origin = loc.origin().pointer();
648   const InputSourceOrigin *inputSourceOrigin;
649   const ExternalInfo *info;
650   Index index = loc.index();
651   for (;;) {
652     if (!origin)
653       return;
654     inputSourceOrigin = origin->asInputSourceOrigin();
655     if (inputSourceOrigin) {
656       info = inputSourceOrigin->externalInfo();
657       if (info)
658 	break;
659     }
660     const Location &loc = origin->parent();
661     index = loc.index();
662     origin = loc.origin().pointer();
663   }
664   Offset off = inputSourceOrigin->startOffset(index);
665   StorageObjectLocation soLoc;
666   if (!ExtendEntityManager::externalize(info, off, soLoc))
667     return;
668   if (soLoc.lineNumber == (unsigned long)-1)
669     return;
670   if (soLoc.storageObjectSpec == lastSos_) {
671     if (soLoc.lineNumber == lastLineno_)
672       return;
673     flushData();
674     os() << locationCode << soLoc.lineNumber << nl;
675     lastLineno_ = soLoc.lineNumber;
676   }
677   else {
678     flushData();
679     os() << locationCode << soLoc.lineNumber << space;
680     outputString(soLoc.actualStorageId);
681     os() << nl;
682     lastLineno_ = soLoc.lineNumber;
683     lastSos_ = soLoc.storageObjectSpec;
684     lastLoc_ = loc;		// make sure lastSos_ doesn't get freed
685   }
686 }
687 
dispatchMessage(const Message & msg)688 void SgmlsEventHandler::dispatchMessage(const Message &msg)
689 {
690   if (!cancelled()) {
691     noteMessage(msg);
692     messenger_->dispatchMessage(msg);
693   }
694 }
695 
initMessage(Message & msg)696 void SgmlsEventHandler::initMessage(Message &msg)
697 {
698   msg.loc = currentLocation_;
699 }
700 
SgmlsSubdocState()701 SgmlsSubdocState::SgmlsSubdocState()
702 : haveLinkProcess_(0), parser_(0)
703 {
704 }
705 
SgmlsSubdocState(const SgmlParser * parser)706 SgmlsSubdocState::SgmlsSubdocState(const SgmlParser *parser)
707 : haveLinkProcess_(0), parser_(parser)
708 {
709 }
710 
init(const SgmlParser * parser)711 void SgmlsSubdocState::init(const SgmlParser *parser)
712 {
713   parser_ = parser;
714   definedNotations_.clear();
715   definedEntities_.clear();
716   haveLinkProcess_ = 0;
717   linkProcess_.clear();
718 }
719 
swap(SgmlsSubdocState & to)720 void SgmlsSubdocState::swap(SgmlsSubdocState &to)
721 {
722   {
723     const SgmlParser *tem = to.parser_;
724     to.parser_ = parser_;
725     parser_ = tem;
726   }
727   {
728     Boolean tem = to.haveLinkProcess_;
729     to.haveLinkProcess_ = haveLinkProcess_;
730     haveLinkProcess_ = tem;
731   }
732   linkProcess_.swap(to.linkProcess_);
733   definedNotations_.swap(to.definedNotations_);
734   definedEntities_.swap(to.definedEntities_);
735 }
736 
737 #ifdef SP_NAMESPACE
738 }
739 #endif
740