590 lines
13 KiB
C
590 lines
13 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
// $TOG: FeatureDefDictionary.C /main/4 1998/04/17 11:48:58 mgreess $
|
|
|
|
|
|
#include "StyleSheet/FeatureDefDictionary.h"
|
|
#include "StyleSheet/Debug.h"
|
|
#include "StyleSheet/StyleSheetExceptions.h"
|
|
#include "utility/const.h"
|
|
#include "utility/funcs.h"
|
|
#include <iostream>
|
|
using namespace std;
|
|
|
|
featureDefDictionary* g_FeatureDefDictionary = 0;
|
|
|
|
extern void report_error_location();
|
|
|
|
extern def_list_t* g_def_list;
|
|
extern FILE *defParserin;
|
|
extern int defParserparse();
|
|
istream* g_defParserin = 0;
|
|
|
|
unsigned g_validation_mode = false;
|
|
unsigned g_hasSemanticError = false;
|
|
|
|
|
|
ostream& out_tabs(ostream& out, int tabs)
|
|
{
|
|
for (int i=0; i<tabs; i++)
|
|
out << "\t";
|
|
|
|
return out;
|
|
}
|
|
|
|
TypeValues::TypeValues(char* t, defv_t* dv) :
|
|
f_type(t), f_default_values(dv)
|
|
{
|
|
}
|
|
|
|
TypeValues::~TypeValues()
|
|
{
|
|
if ( f_default_values ) {
|
|
f_default_values -> clearAndDestroy();
|
|
delete f_default_values;
|
|
}
|
|
}
|
|
|
|
unsigned int TypeValues::operator==(const TypeValues& def)
|
|
{
|
|
return !f_type.compareTo(def.f_type, CC_String::ignoreCase);
|
|
}
|
|
|
|
ostream& operator <<(ostream& out, TypeValues& tvs)
|
|
{
|
|
return tvs.print(out, 0);
|
|
}
|
|
|
|
unsigned TypeValues::check(const FeatureValue* fv)
|
|
{
|
|
/*
|
|
MESSAGE(cerr, "TypeValues::check()");
|
|
debug(cerr, fv -> type());
|
|
*/
|
|
|
|
// type check
|
|
switch ( fv -> type() ) {
|
|
case FeatureValue::real:
|
|
case FeatureValue::integer:
|
|
//debug(cerr, f_type.data());
|
|
if ( strcasecmp(f_type.data(), "REAL") == 0 ||
|
|
strcasecmp(f_type.data(), "INTEGER") == 0
|
|
)
|
|
break;
|
|
else
|
|
return false;
|
|
|
|
case FeatureValue::string:
|
|
//debug(cerr, f_type.data());
|
|
if ( strcasecmp(f_type.data(), "STRING") == 0 ||
|
|
strcasecmp(f_type.data(), "STRING_PREFIX") == 0
|
|
)
|
|
break;
|
|
else
|
|
return false;
|
|
|
|
case FeatureValue::symbol:
|
|
case FeatureValue::expression:
|
|
case FeatureValue::featureset:
|
|
return false;
|
|
|
|
//debug(cerr, f_type.data());
|
|
case FeatureValue::dimension:
|
|
if ( strcasecmp(f_type.data(), "DIMENSION") == 0 ||
|
|
strcasecmp(f_type.data(), "DIMENSION_PIXEL") == 0
|
|
)
|
|
break;
|
|
else
|
|
return false;
|
|
|
|
case FeatureValue::array:
|
|
//debug(cerr, f_type.data());
|
|
if ( strcasecmp(f_type.data(), "ARRAY") == 0 )
|
|
break;
|
|
else
|
|
return false;
|
|
|
|
}
|
|
|
|
// value check
|
|
if ( f_default_values == 0 ) {
|
|
//MESSAGE(cerr, "check() Passed");
|
|
return true;
|
|
}
|
|
|
|
defv_iterator_t next(*f_default_values);
|
|
const char* x, *y;
|
|
|
|
while (++next) {
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// trap string type as FeatureValueString::operator==() uses
|
|
// case sensitive comparsion
|
|
/////////////////////////////////////////////////////////////
|
|
if ( fv -> type() == FeatureValue::string &&
|
|
next.key() -> type() == FeatureValue::string )
|
|
{
|
|
x = *((FeatureValueString*)next.key());
|
|
y = *(FeatureValueString*)fv;
|
|
|
|
//debug(cerr, x);
|
|
//debug(cerr, y);
|
|
|
|
if ( strcasecmp(f_type.data(), "STRING_PREFIX") == 0 ) {
|
|
if ( strncasecmp(x, y, strlen(x)) == 0 )
|
|
return true;
|
|
} else {
|
|
if ( strcasecmp(x, y) == 0 )
|
|
return true;
|
|
}
|
|
|
|
} else
|
|
|
|
if ( next.key() -> operator==(*fv) == true ) {
|
|
//MESSAGE(cerr, "check() Passed");
|
|
return true ;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
ostream& TypeValues::print(ostream& out, int tabs) const
|
|
{
|
|
out_tabs(out, tabs) << f_type << "\n";
|
|
|
|
if ( f_default_values ) {
|
|
defv_iterator_t NextValue (*f_default_values);
|
|
while (++NextValue) {
|
|
out_tabs(out, tabs+1) << *(NextValue.key()) << "\n";
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
unsigned fhash(const FeatureDef& key)
|
|
{
|
|
return key.name() -> hash();
|
|
}
|
|
|
|
FeatureDef::FeatureDef(const char* name) : f_name(name)
|
|
{
|
|
}
|
|
|
|
FeatureDef::~FeatureDef()
|
|
{
|
|
}
|
|
|
|
ostream& operator << (ostream& out, FeatureDef& def)
|
|
{
|
|
return def.print(out, 0);
|
|
}
|
|
|
|
unsigned int FeatureDef::operator==(const FeatureDef& def)
|
|
{
|
|
//debug(cerr, f_name);
|
|
//debug(cerr, def.f_name);
|
|
// unsigned ok = ! f_name.compareTo(def.f_name, CC_String::ignoreCase);
|
|
//debug(cerr, ok);
|
|
//return ok;
|
|
|
|
return !f_name.compareTo(def.f_name, CC_String::ignoreCase);
|
|
}
|
|
|
|
FeatureDefComposite::FeatureDefComposite(const char* name, def_list_t* dl) :
|
|
FeatureDef(name), f_components(dl)
|
|
{
|
|
}
|
|
|
|
FeatureDefComposite::~FeatureDefComposite()
|
|
{
|
|
if ( f_components ) {
|
|
f_components -> clearAndDestroy();
|
|
delete f_components;
|
|
}
|
|
}
|
|
|
|
CC_Boolean compareFunc(FeatureDef* fd, void* nm)
|
|
{
|
|
if ( strcasecmp( fd -> name() -> data(), (char*)nm ) == 0 )
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
// return true:
|
|
// fv confirms to the spec of a component of this def.
|
|
// return false:
|
|
// otherwise
|
|
unsigned FeatureDefComposite::checkContent(const Feature* fv) const
|
|
{
|
|
/*
|
|
const FeatureDef* def = getComponentDef((fv->name()).name());
|
|
|
|
if ( def == 0 )
|
|
return false;
|
|
|
|
if ( def -> type() != FeatureDef::PRIMITIVE )
|
|
return false;
|
|
|
|
return ((FeatureDefPrimitive*)def) -> checkContent(fv);
|
|
*/
|
|
return true;
|
|
}
|
|
|
|
const FeatureDef* FeatureDefComposite::getComponentDef(const char* nm) const
|
|
{
|
|
if ( f_components == 0 )
|
|
return 0;
|
|
else {
|
|
FeatureDef* def = f_components -> find(compareFunc, (void*)nm);
|
|
|
|
if ( def )
|
|
return def;
|
|
else {
|
|
if ( f_components -> first() -> type() == WILDCARD )
|
|
return f_components -> first();
|
|
else
|
|
return 0;
|
|
}
|
|
//return f_components -> find(compareFunc, "*");
|
|
}
|
|
}
|
|
|
|
ostream& FeatureDefComposite::print(ostream& out, int tabs) const
|
|
{
|
|
out_tabs(out, tabs) << f_name << "\n";
|
|
|
|
if ( f_components ) {
|
|
def_list_iterator_t NextComponent(*f_components);
|
|
while (++NextComponent) {
|
|
NextComponent.key() -> print(out, tabs+1) << "\n";
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
FeatureDefPrimitive::FeatureDefPrimitive(const char* name, type_values_list_t* tvl) :
|
|
FeatureDef(name), f_typeValuesList(tvl)
|
|
{
|
|
}
|
|
|
|
FeatureDefPrimitive::~FeatureDefPrimitive()
|
|
{
|
|
if ( f_typeValuesList ) {
|
|
f_typeValuesList -> clearAndDestroy();
|
|
delete f_typeValuesList;
|
|
}
|
|
}
|
|
|
|
unsigned FeatureDefPrimitive::checkContent(const Feature* f) const
|
|
{
|
|
/*
|
|
MESSAGE(cerr, "FeatureDefPrimitive::checkContent");
|
|
f -> print(cerr);
|
|
MESSAGE(cerr, "");
|
|
debug(cerr, *(this -> name()));
|
|
MESSAGE(cerr, "");
|
|
*/
|
|
|
|
if ( f_typeValuesList == 0 ) {
|
|
report_error_location();
|
|
cerr << "No type definition.\n";
|
|
return false;
|
|
}
|
|
|
|
FeatureValue * fv = 0;
|
|
mtry {
|
|
fv = f -> evaluate();
|
|
}
|
|
mcatch (undefinedAttributeException&, e) {
|
|
return true;
|
|
}
|
|
|
|
mcatch (undefinedVariableException&, e) {
|
|
report_error_location();
|
|
cerr << "Undefined variable error.\n";
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
mcatch (badCastException&, e) {
|
|
report_error_location();
|
|
cerr << "Evaluating expression error.\n";
|
|
return false;
|
|
}
|
|
|
|
mcatch (badEvaluationException&, e) {
|
|
report_error_location();
|
|
cerr << "Evaluating expression error.\n";
|
|
return false;
|
|
}
|
|
*/
|
|
|
|
mcatch_any() {
|
|
//report_error_location();
|
|
//cerr << "There might be an error in the expression.\n";
|
|
return true;
|
|
}
|
|
end_try;
|
|
|
|
/*
|
|
debug(cerr, int(fv));
|
|
fv -> print(cerr);
|
|
MESSAGE(cerr, "");
|
|
*/
|
|
|
|
if ( fv == 0 ) {
|
|
report_error_location();
|
|
cerr << "Error in evaluating an expression.\n";
|
|
return false;
|
|
}
|
|
|
|
type_values_list_iterator_t next(*f_typeValuesList);
|
|
|
|
while ( ++ next ) {
|
|
if ( next.key() -> check(fv) == true ) {
|
|
delete fv;
|
|
return true ;
|
|
}
|
|
}
|
|
|
|
delete fv;
|
|
report_error_location();
|
|
cerr << form("Unmatched feature type or illegal feature value: %s.\n",
|
|
(f -> name()).name()
|
|
);
|
|
return false;
|
|
}
|
|
|
|
ostream& FeatureDefPrimitive::print(ostream& out, int tabs) const
|
|
{
|
|
out_tabs(out, tabs) << f_name << "\n";
|
|
|
|
if ( f_typeValuesList ) {
|
|
type_values_list_iterator_t NextValue (*f_typeValuesList);
|
|
while (++NextValue) {
|
|
NextValue.key() -> print(out, tabs+1) << "\n";
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
unsigned FeatureDefReference::checkContent(const Feature* fv) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ostream& FeatureDefReference::print(ostream& out, int tabs) const
|
|
{
|
|
out_tabs(out, tabs) << f_name << "\n";
|
|
return out;
|
|
}
|
|
|
|
unsigned FeatureDefWildCard::checkContent(const Feature* fv) const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
ostream& FeatureDefWildCard::print(ostream& out, int tabs) const
|
|
{
|
|
out_tabs(out, tabs) << f_name << "\n";
|
|
return out;
|
|
}
|
|
|
|
featureDefDictionary::featureDefDictionary() : f_def_list(0)
|
|
{
|
|
}
|
|
|
|
featureDefDictionary::~featureDefDictionary()
|
|
{
|
|
if ( f_def_list ) {
|
|
f_def_list -> clearAndDestroy();
|
|
delete f_def_list;
|
|
}
|
|
}
|
|
|
|
void
|
|
featureDefDictionary::addFeatureDefs(def_list_t* fdefs)
|
|
{
|
|
f_def_list = fdefs;
|
|
|
|
if ( f_def_list == 0 )
|
|
throw(CASTEXCEPT Exception());
|
|
}
|
|
|
|
const FeatureDef*
|
|
featureDefDictionary::getDef(const char* nm)
|
|
{
|
|
//debug(cerr, nm);
|
|
|
|
FeatureDefReference key((char*)nm);
|
|
return f_def_list -> find(&key);
|
|
|
|
/*
|
|
FeatureDef* def = 0;
|
|
def = f_def_list -> find(&key);
|
|
|
|
debug(cerr, int(def));
|
|
return def;
|
|
*/
|
|
}
|
|
|
|
const FeatureDef*
|
|
featureDefDictionary::getDef(const Feature* f)
|
|
{
|
|
return getDef((f -> name()).name());
|
|
}
|
|
|
|
unsigned
|
|
featureDefDictionary::checkSemantics(const FeatureSet* fs)
|
|
{
|
|
/*
|
|
MESSAGE(cerr, "check feature set:");
|
|
fs -> print(cerr);
|
|
MESSAGE(cerr, "");
|
|
*/
|
|
|
|
const FeatureDef* def = 0;
|
|
const Feature *f = 0;
|
|
|
|
CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*)fs);
|
|
while (++next) {
|
|
f = next.key();
|
|
def = getDef(f);
|
|
|
|
if ( def == 0 ) {
|
|
report_error_location();
|
|
cerr << form("Unknown feature name %s.\n",
|
|
((next.key()) -> name()).name());
|
|
return false;
|
|
}
|
|
|
|
if ( _checkSemantics(f, def) == false )
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
unsigned
|
|
featureDefDictionary::_checkSemantics(const Feature* f, const FeatureDef* def)
|
|
{
|
|
const FeatureSet *featureset = 0;
|
|
const Feature *child_f= 0;
|
|
|
|
/*
|
|
MESSAGE(cerr, "_checkSemantics");
|
|
f -> print(cerr);
|
|
MESSAGE(cerr, "");
|
|
def -> print(cerr, 0);
|
|
MESSAGE(cerr, "");
|
|
*/
|
|
|
|
|
|
const FeatureDef* child_def = 0;
|
|
|
|
if ( def -> checkContent(f) == false ) {
|
|
return false;
|
|
}
|
|
|
|
if (f -> value()->type() == FeatureValue::featureset &&
|
|
def -> type() == FeatureDef::COMPOSITE )
|
|
{
|
|
//MESSAGE(cerr, "it is a feature set");
|
|
|
|
|
|
featureset =
|
|
((const FeatureValueFeatureSet *)(f -> value()))->value();
|
|
|
|
CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*)featureset);
|
|
|
|
const char* nm;
|
|
|
|
while ( ++ next ) {
|
|
|
|
nm = ((next.key()) -> name()).name();
|
|
|
|
/*
|
|
debug(cerr, nm);
|
|
report_error_location();
|
|
*/
|
|
|
|
child_def = ((FeatureDefComposite*)def) -> getComponentDef(nm);
|
|
|
|
//debug(cerr, int(child_def));
|
|
if ( child_def == 0 ) {
|
|
report_error_location();
|
|
cerr << form("%s is a undefined feature.\n", nm);
|
|
return false;
|
|
}
|
|
|
|
switch ( child_def -> type() ) {
|
|
case FeatureDef::REFERENCE:
|
|
child_def = getDef(child_def -> name() -> data());
|
|
break;
|
|
case FeatureDef::WILDCARD:
|
|
child_def = getDef(nm);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
child_f = next.key();
|
|
|
|
if ( _checkSemantics(child_f, child_def) == false )
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
istream& operator >>(istream& in, featureDefDictionary& dict)
|
|
{
|
|
g_defParserin = ∈
|
|
|
|
int ok = defParserparse();
|
|
if ( ok != 0 ) {
|
|
MESSAGE(cerr, "bad feature definition file");
|
|
throw(CASTEXCEPT Exception());
|
|
}
|
|
|
|
dict.addFeatureDefs(g_def_list);
|
|
|
|
return in;
|
|
}
|
|
|
|
ostream& operator <<(ostream& out, featureDefDictionary& dict)
|
|
{
|
|
def_list_iterator_t Next(*dict.f_def_list);
|
|
|
|
while (++Next) {
|
|
//debug(cerr, int(Next.key()));
|
|
out << *Next.key() << "\n";
|
|
}
|
|
return out;
|
|
}
|