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