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 "Syntax.h"
13 #include "Entity.h"
14 #include "Notation.h"
15 
16 #ifdef SP_NAMESPACE
17 namespace SP_NAMESPACE {
18 #endif
19 
DeclaredValue()20 DeclaredValue::DeclaredValue()
21 {
22 }
23 
~DeclaredValue()24 DeclaredValue::~DeclaredValue()
25 {
26 }
27 
makeValueFromToken(Text & text,AttributeContext & context,const StringC & name,unsigned & specLength) const28 AttributeValue *DeclaredValue::makeValueFromToken(Text &text,
29 						  AttributeContext &context,
30 						  const StringC &name,
31 						  unsigned &specLength) const
32 {
33   return makeValue(text, context, name, specLength);
34 }
35 
makeSemantics(const TokenizedAttributeValue &,AttributeContext &,const StringC &,unsigned &,unsigned &) const36 AttributeSemantics *DeclaredValue::makeSemantics(const TokenizedAttributeValue &,
37 						 AttributeContext &,
38 						 const StringC &,
39 						 unsigned &,
40 						 unsigned &) const
41 {
42   return 0;
43 }
44 
containsToken(const StringC &) const45 Boolean DeclaredValue::containsToken(const StringC &) const
46 {
47   return 0;
48 }
49 
isNotation() const50 Boolean DeclaredValue::isNotation() const
51 {
52   return 0;
53 }
54 
isEntity() const55 Boolean DeclaredValue::isEntity() const
56 {
57   return 0;
58 }
59 
isId() const60 Boolean DeclaredValue::isId() const
61 {
62   return 0;
63 }
64 
isIdref() const65 Boolean DeclaredValue::isIdref() const
66 {
67   return 0;
68 }
69 
getTokens() const70 const Vector<StringC> *DeclaredValue::getTokens() const
71 {
72   return 0;
73 }
74 
getOrigTokens() const75 const Vector<StringC> *DeclaredValue::getOrigTokens() const
76 {
77   return 0;
78 }
79 
80 
CdataDeclaredValue()81 CdataDeclaredValue::CdataDeclaredValue()
82 {
83 }
84 
tokenized() const85 Boolean CdataDeclaredValue::tokenized() const
86 {
87   return 0;
88 }
89 
checkNormalizedLength(Text & text,AttributeContext & context,unsigned & specLength) const90 void CdataDeclaredValue::checkNormalizedLength(Text &text,
91                                                AttributeContext &context,
92                                                unsigned &specLength) const
93 {
94   const Syntax &syntax = context.attributeSyntax();
95   size_t normsep = syntax.normsep();
96   size_t normalizedLength = text.normalizedLength(normsep);
97   specLength += normalizedLength;
98   size_t litlen = syntax.litlen();
99   // A length error will already have been given if
100   // length > litlen - normsep.
101   if (litlen >= normsep && text.size() <= litlen - normsep
102       && normalizedLength > litlen)
103     context.message(ParserMessages::normalizedAttributeValueLength,
104 		    NumberMessageArg(litlen),
105 		    NumberMessageArg(normalizedLength));
106 }
107 
makeValue(Text & text,AttributeContext & context,const StringC &,unsigned & specLength) const108 AttributeValue *CdataDeclaredValue::makeValue(Text &text, AttributeContext &context,
109 					      const StringC &,
110 					      unsigned &specLength) const
111 {
112   checkNormalizedLength(text, context, specLength);
113   return new CdataAttributeValue(text);
114 }
115 
buildDesc(AttributeDefinitionDesc & desc) const116 void CdataDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
117 {
118   desc.declaredValue = AttributeDefinitionDesc::cdata;
119 }
120 
copy() const121 DeclaredValue *CdataDeclaredValue::copy() const
122 {
123   return new CdataDeclaredValue(*this);
124 }
125 
DataDeclaredValue(const ConstPtr<Notation> & nt,AttributeList & attributes)126 DataDeclaredValue::DataDeclaredValue(const ConstPtr<Notation> &nt,
127                                      AttributeList &attributes)
128 : notation_(nt)
129 {
130   attributes.swap(attributes_);
131 }
132 
makeValue(Text & text,AttributeContext & context,const StringC &,unsigned & specLength) const133 AttributeValue *DataDeclaredValue::makeValue(Text &text,
134                                              AttributeContext &context,
135                                              const StringC &,
136                                              unsigned &specLength) const
137 {
138   checkNormalizedLength(text, context, specLength);
139   return new DataAttributeValue(text, notation_, attributes_);
140 }
141 
copy() const142 DeclaredValue *DataDeclaredValue::copy() const
143 {
144   return new DataDeclaredValue(*this);
145 }
146 
TokenizedDeclaredValue(TokenType type,Boolean isList)147 TokenizedDeclaredValue::TokenizedDeclaredValue(TokenType type,
148 					       Boolean isList)
149 : type_(type), isList_(isList)
150 {
151   switch (type) {
152   case name:
153   case entityName:
154     initialCategories_ = Syntax::nameStartCategory;
155     subsequentCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory
156 			     | Syntax::otherNameCategory);
157     break;
158   case number:
159     initialCategories_ = Syntax::digitCategory;
160     subsequentCategories_ = Syntax::digitCategory;
161     break;
162   case nameToken:
163     initialCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory
164 			  | Syntax::otherNameCategory);
165     subsequentCategories_ = initialCategories_;
166     break;
167   case numberToken:
168     initialCategories_ = Syntax::digitCategory;
169     subsequentCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory
170 			     | Syntax::otherNameCategory);
171     break;
172   }
173 }
174 
tokenized() const175 Boolean TokenizedDeclaredValue::tokenized() const
176 {
177   return 1;
178 }
179 
makeValue(Text & text,AttributeContext & context,const StringC & str,unsigned & specLength) const180 AttributeValue *TokenizedDeclaredValue::makeValue(Text &text,
181 						  AttributeContext &context,
182 						  const StringC &str,
183 						  unsigned &specLength) const
184 {
185   return makeTokenizedValue(text, context, str, specLength);
186 }
187 
188 TokenizedAttributeValue *
makeTokenizedValue(Text & text,AttributeContext & context,const StringC & name,unsigned & specLength) const189 TokenizedDeclaredValue::makeTokenizedValue(Text &text,
190 					   AttributeContext &context,
191 					   const StringC &name,
192 					   unsigned &specLength) const
193 {
194   Vector<size_t> spaceIndex;
195   const Syntax &syntax = context.attributeSyntax();
196   Char space = syntax.space();
197   text.subst(*(type_ == entityName
198 	       ? syntax.entitySubstTable()
199 	       : syntax.generalSubstTable()),
200 	     space);
201   const StringC &value = text.string();
202   size_t i = 0;
203   size_t length = value.size();
204 
205   for (;;) {
206     if (i >= length) {
207       // ends with a space (which would have to have been entered
208       // via a numeric character reference)
209       if (context.validate())
210 	context.message(ParserMessages::attributeValueSyntax);
211       break;
212     }
213     size_t startIndex = i;
214     if (context.validate()) {
215       if (!(syntax.charCategory(value[i]) & initialCategories_)) {
216         context.Messenger::setNextLocation(text.charLocation(i));
217         Char c = value[i];
218 	if (!(syntax.charCategory(value[i]) & subsequentCategories_))
219 	  context.message(ParserMessages::attributeValueChar,
220 	                  StringMessageArg(StringC(&c, 1)),
221 	                  StringMessageArg(name));
222 	else if (initialCategories_ == Syntax::digitCategory)
223 	  context.message(ParserMessages::attributeValueNumberToken,
224 	                  StringMessageArg(StringC(&c, 1)),
225 	                  StringMessageArg(name));
226 	else
227 	  context.message(ParserMessages::attributeValueName,
228 	                  StringMessageArg(StringC(&c, 1)),
229 	                  StringMessageArg(name));
230       }
231       else {
232 	for (++i;
233              i < length
234 	     && (syntax.charCategory(value[i]) & subsequentCategories_);
235 	     i++)
236 	  ;
237 	if (i < length && value[i] != space) {
238 	  Char c = value[i];
239 	  // character value[i] is not allowed anywhere in the value
240 	  context.Messenger::setNextLocation(text.charLocation(i));
241 	  context.message(ParserMessages::attributeValueChar,
242 		          StringMessageArg(StringC(&c, 1)),
243 		          StringMessageArg(name));
244 	}
245       }
246     }
247     while (i < length && value[i] != space)
248       i++;
249     if (i - startIndex > syntax.namelen()) {
250       context.Messenger::setNextLocation(text.charLocation(i));
251       context.message(ParserMessages::nameTokenLength,
252 		      NumberMessageArg(syntax.namelen()));
253     }
254     if (i == length)
255       break;
256     if (!isList_ && context.validate() && spaceIndex.size() == 0) {
257       context.Messenger::setNextLocation(text.charLocation(i));
258       context.message(ParserMessages::attributeValueMultiple,
259 		      StringMessageArg(name));
260     }
261     spaceIndex.push_back(i);
262     i++;
263   }
264   size_t normsep = syntax.normsep();
265   size_t litlen = syntax.litlen();
266   size_t normalizedLength = normsep + length;
267   // should we count CDATA and SDATA entities here?
268   if (isList_) {
269     normalizedLength += 1;
270     // length is now the number of characters in each token in the list
271     // + 1 for each token in the list; so add normsep - 1 for each
272     // token in the list.
273     if (normsep > 0)
274       normalizedLength += (normsep - 1)*(spaceIndex.size() + 1);
275     else
276       normalizedLength -= spaceIndex.size() + 1;
277   }
278   specLength += normalizedLength;
279   // A length error will already have been given if
280   // length > litlen - normsep.
281   if (litlen >= normsep && length <= litlen - normsep
282       && normalizedLength > litlen)
283     context.message(ParserMessages::normalizedAttributeValueLength,
284 		    NumberMessageArg(litlen),
285 		    NumberMessageArg(normalizedLength));
286   return new TokenizedAttributeValue(text, spaceIndex);
287 }
288 
recoverUnquoted(const StringC & str,const Location & strLoc,AttributeContext & context,const StringC & name)289 Boolean TokenizedAttributeValue::recoverUnquoted(const StringC &str,
290 						 const Location &strLoc,
291 						 AttributeContext &context,
292 						 const StringC &name)
293 {
294   TextIter iter(text_);
295   TextItem::Type type;
296   const Char *s;
297   size_t len;
298   const Location *loc;
299   if (iter.next(type, s, len, loc)
300       && type == TextItem::data
301       && len == text_.size()
302       && loc->origin().pointer() == strLoc.origin().pointer()
303       && loc->index() + len == strLoc.index()
304       && !iter.next(type, s, len, loc)) {
305     context.Messenger::setNextLocation(strLoc);
306     context.message(ParserMessages::attributeValueChar,
307 		    StringMessageArg(StringC(str.data(), 1)),
308 		    StringMessageArg(name));
309     return 1;
310   }
311   return 0;
312 }
313 
buildDesc(AttributeDefinitionDesc & desc) const314 void TokenizedDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
315 {
316   desc.declaredValue = AttributeDefinitionDesc::DeclaredValue(
317     type_ - name + (isList_
318 		    ? AttributeDefinitionDesc::names
319 		    : AttributeDefinitionDesc::name));
320 }
321 
copy() const322 DeclaredValue *TokenizedDeclaredValue::copy() const
323 {
324   return new TokenizedDeclaredValue(*this);
325 }
326 
GroupDeclaredValue(TokenType type,Vector<StringC> & vec)327 GroupDeclaredValue::GroupDeclaredValue(TokenType type,
328 				       Vector<StringC> &vec)
329 : TokenizedDeclaredValue(type, 0)
330 {
331   vec.swap(allowedValues_);
332 }
333 
buildDesc(AttributeDefinitionDesc & desc) const334 void GroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
335 {
336   desc.allowedValues = allowedValues_;
337   desc.origAllowedValues = origAllowedValues_;
338 }
339 
copy() const340 DeclaredValue *GroupDeclaredValue::copy() const
341 {
342   return new GroupDeclaredValue(*this);
343 }
344 
setOrigAllowedValues(Vector<StringC> & origAllowedValues)345 void GroupDeclaredValue::setOrigAllowedValues(Vector<StringC> &origAllowedValues)
346 {
347   origAllowedValues.swap(origAllowedValues_);
348 }
349 
makeValue(Text & text,AttributeContext & context,const StringC & name,unsigned & specLength) const350 AttributeValue *GroupDeclaredValue::makeValue(Text &text,
351 					      AttributeContext &context,
352 					      const StringC &name,
353 					      unsigned &specLength) const
354 {
355   TokenizedAttributeValue *val = makeTokenizedValue(text, context, name,
356 						    specLength);
357   if (!val || !context.validate())
358     return val;
359   for (size_t i = 0; i < allowedValues_.size(); i++)
360     if (val->string() == allowedValues_[i])
361       return val;
362   context.message(ParserMessages::attributeValueNotInGroup,
363 		  StringMessageArg(val->string()),
364 		  StringMessageArg(name),
365 		  StringVectorMessageArg(allowedValues_));
366   return val;
367 }
368 
makeValueFromToken(Text & text,AttributeContext & context,const StringC &,unsigned & specLength) const369 AttributeValue *GroupDeclaredValue::makeValueFromToken(Text &text,
370 						       AttributeContext &context,
371 						       const StringC &,
372 						       unsigned &specLength)
373      const
374 {
375   const Syntax &syntax = context.attributeSyntax();
376   size_t litlen = syntax.litlen();
377   size_t normsep = syntax.normsep();
378   if (normsep > litlen || text.size() >  litlen - normsep)
379     context.message(ParserMessages::normalizedAttributeValueLength,
380 		    NumberMessageArg(litlen),
381 		    NumberMessageArg(text.size() + normsep));
382   specLength += text.size() + normsep;
383   return new TokenizedAttributeValue(text, Vector<size_t>());
384 }
385 
containsToken(const StringC & token) const386 Boolean GroupDeclaredValue::containsToken(const StringC &token) const
387 {
388   for (size_t i = 0; i < allowedValues_.size(); i++)
389     if (allowedValues_[i] == token)
390       return 1;
391   return 0;
392 }
393 
getTokens() const394 const Vector<StringC> *GroupDeclaredValue::getTokens() const
395 {
396   return &allowedValues_;
397 }
398 
getOrigTokens() const399 const Vector<StringC> *GroupDeclaredValue::getOrigTokens() const
400 {
401   return &origAllowedValues_;
402 }
403 
NameTokenGroupDeclaredValue(Vector<StringC> & vec)404 NameTokenGroupDeclaredValue::NameTokenGroupDeclaredValue(Vector<StringC> &vec)
405 : GroupDeclaredValue(nameToken, vec)
406 {
407 }
408 
buildDesc(AttributeDefinitionDesc & desc) const409 void NameTokenGroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
410 {
411   GroupDeclaredValue::buildDesc(desc);
412   desc.declaredValue = AttributeDefinitionDesc::nameTokenGroup;
413 }
414 
copy() const415 DeclaredValue *NameTokenGroupDeclaredValue::copy() const
416 {
417   return new NameTokenGroupDeclaredValue(*this);
418 }
419 
NotationDeclaredValue(Vector<StringC> & vec)420 NotationDeclaredValue::NotationDeclaredValue(Vector<StringC> &vec)
421 : GroupDeclaredValue(name, vec)
422 {
423 }
424 
isNotation() const425 Boolean NotationDeclaredValue::isNotation() const
426 {
427   return 1;
428 }
429 
430 AttributeSemantics *
makeSemantics(const TokenizedAttributeValue & value,AttributeContext & context,const StringC &,unsigned &,unsigned &) const431 NotationDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
432 				     AttributeContext &context,
433 				     const StringC &,
434 				     unsigned &,
435 				     unsigned &) const
436 {
437   ConstPtr<Notation> notation
438     = context.getAttributeNotation(value.string(),
439 				   value.tokenLocation(0));
440   if (notation.isNull()) {
441     if (context.validate()) {
442       context.setNextLocation(value.tokenLocation(0));
443       context.message(ParserMessages::invalidNotationAttribute,
444 		      StringMessageArg(value.string()));
445     }
446     return 0;
447   }
448   return new NotationAttributeSemantics(notation);
449 }
450 
buildDesc(AttributeDefinitionDesc & desc) const451 void NotationDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
452 {
453   GroupDeclaredValue::buildDesc(desc);
454   desc.declaredValue = AttributeDefinitionDesc::notation;
455 }
456 
copy() const457 DeclaredValue *NotationDeclaredValue::copy() const
458 {
459   return new NotationDeclaredValue(*this);
460 }
461 
EntityDeclaredValue(Boolean isList)462 EntityDeclaredValue::EntityDeclaredValue(Boolean isList)
463 : TokenizedDeclaredValue(entityName, isList)
464 {
465 }
466 
isEntity() const467 Boolean EntityDeclaredValue::isEntity() const
468 {
469   return 1;
470 }
471 
472 AttributeSemantics *
makeSemantics(const TokenizedAttributeValue & value,AttributeContext & context,const StringC &,unsigned &,unsigned & nEntityNames) const473 EntityDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
474 				   AttributeContext &context,
475 				   const StringC &,
476 				   unsigned &,
477 				   unsigned &nEntityNames) const
478 {
479   Boolean valid = 1;
480   size_t nTokens = value.nTokens();
481   nEntityNames += nTokens;
482   Vector<ConstPtr<Entity> > entities(nTokens);
483   for (size_t i = 0; i < nTokens; i++) {
484     entities[i] = context.getAttributeEntity(value.token(i),
485 					     value.tokenLocation(i));
486     if (entities[i].isNull()) {
487       if (context.validate()) {
488 	context.setNextLocation(value.tokenLocation(i));
489 	context.message(ParserMessages::invalidEntityAttribute,
490 		        StringMessageArg(value.token(i)));
491       }
492       valid = 0;
493     }
494     else if (!entities[i]->isDataOrSubdoc()) {
495       if (context.validate()) {
496         context.Messenger::setNextLocation(value.tokenLocation(i));
497         context.message(ParserMessages::notDataOrSubdocEntity,
498 		        StringMessageArg(value.token(i)));
499       }
500       valid = 0;
501     }
502   }
503   if (valid)
504     return new EntityAttributeSemantics(entities);
505   else
506     return 0;
507 }
508 
copy() const509 DeclaredValue *EntityDeclaredValue::copy() const
510 {
511   return new EntityDeclaredValue(*this);
512 }
513 
IdDeclaredValue()514 IdDeclaredValue::IdDeclaredValue()
515 : TokenizedDeclaredValue(name, 0)
516 {
517 }
518 
isId() const519 Boolean IdDeclaredValue::isId() const
520 {
521   return 1;
522 }
523 
524 AttributeSemantics *
makeSemantics(const TokenizedAttributeValue & value,AttributeContext & context,const StringC &,unsigned &,unsigned &) const525 IdDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
526 			       AttributeContext &context,
527 			       const StringC &,
528 			       unsigned &,
529 			       unsigned &) const
530 {
531   Location prevLoc;
532   if (!context.defineId(value.string(), value.tokenLocation(0), prevLoc)) {
533     context.setNextLocation(value.tokenLocation(0));
534     context.message(ParserMessages::duplicateId,
535 		    StringMessageArg(value.string()),
536 		    prevLoc);
537   }
538   return 0;
539 }
540 
buildDesc(AttributeDefinitionDesc & desc) const541 void IdDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
542 {
543   desc.declaredValue = AttributeDefinitionDesc::id;
544 }
545 
copy() const546 DeclaredValue *IdDeclaredValue::copy() const
547 {
548   return new IdDeclaredValue(*this);
549 }
550 
IdrefDeclaredValue(Boolean isList)551 IdrefDeclaredValue::IdrefDeclaredValue(Boolean isList)
552 : TokenizedDeclaredValue(name, isList)
553 {
554 }
555 
556 AttributeSemantics *
makeSemantics(const TokenizedAttributeValue & value,AttributeContext & context,const StringC &,unsigned & nIdrefs,unsigned &) const557 IdrefDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
558 				  AttributeContext &context,
559 				  const StringC &,
560 				  unsigned &nIdrefs,
561 				  unsigned &) const
562 {
563   size_t nTokens = value.nTokens();
564   nIdrefs += nTokens;
565   for (size_t i = 0; i < nTokens; i++)
566     context.noteIdref(value.token(i), value.tokenLocation(i));
567   return 0;
568 }
569 
isIdref() const570 Boolean IdrefDeclaredValue::isIdref() const
571 {
572   return 1;
573 }
574 
buildDesc(AttributeDefinitionDesc & desc) const575 void IdrefDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
576 {
577   TokenizedDeclaredValue::buildDesc(desc);
578   if (desc.declaredValue == AttributeDefinitionDesc::name)
579     desc.declaredValue = AttributeDefinitionDesc::idref;
580   else
581     desc.declaredValue = AttributeDefinitionDesc::idrefs;
582 }
583 
copy() const584 DeclaredValue *IdrefDeclaredValue::copy() const
585 {
586   return new IdrefDeclaredValue(*this);
587 }
588 
589 
AttributeDefinition(const StringC & name,DeclaredValue * value)590 AttributeDefinition::AttributeDefinition(const StringC &name,
591 					 DeclaredValue *value)
592 : name_(name), declaredValue_(value), implicit_(0), all_(0)
593 {
594 }
595 
setSpecified(Boolean implicit)596 void AttributeDefinition::setSpecified(Boolean implicit)
597 {
598   (implicit ? implicit_ : all_) = 1;
599 }
600 
isSpecified(Boolean & implicit)601 Boolean AttributeDefinition::isSpecified(Boolean &implicit)
602 {
603   implicit = implicit_;
604   return implicit_ || all_;
605 }
606 
setOrigName(StringC & origName)607 void AttributeDefinition::setOrigName(StringC &origName)
608 {
609   if (&origName != NULL)
610     origName.swap(origName_);
611 }
612 
~AttributeDefinition()613 AttributeDefinition::~AttributeDefinition()
614 {
615 }
616 
checkValue(AttributeValue * p,AttributeContext &) const617 AttributeValue *AttributeDefinition::checkValue(AttributeValue *p,
618 						AttributeContext &) const
619 {
620   return p;
621 }
622 
missingValueWouldMatch(const Text &,const AttributeContext &) const623 Boolean AttributeDefinition::missingValueWouldMatch(const Text &,
624 						    const AttributeContext &) const
625 {
626   return 0;
627 }
628 
629 const AttributeValue *
defaultValue(const AttributeValue *) const630 AttributeDefinition::defaultValue(const AttributeValue *) const
631 {
632   return 0;
633 }
634 
getDesc(AttributeDefinitionDesc & desc) const635 void AttributeDefinition::getDesc(AttributeDefinitionDesc &desc) const
636 {
637   desc.allowedValues.clear();
638   desc.defaultValue.clear();
639   desc.currentIndex = 0;
640   buildDesc(desc);
641   declaredValue_->buildDesc(desc);
642 }
643 
isConref() const644 Boolean AttributeDefinition::isConref() const
645 {
646   return 0;
647 }
648 
isCurrent() const649 Boolean AttributeDefinition::isCurrent() const
650 {
651   return 0;
652 }
653 
isFixed() const654 Boolean AttributeDefinition::isFixed() const
655 {
656   return 0;
657 }
658 
RequiredAttributeDefinition(const StringC & name,DeclaredValue * value)659 RequiredAttributeDefinition::RequiredAttributeDefinition(const StringC &name,
660 							 DeclaredValue *value)
661 : AttributeDefinition(name, value)
662 {
663 }
664 
665 ConstPtr<AttributeValue>
makeMissingValue(AttributeContext & context) const666 RequiredAttributeDefinition::makeMissingValue(AttributeContext &context) const
667 {
668   if (context.validate())
669     context.message(ParserMessages::requiredAttributeMissing,
670 		    StringMessageArg(name()));
671   return 0;
672 }
673 
buildDesc(AttributeDefinitionDesc & desc) const674 void RequiredAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
675 {
676   desc.defaultValueType = AttributeDefinitionDesc::required;
677 }
678 
copy() const679 AttributeDefinition *RequiredAttributeDefinition::copy() const
680 {
681   return new RequiredAttributeDefinition(*this);
682 }
683 
CurrentAttributeDefinition(const StringC & name,DeclaredValue * value,size_t index)684 CurrentAttributeDefinition::CurrentAttributeDefinition(const StringC &name, DeclaredValue *value, size_t index)
685 : AttributeDefinition(name, value), currentIndex_(index)
686 {
687 }
688 
689 ConstPtr<AttributeValue>
makeMissingValue(AttributeContext & context) const690 CurrentAttributeDefinition::makeMissingValue(AttributeContext &context) const
691 {
692   if (context.mayDefaultAttribute()) {
693     ConstPtr<AttributeValue> currentValue
694       = context.getCurrentAttribute(currentIndex_);
695     if (currentValue.isNull() && context.validate())
696       context.message(ParserMessages::currentAttributeMissing,
697 		      StringMessageArg(name()));
698     return currentValue;
699   }
700   if (context.validate())
701     context.message(ParserMessages::attributeMissing,
702 		    StringMessageArg(name()));
703   return 0;
704 }
705 
missingValueWouldMatch(const Text & text,const AttributeContext & context) const706 Boolean CurrentAttributeDefinition::missingValueWouldMatch(const Text &text,
707 							   const AttributeContext &context) const
708 {
709   if (!context.mayDefaultAttribute())
710     return 0;
711   ConstPtr<AttributeValue> currentValue
712     = context.getCurrentAttribute(currentIndex_);
713   if (currentValue.isNull())
714     return 0;
715   return text.fixedEqual(*currentValue->text());
716 }
717 
718 AttributeValue *
checkValue(AttributeValue * value,AttributeContext & context) const719 CurrentAttributeDefinition::checkValue(AttributeValue *value,
720 				       AttributeContext &context) const
721 {
722   context.noteCurrentAttribute(currentIndex_, value);
723   return value;
724 }
725 
buildDesc(AttributeDefinitionDesc & desc) const726 void CurrentAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
727 {
728   desc.defaultValueType = AttributeDefinitionDesc::current;
729   desc.currentIndex = currentIndex_;
730 }
731 
copy() const732 AttributeDefinition *CurrentAttributeDefinition::copy() const
733 {
734   return new CurrentAttributeDefinition(*this);
735 }
736 
isCurrent() const737 Boolean CurrentAttributeDefinition::isCurrent() const
738 {
739   return 1;
740 }
741 
ImpliedAttributeDefinition(const StringC & name,DeclaredValue * value)742 ImpliedAttributeDefinition::ImpliedAttributeDefinition(const StringC &name,
743 						       DeclaredValue *value)
744 : AttributeDefinition(name, value)
745 {
746 }
747 
748 ConstPtr<AttributeValue>
makeMissingValue(AttributeContext & context) const749 ImpliedAttributeDefinition::makeMissingValue(AttributeContext &context) const
750 {
751   return context.makeImpliedAttributeValue();
752 }
753 
buildDesc(AttributeDefinitionDesc & desc) const754 void ImpliedAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
755 {
756   desc.defaultValueType = AttributeDefinitionDesc::implied;
757 }
758 
copy() const759 AttributeDefinition *ImpliedAttributeDefinition::copy() const
760 {
761   return new ImpliedAttributeDefinition(*this);
762 }
763 
764 const AttributeValue *
defaultValue(const AttributeValue * impliedValue) const765 ImpliedAttributeDefinition::defaultValue(const AttributeValue *impliedValue)
766      const
767 {
768   return impliedValue;
769 }
770 
ConrefAttributeDefinition(const StringC & name,DeclaredValue * value)771 ConrefAttributeDefinition::ConrefAttributeDefinition(const StringC &name,
772 						     DeclaredValue *value)
773 : ImpliedAttributeDefinition(name, value)
774 {
775 }
776 
isConref() const777 Boolean ConrefAttributeDefinition::isConref() const
778 {
779   return 1;
780 }
781 
buildDesc(AttributeDefinitionDesc & desc) const782 void ConrefAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
783 {
784   desc.defaultValueType = AttributeDefinitionDesc::conref;
785 }
786 
copy() const787 AttributeDefinition *ConrefAttributeDefinition::copy() const
788 {
789   return new ConrefAttributeDefinition(*this);
790 }
791 
DefaultAttributeDefinition(const StringC & name,DeclaredValue * declaredValue,AttributeValue * defaultValue)792 DefaultAttributeDefinition::DefaultAttributeDefinition(const StringC &name,
793 							DeclaredValue *declaredValue,
794 							AttributeValue *defaultValue)
795 : AttributeDefinition(name, declaredValue),
796   value_(defaultValue)
797 {
798 }
799 
800 ConstPtr<AttributeValue>
makeMissingValue(AttributeContext & context) const801 DefaultAttributeDefinition::makeMissingValue(AttributeContext &context) const
802 {
803   if (context.mayDefaultAttribute())
804     return value_;
805   if (context.validate())
806     context.message(ParserMessages::attributeMissing,
807 		    StringMessageArg(name()));
808   return 0;
809 }
810 
missingValueWouldMatch(const Text & text,const AttributeContext & context) const811 Boolean DefaultAttributeDefinition::missingValueWouldMatch(const Text &text,
812 							   const AttributeContext &context) const
813 {
814   return context.mayDefaultAttribute() && text.fixedEqual(*value_->text());
815 }
816 
buildDesc(AttributeDefinitionDesc & desc) const817 void DefaultAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
818 {
819   desc.defaultValueType = AttributeDefinitionDesc::defaulted;
820   desc.defaultValue = value_;
821 }
822 
copy() const823 AttributeDefinition *DefaultAttributeDefinition::copy() const
824 {
825   return new DefaultAttributeDefinition(*this);
826 }
827 
FixedAttributeDefinition(const StringC & name,DeclaredValue * declaredValue,AttributeValue * defaultValue)828 FixedAttributeDefinition:: FixedAttributeDefinition(const StringC &name,
829 						    DeclaredValue *declaredValue,
830 						    AttributeValue *defaultValue)
831 : DefaultAttributeDefinition(name, declaredValue, defaultValue)
832 {
833 }
834 
isFixed() const835 Boolean FixedAttributeDefinition::isFixed() const
836 {
837   return 1;
838 }
839 
checkValue(AttributeValue * value,AttributeContext & context) const840 AttributeValue *FixedAttributeDefinition::checkValue(AttributeValue *value,
841 						     AttributeContext &context)
842      const
843 {
844   const AttributeValue *fixedValue
845     = DefaultAttributeDefinition::defaultValue(0);
846   if (value && fixedValue && context.validate()) {
847     const Text *text;
848     const StringC *str;
849     const Text *fixedText;
850     const StringC *fixedStr;
851     switch (value->info(text, str)) {
852     case AttributeValue::implied:
853       CANNOT_HAPPEN();
854     case AttributeValue::cdata:
855       if (fixedValue->info(fixedText, fixedStr) == AttributeValue::cdata) {
856 	if (!text->fixedEqual(*fixedText))
857 	  context.message(ParserMessages::notFixedValue, StringMessageArg(name()));
858       }
859       break;
860     case AttributeValue::tokenized:
861       if (fixedValue->info(fixedText, fixedStr) == AttributeValue::tokenized) {
862 	if (*str != *fixedStr)
863 	  context.message(ParserMessages::notFixedValue, StringMessageArg(name()));
864       }
865       break;
866     }
867   }
868   return value;
869 }
870 
buildDesc(AttributeDefinitionDesc & desc) const871 void FixedAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
872 {
873   // get the fixed value
874   DefaultAttributeDefinition::buildDesc(desc);
875   desc.defaultValueType = AttributeDefinitionDesc::fixed;
876 }
877 
copy() const878 AttributeDefinition *FixedAttributeDefinition::copy() const
879 {
880   return new FixedAttributeDefinition(*this);
881 }
882 
883 AttributeDefinitionList
AttributeDefinitionList(Vector<CopyOwner<AttributeDefinition>> & vec,size_t index,Boolean anyCurrent,size_t idIndex,size_t notationIndex)884 ::AttributeDefinitionList(Vector<CopyOwner<AttributeDefinition> > &vec,
885 			  size_t index,
886 			  Boolean anyCurrent,
887 			  size_t idIndex,
888 			  size_t notationIndex)
889 : index_(index), anyCurrent_(anyCurrent), idIndex_(idIndex),
890   notationIndex_(notationIndex)
891 {
892   defs_.swap(vec);
893 }
894 
AttributeDefinitionList(const ConstPtr<AttributeDefinitionList> & def)895 AttributeDefinitionList:: AttributeDefinitionList(const ConstPtr<AttributeDefinitionList> &def)
896 : prev_(def), index_(size_t(-1))
897 {
898   if (def.isNull()) {
899     anyCurrent_ = 0;
900     notationIndex_ = size_t(-1);
901     idIndex_ = size_t(-1);
902   }
903   else {
904     anyCurrent_ = def->anyCurrent_;
905     notationIndex_ = def->notationIndex_;
906     idIndex_ = def->idIndex_;
907     defs_ = def->defs_;
908   }
909 }
910 
~AttributeDefinitionList()911 AttributeDefinitionList::~AttributeDefinitionList() {}
912 
tokenIndex(const StringC & token,unsigned & index) const913 Boolean AttributeDefinitionList::tokenIndex(const StringC &token, unsigned &index) const
914 {
915   for (size_t i = 0; i < defs_.size(); i++)
916     if (defs_[i]->containsToken(token)) {
917       index = i;
918       return 1;
919     }
920   return 0;
921 }
922 
tokenIndexUnique(const StringC & token,unsigned i) const923 Boolean AttributeDefinitionList::tokenIndexUnique(const StringC &token, unsigned i) const
924 {
925   for (++i; i < defs_.size(); i++)
926     if (defs_[i]->containsToken(token))
927       return 0;
928   return 1;
929 }
930 
931 
attributeIndex(const StringC & name,unsigned & index) const932 Boolean AttributeDefinitionList::attributeIndex(const StringC &name,
933 						unsigned &index) const
934 {
935   for (size_t i = 0; i < defs_.size(); i++)
936     if (defs_[i]->name() == name) {
937       index = i;
938       return 1;
939     }
940   return 0;
941 }
942 
append(AttributeDefinition * def)943 void AttributeDefinitionList::append(AttributeDefinition *def)
944 {
945   if (def->isId() && idIndex_ == size_t(-1))
946     idIndex_ = defs_.size();
947   if (def->isNotation() && notationIndex_ == size_t(-1))
948     notationIndex_ = defs_.size();
949   if (def->isCurrent())
950     anyCurrent_ = 1;
951   defs_.resize(defs_.size() + 1);
952   defs_.back() = def;
953 }
954 
AttributeSemantics()955 AttributeSemantics::AttributeSemantics()
956 {
957 }
958 
~AttributeSemantics()959 AttributeSemantics::~AttributeSemantics()
960 {
961 }
962 
nEntities() const963 size_t AttributeSemantics::nEntities() const
964 {
965   return 0;
966 }
967 
entity(size_t) const968 ConstPtr<Entity> AttributeSemantics::entity(size_t) const
969 {
970   return 0;
971 }
972 
notation() const973 ConstPtr<Notation> AttributeSemantics::notation() const
974 {
975   return 0;
976 }
977 
978 
NotationAttributeSemantics(const ConstPtr<Notation> & notation)979 NotationAttributeSemantics::NotationAttributeSemantics(const ConstPtr<Notation> &notation)
980 : notation_(notation)
981 {
982 }
983 
notation() const984 ConstPtr<Notation> NotationAttributeSemantics::notation() const
985 {
986   return notation_;
987 }
988 
copy() const989 AttributeSemantics *NotationAttributeSemantics::copy() const
990 {
991   return new NotationAttributeSemantics(*this);
992 }
993 
EntityAttributeSemantics(Vector<ConstPtr<Entity>> & entity)994 EntityAttributeSemantics::EntityAttributeSemantics(Vector<ConstPtr<Entity> > &entity)
995 {
996   entity.swap(entity_);
997 }
998 
nEntities() const999 size_t EntityAttributeSemantics::nEntities() const
1000 {
1001   return entity_.size();
1002 }
1003 
entity(size_t i) const1004 ConstPtr<Entity> EntityAttributeSemantics::entity(size_t i) const
1005 {
1006   return entity_[i];
1007 }
1008 
copy() const1009 AttributeSemantics *EntityAttributeSemantics::copy() const
1010 {
1011   return new EntityAttributeSemantics(*this);
1012 }
1013 
AttributeValue()1014 AttributeValue::AttributeValue()
1015 {
1016 }
1017 
~AttributeValue()1018 AttributeValue::~AttributeValue()
1019 {
1020 }
1021 
makeSemantics(const DeclaredValue *,AttributeContext &,const StringC &,unsigned &,unsigned &) const1022 AttributeSemantics *AttributeValue::makeSemantics(const DeclaredValue *,
1023 						  AttributeContext &,
1024 						  const StringC &,
1025 						  unsigned &,
1026 						  unsigned &) const
1027 {
1028   return 0;
1029 }
1030 
text() const1031 const Text *AttributeValue::text() const
1032 {
1033   return 0;
1034 }
1035 
recoverUnquoted(const StringC &,const Location &,AttributeContext &,const StringC &)1036 Boolean AttributeValue::recoverUnquoted(const StringC &, const Location &,
1037 					AttributeContext &, const StringC &)
1038 {
1039   return 0;
1040 }
1041 
ImpliedAttributeValue()1042 ImpliedAttributeValue::ImpliedAttributeValue()
1043 {
1044 }
1045 
info(const Text * &,const StringC * &) const1046 AttributeValue::Type ImpliedAttributeValue::info(const Text *&,
1047 						 const StringC *&) const
1048 {
1049   return implied;
1050 }
1051 
TokenizedAttributeValue(Text & text,const Vector<size_t> & spaceIndex)1052 TokenizedAttributeValue::TokenizedAttributeValue(Text &text,
1053 						 const Vector<size_t> &spaceIndex)
1054 : spaceIndex_(spaceIndex)
1055 {
1056   text.swap(text_);
1057 }
1058 
info(const Text * &,const StringC * & string) const1059 AttributeValue::Type TokenizedAttributeValue::info(const Text *&,
1060 						   const StringC *&string) const
1061 {
1062   string = &text_.string();
1063   return tokenized;
1064 }
1065 
text() const1066 const Text *TokenizedAttributeValue::text() const
1067 {
1068   return &text_;
1069 }
1070 
1071 AttributeSemantics *
makeSemantics(const DeclaredValue * value,AttributeContext & context,const StringC & name,unsigned & nIdrefs,unsigned & nEntityNames) const1072 TokenizedAttributeValue::makeSemantics(const DeclaredValue *value,
1073 				       AttributeContext &context,
1074 				       const StringC &name,
1075 				       unsigned &nIdrefs,
1076 				       unsigned &nEntityNames) const
1077 {
1078   if (text_.size() == 0)
1079     return 0;
1080   return value->makeSemantics(*this, context, name, nIdrefs, nEntityNames);
1081 }
1082 
CdataAttributeValue(Text & text)1083 CdataAttributeValue::CdataAttributeValue(Text &text)
1084 {
1085   text.swap(text_);
1086 }
1087 
info(const Text * & text,const StringC * &) const1088 AttributeValue::Type CdataAttributeValue::info(const Text *&text,
1089 					       const StringC *&) const
1090 {
1091   text = &text_;
1092   return cdata;
1093 }
1094 
text() const1095 const Text *CdataAttributeValue::text() const
1096 {
1097   return &text_;
1098 }
1099 
recoverUnquoted(const StringC & str,const Location & strLoc,AttributeContext & context,const StringC &)1100 Boolean CdataAttributeValue::recoverUnquoted(const StringC &str,
1101 					     const Location &strLoc,
1102 					     AttributeContext &context,
1103 					     const StringC &)
1104 {
1105   TextIter iter(text_);
1106   TextItem::Type type;
1107   const Char *s;
1108   size_t len;
1109   const Location *loc;
1110   if (iter.next(type, s, len, loc)
1111       && type == TextItem::data
1112       && len == text_.size()
1113       && loc->origin().pointer() == strLoc.origin().pointer()
1114       && loc->index() + len == strLoc.index()
1115       && !iter.next(type, s, len, loc)) {
1116     text_.addChars(str, strLoc);
1117     context.Messenger::setNextLocation(strLoc);
1118     context.message(ParserMessages::unquotedAttributeValue);
1119     return 1;
1120   }
1121   return 0;
1122 }
1123 
notation() const1124 const Notation *CdataAttributeValue::notation() const
1125 {
1126   return 0;
1127 }
1128 
DataAttributeValue(Text & text,const ConstPtr<Notation> & nt,const AttributeList & attributes)1129 DataAttributeValue::DataAttributeValue(Text &text,
1130                                        const ConstPtr<Notation> &nt,
1131                                        const AttributeList &attributes)
1132 : CdataAttributeValue(text), notation_(nt), attributes_(&attributes)
1133 {
1134 }
1135 
attributes() const1136 const AttributeList &DataAttributeValue::attributes() const
1137 {
1138   return *attributes_;
1139 }
1140 
notation() const1141 const Notation *DataAttributeValue::notation() const
1142 {
1143   return notation_.pointer();
1144 }
1145 
Attribute()1146 Attribute::Attribute()
1147 : specIndexPlus_(0)
1148 {
1149 }
1150 
Attribute(const Attribute & x)1151 Attribute::Attribute(const Attribute& x)
1152 	: specIndexPlus_(x.specIndexPlus_),
1153 	  value_(x.value_),
1154 	  semantics_(x.semantics_)
1155 {
1156 }
1157 
~Attribute()1158 Attribute::~Attribute()
1159 {
1160 }
1161 
operator =(const Attribute & x)1162 Attribute& Attribute::operator=(const Attribute& x)
1163 {
1164   if (this != &x) {
1165     specIndexPlus_ = x.specIndexPlus_;
1166     value_ = x.value_;
1167     semantics_ = x.semantics_;
1168   }
1169   return *this;
1170 }
1171 
clear()1172 void Attribute::clear()
1173 {
1174   specIndexPlus_ = 0;
1175   value_.clear();
1176   semantics_.clear();
1177 }
1178 
AttributeList(const ConstPtr<AttributeDefinitionList> & def)1179 AttributeList::AttributeList(const ConstPtr<AttributeDefinitionList> &def)
1180 : def_(def), vec_(def.isNull() ? 0 : def->size()), nSpec_(0), conref_(0),
1181   nIdrefs_(0), nEntityNames_(0)
1182 {
1183 }
1184 
AttributeList()1185 AttributeList::AttributeList()
1186 : nSpec_(0), conref_(0)
1187 {
1188 }
1189 
init(const ConstPtr<AttributeDefinitionList> & def)1190 void AttributeList::init(const ConstPtr<AttributeDefinitionList> &def)
1191 {
1192   def_ = def;
1193   nSpec_ = 0;
1194   conref_ = 0;
1195   nIdrefs_ = 0;
1196   nEntityNames_ = 0;
1197   if (def_.isNull())
1198     vec_.resize(0);
1199   else {
1200     size_t newLength = def_->size();
1201     size_t clearLim = vec_.size();
1202     if (clearLim > newLength)
1203       clearLim = newLength;
1204     vec_.resize(newLength);
1205     for (size_t i = 0; i < clearLim; i++)
1206       vec_[i].clear();
1207   }
1208 }
1209 
changeDef(const ConstPtr<AttributeDefinitionList> & def)1210 void AttributeList::changeDef(const ConstPtr<AttributeDefinitionList> &def)
1211 {
1212   vec_.resize(def.isNull() ? 0 : def->size());
1213   def_ = def;
1214 }
1215 
swap(AttributeList & to)1216 void AttributeList::swap(AttributeList &to)
1217 {
1218   vec_.swap(to.vec_);
1219   def_.swap(to.def_);
1220   {
1221     unsigned tem = to.nIdrefs_;
1222     to.nIdrefs_ = nIdrefs_;
1223     nIdrefs_ = tem;
1224   }
1225   {
1226     unsigned tem = to.nEntityNames_;
1227     to.nEntityNames_ = nEntityNames_;
1228     nEntityNames_ = tem;
1229   }
1230   {
1231     size_t tem = to.nSpec_;
1232     to.nSpec_ = nSpec_;
1233     nSpec_ = tem;
1234   }
1235   {
1236     PackedBoolean tem = to.conref_;
1237     to.conref_ = conref_;
1238     conref_ = tem;
1239   }
1240 }
1241 
finish(AttributeContext & context)1242 void AttributeList::finish(AttributeContext &context)
1243 {
1244   for (size_t i = 0; i < vec_.size(); i++)
1245     if (!vec_[i].specified()) {
1246       ConstPtr<AttributeValue> value
1247 	= def(i)->makeMissingValue(context);
1248       if (!conref_ || def_->notationIndex() != i) {
1249 	vec_[i].setValue(value);
1250         if (!value.isNull())
1251       	  vec_[i].setSemantics(def(i)->makeSemantics(value.pointer(),
1252 						     context,
1253 						     nIdrefs_,
1254 						     nEntityNames_));
1255       }
1256     }
1257   const Syntax &syntax = context.attributeSyntax();
1258   if (nIdrefs_ > syntax.grpcnt())
1259     context.message(ParserMessages::idrefGrpcnt,
1260 		   NumberMessageArg(syntax.grpcnt()));
1261   if (nEntityNames_ > syntax.grpcnt())
1262     context.message(ParserMessages::entityNameGrpcnt,
1263 		   NumberMessageArg(syntax.grpcnt()));
1264   if (context.validate()
1265       && conref_
1266       && def_->notationIndex() != size_t(-1)
1267       && specified(def_->notationIndex()))
1268     context.message(ParserMessages::conrefNotation);
1269 }
1270 
setSpec(unsigned i,AttributeContext & context)1271 void AttributeList::setSpec(unsigned i, AttributeContext &context)
1272 {
1273   if (vec_[i].specified())
1274     context.message(ParserMessages::duplicateAttributeSpec,
1275 		   StringMessageArg(def(i)->name()));
1276   else
1277     vec_[i].setSpec(nSpec_++);
1278 }
1279 
noteInvalidSpec()1280 void AttributeList::noteInvalidSpec()
1281 {
1282   // This is needed for error recovery.
1283   // We don't want nSpec_ to be > 0, if there is no attribute definition.
1284   if (nSpec_)
1285     nSpec_++;
1286 }
1287 
setValue(unsigned i,Text & text,AttributeContext & context,unsigned & specLength)1288 Boolean AttributeList::setValue(unsigned i, Text &text,
1289 				AttributeContext &context,
1290 				unsigned &specLength)
1291 {
1292   AttributeValue *value = def(i)->makeValue(text, context, specLength);
1293   if (def(i)->isConref())
1294     conref_ = 1;
1295   vec_[i].setValue(value);
1296   if (value)
1297     vec_[i].setSemantics(def(i)->makeSemantics(value, context,
1298 					       nIdrefs_, nEntityNames_));
1299   else if (AttributeValue::handleAsUnterminated(text, context))
1300     return 0;
1301   return 1;
1302 }
1303 
setValueToken(unsigned i,Text & text,AttributeContext & context,unsigned & specLength)1304 void AttributeList::setValueToken(unsigned i, Text &text,
1305 				  AttributeContext &context,
1306 				  unsigned &specLength)
1307 {
1308   AttributeValue *value = def(i)->makeValueFromToken(text, context,
1309 						     specLength);
1310   if (def(i)->isConref())
1311     conref_ = 1;
1312   vec_[i].setValue(value);
1313   if (value)
1314     vec_[i].setSemantics(def(i)->makeSemantics(value, context,
1315 					       nIdrefs_, nEntityNames_));
1316 }
1317 
getId() const1318 const StringC *AttributeList::getId() const
1319 {
1320   // Check for no attributes
1321   if (def_.isNull())
1322     return 0;
1323   // Check for no ID declared
1324   size_t i = def_->idIndex();
1325   if (i == size_t(-1))
1326     return 0;
1327   // Check for invalid value
1328   const AttributeValue *v = value(i);
1329   if (!v)
1330     return 0;
1331   // Check for implied value
1332   const Text *t = v->text();
1333   if (!t)
1334     return 0;
1335   return &t->string();
1336 }
1337 
recoverUnquoted(const StringC & str,const Location & strLoc,AttributeContext & context)1338 Boolean AttributeList::recoverUnquoted(const StringC &str,
1339 				       const Location &strLoc,
1340 				       AttributeContext &context)
1341 {
1342   if (nSpec_ > 0) {
1343     for (size_t i = 0; i < vec_.size(); i++)
1344       if (vec_[i].specified() && vec_[i].specIndex() == nSpec_ - 1) {
1345 	const AttributeValue *val = vec_[i].value();
1346 	if (val)
1347 	  // I wish I could avoid casting away const here.
1348 	  return ((AttributeValue *)val)->recoverUnquoted(str, strLoc, context,
1349 							  name(i));
1350 	break;
1351       }
1352     return 1;
1353   }
1354   return 0;
1355 }
1356 
handleAsUnterminated(AttributeContext & context)1357 Boolean AttributeList::handleAsUnterminated(AttributeContext &context)
1358 {
1359   if (nSpec_ > 0) {
1360     for (size_t i = 0; i < vec_.size(); i++) {
1361       if (vec_[i].specified() && vec_[i].specIndex() == nSpec_ - 1) {
1362 	const AttributeValue *val = vec_[i].value();
1363 	const Text *ptr;
1364 	if (val && (ptr = val->text()) != 0
1365 	    && AttributeValue::handleAsUnterminated(*ptr, context))
1366 	  return 1;
1367 	break;
1368       }
1369     }
1370   }
1371   return 0;
1372 }
1373 
1374 // This tries to guess this attribute value looks like if it had
1375 // a missing ending quote.
1376 
handleAsUnterminated(const Text & text,AttributeContext & context)1377 Boolean AttributeValue::handleAsUnterminated(const Text &text,
1378 					     AttributeContext &context)
1379 {
1380   TextIter iter(text);
1381   const Char *lastStr = 0;
1382   size_t lastLen;
1383   Location startLoc;
1384   const Location *loc;
1385   TextItem::Type type;
1386   const Char *str;
1387   size_t len;
1388   while (iter.next(type, str, len, loc)) {
1389     if (startLoc.origin().isNull() && !loc->origin().isNull())
1390       startLoc = *loc;
1391     switch (type) {
1392     case TextItem::data:
1393       if (len != 1 || *str != context.attributeSyntax().space()) {
1394 	lastStr = str;
1395 	lastLen = len;
1396       }
1397       break;
1398     case TextItem::endDelim:
1399     case TextItem::endDelimA:
1400     case TextItem::ignore:
1401       break;
1402     default:
1403       lastStr = 0;
1404       break;
1405     }
1406   }
1407   if (lastStr) {
1408     while (lastLen > 0
1409 	   && lastStr[lastLen - 1] == context.attributeSyntax().space())
1410       lastLen--;
1411     const StringC &vi = context.attributeSyntax().delimGeneral(Syntax::dVI);
1412     if (lastLen >= vi.size()
1413 	&& (vi
1414 	    == StringC(lastStr + (lastLen - vi.size()), vi.size()))) {
1415       context.Messenger::setNextLocation(startLoc);
1416       context.message(ParserMessages::literalClosingDelimiter);
1417       return 1;
1418     }
1419   }
1420   return 0;
1421 }
1422 
AttributeContext()1423 AttributeContext::AttributeContext()
1424 : mayDefaultAttribute_(0), validate_(1)
1425 {
1426 }
1427 
~AttributeContext()1428 AttributeContext::~AttributeContext()
1429 {
1430 }
1431 
defineId(const StringC &,const Location &,Location &)1432 Boolean AttributeContext::defineId(const StringC &, const Location &,
1433 				   Location &)
1434 {
1435   return 1;
1436 }
1437 
noteIdref(const StringC &,const Location &)1438 void AttributeContext::noteIdref(const StringC &, const Location &)
1439 {
1440 }
1441 
noteCurrentAttribute(size_t,AttributeValue *)1442 void AttributeContext::noteCurrentAttribute(size_t, AttributeValue *)
1443 {
1444 }
1445 
getCurrentAttribute(size_t) const1446 ConstPtr<AttributeValue> AttributeContext::getCurrentAttribute(size_t) const
1447 {
1448   return 0;
1449 }
1450 
getAttributeEntity(const StringC &,const Location &)1451 ConstPtr<Entity> AttributeContext::getAttributeEntity(const StringC &,
1452 						      const Location &)
1453 {
1454   return 0;
1455 }
1456 
getAttributeNotation(const StringC &,const Location &)1457 ConstPtr<Notation> AttributeContext::getAttributeNotation(const StringC &,
1458 							  const Location &)
1459 {
1460   return 0;
1461 }
1462 
makeImpliedAttributeValue()1463 ConstPtr<AttributeValue> AttributeContext::makeImpliedAttributeValue()
1464 {
1465   if (impliedAttributeValue_.isNull())
1466     impliedAttributeValue_ = new ImpliedAttributeValue;
1467   return impliedAttributeValue_;
1468 }
1469 
1470 #ifdef SP_NAMESPACE
1471 }
1472 #endif
1473