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