1 // Copyright (c) 1994, 1996 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 
9 #include "splib.h"
10 #include "ContentState.h"
11 #include "IListIter.h"
12 #include "NCVector.h"
13 #include "macros.h"
14 
15 #ifdef SP_NAMESPACE
16 namespace SP_NAMESPACE {
17 #endif
18 
19 const ShortReferenceMap ContentState::theEmptyMap;
20 
21 #ifdef __GNUG__
22 typedef IListIter<OpenElement> Dummy_IListIter_OpenElement;
23 #endif
24 
ContentState()25 ContentState::ContentState()
26 : documentElementContainer_(StringC(), size_t(-1))
27 {
28 }
29 
startContent(const Dtd & dtd)30 void ContentState::startContent(const Dtd &dtd)
31 {
32   NCVector<Owner<ContentToken> > tokens(1);
33   tokens[0] = new ElementToken(dtd.documentElementType(),
34 			       ContentToken::none);
35   Owner<ModelGroup> model(new SeqModelGroup(tokens, ContentToken::none));
36   Owner<CompiledModelGroup> compiledModel(new CompiledModelGroup(model));
37   Vector<ContentModelAmbiguity> ambiguities;
38   Boolean pcdataUnreachable;
39   compiledModel->compile(dtd.nElementTypeIndex(), ambiguities,
40 			 pcdataUnreachable);
41   ASSERT(ambiguities.size() == 0);
42   ConstPtr<ElementDefinition> def
43     = new ElementDefinition(Location(),
44 			    0,
45 			    0,
46 			    ElementDefinition::modelGroup,
47 			    compiledModel);
48   documentElementContainer_.setElementDefinition(def, 0);
49   tagLevel_ = 0;
50   while (!openElements_.empty())
51     delete openElements_.get();
52   openElements_.insert(new OpenElement(&documentElementContainer_,
53 				       0,
54 				       0,
55 				       &theEmptyMap,
56 				       Location()));
57   includeCount_.assign(dtd.nElementTypeIndex(), 0);
58   excludeCount_.assign(dtd.nElementTypeIndex(), 0);
59   openElementCount_.assign(dtd.nElementTypeIndex(), 0);
60   netEnablingCount_ = 0;
61   totalExcludeCount_ = 0;
62   lastEndedElementType_ = 0;
63   nextIndex_ = 0;
64 }
65 
pushElement(OpenElement * e)66 void ContentState::pushElement(OpenElement *e)
67 {
68   tagLevel_++;
69   openElementCount_[e->type()->index()]++;
70   const ElementDefinition *def = e->type()->definition();
71   if (def) {
72     size_t i;
73     for (i = 0; i < def->nInclusions(); i++)
74       includeCount_[def->inclusion(i)->index()]++;
75     for (i = 0; i < def->nExclusions(); i++) {
76       excludeCount_[def->exclusion(i)->index()]++;
77       totalExcludeCount_++;
78     }
79   }
80   if (e->netEnabling())
81     netEnablingCount_++;
82   e->setIndex(nextIndex_++);
83   openElements_.insert(e);
84 }
85 
popSaveElement()86 OpenElement *ContentState::popSaveElement()
87 {
88   ASSERT(tagLevel_ > 0);
89   OpenElement *e = openElements_.get();
90   tagLevel_--;
91   openElementCount_[e->type()->index()]--;
92   const ElementDefinition *def = e->type()->definition();
93   if (def) {
94     size_t i;
95     for (i = 0; i < def->nInclusions(); i++)
96       includeCount_[def->inclusion(i)->index()]--;
97     for (i = 0; i < def->nExclusions(); i++) {
98       excludeCount_[def->exclusion(i)->index()]--;
99       totalExcludeCount_--;
100     }
101   }
102   if (e->netEnabling())
103     netEnablingCount_--;
104   lastEndedElementType_ = e->type();
105   return e;
106 }
107 
popElement()108 void ContentState::popElement()
109 {
110   delete popSaveElement();
111 }
112 
checkImplyLoop(unsigned count)113 Boolean ContentState::checkImplyLoop(unsigned count)
114 {
115   for (IListIter<OpenElement> iter(openElements_);
116        count > 0;
117        iter.next(), count--)
118     if (iter.cur()->type() == openElements_.head()->type()
119 	// I'm not sure whether this is necessary.
120 	&& iter.cur()->matchState() == openElements_.head()->matchState())
121       return 0;
122   return 1;
123 }
124 
getOpenElementInfo(Vector<OpenElementInfo> & v,const StringC & rniPcdata) const125 void ContentState::getOpenElementInfo(Vector<OpenElementInfo> &v,
126 				      const StringC &rniPcdata) const
127 {
128   v.clear();
129   v.resize(tagLevel_);
130   unsigned i = tagLevel_;
131   for (IListIter<OpenElement> iter(openElements_);
132        !iter.done() && i > 0;
133        iter.next()) {
134     OpenElementInfo &e = v[--i];
135     e.gi = iter.cur()->type()->name();
136     const LeafContentToken *token = iter.cur()->currentPosition();
137     if (token && !token->isInitial()) {
138       e.matchIndex = token->typeIndex() + 1;
139       const ElementType *type = token->elementType();
140       e.matchType = type ? type->name() : rniPcdata;
141     }
142     e.included = iter.cur()->included();
143   }
144 }
145 
146 ElementType *
lookupCreateUndefinedElement(const StringC & name,const Location & loc,Dtd & dtd)147 ContentState::lookupCreateUndefinedElement(const StringC &name,
148 					   const Location &loc,
149 					   Dtd &dtd)
150 {
151   ElementType *p = new ElementType(name,
152 				   dtd.allocElementTypeIndex());
153   dtd.insertUndefinedElementType(p);
154   p->setElementDefinition(new ElementDefinition(loc,
155 						size_t(ElementDefinition::undefinedIndex),
156 						0,
157 						ElementDefinition::any),
158 			  0);
159   p->setAttributeDef(dtd.implicitElementAttributeDef());
160 
161   includeCount_.push_back(0);
162   excludeCount_.push_back(0);
163   openElementCount_.push_back(0);
164   return p;
165 }
166 
167 
168 #ifdef SP_NAMESPACE
169 }
170 #endif
171