fcedca2c13e7103b1dee5ec7e48ad77125867f34
[oweals/cde.git] / cde / programs / dtinfo / DtMmdb / StyleSheet / FeatureDefDictionary.C
1 // $TOG: FeatureDefDictionary.C /main/4 1998/04/17 11:48:58 mgreess $
2
3
4 #include "StyleSheet/FeatureDefDictionary.h"
5 #include "StyleSheet/Debug.h"
6 #include "StyleSheet/StyleSheetExceptions.h"
7 #include "utility/const.h"
8 #include "utility/funcs.h"
9 #include <iostream.h>
10
11 featureDefDictionary* g_FeatureDefDictionary = 0;
12
13 extern void report_error_location();
14
15 extern def_list_t* g_def_list;
16 extern FILE *defParserin;
17 extern int defParserparse();
18 istream* g_defParserin = 0;
19
20 unsigned g_validation_mode = false;
21 unsigned g_hasSemanticError = false;
22
23
24 ostream& out_tabs(ostream& out, int tabs) 
25 {
26    for (int i=0; i<tabs; i++)
27       out << "\t";
28
29    return out;
30 }
31
32 TypeValues::TypeValues(char* t, defv_t* dv) : 
33         f_type(t), f_default_values(dv)
34 {
35 }
36
37 TypeValues::~TypeValues()
38 {
39    if ( f_default_values ) {
40       f_default_values -> clearAndDestroy();
41       delete f_default_values;
42    }
43 }
44
45 unsigned int TypeValues::operator==(const TypeValues& def)
46 {
47    return !f_type.compareTo(def.f_type, CC_String::ignoreCase);
48 }
49
50 ostream& operator <<(ostream& out, TypeValues& tvs) 
51 {
52    return tvs.print(out, 0);
53 }
54
55 unsigned TypeValues::check(const FeatureValue* fv)
56 {
57 /*
58 MESSAGE(cerr, "TypeValues::check()");
59 debug(cerr, fv -> type());
60 */
61
62 // type check
63    switch ( fv -> type() ) {
64      case FeatureValue::real:
65      case FeatureValue::integer:
66 //debug(cerr, f_type.data());
67        if ( strcasecmp(f_type.data(), "REAL") == 0 ||
68             strcasecmp(f_type.data(), "INTEGER") == 0 
69        )
70           break;
71        else
72           return false;
73
74      case FeatureValue::string:
75 //debug(cerr, f_type.data());
76        if ( strcasecmp(f_type.data(), "STRING") == 0 ||
77             strcasecmp(f_type.data(), "STRING_PREFIX") == 0 
78        )
79           break;
80        else
81           return false;
82
83      case FeatureValue::symbol:
84      case FeatureValue::expression:
85      case FeatureValue::featureset:
86           return false;
87
88 //debug(cerr, f_type.data());
89      case FeatureValue::dimension:
90        if ( strcasecmp(f_type.data(), "DIMENSION") == 0 ||
91             strcasecmp(f_type.data(), "DIMENSION_PIXEL") == 0 
92        )
93           break;
94        else
95           return false;
96
97      case FeatureValue::array:
98 //debug(cerr, f_type.data());
99        if ( strcasecmp(f_type.data(), "ARRAY") == 0 )
100           break;
101        else
102           return false;
103
104    }
105
106 // value check
107    if ( f_default_values == 0 ) {
108 //MESSAGE(cerr, "check() Passed");
109      return true;
110    }
111
112    defv_iterator_t next(*f_default_values);
113    const char* x, *y; 
114
115    while (++next) {
116
117 /////////////////////////////////////////////////////////////
118 // trap string type as FeatureValueString::operator==() uses
119 // case sensitive comparsion
120 /////////////////////////////////////////////////////////////
121      if ( fv -> type() == FeatureValue::string &&
122           next.key() -> type() == FeatureValue::string ) 
123      {
124         x = *((FeatureValueString*)next.key());
125         y = *(FeatureValueString*)fv;
126
127 //debug(cerr, x);
128 //debug(cerr, y);
129
130         if ( strcasecmp(f_type.data(), "STRING_PREFIX") == 0 ) {
131           if ( strncasecmp(x, y, strlen(x)) == 0 )
132              return true;
133         } else {
134           if ( strcasecmp(x, y) == 0 )
135              return true;
136         }
137
138      } else
139
140      if ( next.key() -> operator==(*fv) == true ) {
141 //MESSAGE(cerr, "check() Passed");
142        return true ;
143      }
144    }
145
146    return false;
147 }
148
149 ostream& TypeValues::print(ostream& out, int tabs) const
150 {
151    out_tabs(out, tabs) << f_type << "\n";
152
153    if ( f_default_values ) {
154       defv_iterator_t NextValue (*f_default_values);
155       while (++NextValue) {
156              out_tabs(out, tabs+1) << *(NextValue.key()) << "\n";
157       }
158    }
159
160    return out;
161 }
162
163 unsigned hash(const FeatureDef& key)
164 {
165    return key.name() -> hash();
166 }
167
168 FeatureDef::FeatureDef(const char* name) : f_name(name)
169 {
170 }
171
172 FeatureDef::~FeatureDef()
173 {
174 }
175
176 ostream& operator << (ostream& out, FeatureDef& def)
177 {
178    return def.print(out, 0);
179 }
180
181 unsigned int FeatureDef::operator==(const FeatureDef& def)
182 {
183 //debug(cerr, f_name);
184 //debug(cerr, def.f_name);
185 //   unsigned ok = ! f_name.compareTo(def.f_name, CC_String::ignoreCase);
186 //debug(cerr, ok);
187 //return ok;
188
189    return !f_name.compareTo(def.f_name, CC_String::ignoreCase);
190 }
191
192 FeatureDefComposite::FeatureDefComposite(const char* name, def_list_t* dl) :
193    FeatureDef(name), f_components(dl)
194 {
195 }
196
197 FeatureDefComposite::~FeatureDefComposite()
198 {
199    if ( f_components ) {
200       f_components -> clearAndDestroy();
201       delete f_components;
202    }
203 }
204
205 CC_Boolean compareFunc(FeatureDef* fd, void* nm)
206 {
207    if ( strcasecmp( fd -> name() -> data(), (char*)nm ) == 0 )
208       return TRUE;
209    else
210       return FALSE;
211 }
212
213 // return true:
214 //    fv confirms to the spec of a component of this def.
215 // return false:
216 //    otherwise
217 unsigned FeatureDefComposite::checkContent(const Feature* fv) const
218 {
219 /*
220    const FeatureDef* def = getComponentDef((fv->name()).name());
221
222    if ( def == 0 )
223      return false;
224
225    if ( def -> type() != FeatureDef::PRIMITIVE )
226      return false;
227
228    return ((FeatureDefPrimitive*)def) -> checkContent(fv);
229 */
230    return true;
231 }
232
233 const FeatureDef* FeatureDefComposite::getComponentDef(const char* nm) const
234 {
235    if ( f_components == 0 )
236       return 0;
237    else {
238       FeatureDef* def = f_components -> find(compareFunc, (void*)nm);
239     
240       if ( def )
241          return def;
242       else {
243          if ( f_components -> first() -> type() == WILDCARD )
244             return f_components -> first();
245          else
246             return 0;
247       }
248 //return f_components -> find(compareFunc, "*");
249    }
250 }
251
252 ostream& FeatureDefComposite::print(ostream& out, int tabs) const
253 {
254     out_tabs(out, tabs) << f_name << "\n";
255
256     if ( f_components ) {
257        def_list_iterator_t NextComponent(*f_components);
258        while (++NextComponent) {
259                NextComponent.key() -> print(out, tabs+1) << "\n";
260        }
261     }
262    return out;
263 }
264
265 FeatureDefPrimitive::FeatureDefPrimitive(const char* name, type_values_list_t* tvl) :
266    FeatureDef(name), f_typeValuesList(tvl)
267 {
268 }
269
270 FeatureDefPrimitive::~FeatureDefPrimitive()
271 {
272    if ( f_typeValuesList ) {
273       f_typeValuesList -> clearAndDestroy();
274       delete f_typeValuesList;
275    }
276 }
277
278 unsigned FeatureDefPrimitive::checkContent(const Feature* f) const
279 {
280 /*
281 MESSAGE(cerr, "FeatureDefPrimitive::checkContent");
282 f -> print(cerr);
283 MESSAGE(cerr, "");
284 debug(cerr, *(this -> name()));
285 MESSAGE(cerr, "");
286 */
287
288    if ( f_typeValuesList == 0 ) {
289      report_error_location();
290      cerr << "No type definition.\n";
291      return false;
292    }
293
294    FeatureValue * fv = 0;
295    try {
296      fv = f -> evaluate();
297    }
298    catch (undefinedAttributeException&, e) {
299       return true;
300    }
301
302    catch (undefinedVariableException&, e) {
303       report_error_location();
304       cerr << "Undefined variable error.\n";
305       return false;
306    }
307
308 /*
309    catch (badCastException&, e) {
310       report_error_location();
311       cerr << "Evaluating expression error.\n";
312       return false;
313    }
314
315    catch (badEvaluationException&, e) {
316       report_error_location();
317       cerr << "Evaluating expression error.\n";
318       return false;
319    }
320 */
321
322    catch_any() {
323       //report_error_location();
324       //cerr << "There might be an error in the expression.\n";
325       return true;
326    }
327    end_try;
328    
329 /*
330 debug(cerr, int(fv));
331 fv -> print(cerr);
332 MESSAGE(cerr, "");
333 */
334
335    if ( fv == 0 ) {
336       report_error_location();
337       cerr << "Error in evaluating an expression.\n";
338       return false;
339    }
340
341    type_values_list_iterator_t next(*f_typeValuesList);
342
343    while ( ++ next ) {
344       if ( next.key() -> check(fv) == true ) {
345         delete fv;
346         return true ;
347       }
348    }
349
350    delete fv;
351    report_error_location();
352    cerr << form("Unmatched feature type or illegal feature value: %s.\n", 
353                 (f -> name()).name()
354                );
355    return false;
356 }
357
358 ostream& FeatureDefPrimitive::print(ostream& out, int tabs) const
359 {
360     out_tabs(out, tabs) << f_name << "\n";
361
362     if ( f_typeValuesList ) {
363        type_values_list_iterator_t NextValue (*f_typeValuesList);
364        while (++NextValue) {
365                NextValue.key() -> print(out, tabs+1) << "\n";
366        }
367     }
368     return out;
369 }
370
371 unsigned FeatureDefReference::checkContent(const Feature* fv) const
372 {
373    return false;
374 }
375
376 ostream& FeatureDefReference::print(ostream& out, int tabs) const
377 {
378     out_tabs(out, tabs) << f_name << "\n";
379     return out;
380 }
381
382 unsigned FeatureDefWildCard::checkContent(const Feature* fv) const
383 {
384    return true;
385 }
386
387 ostream& FeatureDefWildCard::print(ostream& out, int tabs) const
388 {
389     out_tabs(out, tabs) << f_name << "\n";
390     return out;
391 }
392
393 featureDefDictionary::featureDefDictionary() : f_def_list(0)
394 {
395 }
396
397 featureDefDictionary::~featureDefDictionary()
398 {
399    if ( f_def_list ) {
400      f_def_list -> clearAndDestroy();
401      delete f_def_list;
402    }
403 }
404         
405 void 
406 featureDefDictionary::addFeatureDefs(def_list_t* fdefs)
407 {
408    f_def_list = fdefs;
409
410    if ( f_def_list == 0 )
411       throw(CASTEXCEPT Exception());
412 }
413     
414 const FeatureDef* 
415 featureDefDictionary::getDef(const char* nm)
416 {
417 //debug(cerr, nm);
418
419    FeatureDefReference key((char*)nm);
420    return f_def_list -> find(&key);
421
422 /*
423  FeatureDef* def = 0;
424  def = f_def_list -> find(&key);
425
426 debug(cerr, int(def));
427    return def;
428 */
429 }
430
431 const FeatureDef* 
432 featureDefDictionary::getDef(const Feature* f)
433 {
434    return getDef((f -> name()).name());
435 }
436
437 unsigned
438 featureDefDictionary::checkSemantics(const FeatureSet* fs)
439 {
440 /*
441 MESSAGE(cerr, "check feature set:");
442 fs -> print(cerr);
443 MESSAGE(cerr, "");
444 */
445
446   const FeatureDef* def = 0;
447   const Feature *f = 0;
448
449   CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*)fs);
450   while (++next) {
451      f = next.key();
452      def = getDef(f);
453
454      if ( def == 0 ) {
455         report_error_location();
456         cerr << form("Unknown feature name %s.\n", 
457                      ((next.key()) -> name()).name());
458         return false;
459      }
460
461      if ( _checkSemantics(f, def) == false )
462        return false;
463   }
464   return true;
465 }
466
467 unsigned
468 featureDefDictionary::_checkSemantics(const Feature* f, const FeatureDef* def)
469 {
470    const FeatureSet *featureset = 0;
471    const Feature *child_f= 0;
472
473 /*
474 MESSAGE(cerr, "_checkSemantics");
475 f -> print(cerr);
476 MESSAGE(cerr, "");
477 def -> print(cerr, 0);
478 MESSAGE(cerr, "");
479 */
480
481         
482    const FeatureDef* child_def = 0;
483
484    if ( def -> checkContent(f) == false ) {
485       return false;
486    }
487
488    if (f -> value()->type() == FeatureValue::featureset &&
489        def -> type() == FeatureDef::COMPOSITE )
490    {
491 //MESSAGE(cerr, "it is a feature set");
492
493
494       featureset = 
495         ((const FeatureValueFeatureSet *)(f -> value()))->value();
496
497       CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*)featureset);
498
499       const char* nm;
500
501       while ( ++ next ) {
502
503         nm = ((next.key()) -> name()).name();
504
505 /*
506 debug(cerr, nm);
507 report_error_location();
508 */
509
510         child_def = ((FeatureDefComposite*)def) -> getComponentDef(nm);
511
512 //debug(cerr, int(child_def));
513         if ( child_def == 0 ) {
514           report_error_location();
515           cerr << form("%s is a undefined feature.\n", nm);
516           return false;
517         }
518
519         switch ( child_def -> type() ) {
520           case FeatureDef::REFERENCE:
521            child_def = getDef(child_def -> name() -> data());
522            break;
523           case FeatureDef::WILDCARD:
524            child_def = getDef(nm);
525            break;
526           default:
527            break;
528         }
529
530         child_f = next.key();
531
532         if ( _checkSemantics(child_f, child_def) == false )
533            return false;
534
535       }
536
537       return true;
538    } 
539    return true;
540 }
541
542 istream& operator >>(istream& in, featureDefDictionary& dict)
543 {
544    g_defParserin = &in;
545
546    int ok = defParserparse();
547    if ( ok != 0 ) {
548       MESSAGE(cerr, "bad feature definition file");
549       throw(CASTEXCEPT Exception());
550    }
551
552    dict.addFeatureDefs(g_def_list);
553
554    return in;
555 }
556
557 ostream& operator <<(ostream& out, featureDefDictionary& dict)
558 {
559    def_list_iterator_t Next(*dict.f_def_list);
560
561    while (++Next) {
562 //debug(cerr, int(Next.key()));
563       out << *Next.key() << "\n"; 
564    }
565    return out;
566 }