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