1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3 
4 #ifdef __GNUG__
5 #pragma implementation
6 #endif
7 #include "splib.h"
8 #include "Attribute.h"
9 #include "MessageArg.h"
10 #include "macros.h"
11 #include "ParserMessages.h"
12 #include "StringVectorMessageArg.h"
13 #include "Syntax.h"
14 #include "Entity.h"
15 #include "Notation.h"
16 
17 #ifdef SP_NAMESPACE
18 namespace SP_NAMESPACE {
19 #endif
20 
DeclaredValue()21 DeclaredValue::DeclaredValue()
22 {
23 }
24 
~DeclaredValue()25 DeclaredValue::~DeclaredValue()
26 {
27 }
28 
makeValueFromToken(Text & text,AttributeContext & context,const StringC & name,unsigned & specLength) const29 AttributeValue *DeclaredValue::makeValueFromToken(Text &text,
30 						  AttributeContext &context,
31 						  const StringC &name,
32 						  unsigned &specLength) const
33 {
34   return makeValue(text, context, name, specLength);
35 }
36 
makeSemantics(const TokenizedAttributeValue &,AttributeContext &,const StringC &,unsigned &,unsigned &) const37 AttributeSemantics *DeclaredValue::makeSemantics(const TokenizedAttributeValue &,
38 						 AttributeContext &,
39 						 const StringC &,
40 						 unsigned &,
41 						 unsigned &) const
42 {
43   return 0;
44 }
45 
containsToken(const StringC &) const46 Boolean DeclaredValue::containsToken(const StringC &) const
47 {
48   return 0;
49 }
50 
isNotation() const51 Boolean DeclaredValue::isNotation() const
52 {
53   return 0;
54 }
55 
isEntity() const56 Boolean DeclaredValue::isEntity() const
57 {
58   return 0;
59 }
60 
isId() const61 Boolean DeclaredValue::isId() const
62 {
63   return 0;
64 }
65 
isIdref() const66 Boolean DeclaredValue::isIdref() const
67 {
68   return 0;
69 }
70 
getTokens() const71 const Vector<StringC> *DeclaredValue::getTokens() const
72 {
73   return 0;
74 }
75 
76 
CdataDeclaredValue()77 CdataDeclaredValue::CdataDeclaredValue()
78 {
79 }
80 
tokenized() const81 Boolean CdataDeclaredValue::tokenized() const
82 {
83   return 0;
84 }
85 
makeValue(Text & text,AttributeContext & context,const StringC &,unsigned & specLength) const86 AttributeValue *CdataDeclaredValue::makeValue(Text &text, AttributeContext &context,
87 					      const StringC &,
88 					      unsigned &specLength) const
89 {
90   const Syntax &syntax = context.attributeSyntax();
91   size_t normsep = syntax.normsep();
92   size_t normalizedLength = text.normalizedLength(normsep);
93   specLength += normalizedLength;
94   size_t litlen = syntax.litlen();
95   // A length error will already have been given if
96   // length > litlen - normsep.
97   if (litlen >= normsep && text.size() <= litlen - normsep
98       && normalizedLength > litlen)
99     context.message(ParserMessages::normalizedAttributeValueLength,
100 		    NumberMessageArg(litlen),
101 		    NumberMessageArg(normalizedLength));
102   return new CdataAttributeValue(text);
103 }
104 
buildDesc(AttributeDefinitionDesc & desc) const105 void CdataDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
106 {
107   desc.declaredValue = AttributeDefinitionDesc::cdata;
108 }
109 
copy() const110 DeclaredValue *CdataDeclaredValue::copy() const
111 {
112   return new CdataDeclaredValue(*this);
113 }
114 
TokenizedDeclaredValue(TokenType type,Boolean isList)115 TokenizedDeclaredValue::TokenizedDeclaredValue(TokenType type,
116 					       Boolean isList)
117 : type_(type), isList_(isList)
118 {
119   switch (type) {
120   case name:
121   case entityName:
122     initialCategories_ = Syntax::nameStartCategory;
123     subsequentCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory
124 			     | Syntax::otherNameCategory);
125     break;
126   case number:
127     initialCategories_ = Syntax::digitCategory;
128     subsequentCategories_ = Syntax::digitCategory;
129     break;
130   case nameToken:
131     initialCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory
132 			  | Syntax::otherNameCategory);
133     subsequentCategories_ = initialCategories_;
134     break;
135   case numberToken:
136     initialCategories_ = Syntax::digitCategory;
137     subsequentCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory
138 			     | Syntax::otherNameCategory);
139     break;
140   }
141 }
142 
tokenized() const143 Boolean TokenizedDeclaredValue::tokenized() const
144 {
145   return 1;
146 }
147 
makeValue(Text & text,AttributeContext & context,const StringC & str,unsigned & specLength) const148 AttributeValue *TokenizedDeclaredValue::makeValue(Text &text,
149 						  AttributeContext &context,
150 						  const StringC &str,
151 						  unsigned &specLength) const
152 {
153   return makeTokenizedValue(text, context, str, specLength);
154 }
155 
156 TokenizedAttributeValue *
makeTokenizedValue(Text & text,AttributeContext & context,const StringC & name,unsigned & specLength) const157 TokenizedDeclaredValue::makeTokenizedValue(Text &text,
158 					   AttributeContext &context,
159 					   const StringC &name,
160 					   unsigned &specLength) const
161 {
162   Vector<size_t> spaceIndex;
163   const Syntax &syntax = context.attributeSyntax();
164   Char space = syntax.space();
165   text.subst(*(type_ == entityName
166 	       ? syntax.entitySubstTable()
167 	       : syntax.generalSubstTable()),
168 	     space);
169   const StringC &value = text.string();
170   size_t i = 0;
171   size_t length = value.size();
172 
173   for (;;) {
174     if (i >= length) {
175       // ends with a space (which would have to have been entered
176       // via a numeric character reference)
177       if (context.validate())
178 	context.message(ParserMessages::attributeValueSyntax);
179       break;
180     }
181     size_t startIndex = i;
182     if (context.validate()) {
183       if (!(syntax.charCategory(value[i]) & initialCategories_)) {
184         context.Messenger::setNextLocation(text.charLocation(i));
185         Char c = value[i];
186 	if (!(syntax.charCategory(value[i]) & subsequentCategories_))
187 	  context.message(ParserMessages::attributeValueChar,
188 	                  StringMessageArg(StringC(&c, 1)),
189 	                  StringMessageArg(name));
190 	else if (initialCategories_ == Syntax::digitCategory)
191 	  context.message(ParserMessages::attributeValueNumberToken,
192 	                  StringMessageArg(StringC(&c, 1)),
193 	                  StringMessageArg(name));
194 	else
195 	  context.message(ParserMessages::attributeValueName,
196 	                  StringMessageArg(StringC(&c, 1)),
197 	                  StringMessageArg(name));
198       }
199       else {
200 	for (++i;
201              i < length
202 	     && (syntax.charCategory(value[i]) & subsequentCategories_);
203 	     i++)
204 	  ;
205 	if (i < length && value[i] != space) {
206 	  Char c = value[i];
207 	  // character value[i] is not allowed anywhere in the value
208 	  context.Messenger::setNextLocation(text.charLocation(i));
209 	  context.message(ParserMessages::attributeValueChar,
210 		          StringMessageArg(StringC(&c, 1)),
211 		          StringMessageArg(name));
212 	}
213       }
214     }
215     while (i < length && value[i] != space)
216       i++;
217     if (i - startIndex > syntax.namelen()) {
218       context.Messenger::setNextLocation(text.charLocation(i));
219       context.message(ParserMessages::nameTokenLength,
220 		      NumberMessageArg(syntax.namelen()));
221     }
222     if (i == length)
223       break;
224     if (!isList_ && context.validate() && spaceIndex.size() == 0) {
225       context.Messenger::setNextLocation(text.charLocation(i));
226       context.message(ParserMessages::attributeValueMultiple,
227 		      StringMessageArg(name));
228     }
229     spaceIndex.push_back(i);
230     i++;
231   }
232   size_t normsep = syntax.normsep();
233   size_t litlen = syntax.litlen();
234   size_t normalizedLength = normsep + length;
235   // should we count CDATA and SDATA entities here?
236   if (isList_) {
237     normalizedLength += 1;
238     // length is now the number of characters in each token in the list
239     // + 1 for each token in the list; so add normsep - 1 for each
240     // token in the list.
241     if (normsep > 0)
242       normalizedLength += (normsep - 1)*(spaceIndex.size() + 1);
243     else
244       normalizedLength -= spaceIndex.size() + 1;
245   }
246   specLength += normalizedLength;
247   // A length error will already have been given if
248   // length > litlen - normsep.
249   if (litlen >= normsep && length <= litlen - normsep
250       && normalizedLength > litlen)
251     context.message(ParserMessages::normalizedAttributeValueLength,
252 		    NumberMessageArg(litlen),
253 		    NumberMessageArg(normalizedLength));
254   return new TokenizedAttributeValue(text, spaceIndex);
255 }
256 
recoverUnquoted(const StringC & str,const Location & strLoc,AttributeContext & context,const StringC & name)257 Boolean TokenizedAttributeValue::recoverUnquoted(const StringC &str,
258 						 const Location &strLoc,
259 						 AttributeContext &context,
260 						 const StringC &name)
261 {
262   TextIter iter(text_);
263   TextItem::Type type;
264   const Char *s;
265   size_t len;
266   const Location *loc;
267   if (iter.next(type, s, len, loc)
268       && type == TextItem::data
269       && len == text_.size()
270       && loc->origin().pointer() == strLoc.origin().pointer()
271       && loc->index() + len == strLoc.index()
272       && !iter.next(type, s, len, loc)) {
273     context.Messenger::setNextLocation(strLoc);
274     context.message(ParserMessages::attributeValueChar,
275 		    StringMessageArg(StringC(str.data(), 1)),
276 		    StringMessageArg(name));
277     return 1;
278   }
279   return 0;
280 }
281 
buildDesc(AttributeDefinitionDesc & desc) const282 void TokenizedDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
283 {
284   desc.declaredValue = AttributeDefinitionDesc::DeclaredValue(
285     type_ - name + (isList_
286 		    ? AttributeDefinitionDesc::names
287 		    : AttributeDefinitionDesc::name));
288 }
289 
copy() const290 DeclaredValue *TokenizedDeclaredValue::copy() const
291 {
292   return new TokenizedDeclaredValue(*this);
293 }
294 
GroupDeclaredValue(TokenType type,Vector<StringC> & vec)295 GroupDeclaredValue::GroupDeclaredValue(TokenType type,
296 				       Vector<StringC> &vec)
297 : TokenizedDeclaredValue(type, 0)
298 {
299   vec.swap(allowedValues_);
300 }
301 
buildDesc(AttributeDefinitionDesc & desc) const302 void GroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
303 {
304   desc.allowedValues = allowedValues_;
305 }
306 
copy() const307 DeclaredValue *GroupDeclaredValue::copy() const
308 {
309   return new GroupDeclaredValue(*this);
310 }
311 
makeValue(Text & text,AttributeContext & context,const StringC & name,unsigned & specLength) const312 AttributeValue *GroupDeclaredValue::makeValue(Text &text,
313 					      AttributeContext &context,
314 					      const StringC &name,
315 					      unsigned &specLength) const
316 {
317   TokenizedAttributeValue *val = makeTokenizedValue(text, context, name,
318 						    specLength);
319   if (!val || !context.validate())
320     return val;
321   for (size_t i = 0; i < allowedValues_.size(); i++)
322     if (val->string() == allowedValues_[i])
323       return val;
324   context.message(ParserMessages::attributeValueNotInGroup,
325 		  StringMessageArg(val->string()),
326 		  StringMessageArg(name),
327 		  StringVectorMessageArg(allowedValues_));
328   return val;
329 }
330 
makeValueFromToken(Text & text,AttributeContext & context,const StringC &,unsigned & specLength) const331 AttributeValue *GroupDeclaredValue::makeValueFromToken(Text &text,
332 						       AttributeContext &context,
333 						       const StringC &,
334 						       unsigned &specLength)
335      const
336 {
337   const Syntax &syntax = context.attributeSyntax();
338   size_t litlen = syntax.litlen();
339   size_t normsep = syntax.normsep();
340   if (normsep > litlen || text.size() >  litlen - normsep)
341     context.message(ParserMessages::normalizedAttributeValueLength,
342 		    NumberMessageArg(litlen),
343 		    NumberMessageArg(text.size() + normsep));
344   specLength += text.size() + normsep;
345   return new TokenizedAttributeValue(text, Vector<size_t>());
346 }
347 
containsToken(const StringC & token) const348 Boolean GroupDeclaredValue::containsToken(const StringC &token) const
349 {
350   for (size_t i = 0; i < allowedValues_.size(); i++)
351     if (allowedValues_[i] == token)
352       return 1;
353   return 0;
354 }
355 
getTokens() const356 const Vector<StringC> *GroupDeclaredValue::getTokens() const
357 {
358   return &allowedValues_;
359 }
360 
NameTokenGroupDeclaredValue(Vector<StringC> & vec)361 NameTokenGroupDeclaredValue::NameTokenGroupDeclaredValue(Vector<StringC> &vec)
362 : GroupDeclaredValue(nameToken, vec)
363 {
364 }
365 
buildDesc(AttributeDefinitionDesc & desc) const366 void NameTokenGroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
367 {
368   GroupDeclaredValue::buildDesc(desc);
369   desc.declaredValue = AttributeDefinitionDesc::nameTokenGroup;
370 }
371 
copy() const372 DeclaredValue *NameTokenGroupDeclaredValue::copy() const
373 {
374   return new NameTokenGroupDeclaredValue(*this);
375 }
376 
NotationDeclaredValue(Vector<StringC> & vec)377 NotationDeclaredValue::NotationDeclaredValue(Vector<StringC> &vec)
378 : GroupDeclaredValue(name, vec)
379 {
380 }
381 
isNotation() const382 Boolean NotationDeclaredValue::isNotation() const
383 {
384   return 1;
385 }
386 
387 AttributeSemantics *
makeSemantics(const TokenizedAttributeValue & value,AttributeContext & context,const StringC &,unsigned &,unsigned &) const388 NotationDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
389 				     AttributeContext &context,
390 				     const StringC &,
391 				     unsigned &,
392 				     unsigned &) const
393 {
394   ConstPtr<Notation> notation
395     = context.getAttributeNotation(value.string(),
396 				   value.tokenLocation(0));
397   if (notation.isNull()) {
398     if (context.validate()) {
399       context.setNextLocation(value.tokenLocation(0));
400       context.message(ParserMessages::invalidNotationAttribute,
401 		      StringMessageArg(value.string()));
402     }
403     return 0;
404   }
405   return new NotationAttributeSemantics(notation);
406 }
407 
buildDesc(AttributeDefinitionDesc & desc) const408 void NotationDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
409 {
410   GroupDeclaredValue::buildDesc(desc);
411   desc.declaredValue = AttributeDefinitionDesc::notation;
412 }
413 
copy() const414 DeclaredValue *NotationDeclaredValue::copy() const
415 {
416   return new NotationDeclaredValue(*this);
417 }
418 
EntityDeclaredValue(Boolean isList)419 EntityDeclaredValue::EntityDeclaredValue(Boolean isList)
420 : TokenizedDeclaredValue(entityName, isList)
421 {
422 }
423 
isEntity() const424 Boolean EntityDeclaredValue::isEntity() const
425 {
426   return 1;
427 }
428 
429 AttributeSemantics *
makeSemantics(const TokenizedAttributeValue & value,AttributeContext & context,const StringC &,unsigned &,unsigned & nEntityNames) const430 EntityDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
431 				   AttributeContext &context,
432 				   const StringC &,
433 				   unsigned &,
434 				   unsigned &nEntityNames) const
435 {
436   Boolean valid = 1;
437   size_t nTokens = value.nTokens();
438   nEntityNames += nTokens;
439   Vector<ConstPtr<Entity> > entities(nTokens);
440   for (size_t i = 0; i < nTokens; i++) {
441     entities[i] = context.getAttributeEntity(value.token(i),
442 					     value.tokenLocation(i));
443     if (entities[i].isNull()) {
444       if (context.validate()) {
445 	context.setNextLocation(value.tokenLocation(i));
446 	context.message(ParserMessages::invalidEntityAttribute,
447 		        StringMessageArg(value.token(i)));
448       }
449       valid = 0;
450     }
451     else if (!entities[i]->isDataOrSubdoc()) {
452       if (context.validate()) {
453         context.Messenger::setNextLocation(value.tokenLocation(i));
454         context.message(ParserMessages::notDataOrSubdocEntity,
455 		        StringMessageArg(value.token(i)));
456       }
457       valid = 0;
458     }
459   }
460   if (valid)
461     return new EntityAttributeSemantics(entities);
462   else
463     return 0;
464 }
465 
copy() const466 DeclaredValue *EntityDeclaredValue::copy() const
467 {
468   return new EntityDeclaredValue(*this);
469 }
470 
IdDeclaredValue()471 IdDeclaredValue::IdDeclaredValue()
472 : TokenizedDeclaredValue(name, 0)
473 {
474 }
475 
isId() const476 Boolean IdDeclaredValue::isId() const
477 {
478   return 1;
479 }
480 
481 AttributeSemantics *
makeSemantics(const TokenizedAttributeValue & value,AttributeContext & context,const StringC &,unsigned &,unsigned &) const482 IdDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
483 			       AttributeContext &context,
484 			       const StringC &,
485 			       unsigned &,
486 			       unsigned &) const
487 {
488   Location prevLoc;
489   if (!context.defineId(value.string(), value.tokenLocation(0), prevLoc)) {
490     context.setNextLocation(value.tokenLocation(0));
491     context.message(ParserMessages::duplicateId,
492 		    StringMessageArg(value.string()),
493 		    prevLoc);
494   }
495   return 0;
496 }
497 
buildDesc(AttributeDefinitionDesc & desc) const498 void IdDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
499 {
500   desc.declaredValue = AttributeDefinitionDesc::id;
501 }
502 
copy() const503 DeclaredValue *IdDeclaredValue::copy() const
504 {
505   return new IdDeclaredValue(*this);
506 }
507 
IdrefDeclaredValue(Boolean isList)508 IdrefDeclaredValue::IdrefDeclaredValue(Boolean isList)
509 : TokenizedDeclaredValue(name, isList)
510 {
511 }
512 
513 AttributeSemantics *
makeSemantics(const TokenizedAttributeValue & value,AttributeContext & context,const StringC &,unsigned & nIdrefs,unsigned &) const514 IdrefDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
515 				  AttributeContext &context,
516 				  const StringC &,
517 				  unsigned &nIdrefs,
518 				  unsigned &) const
519 {
520   size_t nTokens = value.nTokens();
521   nIdrefs += nTokens;
522   for (size_t i = 0; i < nTokens; i++)
523     context.noteIdref(value.token(i), value.tokenLocation(i));
524   return 0;
525 }
526 
isIdref() const527 Boolean IdrefDeclaredValue::isIdref() const
528 {
529   return 1;
530 }
531 
buildDesc(AttributeDefinitionDesc & desc) const532 void IdrefDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
533 {
534   TokenizedDeclaredValue::buildDesc(desc);
535   if (desc.declaredValue == AttributeDefinitionDesc::name)
536     desc.declaredValue = AttributeDefinitionDesc::idref;
537   else
538     desc.declaredValue = AttributeDefinitionDesc::idrefs;
539 }
540 
copy() const541 DeclaredValue *IdrefDeclaredValue::copy() const
542 {
543   return new IdrefDeclaredValue(*this);
544 }
545 
546 
AttributeDefinition(const StringC & name,DeclaredValue * value)547 AttributeDefinition::AttributeDefinition(const StringC &name,
548 					 DeclaredValue *value)
549 : name_(name), declaredValue_(value)
550 {
551 }
552 
~AttributeDefinition()553 AttributeDefinition::~AttributeDefinition()
554 {
555 }
556 
checkValue(AttributeValue * p,AttributeContext &) const557 AttributeValue *AttributeDefinition::checkValue(AttributeValue *p,
558 						AttributeContext &) const
559 {
560   return p;
561 }
562 
missingValueWouldMatch(const Text &,const AttributeContext &) const563 Boolean AttributeDefinition::missingValueWouldMatch(const Text &,
564 						    const AttributeContext &) const
565 {
566   return 0;
567 }
568 
569 const AttributeValue *
defaultValue(const AttributeValue *) const570 AttributeDefinition::defaultValue(const AttributeValue *) const
571 {
572   return 0;
573 }
574 
getDesc(AttributeDefinitionDesc & desc) const575 void AttributeDefinition::getDesc(AttributeDefinitionDesc &desc) const
576 {
577   desc.allowedValues.clear();
578   desc.defaultValue.clear();
579   desc.currentIndex = 0;
580   buildDesc(desc);
581   declaredValue_->buildDesc(desc);
582 }
583 
isConref() const584 Boolean AttributeDefinition::isConref() const
585 {
586   return 0;
587 }
588 
isCurrent() const589 Boolean AttributeDefinition::isCurrent() const
590 {
591   return 0;
592 }
593 
isFixed() const594 Boolean AttributeDefinition::isFixed() const
595 {
596   return 0;
597 }
598 
RequiredAttributeDefinition(const StringC & name,DeclaredValue * value)599 RequiredAttributeDefinition::RequiredAttributeDefinition(const StringC &name,
600 							 DeclaredValue *value)
601 : AttributeDefinition(name, value)
602 {
603 }
604 
605 ConstPtr<AttributeValue>
makeMissingValue(AttributeContext & context) const606 RequiredAttributeDefinition::makeMissingValue(AttributeContext &context) const
607 {
608   if (context.validate())
609     context.message(ParserMessages::requiredAttributeMissing,
610 		    StringMessageArg(name()));
611   return 0;
612 }
613 
buildDesc(AttributeDefinitionDesc & desc) const614 void RequiredAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
615 {
616   desc.defaultValueType = AttributeDefinitionDesc::required;
617 }
618 
copy() const619 AttributeDefinition *RequiredAttributeDefinition::copy() const
620 {
621   return new RequiredAttributeDefinition(*this);
622 }
623 
CurrentAttributeDefinition(const StringC & name,DeclaredValue * value,size_t index)624 CurrentAttributeDefinition::CurrentAttributeDefinition(const StringC &name, DeclaredValue *value, size_t index)
625 : AttributeDefinition(name, value), currentIndex_(index)
626 {
627 }
628 
629 ConstPtr<AttributeValue>
makeMissingValue(AttributeContext & context) const630 CurrentAttributeDefinition::makeMissingValue(AttributeContext &context) const
631 {
632   if (context.mayDefaultAttribute()) {
633     ConstPtr<AttributeValue> currentValue
634       = context.getCurrentAttribute(currentIndex_);
635     if (currentValue.isNull() && context.validate())
636       context.message(ParserMessages::currentAttributeMissing,
637 		      StringMessageArg(name()));
638     return currentValue;
639   }
640   if (context.validate())
641     context.message(ParserMessages::attributeMissing,
642 		    StringMessageArg(name()));
643   return 0;
644 }
645 
missingValueWouldMatch(const Text & text,const AttributeContext & context) const646 Boolean CurrentAttributeDefinition::missingValueWouldMatch(const Text &text,
647 							   const AttributeContext &context) const
648 {
649   if (!context.mayDefaultAttribute())
650     return 0;
651   ConstPtr<AttributeValue> currentValue
652     = context.getCurrentAttribute(currentIndex_);
653   if (currentValue.isNull())
654     return 0;
655   return text.fixedEqual(*currentValue->text());
656 }
657 
658 AttributeValue *
checkValue(AttributeValue * value,AttributeContext & context) const659 CurrentAttributeDefinition::checkValue(AttributeValue *value,
660 				       AttributeContext &context) const
661 {
662   context.noteCurrentAttribute(currentIndex_, value);
663   return value;
664 }
665 
buildDesc(AttributeDefinitionDesc & desc) const666 void CurrentAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
667 {
668   desc.defaultValueType = AttributeDefinitionDesc::current;
669   desc.currentIndex = currentIndex_;
670 }
671 
copy() const672 AttributeDefinition *CurrentAttributeDefinition::copy() const
673 {
674   return new CurrentAttributeDefinition(*this);
675 }
676 
isCurrent() const677 Boolean CurrentAttributeDefinition::isCurrent() const
678 {
679   return 1;
680 }
681 
ImpliedAttributeDefinition(const StringC & name,DeclaredValue * value)682 ImpliedAttributeDefinition::ImpliedAttributeDefinition(const StringC &name,
683 						       DeclaredValue *value)
684 : AttributeDefinition(name, value)
685 {
686 }
687 
688 ConstPtr<AttributeValue>
makeMissingValue(AttributeContext & context) const689 ImpliedAttributeDefinition::makeMissingValue(AttributeContext &context) const
690 {
691   return context.makeImpliedAttributeValue();
692 }
693 
buildDesc(AttributeDefinitionDesc & desc) const694 void ImpliedAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
695 {
696   desc.defaultValueType = AttributeDefinitionDesc::implied;
697 }
698 
copy() const699 AttributeDefinition *ImpliedAttributeDefinition::copy() const
700 {
701   return new ImpliedAttributeDefinition(*this);
702 }
703 
704 const AttributeValue *
defaultValue(const AttributeValue * impliedValue) const705 ImpliedAttributeDefinition::defaultValue(const AttributeValue *impliedValue)
706      const
707 {
708   return impliedValue;
709 }
710 
ConrefAttributeDefinition(const StringC & name,DeclaredValue * value)711 ConrefAttributeDefinition::ConrefAttributeDefinition(const StringC &name,
712 						     DeclaredValue *value)
713 : ImpliedAttributeDefinition(name, value)
714 {
715 }
716 
isConref() const717 Boolean ConrefAttributeDefinition::isConref() const
718 {
719   return 1;
720 }
721 
buildDesc(AttributeDefinitionDesc & desc) const722 void ConrefAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
723 {
724   desc.defaultValueType = AttributeDefinitionDesc::conref;
725 }
726 
copy() const727 AttributeDefinition *ConrefAttributeDefinition::copy() const
728 {
729   return new ConrefAttributeDefinition(*this);
730 }
731 
DefaultAttributeDefinition(const StringC & name,DeclaredValue * declaredValue,AttributeValue * defaultValue)732 DefaultAttributeDefinition::DefaultAttributeDefinition(const StringC &name,
733 							DeclaredValue *declaredValue,
734 							AttributeValue *defaultValue)
735 : AttributeDefinition(name, declaredValue),
736   value_(defaultValue)
737 {
738 }
739 
740 ConstPtr<AttributeValue>
makeMissingValue(AttributeContext & context) const741 DefaultAttributeDefinition::makeMissingValue(AttributeContext &context) const
742 {
743   if (context.mayDefaultAttribute())
744     return value_;
745   if (context.validate())
746     context.message(ParserMessages::attributeMissing,
747 		    StringMessageArg(name()));
748   return 0;
749 }
750 
missingValueWouldMatch(const Text & text,const AttributeContext & context) const751 Boolean DefaultAttributeDefinition::missingValueWouldMatch(const Text &text,
752 							   const AttributeContext &context) const
753 {
754   return context.mayDefaultAttribute() && text.fixedEqual(*value_->text());
755 }
756 
buildDesc(AttributeDefinitionDesc & desc) const757 void DefaultAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
758 {
759   desc.defaultValueType = AttributeDefinitionDesc::defaulted;
760   desc.defaultValue = value_;
761 }
762 
copy() const763 AttributeDefinition *DefaultAttributeDefinition::copy() const
764 {
765   return new DefaultAttributeDefinition(*this);
766 }
767 
FixedAttributeDefinition(const StringC & name,DeclaredValue * declaredValue,AttributeValue * defaultValue)768 FixedAttributeDefinition:: FixedAttributeDefinition(const StringC &name,
769 						    DeclaredValue *declaredValue,
770 						    AttributeValue *defaultValue)
771 : DefaultAttributeDefinition(name, declaredValue, defaultValue)
772 {
773 }
774 
isFixed() const775 Boolean FixedAttributeDefinition::isFixed() const
776 {
777   return 1;
778 }
779 
checkValue(AttributeValue * value,AttributeContext & context) const780 AttributeValue *FixedAttributeDefinition::checkValue(AttributeValue *value,
781 						     AttributeContext &context)
782      const
783 {
784   const AttributeValue *fixedValue
785     = DefaultAttributeDefinition::defaultValue(0);
786   if (value && fixedValue && context.validate()) {
787     const Text *text;
788     const StringC *str;
789     const Text *fixedText;
790     const StringC *fixedStr;
791     switch (value->info(text, str)) {
792     case AttributeValue::implied:
793       CANNOT_HAPPEN();
794     case AttributeValue::cdata:
795       if (fixedValue->info(fixedText, fixedStr) == AttributeValue::cdata) {
796 	if (!text->fixedEqual(*fixedText))
797 	  context.message(ParserMessages::notFixedValue, StringMessageArg(name()));
798       }
799       break;
800     case AttributeValue::tokenized:
801       if (fixedValue->info(fixedText, fixedStr) == AttributeValue::tokenized) {
802 	if (*str != *fixedStr)
803 	  context.message(ParserMessages::notFixedValue, StringMessageArg(name()));
804       }
805       break;
806     }
807   }
808   return value;
809 }
810 
buildDesc(AttributeDefinitionDesc & desc) const811 void FixedAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
812 {
813   // get the fixed value
814   DefaultAttributeDefinition::buildDesc(desc);
815   desc.defaultValueType = AttributeDefinitionDesc::fixed;
816 }
817 
copy() const818 AttributeDefinition *FixedAttributeDefinition::copy() const
819 {
820   return new FixedAttributeDefinition(*this);
821 }
822 
823 AttributeDefinitionList
AttributeDefinitionList(Vector<CopyOwner<AttributeDefinition>> & vec,size_t index,Boolean anyCurrent,size_t idIndex,size_t notationIndex)824 ::AttributeDefinitionList(Vector<CopyOwner<AttributeDefinition> > &vec,
825 			  size_t index,
826 			  Boolean anyCurrent,
827 			  size_t idIndex,
828 			  size_t notationIndex)
829 : index_(index), anyCurrent_(anyCurrent), idIndex_(idIndex),
830   notationIndex_(notationIndex)
831 {
832   defs_.swap(vec);
833 }
834 
AttributeDefinitionList(const ConstPtr<AttributeDefinitionList> & def)835 AttributeDefinitionList:: AttributeDefinitionList(const ConstPtr<AttributeDefinitionList> &def)
836 : prev_(def), index_(size_t(-1))
837 {
838   if (def.isNull()) {
839     anyCurrent_ = 0;
840     notationIndex_ = size_t(-1);
841     idIndex_ = size_t(-1);
842   }
843   else {
844     anyCurrent_ = def->anyCurrent_;
845     notationIndex_ = def->notationIndex_;
846     idIndex_ = def->idIndex_;
847     defs_ = def->defs_;
848   }
849 }
850 
tokenIndex(const StringC & token,unsigned & index) const851 Boolean AttributeDefinitionList::tokenIndex(const StringC &token, unsigned &index) const
852 {
853   for (size_t i = 0; i < defs_.size(); i++)
854     if (defs_[i]->containsToken(token)) {
855       index = i;
856       return 1;
857     }
858   return 0;
859 }
860 
tokenIndexUnique(const StringC & token,unsigned i) const861 Boolean AttributeDefinitionList::tokenIndexUnique(const StringC &token, unsigned i) const
862 {
863   for (++i; i < defs_.size(); i++)
864     if (defs_[i]->containsToken(token))
865       return 0;
866   return 1;
867 }
868 
869 
attributeIndex(const StringC & name,unsigned & index) const870 Boolean AttributeDefinitionList::attributeIndex(const StringC &name,
871 						unsigned &index) const
872 {
873   for (size_t i = 0; i < defs_.size(); i++)
874     if (defs_[i]->name() == name) {
875       index = i;
876       return 1;
877     }
878   return 0;
879 }
880 
append(AttributeDefinition * def)881 void AttributeDefinitionList::append(AttributeDefinition *def)
882 {
883   if (def->isId() && idIndex_ == size_t(-1))
884     idIndex_ = defs_.size();
885   if (def->isNotation() && notationIndex_ == size_t(-1))
886     notationIndex_ = defs_.size();
887   if (def->isCurrent())
888     anyCurrent_ = 1;
889   defs_.resize(defs_.size() + 1);
890   defs_.back() = def;
891 }
892 
AttributeSemantics()893 AttributeSemantics::AttributeSemantics()
894 {
895 }
896 
~AttributeSemantics()897 AttributeSemantics::~AttributeSemantics()
898 {
899 }
900 
nEntities() const901 size_t AttributeSemantics::nEntities() const
902 {
903   return 0;
904 }
905 
entity(size_t) const906 ConstPtr<Entity> AttributeSemantics::entity(size_t) const
907 {
908   return 0;
909 }
910 
notation() const911 ConstPtr<Notation> AttributeSemantics::notation() const
912 {
913   return 0;
914 }
915 
916 
NotationAttributeSemantics(const ConstPtr<Notation> & notation)917 NotationAttributeSemantics::NotationAttributeSemantics(const ConstPtr<Notation> &notation)
918 : notation_(notation)
919 {
920 }
921 
notation() const922 ConstPtr<Notation> NotationAttributeSemantics::notation() const
923 {
924   return notation_;
925 }
926 
copy() const927 AttributeSemantics *NotationAttributeSemantics::copy() const
928 {
929   return new NotationAttributeSemantics(*this);
930 }
931 
EntityAttributeSemantics(Vector<ConstPtr<Entity>> & entity)932 EntityAttributeSemantics::EntityAttributeSemantics(Vector<ConstPtr<Entity> > &entity)
933 {
934   entity.swap(entity_);
935 }
936 
nEntities() const937 size_t EntityAttributeSemantics::nEntities() const
938 {
939   return entity_.size();
940 }
941 
entity(size_t i) const942 ConstPtr<Entity> EntityAttributeSemantics::entity(size_t i) const
943 {
944   return entity_[i];
945 }
946 
copy() const947 AttributeSemantics *EntityAttributeSemantics::copy() const
948 {
949   return new EntityAttributeSemantics(*this);
950 }
951 
AttributeValue()952 AttributeValue::AttributeValue()
953 {
954 }
955 
~AttributeValue()956 AttributeValue::~AttributeValue()
957 {
958 }
959 
makeSemantics(const DeclaredValue *,AttributeContext &,const StringC &,unsigned &,unsigned &) const960 AttributeSemantics *AttributeValue::makeSemantics(const DeclaredValue *,
961 						  AttributeContext &,
962 						  const StringC &,
963 						  unsigned &,
964 						  unsigned &) const
965 {
966   return 0;
967 }
968 
text() const969 const Text *AttributeValue::text() const
970 {
971   return 0;
972 }
973 
recoverUnquoted(const StringC &,const Location &,AttributeContext &,const StringC &)974 Boolean AttributeValue::recoverUnquoted(const StringC &, const Location &,
975 					AttributeContext &, const StringC &)
976 {
977   return 0;
978 }
979 
ImpliedAttributeValue()980 ImpliedAttributeValue::ImpliedAttributeValue()
981 {
982 }
983 
info(const Text * &,const StringC * &) const984 AttributeValue::Type ImpliedAttributeValue::info(const Text *&,
985 						 const StringC *&) const
986 {
987   return implied;
988 }
989 
TokenizedAttributeValue(Text & text,const Vector<size_t> & spaceIndex)990 TokenizedAttributeValue::TokenizedAttributeValue(Text &text,
991 						 const Vector<size_t> &spaceIndex)
992 : spaceIndex_(spaceIndex)
993 {
994   text.swap(text_);
995 }
996 
info(const Text * &,const StringC * & string) const997 AttributeValue::Type TokenizedAttributeValue::info(const Text *&,
998 						   const StringC *&string) const
999 {
1000   string = &text_.string();
1001   return tokenized;
1002 }
1003 
text() const1004 const Text *TokenizedAttributeValue::text() const
1005 {
1006   return &text_;
1007 }
1008 
1009 AttributeSemantics *
makeSemantics(const DeclaredValue * value,AttributeContext & context,const StringC & name,unsigned & nIdrefs,unsigned & nEntityNames) const1010 TokenizedAttributeValue::makeSemantics(const DeclaredValue *value,
1011 				       AttributeContext &context,
1012 				       const StringC &name,
1013 				       unsigned &nIdrefs,
1014 				       unsigned &nEntityNames) const
1015 {
1016   if (text_.size() == 0)
1017     return 0;
1018   return value->makeSemantics(*this, context, name, nIdrefs, nEntityNames);
1019 }
1020 
CdataAttributeValue(Text & text)1021 CdataAttributeValue::CdataAttributeValue(Text &text)
1022 {
1023   text.swap(text_);
1024 }
1025 
info(const Text * & text,const StringC * &) const1026 AttributeValue::Type CdataAttributeValue::info(const Text *&text,
1027 					       const StringC *&) const
1028 {
1029   text = &text_;
1030   return cdata;
1031 }
1032 
text() const1033 const Text *CdataAttributeValue::text() const
1034 {
1035   return &text_;
1036 }
1037 
recoverUnquoted(const StringC & str,const Location & strLoc,AttributeContext & context,const StringC &)1038 Boolean CdataAttributeValue::recoverUnquoted(const StringC &str,
1039 					     const Location &strLoc,
1040 					     AttributeContext &context,
1041 					     const StringC &)
1042 {
1043   TextIter iter(text_);
1044   TextItem::Type type;
1045   const Char *s;
1046   size_t len;
1047   const Location *loc;
1048   if (iter.next(type, s, len, loc)
1049       && type == TextItem::data
1050       && len == text_.size()
1051       && loc->origin().pointer() == strLoc.origin().pointer()
1052       && loc->index() + len == strLoc.index()
1053       && !iter.next(type, s, len, loc)) {
1054     text_.addChars(str, strLoc);
1055     context.Messenger::setNextLocation(strLoc);
1056     context.message(ParserMessages::unquotedAttributeValue);
1057     return 1;
1058   }
1059   return 0;
1060 }
1061 
Attribute()1062 Attribute::Attribute()
1063 : specIndexPlus_(0)
1064 {
1065 }
1066 
clear()1067 void Attribute::clear()
1068 {
1069   specIndexPlus_ = 0;
1070   value_.clear();
1071   semantics_.clear();
1072 }
1073 
AttributeList(const ConstPtr<AttributeDefinitionList> & def)1074 AttributeList::AttributeList(const ConstPtr<AttributeDefinitionList> &def)
1075 : def_(def), vec_(def.isNull() ? 0 : def->size()), nSpec_(0), conref_(0),
1076   nIdrefs_(0), nEntityNames_(0)
1077 {
1078 }
1079 
AttributeList()1080 AttributeList::AttributeList()
1081 : nSpec_(0), conref_(0)
1082 {
1083 }
1084 
init(const ConstPtr<AttributeDefinitionList> & def)1085 void AttributeList::init(const ConstPtr<AttributeDefinitionList> &def)
1086 {
1087   def_ = def;
1088   nSpec_ = 0;
1089   conref_ = 0;
1090   nIdrefs_ = 0;
1091   nEntityNames_ = 0;
1092   if (def_.isNull())
1093     vec_.resize(0);
1094   else {
1095     size_t newLength = def_->size();
1096     size_t clearLim = vec_.size();
1097     if (clearLim > newLength)
1098       clearLim = newLength;
1099     vec_.resize(newLength);
1100     for (size_t i = 0; i < clearLim; i++)
1101       vec_[i].clear();
1102   }
1103 }
1104 
changeDef(const ConstPtr<AttributeDefinitionList> & def)1105 void AttributeList::changeDef(const ConstPtr<AttributeDefinitionList> &def)
1106 {
1107   vec_.resize(def.isNull() ? 0 : def->size());
1108   def_ = def;
1109 }
1110 
swap(AttributeList & to)1111 void AttributeList::swap(AttributeList &to)
1112 {
1113   vec_.swap(to.vec_);
1114   def_.swap(to.def_);
1115   {
1116     unsigned tem = to.nIdrefs_;
1117     to.nIdrefs_ = nIdrefs_;
1118     nIdrefs_ = tem;
1119   }
1120   {
1121     unsigned tem = to.nEntityNames_;
1122     to.nEntityNames_ = nEntityNames_;
1123     nEntityNames_ = tem;
1124   }
1125   {
1126     size_t tem = to.nSpec_;
1127     to.nSpec_ = nSpec_;
1128     nSpec_ = tem;
1129   }
1130   {
1131     PackedBoolean tem = to.conref_;
1132     to.conref_ = conref_;
1133     conref_ = tem;
1134   }
1135 }
1136 
finish(AttributeContext & context)1137 void AttributeList::finish(AttributeContext &context)
1138 {
1139   for (size_t i = 0; i < vec_.size(); i++)
1140     if (!vec_[i].specified()) {
1141       ConstPtr<AttributeValue> value
1142 	= def(i)->makeMissingValue(context);
1143       if (!conref_ || def_->notationIndex() != i) {
1144 	vec_[i].setValue(value);
1145         if (!value.isNull())
1146       	  vec_[i].setSemantics(def(i)->makeSemantics(value.pointer(),
1147 						     context,
1148 						     nIdrefs_,
1149 						     nEntityNames_));
1150       }
1151     }
1152   const Syntax &syntax = context.attributeSyntax();
1153   if (nIdrefs_ > syntax.grpcnt())
1154     context.message(ParserMessages::idrefGrpcnt,
1155 		   NumberMessageArg(syntax.grpcnt()));
1156   if (nEntityNames_ > syntax.grpcnt())
1157     context.message(ParserMessages::entityNameGrpcnt,
1158 		   NumberMessageArg(syntax.grpcnt()));
1159   if (context.validate()
1160       && conref_
1161       && def_->notationIndex() != size_t(-1)
1162       && specified(def_->notationIndex()))
1163     context.message(ParserMessages::conrefNotation);
1164 }
1165 
setSpec(unsigned i,AttributeContext & context)1166 void AttributeList::setSpec(unsigned i, AttributeContext &context)
1167 {
1168   if (vec_[i].specified())
1169     context.message(ParserMessages::duplicateAttributeSpec,
1170 		   StringMessageArg(def(i)->name()));
1171   else
1172     vec_[i].setSpec(nSpec_++);
1173 }
1174 
noteInvalidSpec()1175 void AttributeList::noteInvalidSpec()
1176 {
1177   // This is needed for error recovery.
1178   // We don't want nSpec_ to be > 0, if there is no attribute definition.
1179   if (nSpec_)
1180     nSpec_++;
1181 }
1182 
setValue(unsigned i,Text & text,AttributeContext & context,unsigned & specLength)1183 Boolean AttributeList::setValue(unsigned i, Text &text,
1184 				AttributeContext &context,
1185 				unsigned &specLength)
1186 {
1187   AttributeValue *value = def(i)->makeValue(text, context, specLength);
1188   if (def(i)->isConref())
1189     conref_ = 1;
1190   vec_[i].setValue(value);
1191   if (value)
1192     vec_[i].setSemantics(def(i)->makeSemantics(value, context,
1193 					       nIdrefs_, nEntityNames_));
1194   else if (AttributeValue::handleAsUnterminated(text, context))
1195     return 0;
1196   return 1;
1197 }
1198 
setValueToken(unsigned i,Text & text,AttributeContext & context,unsigned & specLength)1199 void AttributeList::setValueToken(unsigned i, Text &text,
1200 				  AttributeContext &context,
1201 				  unsigned &specLength)
1202 {
1203   AttributeValue *value = def(i)->makeValueFromToken(text, context,
1204 						     specLength);
1205   if (def(i)->isConref())
1206     conref_ = 1;
1207   vec_[i].setValue(value);
1208   if (value)
1209     vec_[i].setSemantics(def(i)->makeSemantics(value, context,
1210 					       nIdrefs_, nEntityNames_));
1211 }
1212 
getId() const1213 const StringC *AttributeList::getId() const
1214 {
1215   // Check for no attributes
1216   if (def_.isNull())
1217     return 0;
1218   // Check for no ID declared
1219   size_t i = def_->idIndex();
1220   if (i == size_t(-1))
1221     return 0;
1222   // Check for invalid value
1223   const AttributeValue *v = value(i);
1224   if (!v)
1225     return 0;
1226   // Check for implied value
1227   const Text *t = v->text();
1228   if (!t)
1229     return 0;
1230   return &t->string();
1231 }
1232 
recoverUnquoted(const StringC & str,const Location & strLoc,AttributeContext & context)1233 Boolean AttributeList::recoverUnquoted(const StringC &str,
1234 				       const Location &strLoc,
1235 				       AttributeContext &context)
1236 {
1237   if (nSpec_ > 0) {
1238     for (size_t i = 0; i < vec_.size(); i++)
1239       if (vec_[i].specified() && vec_[i].specIndex() == nSpec_ - 1) {
1240 	const AttributeValue *val = vec_[i].value();
1241 	if (val)
1242 	  // I wish I could avoid casting away const here.
1243 	  return ((AttributeValue *)val)->recoverUnquoted(str, strLoc, context,
1244 							  name(i));
1245 	break;
1246       }
1247     return 1;
1248   }
1249   return 0;
1250 }
1251 
handleAsUnterminated(AttributeContext & context)1252 Boolean AttributeList::handleAsUnterminated(AttributeContext &context)
1253 {
1254   if (nSpec_ > 0) {
1255     for (size_t i = 0; i < vec_.size(); i++) {
1256       if (vec_[i].specified() && vec_[i].specIndex() == nSpec_ - 1) {
1257 	const AttributeValue *val = vec_[i].value();
1258 	const Text *ptr;
1259 	if (val && (ptr = val->text()) != 0
1260 	    && AttributeValue::handleAsUnterminated(*ptr, context))
1261 	  return 1;
1262 	break;
1263       }
1264     }
1265   }
1266   return 0;
1267 }
1268 
1269 // This tries to guess this attribute value looks like if it had
1270 // a missing ending quote.
1271 
handleAsUnterminated(const Text & text,AttributeContext & context)1272 Boolean AttributeValue::handleAsUnterminated(const Text &text,
1273 					     AttributeContext &context)
1274 {
1275   TextIter iter(text);
1276   const Char *lastStr = 0;
1277   size_t lastLen;
1278   Location startLoc;
1279   const Location *loc;
1280   TextItem::Type type;
1281   const Char *str;
1282   size_t len;
1283   while (iter.next(type, str, len, loc)) {
1284     if (startLoc.origin().isNull() && !loc->origin().isNull())
1285       startLoc = *loc;
1286     switch (type) {
1287     case TextItem::data:
1288       if (len != 1 || *str != context.attributeSyntax().space()) {
1289 	lastStr = str;
1290 	lastLen = len;
1291       }
1292       break;
1293     case TextItem::endDelim:
1294     case TextItem::endDelimA:
1295     case TextItem::ignore:
1296       break;
1297     default:
1298       lastStr = 0;
1299       break;
1300     }
1301   }
1302   if (lastStr) {
1303     while (lastLen > 0
1304 	   && lastStr[lastLen - 1] == context.attributeSyntax().space())
1305       lastLen--;
1306     const StringC &vi = context.attributeSyntax().delimGeneral(Syntax::dVI);
1307     if (lastLen >= vi.size()
1308 	&& (vi
1309 	    == StringC(lastStr + (lastLen - vi.size()), vi.size()))) {
1310       context.Messenger::setNextLocation(startLoc);
1311       context.message(ParserMessages::literalClosingDelimiter);
1312       return 1;
1313     }
1314   }
1315   return 0;
1316 }
1317 
AttributeContext()1318 AttributeContext::AttributeContext()
1319 : mayDefaultAttribute_(0), validate_(1)
1320 {
1321 }
1322 
~AttributeContext()1323 AttributeContext::~AttributeContext()
1324 {
1325 }
1326 
defineId(const StringC &,const Location &,Location &)1327 Boolean AttributeContext::defineId(const StringC &, const Location &,
1328 				   Location &)
1329 {
1330   return 1;
1331 }
1332 
noteIdref(const StringC &,const Location &)1333 void AttributeContext::noteIdref(const StringC &, const Location &)
1334 {
1335 }
1336 
noteCurrentAttribute(size_t,AttributeValue *)1337 void AttributeContext::noteCurrentAttribute(size_t, AttributeValue *)
1338 {
1339 }
1340 
getCurrentAttribute(size_t) const1341 ConstPtr<AttributeValue> AttributeContext::getCurrentAttribute(size_t) const
1342 {
1343   return 0;
1344 }
1345 
getAttributeEntity(const StringC &,const Location &)1346 ConstPtr<Entity> AttributeContext::getAttributeEntity(const StringC &,
1347 						      const Location &)
1348 {
1349   return 0;
1350 }
1351 
getAttributeNotation(const StringC &,const Location &)1352 ConstPtr<Notation> AttributeContext::getAttributeNotation(const StringC &,
1353 							  const Location &)
1354 {
1355   return 0;
1356 }
1357 
makeImpliedAttributeValue()1358 ConstPtr<AttributeValue> AttributeContext::makeImpliedAttributeValue()
1359 {
1360   if (impliedAttributeValue_.isNull())
1361     impliedAttributeValue_ = new ImpliedAttributeValue;
1362   return impliedAttributeValue_;
1363 }
1364 
1365 #ifdef SP_NAMESPACE
1366 }
1367 #endif
1368