1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3
4 #ifdef __GNUG__
5 #pragma implementation
6 #endif
7 #include "splib.h"
8 #include "LinkProcess.h"
9 // ParserState is used for access to parser messages
10 #include "ParserState.h"
11 #include "MessageArg.h"
12 #include "ParserMessages.h"
13
14 #ifdef SP_NAMESPACE
15 namespace SP_NAMESPACE {
16 #endif
17
LinkProcess()18 LinkProcess::LinkProcess()
19 {
20 }
21
init(const ConstPtr<ComplexLpd> & lpd)22 void LinkProcess::init(const ConstPtr<ComplexLpd> &lpd)
23 {
24 lpd_ = lpd;
25 open_.clear();
26 open_.insert(new LinkProcessOpenElement(lpd_->initialLinkSet()));
27 }
28
startElement(const ElementType * element,const AttributeList & attributes,const Location & location,Messenger & mgr,const AttributeList * & linkAttributes,const ResultElementSpec * & resultElementSpec)29 Boolean LinkProcess::startElement(const ElementType *element,
30 const AttributeList &attributes,
31 const Location &location,
32 Messenger &mgr,
33 const AttributeList *&linkAttributes,
34 const ResultElementSpec *&resultElementSpec)
35 {
36 if (lpd_.isNull()) {
37 linkAttributes = 0;
38 resultElementSpec = 0;
39 return 1;
40 }
41 const StringC *id = attributes.getId();
42 if (id) {
43 const IdLinkRuleGroup *p = lpd_->lookupIdLink(*id);
44 if (p) {
45 size_t selected;
46 if (p->nLinkRules() > 1) {
47 linkAttributes_.resize(p->nLinkRules());
48 for (size_t i = 0; i < linkAttributes_.size(); i++)
49 linkAttributes_[i] = &p->linkRule(i).attributes();
50 if (!selectLinkRule(linkAttributes_,
51 location,
52 selected))
53 return 0;
54 }
55 else
56 selected = 0;
57 const IdLinkRule &rule = p->linkRule(selected);
58 open_.insert(new LinkProcessOpenElement(open_.head()->current,
59 rule));
60 linkAttributes = &rule.attributes();
61 resultElementSpec = &rule.resultElementSpec();
62 if (!rule.isAssociatedWith(element)) {
63 mgr.setNextLocation(location);
64 mgr.message(ParserMessages::idlinkElementType,
65 StringMessageArg(element->name()),
66 StringMessageArg(*id));
67 }
68 return 1;
69 }
70 }
71 const LinkSet *currentLinkSet = open_.head()->current;
72 size_t nRules = currentLinkSet->nLinkRules(element);
73 if (nRules > 0) {
74 size_t selected;
75 if (nRules > 1) {
76 linkAttributes_.resize(nRules);
77 for (size_t i = 0; i < nRules; i++)
78 linkAttributes_[i]
79 = ¤tLinkSet->linkRule(element, i).attributes();
80 if (!selectLinkRule(linkAttributes_,
81 location,
82 selected))
83 return 0;
84 }
85 else
86 selected = 0;
87 const SourceLinkRule &rule = currentLinkSet->linkRule(element, selected);
88 open_.insert(new LinkProcessOpenElement(open_.head()->current,
89 rule));
90 linkAttributes = &rule.attributes();
91 resultElementSpec = &rule.resultElementSpec();
92 return 1;
93 }
94 // FIXME construct attributes from attribute definition list
95 linkAttributes = 0;
96 resultElementSpec = 0;
97 open_.insert(new LinkProcessOpenElement(open_.head()->current));
98 return 1;
99 }
100
101
endElement()102 void LinkProcess::endElement()
103 {
104 if (lpd_.isNull())
105 return;
106 LinkProcessOpenElement *top = open_.get();
107 if (top->post)
108 open_.head()->current = top->post;
109 else if (top->postRestore)
110 open_.head()->current = open_.head()->restore;
111 delete top;
112 }
113
uselink(const LinkSet * linkSet,Boolean restore,const Lpd * lpd)114 void LinkProcess::uselink(const LinkSet *linkSet,
115 Boolean restore,
116 const Lpd *lpd)
117 {
118 if (lpd_.isNull())
119 return;
120 if (lpd != lpd_.pointer())
121 return;
122 if (restore)
123 open_.head()->current = open_.head()->restore;
124 else if (linkSet)
125 open_.head()->current = linkSet;
126 }
127
nImpliedLinkRules() const128 size_t LinkProcess::nImpliedLinkRules() const
129 {
130 if (!open_.head())
131 return 0;
132 return open_.head()->current->nImpliedLinkRules();
133 }
134
impliedLinkRule(size_t i) const135 const ResultElementSpec &LinkProcess::impliedLinkRule(size_t i) const
136 {
137 return open_.head()->current->impliedLinkRule(i);
138 }
139
140 // Usually redefined by application.
141
selectLinkRule(const Vector<const AttributeList * > &,const Location &,size_t & selected)142 Boolean LinkProcess::selectLinkRule(const Vector<const AttributeList *> &,
143 const Location &,
144 size_t &selected)
145 {
146 selected = 0;
147 return 1;
148 }
149
clear()150 void LinkProcess::clear()
151 {
152 open_.clear();
153 lpd_.clear();
154 linkAttributes_.clear();
155 }
156
swap(LinkProcess & to)157 void LinkProcess::swap(LinkProcess &to)
158 {
159 open_.swap(to.open_);
160 lpd_.swap(to.lpd_);
161 linkAttributes_.swap(to.linkAttributes_);
162 }
163
LinkProcessOpenElement(const LinkSet * cur,const SourceLinkRule & rule)164 LinkProcessOpenElement::LinkProcessOpenElement(const LinkSet *cur,
165 const SourceLinkRule &rule)
166 {
167 current = rule.uselink();
168 if (!current)
169 current = cur;
170 restore = cur;
171 post = rule.postlink();
172 postRestore = rule.postlinkRestore();
173 }
174
LinkProcessOpenElement(const LinkSet * cur)175 LinkProcessOpenElement::LinkProcessOpenElement(const LinkSet *cur)
176 {
177 restore = current = cur;
178 post = 0;
179 postRestore = 0;
180 }
181
182
183 #ifdef SP_NAMESPACE
184 }
185 #endif
186