diff host/libcdl/func.cxx @ 163:0d2b193a635f

Merge from eCos master repository on 2001-06-22-17:38:39-BST
author jlarmour
date Fri, 22 Jun 2001 18:18:44 +0000
parents 511f4dc167f6
children 74dbf4c3f2e1
line wrap: on
line diff
--- a/host/libcdl/func.cxx
+++ b/host/libcdl/func.cxx
@@ -334,6 +334,99 @@ static bool
 is_substr_infer_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level)
 {
     CYG_REPORT_FUNCNAMETYPE("is_substr_infer_bool", "result %d");
+    CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level);
+
+    bool result = false;
+
+    CdlSubexpression& subexpr   = expr->sub_expressions[index];
+    CdlSubexpression& arg0      = expr->sub_expressions[subexpr.args[0]];
+    try {
+        if (CdlExprOp_Reference == arg0.op) {
+
+            CdlSimpleValue  needle_value;
+            CdlEvalContext context(transaction);
+            expr->eval_subexpression(context, subexpr.args[1], needle_value);
+            std::string     needle  = needle_value.get_value();
+
+            CdlNode         node        = expr->references[arg0.reference_index].get_destination();
+            CdlValuable     valuable    = 0;
+            if (0 != node) {
+                valuable = dynamic_cast<CdlValuable>(node);
+            }
+            if ((0 != valuable) && ((CdlValueFlavor_BoolData == valuable->get_flavor()) ||
+                                    (CdlValueFlavor_Data == valuable->get_flavor()))) {
+                // OK, we have a valuable which can be given a suitable value.
+                // What is the current string?
+                const CdlValue& current_value   = transaction->get_whole_value(valuable);
+                std::string haystack            = current_value.get_simple_value().get_value();
+
+                // What is the goal? If the needle should be in the
+                // haystack, append it if necessary. If the needle
+                // should not be in the haystack, remove all current occurrences.
+                if (goal) {
+                    std::string::size_type len;
+                    if (std::string::npos == is_substr_find(haystack, needle, len)) {
+                        haystack = haystack + needle;
+                    }
+                } else {
+                    std::string::size_type posn, len;
+                    for (posn = is_substr_find(haystack, needle, len);
+                         std::string::npos != posn;
+                         posn = is_substr_find(haystack, needle, len)) {
+                        haystack.erase(posn, len);
+                    }
+                }
+
+                // OK, we have a new value for the haystack which should match the desired goal.
+                // Try and set this value.
+                CdlSimpleValue  new_value(haystack);
+                result = CdlInfer::set_valuable_value(transaction, valuable, new_value, level);
+            }
+        }
+    } catch (...) {
+        result = false;
+    }
+    
+    CYG_REPORT_RETVAL(result);
+    return result;
+}
+
+static CdlFunction is_substr("is_substr", 2, CdlFunction::null_check, &is_substr_eval,
+                             &is_substr_infer_bool, CdlFunction::null_infer_value);
+
+//}}}
+//{{{  is_xsubstr()                     
+
+// ----------------------------------------------------------------------------
+// is_xsubstr(A, B)
+//
+// Like is_substr() but only deals with exact matches, i.e. there is no special
+// treatment for leading and trailing spaces in the needle.
+
+static void
+is_xsubstr_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
+{
+    CYG_REPORT_FUNCNAME("is_xsubstr_eval");
+    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
+    CYG_PRECONDITION_CLASSOC(context);
+    CYG_PRECONDITION_CLASSC(expr);
+
+    CdlSimpleValue      arg0;
+    CdlSimpleValue      arg1;
+    expr->eval_subexpression(context, subexpr.args[0], arg0);
+    expr->eval_subexpression(context, subexpr.args[1], arg1);
+
+    result = (std::string::npos != arg0.get_value().find(arg1.get_value()));
+    CYG_REPORT_RETURN();
+}
+
+// Inference is only supported if the haystack argument is a reference that can be
+// updated. The needle can be an arbitrary expression.
+static bool
+is_xsubstr_infer_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level)
+{
+    CYG_REPORT_FUNCNAMETYPE("is_xsubstr_infer_bool", "result %d");
+    CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level);
 
     bool result = false;
 
