3065 some functions in the tcp module can be static
[unleashed.git] / usr / src / cmd / man / src / util / nsgmls.src / lib / Attribute.cxx
blob6e386db699b0989c2997722bdcc36a647dcd5c21
1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3 #pragma ident "%Z%%M% %I% %E% SMI"
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"
18 #ifdef SP_NAMESPACE
19 namespace SP_NAMESPACE {
20 #endif
22 DeclaredValue::DeclaredValue()
26 DeclaredValue::~DeclaredValue()
30 AttributeValue *DeclaredValue::makeValueFromToken(Text &text,
31 AttributeContext &context,
32 const StringC &name,
33 unsigned &specLength) const
35 return makeValue(text, context, name, specLength);
38 AttributeSemantics *DeclaredValue::makeSemantics(const TokenizedAttributeValue &,
39 AttributeContext &,
40 const StringC &,
41 unsigned &,
42 unsigned &) const
44 return 0;
47 Boolean DeclaredValue::containsToken(const StringC &) const
49 return 0;
52 Boolean DeclaredValue::isNotation() const
54 return 0;
57 Boolean DeclaredValue::isEntity() const
59 return 0;
62 Boolean DeclaredValue::isId() const
64 return 0;
67 Boolean DeclaredValue::isIdref() const
69 return 0;
72 const Vector<StringC> *DeclaredValue::getTokens() const
74 return 0;
78 CdataDeclaredValue::CdataDeclaredValue()
82 Boolean CdataDeclaredValue::tokenized() const
84 return 0;
87 AttributeValue *CdataDeclaredValue::makeValue(Text &text, AttributeContext &context,
88 const StringC &,
89 unsigned &specLength) const
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);
106 void CdataDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
108 desc.declaredValue = AttributeDefinitionDesc::cdata;
111 DeclaredValue *CdataDeclaredValue::copy() const
113 return new CdataDeclaredValue(*this);
116 TokenizedDeclaredValue::TokenizedDeclaredValue(TokenType type,
117 Boolean isList)
118 : type_(type), isList_(isList)
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;
144 Boolean TokenizedDeclaredValue::tokenized() const
146 return 1;
149 AttributeValue *TokenizedDeclaredValue::makeValue(Text &text,
150 AttributeContext &context,
151 const StringC &str,
152 unsigned &specLength) const
154 return makeTokenizedValue(text, context, str, specLength);
157 TokenizedAttributeValue *
158 TokenizedDeclaredValue::makeTokenizedValue(Text &text,
159 AttributeContext &context,
160 const StringC &LOCALname,
161 unsigned &specLength) const
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();
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;
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));
200 else {
201 for (++i;
202 i < length
203 && (syntax.charCategory(value[i]) & subsequentCategories_);
204 i++)
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));
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()));
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));
230 spaceIndex.push_back(i);
231 i++;
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;
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);
258 Boolean TokenizedAttributeValue::recoverUnquoted(const StringC &str,
259 const Location &strLoc,
260 AttributeContext &context,
261 const StringC &name)
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;
280 return 0;
283 void TokenizedDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
285 desc.declaredValue = AttributeDefinitionDesc::DeclaredValue(
286 type_ - name + (isList_
287 ? AttributeDefinitionDesc::names
288 : AttributeDefinitionDesc::name));
291 DeclaredValue *TokenizedDeclaredValue::copy() const
293 return new TokenizedDeclaredValue(*this);
296 GroupDeclaredValue::GroupDeclaredValue(TokenType type,
297 Vector<StringC> &vec)
298 : TokenizedDeclaredValue(type, 0)
300 vec.swap(allowedValues_);
303 void GroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
305 desc.allowedValues = allowedValues_;
308 DeclaredValue *GroupDeclaredValue::copy() const
310 return new GroupDeclaredValue(*this);
313 AttributeValue *GroupDeclaredValue::makeValue(Text &text,
314 AttributeContext &context,
315 const StringC &LOCALname,
316 unsigned &specLength) const
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;
332 AttributeValue *GroupDeclaredValue::makeValueFromToken(Text &text,
333 AttributeContext &context,
334 const StringC &,
335 unsigned &specLength)
336 const
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>());
349 Boolean GroupDeclaredValue::containsToken(const StringC &token) const
351 for (size_t i = 0; i < allowedValues_.size(); i++)
352 if (allowedValues_[i] == token)
353 return 1;
354 return 0;
357 const Vector<StringC> *GroupDeclaredValue::getTokens() const
359 return &allowedValues_;
362 NameTokenGroupDeclaredValue::NameTokenGroupDeclaredValue(Vector<StringC> &vec)
363 : GroupDeclaredValue(nameToken, vec)
367 void NameTokenGroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
369 GroupDeclaredValue::buildDesc(desc);
370 desc.declaredValue = AttributeDefinitionDesc::nameTokenGroup;
373 DeclaredValue *NameTokenGroupDeclaredValue::copy() const
375 return new NameTokenGroupDeclaredValue(*this);
378 NotationDeclaredValue::NotationDeclaredValue(Vector<StringC> &vec)
379 : GroupDeclaredValue(name, vec)
383 Boolean NotationDeclaredValue::isNotation() const
385 return 1;
388 AttributeSemantics *
389 NotationDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
390 AttributeContext &context,
391 const StringC &,
392 unsigned &,
393 unsigned &) const
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()));
404 return 0;
406 return new NotationAttributeSemantics(notation);
409 void NotationDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
411 GroupDeclaredValue::buildDesc(desc);
412 desc.declaredValue = AttributeDefinitionDesc::notation;
415 DeclaredValue *NotationDeclaredValue::copy() const
417 return new NotationDeclaredValue(*this);
420 EntityDeclaredValue::EntityDeclaredValue(Boolean isList)
421 : TokenizedDeclaredValue(entityName, isList)
425 Boolean EntityDeclaredValue::isEntity() const
427 return 1;
430 AttributeSemantics *
431 EntityDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
432 AttributeContext &context,
433 const StringC &,
434 unsigned &,
435 unsigned &nEntityNames) const
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)));
450 valid = 0;
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)));
458 valid = 0;
461 if (valid)
462 return new EntityAttributeSemantics(entities);
463 else
464 return 0;
467 DeclaredValue *EntityDeclaredValue::copy() const
469 return new EntityDeclaredValue(*this);
472 IdDeclaredValue::IdDeclaredValue()
473 : TokenizedDeclaredValue(name, 0)
477 Boolean IdDeclaredValue::isId() const
479 return 1;
482 AttributeSemantics *
483 IdDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
484 AttributeContext &context,
485 const StringC &,
486 unsigned &,
487 unsigned &) const
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);
496 return 0;
499 void IdDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
501 desc.declaredValue = AttributeDefinitionDesc::id;
504 DeclaredValue *IdDeclaredValue::copy() const
506 return new IdDeclaredValue(*this);
509 IdrefDeclaredValue::IdrefDeclaredValue(Boolean isList)
510 : TokenizedDeclaredValue(name, isList)
514 AttributeSemantics *
515 IdrefDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
516 AttributeContext &context,
517 const StringC &,
518 unsigned &nIdrefs,
519 unsigned &) const
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;
528 Boolean IdrefDeclaredValue::isIdref() const
530 return 1;
533 void IdrefDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
535 TokenizedDeclaredValue::buildDesc(desc);
536 if (desc.declaredValue == AttributeDefinitionDesc::name)
537 desc.declaredValue = AttributeDefinitionDesc::idref;
538 else
539 desc.declaredValue = AttributeDefinitionDesc::idrefs;
542 DeclaredValue *IdrefDeclaredValue::copy() const
544 return new IdrefDeclaredValue(*this);
548 AttributeDefinition::AttributeDefinition(const StringC &name,
549 DeclaredValue *value)
550 : name_(name), declaredValue_(value)
554 AttributeDefinition::~AttributeDefinition()
558 AttributeValue *AttributeDefinition::checkValue(AttributeValue *p,
559 AttributeContext &) const
561 return p;
564 Boolean AttributeDefinition::missingValueWouldMatch(const Text &,
565 const AttributeContext &) const
567 return 0;
570 const AttributeValue *
571 AttributeDefinition::defaultValue(const AttributeValue *) const
573 return 0;
576 void AttributeDefinition::getDesc(AttributeDefinitionDesc &desc) const
578 desc.allowedValues.clear();
579 desc.defaultValue.clear();
580 desc.currentIndex = 0;
581 buildDesc(desc);
582 declaredValue_->buildDesc(desc);
585 Boolean AttributeDefinition::isConref() const
587 return 0;
590 Boolean AttributeDefinition::isCurrent() const
592 return 0;
595 Boolean AttributeDefinition::isFixed() const
597 return 0;
600 RequiredAttributeDefinition::RequiredAttributeDefinition(const StringC &name,
601 DeclaredValue *value)
602 : AttributeDefinition(name, value)
606 ConstPtr<AttributeValue>
607 RequiredAttributeDefinition::makeMissingValue(AttributeContext &context) const
609 if (context.validate())
610 context.message(ParserMessages::requiredAttributeMissing,
611 StringMessageArg(name()));
612 return 0;
615 void RequiredAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
617 desc.defaultValueType = AttributeDefinitionDesc::required;
620 AttributeDefinition *RequiredAttributeDefinition::copy() const
622 return new RequiredAttributeDefinition(*this);
625 CurrentAttributeDefinition::CurrentAttributeDefinition(const StringC &name, DeclaredValue *value, size_t index)
626 : AttributeDefinition(name, value), currentIndex_(index)
630 ConstPtr<AttributeValue>
631 CurrentAttributeDefinition::makeMissingValue(AttributeContext &context) const
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;
641 if (context.validate())
642 context.message(ParserMessages::attributeMissing,
643 StringMessageArg(name()));
644 return 0;
647 Boolean CurrentAttributeDefinition::missingValueWouldMatch(const Text &text,
648 const AttributeContext &context) const
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());
659 AttributeValue *
660 CurrentAttributeDefinition::checkValue(AttributeValue *value,
661 AttributeContext &context) const
663 context.noteCurrentAttribute(currentIndex_, value);
664 return value;
667 void CurrentAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
669 desc.defaultValueType = AttributeDefinitionDesc::current;
670 desc.currentIndex = currentIndex_;
673 AttributeDefinition *CurrentAttributeDefinition::copy() const
675 return new CurrentAttributeDefinition(*this);
678 Boolean CurrentAttributeDefinition::isCurrent() const
680 return 1;
683 ImpliedAttributeDefinition::ImpliedAttributeDefinition(const StringC &name,
684 DeclaredValue *value)
685 : AttributeDefinition(name, value)
689 ConstPtr<AttributeValue>
690 ImpliedAttributeDefinition::makeMissingValue(AttributeContext &context) const
692 return context.makeImpliedAttributeValue();
695 void ImpliedAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
697 desc.defaultValueType = AttributeDefinitionDesc::implied;
700 AttributeDefinition *ImpliedAttributeDefinition::copy() const
702 return new ImpliedAttributeDefinition(*this);
705 const AttributeValue *
706 ImpliedAttributeDefinition::defaultValue(const AttributeValue *impliedValue)
707 const
709 return impliedValue;
712 ConrefAttributeDefinition::ConrefAttributeDefinition(const StringC &name,
713 DeclaredValue *value)
714 : ImpliedAttributeDefinition(name, value)
718 Boolean ConrefAttributeDefinition::isConref() const
720 return 1;
723 void ConrefAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
725 desc.defaultValueType = AttributeDefinitionDesc::conref;
728 AttributeDefinition *ConrefAttributeDefinition::copy() const
730 return new ConrefAttributeDefinition(*this);
733 DefaultAttributeDefinition::DefaultAttributeDefinition(const StringC &name,
734 DeclaredValue *declaredValue,
735 AttributeValue *defaultValue)
736 : AttributeDefinition(name, declaredValue),
737 value_(defaultValue)
741 ConstPtr<AttributeValue>
742 DefaultAttributeDefinition::makeMissingValue(AttributeContext &context) const
744 if (context.mayDefaultAttribute())
745 return value_;
746 if (context.validate())
747 context.message(ParserMessages::attributeMissing,
748 StringMessageArg(name()));
749 return 0;
752 Boolean DefaultAttributeDefinition::missingValueWouldMatch(const Text &text,
753 const AttributeContext &context) const
755 return context.mayDefaultAttribute() && text.fixedEqual(*value_->text());
758 void DefaultAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
760 desc.defaultValueType = AttributeDefinitionDesc::defaulted;
761 desc.defaultValue = value_;
764 AttributeDefinition *DefaultAttributeDefinition::copy() const
766 return new DefaultAttributeDefinition(*this);
769 FixedAttributeDefinition:: FixedAttributeDefinition(const StringC &name,
770 DeclaredValue *declaredValue,
771 AttributeValue *defaultValue)
772 : DefaultAttributeDefinition(name, declaredValue, defaultValue)
776 Boolean FixedAttributeDefinition::isFixed() const
778 return 1;
781 AttributeValue *FixedAttributeDefinition::checkValue(AttributeValue *value,
782 AttributeContext &context)
783 const
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()));
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()));
806 break;
809 return value;
812 void FixedAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
814 // get the fixed value
815 DefaultAttributeDefinition::buildDesc(desc);
816 desc.defaultValueType = AttributeDefinitionDesc::fixed;
819 AttributeDefinition *FixedAttributeDefinition::copy() const
821 return new FixedAttributeDefinition(*this);
824 AttributeDefinitionList
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)
833 defs_.swap(vec);
836 AttributeDefinitionList:: AttributeDefinitionList(const ConstPtr<AttributeDefinitionList> &def)
837 : prev_(def), index_(size_t(-1))
839 if (def.isNull()) {
840 anyCurrent_ = 0;
841 notationIndex_ = size_t(-1);
842 idIndex_ = size_t(-1);
844 else {
845 anyCurrent_ = def->anyCurrent_;
846 notationIndex_ = def->notationIndex_;
847 idIndex_ = def->idIndex_;
848 defs_ = def->defs_;
852 Boolean AttributeDefinitionList::tokenIndex(const StringC &token, unsigned &index) const
854 for (size_t i = 0; i < defs_.size(); i++)
855 if (defs_[i]->containsToken(token)) {
856 index = i;
857 return 1;
859 return 0;
862 Boolean AttributeDefinitionList::tokenIndexUnique(const StringC &token, unsigned i) const
864 for (++i; i < defs_.size(); i++)
865 if (defs_[i]->containsToken(token))
866 return 0;
867 return 1;
871 Boolean AttributeDefinitionList::attributeIndex(const StringC &name,
872 unsigned &index) const
874 for (size_t i = 0; i < defs_.size(); i++)
875 if (defs_[i]->name() == name) {
876 index = i;
877 return 1;
879 return 0;
882 void AttributeDefinitionList::append(AttributeDefinition *def)
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;
894 AttributeSemantics::AttributeSemantics()
898 AttributeSemantics::~AttributeSemantics()
902 size_t AttributeSemantics::nEntities() const
904 return 0;
907 ConstPtr<Entity> AttributeSemantics::entity(size_t) const
909 return 0;
912 ConstPtr<Notation> AttributeSemantics::notation() const
914 return 0;
918 NotationAttributeSemantics::NotationAttributeSemantics(const ConstPtr<Notation> &notation)
919 : notation_(notation)
923 ConstPtr<Notation> NotationAttributeSemantics::notation() const
925 return notation_;
928 AttributeSemantics *NotationAttributeSemantics::copy() const
930 return new NotationAttributeSemantics(*this);
933 EntityAttributeSemantics::EntityAttributeSemantics(Vector<ConstPtr<Entity> > &entity)
935 entity.swap(entity_);
938 size_t EntityAttributeSemantics::nEntities() const
940 return entity_.size();
943 ConstPtr<Entity> EntityAttributeSemantics::entity(size_t i) const
945 return entity_[i];
948 AttributeSemantics *EntityAttributeSemantics::copy() const
950 return new EntityAttributeSemantics(*this);
953 AttributeValue::AttributeValue()
957 AttributeValue::~AttributeValue()
961 AttributeSemantics *AttributeValue::makeSemantics(const DeclaredValue *,
962 AttributeContext &,
963 const StringC &,
964 unsigned &,
965 unsigned &) const
967 return 0;
970 const Text *AttributeValue::text() const
972 return 0;
975 Boolean AttributeValue::recoverUnquoted(const StringC &, const Location &,
976 AttributeContext &, const StringC &)
978 return 0;
981 ImpliedAttributeValue::ImpliedAttributeValue()
985 AttributeValue::Type ImpliedAttributeValue::info(const Text *&,
986 const StringC *&) const
988 return implied;
991 TokenizedAttributeValue::TokenizedAttributeValue(Text &text,
992 const Vector<size_t> &spaceIndex)
993 : spaceIndex_(spaceIndex)
995 text.swap(text_);
998 AttributeValue::Type TokenizedAttributeValue::info(const Text *&,
999 const StringC *&string) const
1001 string = &text_.string();
1002 return tokenized;
1005 const Text *TokenizedAttributeValue::text() const
1007 return &text_;
1010 AttributeSemantics *
1011 TokenizedAttributeValue::makeSemantics(const DeclaredValue *value,
1012 AttributeContext &context,
1013 const StringC &name,
1014 unsigned &nIdrefs,
1015 unsigned &nEntityNames) const
1017 if (text_.size() == 0)
1018 return 0;
1019 return value->makeSemantics(*this, context, name, nIdrefs, nEntityNames);
1022 CdataAttributeValue::CdataAttributeValue(Text &text)
1024 text.swap(text_);
1027 AttributeValue::Type CdataAttributeValue::info(const Text *&text,
1028 const StringC *&) const
1030 text = &text_;
1031 return cdata;
1034 const Text *CdataAttributeValue::text() const
1036 return &text_;
1039 Boolean CdataAttributeValue::recoverUnquoted(const StringC &str,
1040 const Location &strLoc,
1041 AttributeContext &context,
1042 const StringC &)
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;
1060 return 0;
1063 Attribute::Attribute()
1064 : specIndexPlus_(0)
1068 void Attribute::clear()
1070 specIndexPlus_ = 0;
1071 value_.clear();
1072 semantics_.clear();
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)
1081 AttributeList::AttributeList()
1082 : nSpec_(0), conref_(0)
1086 void AttributeList::init(const ConstPtr<AttributeDefinitionList> &def)
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();
1106 void AttributeList::changeDef(const ConstPtr<AttributeDefinitionList> &def)
1108 vec_.resize(def.isNull() ? 0 : def->size());
1109 def_ = def;
1112 void AttributeList::swap(AttributeList &to)
1114 vec_.swap(to.vec_);
1115 def_.swap(to.def_);
1117 unsigned tem = to.nIdrefs_;
1118 to.nIdrefs_ = nIdrefs_;
1119 nIdrefs_ = tem;
1122 unsigned tem = to.nEntityNames_;
1123 to.nEntityNames_ = nEntityNames_;
1124 nEntityNames_ = tem;
1127 size_t tem = to.nSpec_;
1128 to.nSpec_ = nSpec_;
1129 nSpec_ = tem;
1132 PackedBoolean tem = to.conref_;
1133 to.conref_ = conref_;
1134 conref_ = tem;
1138 void AttributeList::finish(AttributeContext &context)
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_));
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);
1165 void AttributeList::setSpec(unsigned i, AttributeContext &context)
1167 if (vec_[i].specified())
1168 context.message(ParserMessages::duplicateAttributeSpec,
1169 StringMessageArg(def(i)->name()));
1170 else
1171 vec_[i].setSpec(nSpec_++);
1174 void AttributeList::noteInvalidSpec()
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_++;
1182 Boolean AttributeList::setValue(unsigned i, Text &text,
1183 AttributeContext &context,
1184 unsigned &specLength)
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;
1198 void AttributeList::setValueToken(unsigned i, Text &text,
1199 AttributeContext &context,
1200 unsigned &specLength)
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_));
1212 const StringC *AttributeList::getId() const
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();
1232 Boolean AttributeList::recoverUnquoted(const StringC &str,
1233 const Location &strLoc,
1234 AttributeContext &context)
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;
1246 return 1;
1248 return 0;
1251 Boolean AttributeList::handleAsUnterminated(AttributeContext &context)
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;
1265 return 0;
1268 // This tries to guess this attribute value looks like if it had
1269 // a missing ending quote.
1271 Boolean AttributeValue::handleAsUnterminated(const Text &text,
1272 AttributeContext &context)
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;
1291 break;
1292 case TextItem::endDelim:
1293 case TextItem::endDelimA:
1294 case TextItem::ignore:
1295 break;
1296 default:
1297 lastStr = 0;
1298 break;
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;
1314 return 0;
1317 AttributeContext::AttributeContext()
1318 : mayDefaultAttribute_(0), validate_(1)
1322 AttributeContext::~AttributeContext()
1326 Boolean AttributeContext::defineId(const StringC &, const Location &,
1327 Location &)
1329 return 1;
1332 void AttributeContext::noteIdref(const StringC &, const Location &)
1336 void AttributeContext::noteCurrentAttribute(size_t, AttributeValue *)
1340 ConstPtr<AttributeValue> AttributeContext::getCurrentAttribute(size_t) const
1342 return 0;
1345 ConstPtr<Entity> AttributeContext::getAttributeEntity(const StringC &,
1346 const Location &)
1348 return 0;
1351 ConstPtr<Notation> AttributeContext::getAttributeNotation(const StringC &,
1352 const Location &)
1354 return 0;
1357 ConstPtr<AttributeValue> AttributeContext::makeImpliedAttributeValue()
1359 if (impliedAttributeValue_.isNull())
1360 impliedAttributeValue_ = new ImpliedAttributeValue;
1361 return impliedAttributeValue_;
1364 #ifdef SP_NAMESPACE
1366 #endif