5f2130e49f3d6e6343c68e19fce96f6a05c6f638
[oweals/cde.git] / cde / programs / dtinfo / DtMmdb / StyleSheet / Expression.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 libraries 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 // $TOG: Expression.C /main/9 1998/04/17 11:48:40 mgreess $
24 #include "Attribute.h"
25 #include "AttributeList.h"
26 #include "Expression.h"
27 #include "FeatureValue.h"
28 #include "ResolverStack.h"
29 #include "StyleSheetExceptions.h"
30 #include "VariableTable.h"
31 #include "Renderer.h"
32 #include "Debug.h"
33 #include <sstream>
34
35 #include "HardCopy/autoNumberFP.h"
36
37
38 extern const Element            *gCurrentElement;
39 extern const FeatureSet         *gCurrentLocalSet;
40 extern const FeatureSet         *gParentCompleteSet;
41
42 Expression::Expression(TermNode *root)
43 : f_root(root)
44 {
45 }
46
47 Expression::Expression(const Expression &e)
48 : f_root(e.f_root->clone())
49 {
50 }
51
52 ConstantNode::ConstantNode(FeatureValue *v)
53 : f_value(v)
54 {
55 }
56
57 VariableNode::VariableNode(const Symbol &name)
58 : f_name(name)
59 {
60 }
61
62 CompositeVariableNode::CompositeVariableNode()
63 : f_items(4)
64 {
65 }
66
67 CompositeVariableNode::CompositeVariableNode(size_t capac)
68 : f_items(capac)
69 {
70 }
71
72 CompositeVariableNode::~CompositeVariableNode()
73 {
74   f_items.clearAndDestroy();
75 }
76
77 void
78 CompositeVariableNode::prependItem(const Symbol& item)
79 {
80   f_items.prepend(new Symbol(item));
81 }
82
83 void
84 CompositeVariableNode::appendItem(const Symbol& item)
85 {
86   f_items.append(new Symbol(item));
87 }
88
89 const Symbol* 
90 CompositeVariableNode::convertableToVariable()
91 {
92    const Symbol* x = 0;
93    if ( f_items.entries() == 1 ) {
94       x = f_items.first();
95       if ( gVariableTable -> exists(*x) ) 
96          return x; 
97    }
98  
99    return 0;
100 }
101
102 BinaryOperatorNode::BinaryOperatorNode(operatorType t,
103                                        TermNode *left, TermNode *right)
104 : f_operator(t), f_left(left), f_right(right)
105 {
106 }
107
108 BinaryOperatorNode::~BinaryOperatorNode()
109 {
110   delete f_left ;
111   delete f_right;
112 }
113
114 SgmlAttributeNode::SgmlAttributeNode(const Symbol &name)
115 : f_name(name)
116 {
117 }
118
119 FeatureValue *
120 Expression::evaluate() const
121 {
122   return f_root->evaluate();
123 }
124
125 Expression::~Expression()
126 {
127   delete  f_root ;
128 }
129
130 TermNode::~TermNode()
131 {
132 }
133
134 ConstantNode::~ConstantNode()
135 {
136   delete f_value ;
137 }
138
139 FeatureValue *
140 BinaryOperatorNode::evaluate() const
141 {
142   // calculate children trees and then have feature value do the operation 
143
144 #if !defined(SC3) && !defined(_IBMR2) && !defined(linux) && \
145     !defined(CSRG_BASED) && !defined(sun)
146   volatile
147 #endif
148   FeatureValue *left =  0;
149 #if !defined(SC3) && !defined(_IBMR2) && !defined(linux) && \
150     !defined(CSRG_BASED) && !defined(sun)
151   volatile
152 #endif
153   FeatureValue *right = 0;
154 #if !defined(SC3) && !defined(_IBMR2) && !defined(linux) && \
155     !defined(CSRG_BASED) && !defined(sun)
156   volatile
157 #endif
158   FeatureValue *result = 0;
159
160   mtry
161     {
162       left  = f_left->evaluate();
163       right = f_right->evaluate();
164
165       switch (f_operator)
166         {
167         case PLUS:
168           result = *left + *right ;
169           break;
170         case MINUS:
171           result = *left - *right ;
172           break;
173         case TIMES:
174           result = *left * *right ;
175           break;
176         case DIVIDE:
177           result = *left / *right ;
178           break;
179         }
180
181     }
182   mcatch_any()
183     {
184       delete left ;
185       delete right ;
186       delete result ;
187       rethrow;
188     }
189   end_try ;
190   delete left ;
191   delete right ;
192   return result ;
193
194 }
195
196
197 FeatureValue *
198 VariableNode::evaluate() const
199 {
200   // this could be a feature or a variable 
201   // first look in the parent feature set 
202
203   // NOTE: actual operation should be to look in the local feature set first
204   // before going to the parent unless the inherit operator was used. Not sure
205   // how to do this, because at this point, we are trying to evaluate the
206   // current feature set
207
208   // see if item exists in parent feature hierarchy, and if not, then we go to
209   // the variable table
210
211 //MESSAGE(cerr, "VariableNode::evaluate()");
212 //f_name.print(cerr);
213   
214   FeatureValue *variable_value = gVariableTable->lookup(f_name).evaluate();
215
216 //debug(cerr, int(variable_value));
217
218   if (!variable_value)
219     throw(CASTUVEXCEPT undefinedVariableException(f_name));
220
221   // have to evaluate it in case it contains expressions or other variables
222   // etc.  
223   FeatureValue *return_variable = 0;
224
225   mtry
226     {
227       return_variable = variable_value->evaluate() ;
228     }
229   mcatch_any()
230     {
231       delete return_variable; 
232       delete variable_value ;
233       rethrow;
234     }
235   end_try;
236
237 //MESSAGE(cerr, "VariableNode::evaluate() completes");
238
239   delete variable_value ;
240   return return_variable;
241 }
242
243 FeatureValue *
244 CompositeVariableNode::evaluate() const
245 {
246 /*
247 MESSAGE(cerr, "CompositeVariableNode::evaluate():");
248 print(cerr);
249 cerr << "\n";
250 f_items[0] -> print(cerr);
251 MESSAGE(cerr, "");
252 */
253
254 //debug(cerr, int(gCurrentLocalSet));
255 //debug(cerr, int(gParentCompleteSet));
256
257   const Feature *f = 0;
258
259   if ( gCurrentLocalSet )
260      f = gCurrentLocalSet->deep_lookup(f_items) ;
261
262 //debug(cerr, int(f));
263
264   if (!f && gParentCompleteSet )
265     f = gParentCompleteSet->deep_lookup(f_items);
266
267 //debug(cerr, int(f));
268
269   //if ( f == 0 && gRenderer ) {
270   if ( f == 0 ) {
271     FeatureValue* fv = gAutoNumberFP.evaluate(f_items[0] -> name());
272     if ( fv == 0 ) {
273        //print(cerr);
274        throw(CASTBEEXCEPT badEvaluationException());
275     } else
276        return fv;
277   }
278
279   if (!f) {
280     //print(cerr);
281     throw(CASTBEEXCEPT badEvaluationException());
282   }
283
284   return f->evaluate();
285 }
286
287
288
289
290 FeatureValue *
291 ConstantNode::evaluate() const
292 {
293   //return f_value->clone();
294   return f_value->evaluate();
295 }
296
297 extern unsigned g_validation_mode;
298
299 #if defined(__FreeBSD__) && (__FreeBSD__ >= 10) && !defined(__llvm__)
300 __attribute__((optimize(0)))
301 #endif
302 FeatureValue *
303 SgmlAttributeNode::evaluate() const
304 {
305   if ( g_validation_mode == true ) {
306     throw(CASTUAEXCEPT undefinedAttributeException(f_name));
307   }
308
309   const Attribute *attr = gCurrentElement->get_attribute(f_name);
310
311   if (attr)
312     return new FeatureValueString(attr->value());
313   
314   throw(CASTUAEXCEPT undefinedAttributeException(f_name));
315
316   return 0 ;
317 }
318
319
320  // ////////////////////////////////////////////////////////////////////////
321  // Printing
322  // ////////////////////////////////////////////////////////////////////////
323
324 ostream &operator<<(ostream &o, const Expression &e)
325 {
326   return e.print(o);
327 }
328
329 ostream &operator<< (ostream &o, const TermNode &t)
330 {
331   return t.print(o);
332 }
333
334 ostream &
335 Expression::print(ostream &o) const
336 {
337   return o << *f_root ; 
338 }
339
340 ostream &
341 VariableNode::print(ostream &o) const
342 {
343   return o << f_name ;
344 }
345
346 ostream &
347 BinaryOperatorNode::print(ostream &o) const
348 {
349   o << "(" << *f_left << ' ';
350   switch (f_operator)
351     {
352     case PLUS:
353       o << '+' ;
354       break;
355     case MINUS:
356       o << '-';
357       break;
358     case TIMES:
359       o << '*' ;
360       break;
361     case DIVIDE:
362       o << '/';
363       break;
364     }
365
366   return o << ' ' << *f_right << ')' ;
367 }
368
369 ostream &
370 SgmlAttributeNode::print(ostream &o) const
371 {
372   return o << '@' << f_name ;
373 }
374
375 ostream &
376 ConstantNode::print(ostream &o) const
377 {
378   return o << *f_value ;
379 }
380
381
382 ostream &
383 CompositeVariableNode::print(ostream &o) const
384 {
385   int length = f_items.entries();
386   for (int i = 0; i < length; i++)
387     {
388       o << *f_items[i] ;
389       if (i < length - 1)
390         o << "." ;
391     }
392
393   return o ;
394 }
395
396 // /////////////////////////////////////////////////////////////////////////
397 // cloning
398 // /////////////////////////////////////////////////////////////////////////
399
400 TermNode *
401 VariableNode::clone() const
402 {
403   return new VariableNode(f_name);
404 }
405
406 TermNode *
407 CompositeVariableNode::clone() const
408 {
409   int nitems = f_items.entries();
410   CompositeVariableNode *node = new CompositeVariableNode(nitems);
411
412   for (int i = 0; i < nitems; i++)
413     node->appendItem(*f_items(i));
414
415   return node ;
416 }
417
418 TermNode *
419 BinaryOperatorNode::clone() const
420 {
421   return new BinaryOperatorNode(f_operator, f_left->clone(), f_right->clone());
422 }
423
424 TermNode *
425 SgmlAttributeNode::clone() const
426 {
427   return new SgmlAttributeNode(f_name);
428 }
429
430 TermNode *
431 ConstantNode::clone() const
432 {
433   return new ConstantNode(f_value->clone());
434 }
435