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> ¬ation)
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