@@ -352,7 +445,8 @@ is_substr_infer_bool(CdlTransaction tran
             if (0 != node) {
                 valuable = dynamic_cast<CdlValuable>(node);
             }
-            if ((0 != valuable) && ((CdlValueFlavor_BoolData == valuable->get_flavor()) || (CdlValueFlavor_Data == valuable->get_flavor()))) {
+            if ((0 != valuable) && ((CdlValueFlavor_BoolData == valuable->get_flavor()) ||
+                                    (CdlValueFlavor_Data == valuable->get_flavor()))) {
                 // OK, we have a valuable which can be given a suitable value.
                 // What is the current string?
                 const CdlValue& current_value   = transaction->get_whole_value(valuable);
@@ -362,14 +456,13 @@ is_substr_infer_bool(CdlTransaction tran
                 // haystack, append it if necessary. If the needle
                 // should not be in the haystack, remove all current occurrences.
                 if (goal) {
-                    std::string::size_type len;
-                    if (std::string::npos == is_substr_find(haystack, needle, len)) {
+                    if (std::string::npos == haystack.find(needle)) {
                         haystack = haystack + needle;
                     }
                 } else {
-                    std::string::size_type posn, len;
-                    for (posn = is_substr_find(haystack, needle, len); std::string::npos != posn; posn = is_substr_find(haystack, needle, len)) {
-                        haystack.erase(posn, len);
+                    std::string::size_type posn;
+                    for (posn = haystack.find(needle); std::string::npos != posn; posn = haystack.find(needle)) {
+                        haystack.erase(posn, needle.length());
                     }
                 }
 
@@ -387,6 +480,351 @@ is_substr_infer_bool(CdlTransaction tran
     return result;
 }
 
-static CdlFunction is_substr("is_substr", 2, CdlFunction::null_check, &is_substr_eval, &is_substr_infer_bool, CdlFunction::null_infer_value);
+static CdlFunction is_xsubstr("is_xsubstr", 2, CdlFunction::null_check, &is_xsubstr_eval,
+                              &is_xsubstr_infer_bool, CdlFunction::null_infer_value);
+
+//}}}
+//{{{  is_loaded()                      
+
+// ----------------------------------------------------------------------------
+// is_loaded(x)
+// Check whether or not a particular configuration option is loaded.
+// This takes a single argument which must be a reference. No
+// inference is possible, since loading and unloading packages is
+// currently beyond the scope of the inference engine.
+
+static void
+is_loaded_check(CdlExpression expr, const CdlSubexpression& subexpr)
+{
+    CYG_REPORT_FUNCNAME("is_loaded_check");
+    CYG_REPORT_FUNCARG2XV(expr, &subexpr);
+
+    CdlSubexpression& arg0 = expr->sub_expressions[subexpr.args[0]];
+    if (CdlExprOp_Reference != arg0.op) {
+        throw CdlParseException(std::string("The argument to is_loaded() should be a reference to a configuration option.\n") +
+                                CdlParse::get_expression_error_location());
+    }
+    
+    CYG_REPORT_RETURN();
+}
+
+static void
+is_loaded_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
+{
+    CYG_REPORT_FUNCNAME("is_loaded_eval");
+    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
+    CYG_PRECONDITION_CLASSOC(context);
+    CYG_PRECONDITION_CLASSC(expr);
+
+    CdlSubexpression arg0 = expr->sub_expressions[subexpr.args[0]];
+    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
+
+    result = (0 != context.resolve_reference(expr, arg0.reference_index));
+    CYG_REPORT_RETURN();
+}
+
+static CdlFunction is_loaded("is_loaded", 1, &is_loaded_check, &is_loaded_eval,
+                             CdlFunction::null_infer_bool, CdlFunction::null_infer_value);
+
+//}}}
+//{{{  is_active()                      
+
+// ----------------------------------------------------------------------------
+// is_active(x)
+// Check whether or not a particular configuration option is loaded
+// and active. This takes a single argument which must be a reference.
+
+static void
+is_active_check(CdlExpression expr, const CdlSubexpression& subexpr)
+{
+    CYG_REPORT_FUNCNAME("is_active_check");
+    CYG_REPORT_FUNCARG2XV(expr, &subexpr);
+
+    CdlSubexpression& arg0 = expr->sub_expressions[subexpr.args[0]];
+    if (CdlExprOp_Reference != arg0.op) {
+        throw CdlParseException(std::string("The argument to is_active() should be a reference to a configuration option.\n") +
+                                CdlParse::get_expression_error_location());
+    }
+    
+    CYG_REPORT_RETURN();
+}
+
+static void
+is_active_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
+{
+    CYG_REPORT_FUNCNAME("is_active_eval");
+    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
+    CYG_PRECONDITION_CLASSOC(context);
+    CYG_PRECONDITION_CLASSC(expr);
+
+    CdlSubexpression arg0 = expr->sub_expressions[subexpr.args[0]];
+    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
+
+    CdlNode node = context.resolve_reference(expr, arg0.reference_index);
+    if (0 != node) {
+        result = node->is_active(context.transaction);
+    } else {
+        result = false;
+    }
+    CYG_REPORT_RETURN();
+}
+
+static bool
+is_active_infer_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level)
+{
+    CYG_REPORT_FUNCNAMETYPE("is_active_infer_bool", "result %d");
+    CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level);
+
+    bool result = false;
+
+    CdlSubexpression subexpr    = expr->sub_expressions[index];
+    CdlSubexpression arg0       = expr->sub_expressions[subexpr.args[0]];
+    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
+
+    CdlNode node = expr->references[arg0.reference_index].get_destination();
+    if (0 != node) {
+        if (goal) {
+            result = CdlInfer::make_active(transaction, node, level);
+        } else {
+            result = CdlInfer::make_inactive(transaction, node, level);
+        }
+    }
+    
+    CYG_REPORT_RETVAL(result);
+    return result;
+}
+
+static CdlFunction is_active("is_active", 1, &is_active_check, &is_active_eval,
+                             &is_active_infer_bool, CdlFunction::null_infer_value);
 
 //}}}
+//{{{  is_enabled()                     
+
+// ----------------------------------------------------------------------------
+// is_enabled(x)
+// Check whether or not a particular configuration option is loaded
+// and enabled. The active/inactive state is ignored. This function
+// takes a single argument which must be a reference.
+
+static void
+is_enabled_check(CdlExpression expr, const CdlSubexpression& subexpr)
+{
+    CYG_REPORT_FUNCNAME("is_enabled_check");
+    CYG_REPORT_FUNCARG2XV(expr, &subexpr);
+
+    CdlSubexpression& arg0 = expr->sub_expressions[subexpr.args[0]];
+    if (CdlExprOp_Reference != arg0.op) {
+        throw CdlParseException(std::string("The argument to is_enabled() should be a reference to a configuration option.\n") +
+                                CdlParse::get_expression_error_location());
+    }
+    
+    CYG_REPORT_RETURN();
+}
+
+static void
+is_enabled_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
+{
+    CYG_REPORT_FUNCNAME("is_enabled_eval");
+    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
+    CYG_PRECONDITION_CLASSOC(context);
+    CYG_PRECONDITION_CLASSC(expr);
+
+    CdlSubexpression arg0 = expr->sub_expressions[subexpr.args[0]];
+    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
+
+    CdlValuable valuable = context.resolve_valuable_reference(expr, arg0.reference_index);
+    if (0 != valuable) {
+        if (0 != context.transaction) {
+            result = valuable->is_enabled(context.transaction);
+        } else {
+            result = valuable->is_enabled();
+        }
+    } else {
+        result = false;
+    }
+    CYG_REPORT_RETURN();
+}
+
+static bool
+is_enabled_infer_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level)
+{
+    CYG_REPORT_FUNCNAMETYPE("is_enabled_infer_bool", "result %d");
+    CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level);
+
+    bool result = false;
+
+    CdlSubexpression subexpr    = expr->sub_expressions[index];
+    CdlSubexpression arg0       = expr->sub_expressions[subexpr.args[0]];
+    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
+
+    CdlNode node = expr->references[arg0.reference_index].get_destination();
+    if (0 != node) {
+        CdlValuable valuable    = dynamic_cast<CdlValuable>(node);
+        if (0 != valuable) {
+            // OK, we have found a valuable. Is it already enabled?
+            // Does it have a boolean component? Is it modifiable? Has
+            // it already been modified by the user in this transaction?
+            if (goal == valuable->is_enabled()) {
+                result = true;
+            } else {
+                CdlValueFlavor flavor = valuable->get_flavor();
+                if ((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor)) {
+                    if (valuable->is_modifiable()) {
+                        if (!transaction->changed_by_user(valuable)) {
+                            // We have a modifiable option and want to set the enabled flag.
+                            // However we do not want to lose the current data part - unless
+                            // some other constraint has caused that to be set.
+                            const CdlValue& old_value   = transaction->get_whole_value(valuable);
+                            CdlValue        new_value   = old_value;
+                            if (!old_value.has_source(CdlValueSource_Inferred)) {
+                                CdlSimpleValue simple_value = old_value.get_simple_value(CdlValueSource_Current);
+                                new_value.set_value(simple_value, CdlValueSource_Inferred);
+                            }
+                            new_value.set_enabled(goal, CdlValueSource_Inferred);
+                            new_value.set_source(CdlValueSource_Inferred);
+                            transaction->set_whole_value(valuable, old_value, new_value);
+                            result = transaction->resolve_recursion(level);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    CYG_REPORT_RETVAL(result);
+    return result;
+}
+
+static CdlFunction is_enabled("is_enabled", 1, &is_enabled_check, &is_enabled_eval,
+                              &is_enabled_infer_bool, CdlFunction::null_infer_value);
+
+//}}}
+//{{{  get_data()                       
+
+// ----------------------------------------------------------------------------
+// get_data(x)
+// Returns "0" if the specified option is not enabled, otherwise
+// the current data part fo the value. The active/inactive and the
+// enabled states are ignored. This function takes a single argument
+// which must be a reference.
+
+static void
+get_data_check(CdlExpression expr, const CdlSubexpression& subexpr)
+{
+    CYG_REPORT_FUNCNAME("get_data_check");
+    CYG_REPORT_FUNCARG2XV(expr, &subexpr);
+
+    CdlSubexpression& arg0 = expr->sub_expressions[subexpr.args[0]];
+    if (CdlExprOp_Reference != arg0.op) {
+        throw CdlParseException(std::string("The argument to get_data() should be a reference to a configuration option.\n") +
+                                CdlParse::get_expression_error_location());
+    }
+    
+    CYG_REPORT_RETURN();
+}
+
+static void
+get_data_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
+{
+    CYG_REPORT_FUNCNAME("get_data_eval");
+    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
+    CYG_PRECONDITION_CLASSOC(context);
+    CYG_PRECONDITION_CLASSC(expr);
+
+    CdlSubexpression arg0 = expr->sub_expressions[subexpr.args[0]];
+    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
+
+    CdlValuable valuable = context.resolve_valuable_reference(expr, arg0.reference_index);
+    if (0 != valuable) {
+        if (0 != context.transaction) {
+            result = valuable->get_value(context.transaction);
+        } else {
+            result = valuable->get_value();
+        }
+    } else {
+        result = false;
+    }
+    CYG_REPORT_RETURN();
+}
+
+static bool
+get_data_infer_value(CdlTransaction transaction, CdlExpression expr, unsigned int index,  CdlSimpleValue& goal, int level)
+{
+    CYG_REPORT_FUNCNAMETYPE("get_data_infer_value", "result %d");
+    CYG_REPORT_FUNCARG5XV(transaction, expr, index, &goal, level);
+
+    bool result = false;
+
+    CdlSubexpression subexpr    = expr->sub_expressions[index];
+    CdlSubexpression arg0       = expr->sub_expressions[subexpr.args[0]];
+    CYG_ASSERTC(CdlExprOp_Reference == arg0.op);
+
+    CdlNode node = expr->references[arg0.reference_index].get_destination();
+    if (0 != node) {
+        CdlValuable valuable    = dynamic_cast<CdlValuable>(node);
+        if (0 != valuable) {
+            // OK, we have found a valuable. Does it have a data component?
+            // Does it already have the right value. Is it modifiable? Has
+            // it already been modified by the user in this transaction?
+            CdlValueFlavor flavor = valuable->get_flavor();
+            if ((CdlValueFlavor_Data == flavor) || (CdlValueFlavor_BoolData == flavor)) {
+                CdlSimpleValue current_value = valuable->get_simple_value(transaction);
+                if (goal != current_value) {
+                    if (valuable->is_modifiable()) {
+                        if (!transaction->changed_by_user(valuable)) {
+                            // We have a modifiable option and want to set the data part.
+                            // However we do not want to lose the enabled part - unless
+                            // some other constraint has caused that to be set.
+                            const CdlValue& old_value   = transaction->get_whole_value(valuable);
+                            CdlValue        new_value   = old_value;
+                            if (!old_value.has_source(CdlValueSource_Inferred)) {
+                                new_value.set_enabled(old_value.is_enabled(), CdlValueSource_Inferred);
+                            }
+                            new_value.set_value(goal, CdlValueSource_Inferred);
+                            new_value.set_source(CdlValueSource_Inferred);
+                            transaction->set_whole_value(valuable, old_value, new_value);
+                            result = transaction->resolve_recursion(level);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    CYG_REPORT_RETVAL(result);
+    return result;
+}
+
+static CdlFunction get_data("get_data", 1, &get_data_check, &get_data_eval,
+                            CdlFunction::null_infer_bool, &get_data_infer_value);
+
+//}}}
+//{{{  version_cmp()                    
+
+// ----------------------------------------------------------------------------
+// version_cmp(a, b)
+// Evaluate both arguments, interpret them as version strings, and then
+// return -1, 0 or 1.
+
+static void
+version_cmp_eval(CdlEvalContext& context, CdlExpression expr, const CdlSubexpression& subexpr, CdlSimpleValue& result)
+{
+    CYG_REPORT_FUNCNAME("version_cmp_eval");
+    CYG_REPORT_FUNCARG4XV(&context, expr, &subexpr, &result);
+    CYG_PRECONDITION_CLASSOC(context);
+    CYG_PRECONDITION_CLASSC(expr);
+
+    CdlSimpleValue      arg0;
+    CdlSimpleValue      arg1;
+    expr->eval_subexpression(context, subexpr.args[0], arg0);
+    expr->eval_subexpression(context, subexpr.args[1], arg1);
+
+    result = (cdl_int) Cdl::compare_versions(arg0.get_value(), arg1.get_value());
+    
+    CYG_REPORT_RETURN();
+}
+
+static CdlFunction version_cmp("version_cmp", 2, CdlFunction::null_check, &version_cmp_eval,
+                               CdlFunction::null_infer_bool, CdlFunction::null_infer_value);
+
+//}}}